From 5100311e86264fa3f4495a74d7794d193f70011a Mon Sep 17 00:00:00 2001 From: Ruichao Wu Date: Wed, 24 Jul 2024 11:58:39 +0200 Subject: [PATCH 1/8] fixed by npm audit fix --- package-lock.json | 635 +++++++++++++++++----------------------------- 1 file changed, 233 insertions(+), 402 deletions(-) diff --git a/package-lock.json b/package-lock.json index 44920cb2..985683c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -272,26 +272,12 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@npmcli/fs/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -320,13 +306,11 @@ } }, "node_modules/@npmcli/git/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -334,18 +318,6 @@ "node": ">=10" } }, - "node_modules/@npmcli/git/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@npmcli/git/node_modules/which": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", @@ -889,10 +861,11 @@ } }, "node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1150,10 +1123,11 @@ } }, "node_modules/boxen/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1354,26 +1328,12 @@ "semver": "^7.0.0" } }, - "node_modules/builtins/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/builtins/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -1677,10 +1637,11 @@ } }, "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2332,10 +2293,11 @@ } }, "node_modules/eslint/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2990,10 +2952,11 @@ } }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -4015,11 +3978,26 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, - "node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "dev": true + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/is-absolute": { "version": "1.0.0", @@ -4328,6 +4306,13 @@ "xmlcreate": "^2.0.4" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, + "license": "MIT" + }, "node_modules/jsdoc": { "version": "3.6.11", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", @@ -4896,13 +4881,11 @@ } }, "node_modules/make-fetch-happen/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -4910,18 +4893,6 @@ "node": ">=10" } }, - "node_modules/make-fetch-happen/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-fetch-happen/node_modules/ssri": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", @@ -5519,18 +5490,6 @@ "node": "^12.13 || ^14.13 || >=16" } }, - "node_modules/node-gyp/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/node-gyp/node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -5547,13 +5506,11 @@ } }, "node_modules/node-gyp/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5588,26 +5545,12 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5648,26 +5591,12 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-install-checks/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/npm-install-checks/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5699,26 +5628,12 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/npm-package-arg/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5753,26 +5668,12 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-pick-manifest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/npm-pick-manifest/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -6808,10 +6709,11 @@ "dev": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -7000,16 +6902,17 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, + "license": "MIT", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -7205,10 +7108,11 @@ } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -7324,18 +7228,19 @@ "node_modules/taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", "dev": true }, "node_modules/tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -7368,6 +7273,16 @@ "node": ">=8" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, "node_modules/terser": { "version": "5.14.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", @@ -7407,7 +7322,8 @@ "node_modules/three": { "version": "0.89.0", "resolved": "https://registry.npmjs.org/three/-/three-0.89.0.tgz", - "integrity": "sha1-RELYGaYWiHG40ss3rRKiQxDBcPU=" + "integrity": "sha512-Evv3JolLQtag/lCWu1o3cgz2E5UYCSZHbh9lfBjeLz7nlK8DMmASID680Odl++ZPYk63rrZjPAMq88IrMP3GCA==", + "license": "MIT" }, "node_modules/through": { "version": "2.3.8", @@ -7877,10 +7793,11 @@ } }, "node_modules/widest-line/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8060,10 +7977,11 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8256,10 +8174,11 @@ } }, "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8503,23 +8422,11 @@ "semver": "^7.3.5" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -8541,24 +8448,10 @@ }, "dependencies": { "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "which": { "version": "3.0.0", @@ -8958,9 +8851,9 @@ "dev": true }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "ansi-styles": { @@ -9174,9 +9067,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "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": { @@ -9332,23 +9225,11 @@ "semver": "^7.0.0" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -9576,9 +9457,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "emoji-regex": { @@ -10068,9 +9949,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true }, "cross-spawn": { @@ -10596,9 +10477,9 @@ "dev": true }, "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true }, "get-intrinsic": { @@ -10993,7 +10874,7 @@ "version": "git+ssh://git@github.com/RobotWebTools/grunt-pipe.git#d0937a52726f8f73df5d6d704d0519473150fb0e", "integrity": "sha512-DPgn249Wea0hGLV8SHUGHk7Wdk9r4rY/L3tRHPSrYFRsCV9o8jR0P31wUXCEz2u5ci/0JEJ7eLn1jtYJ2+wS1g==", "dev": true, - "from": "grunt-pipe@git+https://github.com/RobotWebTools/grunt-pipe.git#d0937a52726f8f73df5d6d704d0519473150fb0e", + "from": "grunt-pipe@git+https://github.com/RobotWebTools/grunt-pipe.git", "requires": { "cheerio": "^1.0.0-rc.12" } @@ -11371,11 +11252,23 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, - "ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "dev": true + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + } + } }, "is-absolute": { "version": "1.0.0", @@ -11597,6 +11490,12 @@ "xmlcreate": "^2.0.4" } }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "jsdoc": { "version": "3.6.11", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", @@ -12059,24 +11958,10 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "ssri": { "version": "9.0.1", @@ -12544,15 +12429,6 @@ "which": "^2.0.2" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -12563,13 +12439,10 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -12594,23 +12467,11 @@ "validate-npm-package-license": "^3.0.4" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -12638,23 +12499,11 @@ "semver": "^7.1.1" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -12676,23 +12525,11 @@ "validate-npm-package-name": "^5.0.0" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -12717,23 +12554,11 @@ "semver": "^7.3.5" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true } } }, @@ -13529,9 +13354,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "serialize-javascript": { @@ -13684,12 +13509,12 @@ } }, "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "requires": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, @@ -13816,9 +13641,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true }, "strip-ansi": { @@ -13947,18 +13772,18 @@ "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", "dev": true }, "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -13983,6 +13808,12 @@ } } } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true } } }, @@ -14015,7 +13846,7 @@ "three": { "version": "0.89.0", "resolved": "https://registry.npmjs.org/three/-/three-0.89.0.tgz", - "integrity": "sha1-RELYGaYWiHG40ss3rRKiQxDBcPU=" + "integrity": "sha512-Evv3JolLQtag/lCWu1o3cgz2E5UYCSZHbh9lfBjeLz7nlK8DMmASID680Odl++ZPYk63rrZjPAMq88IrMP3GCA==" }, "through": { "version": "2.3.8", @@ -14375,9 +14206,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "emoji-regex": { @@ -14438,9 +14269,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "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": { @@ -14642,9 +14473,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "emoji-regex": { From fb2586ead653b354c87658077336e6378bf79fa3 Mon Sep 17 00:00:00 2001 From: Ruichao Wu Date: Wed, 24 Jul 2024 12:06:30 +0200 Subject: [PATCH 2/8] change to "eventemitter3": "^5.0.1" --- .eslintrc | 2 +- build/ros3d.cjs.js | 1694 +---------------- build/ros3d.esm.js | 1694 +---------------- build/ros3d.js | 1648 +--------------- build/ros3d.min.js | 13 +- package-lock.json | 33 +- package.json | 2 +- .../InteractiveMarkerHandle.js | 2 +- src/markers/MarkerArrayClient.js | 2 +- src/markers/MarkerClient.js | 2 +- src/navigation/OcTreeClient.js | 4 +- src/navigation/OccupancyGridClient.js | 4 +- 12 files changed, 89 insertions(+), 5011 deletions(-) diff --git a/.eslintrc b/.eslintrc index 5d29595c..4db82389 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,7 +6,7 @@ "mocha": true }, "globals": { - "EventEmitter2": true, + "EventEmitter3": true, "THREE": true, "ROS3D": true, "ROSLIB": true, diff --git a/build/ros3d.cjs.js b/build/ros3d.cjs.js index 8d89cddb..b6caaa3f 100644 --- a/build/ros3d.cjs.js +++ b/build/ros3d.cjs.js @@ -53248,1658 +53248,14 @@ var InteractiveMarker = /*@__PURE__*/(function (superclass) { return InteractiveMarker; }(THREE.Object3D)); -function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; -} - -var eventemitter2 = {exports: {}}; - -/*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */ -eventemitter2.exports; - -(function (module, exports) { -!function(undefined$1) { - var hasOwnProperty= Object.hasOwnProperty; - var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - var defaultMaxListeners = 10; - var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; - var symbolsSupported= typeof Symbol==='function'; - var reflectSupported= typeof Reflect === 'object'; - var setImmediateSupported= typeof setImmediate === 'function'; - var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; - var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ - var arr= Object.getOwnPropertyNames(obj); - arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); - return arr; - }) : Object.keys; - - function init() { - this._events = {}; - if (this._conf) { - configure.call(this, this._conf); - } - } - - function configure(conf) { - if (conf) { - this._conf = conf; - - conf.delimiter && (this.delimiter = conf.delimiter); - - if(conf.maxListeners!==undefined$1){ - this._maxListeners= conf.maxListeners; - } - - conf.wildcard && (this.wildcard = conf.wildcard); - conf.newListener && (this._newListener = conf.newListener); - conf.removeListener && (this._removeListener = conf.removeListener); - conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); - conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); - - if (this.wildcard) { - this.listenerTree = {}; - } - } - } - - function logPossibleMemoryLeak(count, eventName) { - var errorMsg = '(node) warning: possible EventEmitter memory ' + - 'leak detected. ' + count + ' listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.'; - - if(this.verboseMemoryLeak){ - errorMsg += ' Event name: ' + eventName + '.'; - } - - if(typeof process !== 'undefined' && process.emitWarning){ - var e = new Error(errorMsg); - e.name = 'MaxListenersExceededWarning'; - e.emitter = this; - e.count = count; - process.emitWarning(e); - } else { - console.error(errorMsg); - - if (console.trace){ - console.trace(); - } - } - } - - var toArray = function (a, b, c) { - var arguments$1 = arguments; - - var n = arguments.length; - switch (n) { - case 0: - return []; - case 1: - return [a]; - case 2: - return [a, b]; - case 3: - return [a, b, c]; - default: - var arr = new Array(n); - while (n--) { - arr[n] = arguments$1[n]; - } - return arr; - } - }; - - function toObject(keys, values) { - var obj = {}; - var key; - var len = keys.length; - var valuesCount = values ? value.length : 0; - for (var i = 0; i < len; i++) { - key = keys[i]; - obj[key] = i < valuesCount ? values[i] : undefined$1; - } - return obj; - } - - function TargetObserver(emitter, target, options) { - this._emitter = emitter; - this._target = target; - this._listeners = {}; - this._listenersCount = 0; - - var on, off; - - if (options.on || options.off) { - on = options.on; - off = options.off; - } - - if (target.addEventListener) { - on = target.addEventListener; - off = target.removeEventListener; - } else if (target.addListener) { - on = target.addListener; - off = target.removeListener; - } else if (target.on) { - on = target.on; - off = target.off; - } - - if (!on && !off) { - throw Error('target does not implement any known event API'); - } - - if (typeof on !== 'function') { - throw TypeError('on method must be a function'); - } - - if (typeof off !== 'function') { - throw TypeError('off method must be a function'); - } - - this._on = on; - this._off = off; - - var _observers= emitter._observers; - if(_observers){ - _observers.push(this); - }else { - emitter._observers= [this]; - } - } - - Object.assign(TargetObserver.prototype, { - subscribe: function(event, localEvent, reducer){ - var observer= this; - var target= this._target; - var emitter= this._emitter; - var listeners= this._listeners; - var handler= function(){ - var args= toArray.apply(null, arguments); - var eventObj= { - data: args, - name: localEvent, - original: event - }; - if(reducer){ - var result= reducer.call(target, eventObj); - if(result!==false){ - emitter.emit.apply(emitter, [eventObj.name].concat(args)); - } - return; - } - emitter.emit.apply(emitter, [localEvent].concat(args)); - }; - - - if(listeners[event]){ - throw Error('Event \'' + event + '\' is already listening'); - } - - this._listenersCount++; - - if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ - - this._onNewListener = function (_event) { - if (_event === localEvent && listeners[event] === null) { - listeners[event] = handler; - observer._on.call(target, event, handler); - } - }; - - emitter.on('newListener', this._onNewListener); - - this._onRemoveListener= function(_event){ - if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ - listeners[event]= null; - observer._off.call(target, event, handler); - } - }; - - listeners[event]= null; - - emitter.on('removeListener', this._onRemoveListener); - }else { - listeners[event]= handler; - observer._on.call(target, event, handler); - } - }, - - unsubscribe: function(event){ - var observer= this; - var listeners= this._listeners; - var emitter= this._emitter; - var handler; - var events; - var off= this._off; - var target= this._target; - var i; - - if(event && typeof event!=='string'){ - throw TypeError('event must be a string'); - } - - function clearRefs(){ - if(observer._onNewListener){ - emitter.off('newListener', observer._onNewListener); - emitter.off('removeListener', observer._onRemoveListener); - observer._onNewListener= null; - observer._onRemoveListener= null; - } - var index= findTargetIndex.call(emitter, observer); - emitter._observers.splice(index, 1); - } - - if(event){ - handler= listeners[event]; - if(!handler) { return; } - off.call(target, event, handler); - delete listeners[event]; - if(!--this._listenersCount){ - clearRefs(); - } - }else { - events= ownKeys(listeners); - i= events.length; - while(i-->0){ - event= events[i]; - off.call(target, event, listeners[event]); - } - this._listeners= {}; - this._listenersCount= 0; - clearRefs(); - } - } - }); - - function resolveOptions(options, schema, reducers, allowUnknown) { - var computedOptions = Object.assign({}, schema); - - if (!options) { return computedOptions; } - - if (typeof options !== 'object') { - throw TypeError('options must be an object') - } - - var keys = Object.keys(options); - var length = keys.length; - var option, value; - var reducer; - - function reject(reason) { - throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) - } - - for (var i = 0; i < length; i++) { - option = keys[i]; - if (!allowUnknown && !hasOwnProperty.call(schema, option)) { - throw Error('Unknown "' + option + '" option'); - } - value = options[option]; - if (value !== undefined$1) { - reducer = reducers[option]; - computedOptions[option] = reducer ? reducer(value, reject) : value; - } - } - return computedOptions; - } - - function constructorReducer(value, reject) { - if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { - reject('value must be a constructor'); - } - return value; - } - - function makeTypeReducer(types) { - var message= 'value must be type of ' + types.join('|'); - var len= types.length; - var firstType= types[0]; - var secondType= types[1]; - - if (len === 1) { - return function (v, reject) { - if (typeof v === firstType) { - return v; - } - reject(message); - } - } - - if (len === 2) { - return function (v, reject) { - var kind= typeof v; - if (kind === firstType || kind === secondType) { return v; } - reject(message); - } - } - - return function (v, reject) { - var kind = typeof v; - var i = len; - while (i-- > 0) { - if (kind === types[i]) { return v; } - } - reject(message); - } - } - - var functionReducer= makeTypeReducer(['function']); - - var objectFunctionReducer= makeTypeReducer(['object', 'function']); - - function makeCancelablePromise(Promise, executor, options) { - var isCancelable; - var callbacks; - var timer= 0; - var subscriptionClosed; - - var promise = new Promise(function (resolve, reject, onCancel) { - options= resolveOptions(options, { - timeout: 0, - overload: false - }, { - timeout: function(value, reject){ - value*= 1; - if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { - reject('timeout must be a positive number'); - } - return value; - } - }); - - isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; - - function cleanup() { - if (callbacks) { - callbacks = null; - } - if (timer) { - clearTimeout(timer); - timer = 0; - } - } - - var _resolve= function(value){ - cleanup(); - resolve(value); - }; - - var _reject= function(err){ - cleanup(); - reject(err); - }; - - if (isCancelable) { - executor(_resolve, _reject, onCancel); - } else { - callbacks = [function(reason){ - _reject(reason || Error('canceled')); - }]; - executor(_resolve, _reject, function (cb) { - if (subscriptionClosed) { - throw Error('Unable to subscribe on cancel event asynchronously') - } - if (typeof cb !== 'function') { - throw TypeError('onCancel callback must be a function'); - } - callbacks.push(cb); - }); - subscriptionClosed= true; - } - - if (options.timeout > 0) { - timer= setTimeout(function(){ - var reason= Error('timeout'); - reason.code = 'ETIMEDOUT'; - timer= 0; - promise.cancel(reason); - reject(reason); - }, options.timeout); - } - }); - - if (!isCancelable) { - promise.cancel = function (reason) { - if (!callbacks) { - return; - } - var length = callbacks.length; - for (var i = 1; i < length; i++) { - callbacks[i](reason); - } - // internal callback to reject the promise - callbacks[0](reason); - callbacks = null; - }; - } - - return promise; - } - - function findTargetIndex(observer) { - var observers = this._observers; - if(!observers){ - return -1; - } - var len = observers.length; - for (var i = 0; i < len; i++) { - if (observers[i]._target === observer) { return i; } - } - return -1; - } - - // Attention, function return type now is array, always ! - // It has zero elements if no any matches found and one or more - // elements (leafs) if there are matches - // - function searchListenerTree(handlers, type, tree, i, typeLength) { - if (!tree) { - return null; - } - - if (i === 0) { - var kind = typeof type; - if (kind === 'string') { - var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; - if ((n = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[l++] = type.slice(j, n); - j = n + dl; - } while ((n = type.indexOf(delimiter, j)) !== -1); - - ns[l++] = type.slice(j); - type = ns; - typeLength = l; - } else { - type = [type]; - typeLength = 1; - } - } else if (kind === 'object') { - typeLength = type.length; - } else { - type = [type]; - typeLength = 1; - } - } - - var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], - nextType = type[i + 1], branches, _listeners; - - if (i === typeLength) { - // - // If at the end of the event(s) list and the tree has listeners - // invoke those listeners. - // - - if(tree._listeners) { - if (typeof tree._listeners === 'function') { - handlers && handlers.push(tree._listeners); - listeners = [tree]; - } else { - handlers && handlers.push.apply(handlers, tree._listeners); - listeners = [tree]; - } - } - } else { - - if (currentType === '*') { - // - // If the event emitted is '*' at this part - // or there is a concrete match at this patch - // - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (currentType === '**') { - endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); - if (endReached && tree._listeners) { - // The next element has a _listeners, add it to the handlers. - listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); - } - - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - if (branch === '*' || branch === '**') { - if (tree[branch]._listeners && !endReached) { - _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } else if (branch === nextType) { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); - } else { - // No match on this one, shift into the tree but not in the type array. - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (tree[currentType]) { - listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); - } - } - - xTree = tree['*']; - if (xTree) { - // - // If the listener tree will allow any match for this part, - // then recursively explore all branches of the tree - // - searchListenerTree(handlers, type, xTree, i + 1, typeLength); - } - - xxTree = tree['**']; - if (xxTree) { - if (i < typeLength) { - if (xxTree._listeners) { - // If we have a listener on a '**', it will catch all, so add its handler. - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } - - // Build arrays of matching next branches and others. - branches= ownKeys(xxTree); - n= branches.length; - while(n-->0){ - branch= branches[n]; - if (branch !== '_listeners') { - if (branch === nextType) { - // We know the next element will match, so jump twice. - searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); - } else if (branch === currentType) { - // Current node matches, move into the tree. - searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); - } else { - isolatedBranch = {}; - isolatedBranch[branch] = xxTree[branch]; - searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); - } - } - } - } else if (xxTree._listeners) { - // We have reached the end and still on a '**' - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } else if (xxTree['*'] && xxTree['*']._listeners) { - searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); - } - } - - return listeners; - } - - function growListenerTree(type, listener, prepend) { - var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; - - if(typeof type==='string') { - if ((i = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[len++] = type.slice(j, i); - j = i + dl; - } while ((i = type.indexOf(delimiter, j)) !== -1); - - ns[len++] = type.slice(j); - }else { - ns= [type]; - len= 1; - } - }else { - ns= type; - len= type.length; - } - - // - // Looks for two consecutive '**', if so, don't add the event at all. - // - if (len > 1) { - for (i = 0; i + 1 < len; i++) { - if (ns[i] === '**' && ns[i + 1] === '**') { - return; - } - } - } - - - - var tree = this.listenerTree, name; - - for (i = 0; i < len; i++) { - name = ns[i]; - - tree = tree[name] || (tree[name] = {}); - - if (i === len - 1) { - if (!tree._listeners) { - tree._listeners = listener; - } else { - if (typeof tree._listeners === 'function') { - tree._listeners = [tree._listeners]; - } - - if (prepend) { - tree._listeners.unshift(listener); - } else { - tree._listeners.push(listener); - } - - if ( - !tree._listeners.warned && - this._maxListeners > 0 && - tree._listeners.length > this._maxListeners - ) { - tree._listeners.warned = true; - logPossibleMemoryLeak.call(this, tree._listeners.length, name); - } - } - return true; - } - } - - return true; - } - - function collectTreeEvents(tree, events, root, asArray){ - var branches= ownKeys(tree); - var i= branches.length; - var branch, branchName, path; - var hasListeners= tree['_listeners']; - var isArrayPath; - - while(i-->0){ - branchName= branches[i]; - - branch= tree[branchName]; - - if(branchName==='_listeners'){ - path= root; - }else { - path = root ? root.concat(branchName) : [branchName]; - } - - isArrayPath= asArray || typeof branchName==='symbol'; - - hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); - - if(typeof branch==='object'){ - collectTreeEvents.call(this, branch, events, path, isArrayPath); - } - } - - return events; - } - - function recursivelyGarbageCollect(root) { - var keys = ownKeys(root); - var i= keys.length; - var obj, key, flag; - while(i-->0){ - key = keys[i]; - obj = root[key]; - - if(obj){ - flag= true; - if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ - delete root[key]; - } - } - } - - return flag; - } - - function Listener(emitter, event, listener){ - this.emitter= emitter; - this.event= event; - this.listener= listener; - } - - Listener.prototype.off= function(){ - this.emitter.off(this.event, this.listener); - return this; - }; - - function setupListener(event, listener, options){ - if (options === true) { - promisify = true; - } else if (options === false) { - async = true; - } else { - if (!options || typeof options !== 'object') { - throw TypeError('options should be an object or true'); - } - var async = options.async; - var promisify = options.promisify; - var nextTick = options.nextTick; - var objectify = options.objectify; - } - - if (async || nextTick || promisify) { - var _listener = listener; - var _origin = listener._origin || listener; - - if (nextTick && !nextTickSupported) { - throw Error('process.nextTick is not supported'); - } - - if (promisify === undefined$1) { - promisify = listener.constructor.name === 'AsyncFunction'; - } - - listener = function () { - var args = arguments; - var context = this; - var event = this.event; - - return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { - _setImmediate(resolve); - }).then(function () { - context.event = event; - return _listener.apply(context, args) - })) : (nextTick ? process.nextTick : _setImmediate)(function () { - context.event = event; - _listener.apply(context, args); - }); - }; - - listener._async = true; - listener._origin = _origin; - } - - return [listener, objectify? new Listener(this, event, listener): this]; - } - - function EventEmitter(conf) { - this._events = {}; - this._newListener = false; - this._removeListener = false; - this.verboseMemoryLeak = false; - configure.call(this, conf); - } - - EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property - - EventEmitter.prototype.listenTo= function(target, events, options){ - if(typeof target!=='object'){ - throw TypeError('target musts be an object'); - } - - var emitter= this; - - options = resolveOptions(options, { - on: undefined$1, - off: undefined$1, - reducers: undefined$1 - }, { - on: functionReducer, - off: functionReducer, - reducers: objectFunctionReducer - }); - - function listen(events){ - if(typeof events!=='object'){ - throw TypeError('events must be an object'); - } - - var reducers= options.reducers; - var index= findTargetIndex.call(emitter, target); - var observer; - - if(index===-1){ - observer= new TargetObserver(emitter, target, options); - }else { - observer= emitter._observers[index]; - } - - var keys= ownKeys(events); - var len= keys.length; - var event; - var isSingleReducer= typeof reducers==='function'; - - for(var i=0; i 0) { - observer = observers[i]; - if (!target || observer._target === target) { - observer.unsubscribe(event); - matched= true; - } - } - - return matched; - }; - - // By default EventEmitters will print a warning if more than - // 10 listeners are added to it. This is a useful default which - // helps finding memory leaks. - // - // Obviously not all Emitters should be limited to 10. This function allows - // that to be increased. Set to zero for unlimited. - - EventEmitter.prototype.delimiter = '.'; - - EventEmitter.prototype.setMaxListeners = function(n) { - if (n !== undefined$1) { - this._maxListeners = n; - if (!this._conf) { this._conf = {}; } - this._conf.maxListeners = n; - } - }; - - EventEmitter.prototype.getMaxListeners = function() { - return this._maxListeners; - }; - - EventEmitter.prototype.event = ''; - - EventEmitter.prototype.once = function(event, fn, options) { - return this._once(event, fn, false, options); - }; - - EventEmitter.prototype.prependOnceListener = function(event, fn, options) { - return this._once(event, fn, true, options); - }; - - EventEmitter.prototype._once = function(event, fn, prepend, options) { - return this._many(event, 1, fn, prepend, options); - }; - - EventEmitter.prototype.many = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, false, options); - }; - - EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, true, options); - }; - - EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { - var self = this; - - if (typeof fn !== 'function') { - throw new Error('many only accepts instances of Function'); - } - - function listener() { - if (--ttl === 0) { - self.off(event, listener); - } - return fn.apply(this, arguments); - } - - listener._origin = fn; - - return this._on(event, listener, prepend, options); - }; - - EventEmitter.prototype.emit = function() { - var arguments$1 = arguments; - - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], ns, wildcard= this.wildcard; - var args,l,i,j, containsSymbol; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { - return false; - } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var al = arguments.length; - var handler; - - if (this._all && this._all.length) { - handler = this._all.slice(); - - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this, type); - break; - case 2: - handler[i].call(this, type, arguments$1[1]); - break; - case 3: - handler[i].call(this, type, arguments$1[1], arguments$1[2]); - break; - default: - handler[i].apply(this, arguments$1); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); - } else { - handler = this._events[type]; - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - handler.apply(this, args); - } - return true; - } else if (handler) { - // need to make copy of handlers because list can change in the middle - // of emit call - handler = handler.slice(); - } - } - - if (handler && handler.length) { - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this); - break; - case 2: - handler[i].call(this, arguments$1[1]); - break; - case 3: - handler[i].call(this, arguments$1[1], arguments$1[2]); - break; - default: - handler[i].apply(this, args); - } - } - return true; - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - } - - return !!this._all; - }; - - EventEmitter.prototype.emitAsync = function() { - var arguments$1 = arguments; - - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; - var args,l,i,j; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { return Promise.resolve([false]); } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var promises= []; - - var al = arguments.length; - var handler; - - if (this._all) { - for (i = 0, l = this._all.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(this._all[i].call(this, type)); - break; - case 2: - promises.push(this._all[i].call(this, type, arguments$1[1])); - break; - case 3: - promises.push(this._all[i].call(this, type, arguments$1[1], arguments$1[2])); - break; - default: - promises.push(this._all[i].apply(this, arguments$1)); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0); - } else { - handler = this._events[type]; - } - - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - promises.push(handler.call(this)); - break; - case 2: - promises.push(handler.call(this, arguments[1])); - break; - case 3: - promises.push(handler.call(this, arguments[1], arguments[2])); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - promises.push(handler.apply(this, args)); - } - } else if (handler && handler.length) { - handler = handler.slice(); - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(handler[i].call(this)); - break; - case 2: - promises.push(handler[i].call(this, arguments$1[1])); - break; - case 3: - promises.push(handler[i].call(this, arguments$1[1], arguments$1[2])); - break; - default: - promises.push(handler[i].apply(this, args)); - } - } - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - return Promise.reject(arguments[1]); // Unhandled 'error' event - } else { - return Promise.reject("Uncaught, unspecified 'error' event."); - } - } - - return Promise.all(promises); - }; - - EventEmitter.prototype.on = function(type, listener, options) { - return this._on(type, listener, false, options); - }; - - EventEmitter.prototype.prependListener = function(type, listener, options) { - return this._on(type, listener, true, options); - }; - - EventEmitter.prototype.onAny = function(fn) { - return this._onAny(fn, false); - }; - - EventEmitter.prototype.prependAny = function(fn) { - return this._onAny(fn, true); - }; - - EventEmitter.prototype.addListener = EventEmitter.prototype.on; - - EventEmitter.prototype._onAny = function(fn, prepend){ - if (typeof fn !== 'function') { - throw new Error('onAny only accepts instances of Function'); - } - - if (!this._all) { - this._all = []; - } - - // Add the function to the event listener collection. - if(prepend){ - this._all.unshift(fn); - }else { - this._all.push(fn); - } - - return this; - }; - - EventEmitter.prototype._on = function(type, listener, prepend, options) { - if (typeof type === 'function') { - this._onAny(type, listener); - return this; - } - - if (typeof listener !== 'function') { - throw new Error('on only accepts instances of Function'); - } - this._events || init.call(this); - - var returnValue= this, temp; - - if (options !== undefined$1) { - temp = setupListener.call(this, type, listener, options); - listener = temp[0]; - returnValue = temp[1]; - } - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._newListener) { - this.emit('newListener', type, listener); - } - - if (this.wildcard) { - growListenerTree.call(this, type, listener, prepend); - return returnValue; - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else { - if (typeof this._events[type] === 'function') { - // Change to array. - this._events[type] = [this._events[type]]; - } - - // If we've already got an array, just add - if(prepend){ - this._events[type].unshift(listener); - }else { - this._events[type].push(listener); - } - - // Check for listener leak - if ( - !this._events[type].warned && - this._maxListeners > 0 && - this._events[type].length > this._maxListeners - ) { - this._events[type].warned = true; - logPossibleMemoryLeak.call(this, this._events[type].length, type); - } - } - - return returnValue; - }; - - EventEmitter.prototype.off = function(type, listener) { - if (typeof listener !== 'function') { - throw new Error('removeListener only takes instances of Function'); - } - - var handlers,leafs=[]; - - if(this.wildcard) { - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); - if(!leafs) { return this; } - } else { - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events[type]) { return this; } - handlers = this._events[type]; - leafs.push({_listeners:handlers}); - } - - for (var iLeaf=0; iLeaf 0) { - fns = this._all; - for(i = 0, l = fns.length; i < l; i++) { - if(fn === fns[i]) { - fns.splice(i, 1); - if (this._removeListener) - { this.emit("removeListenerAny", fn); } - return this; - } - } - } else { - fns = this._all; - if (this._removeListener) { - for(i = 0, l = fns.length; i < l; i++) - { this.emit("removeListenerAny", fns[i]); } - } - this._all = []; - } - return this; - }; - - EventEmitter.prototype.removeListener = EventEmitter.prototype.off; - - EventEmitter.prototype.removeAllListeners = function (type) { - if (type === undefined$1) { - !this._events || init.call(this); - return this; - } - - if (this.wildcard) { - var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; - if (!leafs) { return this; } - for (i = 0; i < leafs.length; i++) { - leaf = leafs[i]; - leaf._listeners = null; - } - this.listenerTree && recursivelyGarbageCollect(this.listenerTree); - } else if (this._events) { - this._events[type] = null; - } - return this; - }; - - EventEmitter.prototype.listeners = function (type) { - var _events = this._events; - var keys, listeners, allListeners; - var i; - var listenerTree; - - if (type === undefined$1) { - if (this.wildcard) { - throw Error('event name required for wildcard emitter'); - } - - if (!_events) { - return []; - } - - keys = ownKeys(_events); - i = keys.length; - allListeners = []; - while (i-- > 0) { - listeners = _events[keys[i]]; - if (typeof listeners === 'function') { - allListeners.push(listeners); - } else { - allListeners.push.apply(allListeners, listeners); - } - } - return allListeners; - } else { - if (this.wildcard) { - listenerTree= this.listenerTree; - if(!listenerTree) { return []; } - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, listenerTree, 0); - return handlers; - } - - if (!_events) { - return []; - } - - listeners = _events[type]; - - if (!listeners) { - return []; - } - return typeof listeners === 'function' ? [listeners] : listeners; - } - }; - - EventEmitter.prototype.eventNames = function(nsAsArray){ - var _events= this._events; - return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); - }; - - EventEmitter.prototype.listenerCount = function(type) { - return this.listeners(type).length; - }; - - EventEmitter.prototype.hasListeners = function (type) { - if (this.wildcard) { - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); - return handlers.length > 0; - } - - var _events = this._events; - var _all = this._all; - - return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); - }; - - EventEmitter.prototype.listenersAny = function() { - - if(this._all) { - return this._all; - } - else { - return []; - } - - }; - - EventEmitter.prototype.waitFor = function (event, options) { - var self = this; - var type = typeof options; - if (type === 'number') { - options = {timeout: options}; - } else if (type === 'function') { - options = {filter: options}; - } - - options= resolveOptions(options, { - timeout: 0, - filter: undefined$1, - handleError: false, - Promise: Promise, - overload: false - }, { - filter: functionReducer, - Promise: constructorReducer - }); - - return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { - function listener() { - var filter= options.filter; - if (filter && !filter.apply(self, arguments)) { - return; - } - self.off(event, listener); - if (options.handleError) { - var err = arguments[0]; - err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); - } else { - resolve(toArray.apply(null, arguments)); - } - } - - onCancel(function(){ - self.off(event, listener); - }); - - self._on(event, listener, false); - }, { - timeout: options.timeout, - overload: options.overload - }) - }; - - function once(emitter, name, options) { - options= resolveOptions(options, { - Promise: Promise, - timeout: 0, - overload: false - }, { - Promise: constructorReducer - }); - - var _Promise= options.Promise; - - return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ - var handler; - if (typeof emitter.addEventListener === 'function') { - handler= function () { - resolve(toArray.apply(null, arguments)); - }; - - onCancel(function(){ - emitter.removeEventListener(name, handler); - }); - - emitter.addEventListener( - name, - handler, - {once: true} - ); - return; - } - - var eventListener = function(){ - errorListener && emitter.removeListener('error', errorListener); - resolve(toArray.apply(null, arguments)); - }; - - var errorListener; - - if (name !== 'error') { - errorListener = function (err){ - emitter.removeListener(name, eventListener); - reject(err); - }; - - emitter.once('error', errorListener); - } - - onCancel(function(){ - errorListener && emitter.removeListener('error', errorListener); - emitter.removeListener(name, eventListener); - }); - - emitter.once(name, eventListener); - }, { - timeout: options.timeout, - overload: options.overload - }); - } - - var prototype= EventEmitter.prototype; - - Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - get: function () { - return prototype._maxListeners; - }, - set: function (n) { - if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { - throw TypeError('n must be a non-negative number') - } - prototype._maxListeners = n; - }, - enumerable: true - }, - once: { - value: once, - writable: true, - configurable: true - } - }); - - Object.defineProperties(prototype, { - _maxListeners: { - value: defaultMaxListeners, - writable: true, - configurable: true - }, - _observers: {value: null, writable: true, configurable: true} - }); - - if (typeof undefined$1 === 'function' && undefined$1.amd) { - // AMD. Register as an anonymous module. - undefined$1(function() { - return EventEmitter; - }); - } else { - // CommonJS - module.exports = EventEmitter; - } - }(); -} (eventemitter2, eventemitter2.exports)); - -var eventemitter2Exports = eventemitter2.exports; -var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); - /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter2) { +var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter3) { function InteractiveMarkerHandle(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.message = options.message; this.feedbackTopic = options.feedbackTopic; @@ -54925,8 +53281,8 @@ var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter2) { this.tfUpdateBound = this.tfUpdate.bind(this); } - if ( EventEmitter2 ) InteractiveMarkerHandle.__proto__ = EventEmitter2; - InteractiveMarkerHandle.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) InteractiveMarkerHandle.__proto__ = EventEmitter3; + InteractiveMarkerHandle.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); InteractiveMarkerHandle.prototype.constructor = InteractiveMarkerHandle; /** * Subscribe to the TF associated with this interactive marker. @@ -55065,7 +53421,7 @@ var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter2) { }; return InteractiveMarkerHandle; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview @@ -55322,9 +53678,9 @@ var SceneNode = /*@__PURE__*/(function (superclass) { * @author Nils Berg - berg.nils@gmail.com */ -var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { +var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter3) { function MarkerArrayClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic; @@ -55340,8 +53696,8 @@ var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) MarkerArrayClient.__proto__ = EventEmitter2; - MarkerArrayClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) MarkerArrayClient.__proto__ = EventEmitter3; + MarkerArrayClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); MarkerArrayClient.prototype.constructor = MarkerArrayClient; MarkerArrayClient.prototype.subscribe = function subscribe (){ this.unsubscribe(); @@ -55417,16 +53773,16 @@ var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { }; return MarkerArrayClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { +var MarkerClient = /*@__PURE__*/(function (EventEmitter3) { function MarkerClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic; @@ -55444,8 +53800,8 @@ var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) MarkerClient.__proto__ = EventEmitter2; - MarkerClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) MarkerClient.__proto__ = EventEmitter3; + MarkerClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); MarkerClient.prototype.constructor = MarkerClient; MarkerClient.prototype.unsubscribe = function unsubscribe (){ if(this.rosTopic){ @@ -55517,7 +53873,7 @@ var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { }; return MarkerClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview @@ -55822,9 +54178,9 @@ var OccupancyGrid = /*@__PURE__*/(function (superclass) { * @author Russell Toris - rctoris@wpi.edu */ -var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter2) { +var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter3) { function OccupancyGridClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/map'; @@ -55845,8 +54201,8 @@ var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) OccupancyGridClient.__proto__ = EventEmitter2; - OccupancyGridClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) OccupancyGridClient.__proto__ = EventEmitter3; + OccupancyGridClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); OccupancyGridClient.prototype.constructor = OccupancyGridClient; OccupancyGridClient.prototype.unsubscribe = function unsubscribe (){ if(this.rosTopic){ @@ -55915,7 +54271,7 @@ var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter2) { }; return OccupancyGridClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview @@ -56582,9 +54938,9 @@ var ColorOcTree = /*@__PURE__*/(function (OcTree) { * @author Peter Sari - sari@photoneo.com */ -var OcTreeClient = /*@__PURE__*/(function (EventEmitter2) { +var OcTreeClient = /*@__PURE__*/(function (EventEmitter3) { function OcTreeClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/octomap'; @@ -56614,8 +54970,8 @@ var OcTreeClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) OcTreeClient.__proto__ = EventEmitter2; - OcTreeClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) OcTreeClient.__proto__ = EventEmitter3; + OcTreeClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); OcTreeClient.prototype.constructor = OcTreeClient; OcTreeClient.prototype.unsubscribe = function unsubscribe () { @@ -56725,7 +55081,7 @@ var OcTreeClient = /*@__PURE__*/(function (EventEmitter2) { }; return OcTreeClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview diff --git a/build/ros3d.esm.js b/build/ros3d.esm.js index 23e4c21c..def9f892 100644 --- a/build/ros3d.esm.js +++ b/build/ros3d.esm.js @@ -53224,1658 +53224,14 @@ var InteractiveMarker = /*@__PURE__*/(function (superclass) { return InteractiveMarker; }(THREE.Object3D)); -function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; -} - -var eventemitter2 = {exports: {}}; - -/*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */ -eventemitter2.exports; - -(function (module, exports) { -!function(undefined$1) { - var hasOwnProperty= Object.hasOwnProperty; - var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - var defaultMaxListeners = 10; - var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; - var symbolsSupported= typeof Symbol==='function'; - var reflectSupported= typeof Reflect === 'object'; - var setImmediateSupported= typeof setImmediate === 'function'; - var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; - var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ - var arr= Object.getOwnPropertyNames(obj); - arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); - return arr; - }) : Object.keys; - - function init() { - this._events = {}; - if (this._conf) { - configure.call(this, this._conf); - } - } - - function configure(conf) { - if (conf) { - this._conf = conf; - - conf.delimiter && (this.delimiter = conf.delimiter); - - if(conf.maxListeners!==undefined$1){ - this._maxListeners= conf.maxListeners; - } - - conf.wildcard && (this.wildcard = conf.wildcard); - conf.newListener && (this._newListener = conf.newListener); - conf.removeListener && (this._removeListener = conf.removeListener); - conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); - conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); - - if (this.wildcard) { - this.listenerTree = {}; - } - } - } - - function logPossibleMemoryLeak(count, eventName) { - var errorMsg = '(node) warning: possible EventEmitter memory ' + - 'leak detected. ' + count + ' listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.'; - - if(this.verboseMemoryLeak){ - errorMsg += ' Event name: ' + eventName + '.'; - } - - if(typeof process !== 'undefined' && process.emitWarning){ - var e = new Error(errorMsg); - e.name = 'MaxListenersExceededWarning'; - e.emitter = this; - e.count = count; - process.emitWarning(e); - } else { - console.error(errorMsg); - - if (console.trace){ - console.trace(); - } - } - } - - var toArray = function (a, b, c) { - var arguments$1 = arguments; - - var n = arguments.length; - switch (n) { - case 0: - return []; - case 1: - return [a]; - case 2: - return [a, b]; - case 3: - return [a, b, c]; - default: - var arr = new Array(n); - while (n--) { - arr[n] = arguments$1[n]; - } - return arr; - } - }; - - function toObject(keys, values) { - var obj = {}; - var key; - var len = keys.length; - var valuesCount = values ? value.length : 0; - for (var i = 0; i < len; i++) { - key = keys[i]; - obj[key] = i < valuesCount ? values[i] : undefined$1; - } - return obj; - } - - function TargetObserver(emitter, target, options) { - this._emitter = emitter; - this._target = target; - this._listeners = {}; - this._listenersCount = 0; - - var on, off; - - if (options.on || options.off) { - on = options.on; - off = options.off; - } - - if (target.addEventListener) { - on = target.addEventListener; - off = target.removeEventListener; - } else if (target.addListener) { - on = target.addListener; - off = target.removeListener; - } else if (target.on) { - on = target.on; - off = target.off; - } - - if (!on && !off) { - throw Error('target does not implement any known event API'); - } - - if (typeof on !== 'function') { - throw TypeError('on method must be a function'); - } - - if (typeof off !== 'function') { - throw TypeError('off method must be a function'); - } - - this._on = on; - this._off = off; - - var _observers= emitter._observers; - if(_observers){ - _observers.push(this); - }else { - emitter._observers= [this]; - } - } - - Object.assign(TargetObserver.prototype, { - subscribe: function(event, localEvent, reducer){ - var observer= this; - var target= this._target; - var emitter= this._emitter; - var listeners= this._listeners; - var handler= function(){ - var args= toArray.apply(null, arguments); - var eventObj= { - data: args, - name: localEvent, - original: event - }; - if(reducer){ - var result= reducer.call(target, eventObj); - if(result!==false){ - emitter.emit.apply(emitter, [eventObj.name].concat(args)); - } - return; - } - emitter.emit.apply(emitter, [localEvent].concat(args)); - }; - - - if(listeners[event]){ - throw Error('Event \'' + event + '\' is already listening'); - } - - this._listenersCount++; - - if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ - - this._onNewListener = function (_event) { - if (_event === localEvent && listeners[event] === null) { - listeners[event] = handler; - observer._on.call(target, event, handler); - } - }; - - emitter.on('newListener', this._onNewListener); - - this._onRemoveListener= function(_event){ - if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ - listeners[event]= null; - observer._off.call(target, event, handler); - } - }; - - listeners[event]= null; - - emitter.on('removeListener', this._onRemoveListener); - }else { - listeners[event]= handler; - observer._on.call(target, event, handler); - } - }, - - unsubscribe: function(event){ - var observer= this; - var listeners= this._listeners; - var emitter= this._emitter; - var handler; - var events; - var off= this._off; - var target= this._target; - var i; - - if(event && typeof event!=='string'){ - throw TypeError('event must be a string'); - } - - function clearRefs(){ - if(observer._onNewListener){ - emitter.off('newListener', observer._onNewListener); - emitter.off('removeListener', observer._onRemoveListener); - observer._onNewListener= null; - observer._onRemoveListener= null; - } - var index= findTargetIndex.call(emitter, observer); - emitter._observers.splice(index, 1); - } - - if(event){ - handler= listeners[event]; - if(!handler) { return; } - off.call(target, event, handler); - delete listeners[event]; - if(!--this._listenersCount){ - clearRefs(); - } - }else { - events= ownKeys(listeners); - i= events.length; - while(i-->0){ - event= events[i]; - off.call(target, event, listeners[event]); - } - this._listeners= {}; - this._listenersCount= 0; - clearRefs(); - } - } - }); - - function resolveOptions(options, schema, reducers, allowUnknown) { - var computedOptions = Object.assign({}, schema); - - if (!options) { return computedOptions; } - - if (typeof options !== 'object') { - throw TypeError('options must be an object') - } - - var keys = Object.keys(options); - var length = keys.length; - var option, value; - var reducer; - - function reject(reason) { - throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) - } - - for (var i = 0; i < length; i++) { - option = keys[i]; - if (!allowUnknown && !hasOwnProperty.call(schema, option)) { - throw Error('Unknown "' + option + '" option'); - } - value = options[option]; - if (value !== undefined$1) { - reducer = reducers[option]; - computedOptions[option] = reducer ? reducer(value, reject) : value; - } - } - return computedOptions; - } - - function constructorReducer(value, reject) { - if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { - reject('value must be a constructor'); - } - return value; - } - - function makeTypeReducer(types) { - var message= 'value must be type of ' + types.join('|'); - var len= types.length; - var firstType= types[0]; - var secondType= types[1]; - - if (len === 1) { - return function (v, reject) { - if (typeof v === firstType) { - return v; - } - reject(message); - } - } - - if (len === 2) { - return function (v, reject) { - var kind= typeof v; - if (kind === firstType || kind === secondType) { return v; } - reject(message); - } - } - - return function (v, reject) { - var kind = typeof v; - var i = len; - while (i-- > 0) { - if (kind === types[i]) { return v; } - } - reject(message); - } - } - - var functionReducer= makeTypeReducer(['function']); - - var objectFunctionReducer= makeTypeReducer(['object', 'function']); - - function makeCancelablePromise(Promise, executor, options) { - var isCancelable; - var callbacks; - var timer= 0; - var subscriptionClosed; - - var promise = new Promise(function (resolve, reject, onCancel) { - options= resolveOptions(options, { - timeout: 0, - overload: false - }, { - timeout: function(value, reject){ - value*= 1; - if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { - reject('timeout must be a positive number'); - } - return value; - } - }); - - isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; - - function cleanup() { - if (callbacks) { - callbacks = null; - } - if (timer) { - clearTimeout(timer); - timer = 0; - } - } - - var _resolve= function(value){ - cleanup(); - resolve(value); - }; - - var _reject= function(err){ - cleanup(); - reject(err); - }; - - if (isCancelable) { - executor(_resolve, _reject, onCancel); - } else { - callbacks = [function(reason){ - _reject(reason || Error('canceled')); - }]; - executor(_resolve, _reject, function (cb) { - if (subscriptionClosed) { - throw Error('Unable to subscribe on cancel event asynchronously') - } - if (typeof cb !== 'function') { - throw TypeError('onCancel callback must be a function'); - } - callbacks.push(cb); - }); - subscriptionClosed= true; - } - - if (options.timeout > 0) { - timer= setTimeout(function(){ - var reason= Error('timeout'); - reason.code = 'ETIMEDOUT'; - timer= 0; - promise.cancel(reason); - reject(reason); - }, options.timeout); - } - }); - - if (!isCancelable) { - promise.cancel = function (reason) { - if (!callbacks) { - return; - } - var length = callbacks.length; - for (var i = 1; i < length; i++) { - callbacks[i](reason); - } - // internal callback to reject the promise - callbacks[0](reason); - callbacks = null; - }; - } - - return promise; - } - - function findTargetIndex(observer) { - var observers = this._observers; - if(!observers){ - return -1; - } - var len = observers.length; - for (var i = 0; i < len; i++) { - if (observers[i]._target === observer) { return i; } - } - return -1; - } - - // Attention, function return type now is array, always ! - // It has zero elements if no any matches found and one or more - // elements (leafs) if there are matches - // - function searchListenerTree(handlers, type, tree, i, typeLength) { - if (!tree) { - return null; - } - - if (i === 0) { - var kind = typeof type; - if (kind === 'string') { - var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; - if ((n = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[l++] = type.slice(j, n); - j = n + dl; - } while ((n = type.indexOf(delimiter, j)) !== -1); - - ns[l++] = type.slice(j); - type = ns; - typeLength = l; - } else { - type = [type]; - typeLength = 1; - } - } else if (kind === 'object') { - typeLength = type.length; - } else { - type = [type]; - typeLength = 1; - } - } - - var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], - nextType = type[i + 1], branches, _listeners; - - if (i === typeLength) { - // - // If at the end of the event(s) list and the tree has listeners - // invoke those listeners. - // - - if(tree._listeners) { - if (typeof tree._listeners === 'function') { - handlers && handlers.push(tree._listeners); - listeners = [tree]; - } else { - handlers && handlers.push.apply(handlers, tree._listeners); - listeners = [tree]; - } - } - } else { - - if (currentType === '*') { - // - // If the event emitted is '*' at this part - // or there is a concrete match at this patch - // - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (currentType === '**') { - endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); - if (endReached && tree._listeners) { - // The next element has a _listeners, add it to the handlers. - listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); - } - - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - if (branch === '*' || branch === '**') { - if (tree[branch]._listeners && !endReached) { - _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } else if (branch === nextType) { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); - } else { - // No match on this one, shift into the tree but not in the type array. - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (tree[currentType]) { - listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); - } - } - - xTree = tree['*']; - if (xTree) { - // - // If the listener tree will allow any match for this part, - // then recursively explore all branches of the tree - // - searchListenerTree(handlers, type, xTree, i + 1, typeLength); - } - - xxTree = tree['**']; - if (xxTree) { - if (i < typeLength) { - if (xxTree._listeners) { - // If we have a listener on a '**', it will catch all, so add its handler. - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } - - // Build arrays of matching next branches and others. - branches= ownKeys(xxTree); - n= branches.length; - while(n-->0){ - branch= branches[n]; - if (branch !== '_listeners') { - if (branch === nextType) { - // We know the next element will match, so jump twice. - searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); - } else if (branch === currentType) { - // Current node matches, move into the tree. - searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); - } else { - isolatedBranch = {}; - isolatedBranch[branch] = xxTree[branch]; - searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); - } - } - } - } else if (xxTree._listeners) { - // We have reached the end and still on a '**' - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } else if (xxTree['*'] && xxTree['*']._listeners) { - searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); - } - } - - return listeners; - } - - function growListenerTree(type, listener, prepend) { - var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; - - if(typeof type==='string') { - if ((i = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[len++] = type.slice(j, i); - j = i + dl; - } while ((i = type.indexOf(delimiter, j)) !== -1); - - ns[len++] = type.slice(j); - }else { - ns= [type]; - len= 1; - } - }else { - ns= type; - len= type.length; - } - - // - // Looks for two consecutive '**', if so, don't add the event at all. - // - if (len > 1) { - for (i = 0; i + 1 < len; i++) { - if (ns[i] === '**' && ns[i + 1] === '**') { - return; - } - } - } - - - - var tree = this.listenerTree, name; - - for (i = 0; i < len; i++) { - name = ns[i]; - - tree = tree[name] || (tree[name] = {}); - - if (i === len - 1) { - if (!tree._listeners) { - tree._listeners = listener; - } else { - if (typeof tree._listeners === 'function') { - tree._listeners = [tree._listeners]; - } - - if (prepend) { - tree._listeners.unshift(listener); - } else { - tree._listeners.push(listener); - } - - if ( - !tree._listeners.warned && - this._maxListeners > 0 && - tree._listeners.length > this._maxListeners - ) { - tree._listeners.warned = true; - logPossibleMemoryLeak.call(this, tree._listeners.length, name); - } - } - return true; - } - } - - return true; - } - - function collectTreeEvents(tree, events, root, asArray){ - var branches= ownKeys(tree); - var i= branches.length; - var branch, branchName, path; - var hasListeners= tree['_listeners']; - var isArrayPath; - - while(i-->0){ - branchName= branches[i]; - - branch= tree[branchName]; - - if(branchName==='_listeners'){ - path= root; - }else { - path = root ? root.concat(branchName) : [branchName]; - } - - isArrayPath= asArray || typeof branchName==='symbol'; - - hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); - - if(typeof branch==='object'){ - collectTreeEvents.call(this, branch, events, path, isArrayPath); - } - } - - return events; - } - - function recursivelyGarbageCollect(root) { - var keys = ownKeys(root); - var i= keys.length; - var obj, key, flag; - while(i-->0){ - key = keys[i]; - obj = root[key]; - - if(obj){ - flag= true; - if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ - delete root[key]; - } - } - } - - return flag; - } - - function Listener(emitter, event, listener){ - this.emitter= emitter; - this.event= event; - this.listener= listener; - } - - Listener.prototype.off= function(){ - this.emitter.off(this.event, this.listener); - return this; - }; - - function setupListener(event, listener, options){ - if (options === true) { - promisify = true; - } else if (options === false) { - async = true; - } else { - if (!options || typeof options !== 'object') { - throw TypeError('options should be an object or true'); - } - var async = options.async; - var promisify = options.promisify; - var nextTick = options.nextTick; - var objectify = options.objectify; - } - - if (async || nextTick || promisify) { - var _listener = listener; - var _origin = listener._origin || listener; - - if (nextTick && !nextTickSupported) { - throw Error('process.nextTick is not supported'); - } - - if (promisify === undefined$1) { - promisify = listener.constructor.name === 'AsyncFunction'; - } - - listener = function () { - var args = arguments; - var context = this; - var event = this.event; - - return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { - _setImmediate(resolve); - }).then(function () { - context.event = event; - return _listener.apply(context, args) - })) : (nextTick ? process.nextTick : _setImmediate)(function () { - context.event = event; - _listener.apply(context, args); - }); - }; - - listener._async = true; - listener._origin = _origin; - } - - return [listener, objectify? new Listener(this, event, listener): this]; - } - - function EventEmitter(conf) { - this._events = {}; - this._newListener = false; - this._removeListener = false; - this.verboseMemoryLeak = false; - configure.call(this, conf); - } - - EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property - - EventEmitter.prototype.listenTo= function(target, events, options){ - if(typeof target!=='object'){ - throw TypeError('target musts be an object'); - } - - var emitter= this; - - options = resolveOptions(options, { - on: undefined$1, - off: undefined$1, - reducers: undefined$1 - }, { - on: functionReducer, - off: functionReducer, - reducers: objectFunctionReducer - }); - - function listen(events){ - if(typeof events!=='object'){ - throw TypeError('events must be an object'); - } - - var reducers= options.reducers; - var index= findTargetIndex.call(emitter, target); - var observer; - - if(index===-1){ - observer= new TargetObserver(emitter, target, options); - }else { - observer= emitter._observers[index]; - } - - var keys= ownKeys(events); - var len= keys.length; - var event; - var isSingleReducer= typeof reducers==='function'; - - for(var i=0; i 0) { - observer = observers[i]; - if (!target || observer._target === target) { - observer.unsubscribe(event); - matched= true; - } - } - - return matched; - }; - - // By default EventEmitters will print a warning if more than - // 10 listeners are added to it. This is a useful default which - // helps finding memory leaks. - // - // Obviously not all Emitters should be limited to 10. This function allows - // that to be increased. Set to zero for unlimited. - - EventEmitter.prototype.delimiter = '.'; - - EventEmitter.prototype.setMaxListeners = function(n) { - if (n !== undefined$1) { - this._maxListeners = n; - if (!this._conf) { this._conf = {}; } - this._conf.maxListeners = n; - } - }; - - EventEmitter.prototype.getMaxListeners = function() { - return this._maxListeners; - }; - - EventEmitter.prototype.event = ''; - - EventEmitter.prototype.once = function(event, fn, options) { - return this._once(event, fn, false, options); - }; - - EventEmitter.prototype.prependOnceListener = function(event, fn, options) { - return this._once(event, fn, true, options); - }; - - EventEmitter.prototype._once = function(event, fn, prepend, options) { - return this._many(event, 1, fn, prepend, options); - }; - - EventEmitter.prototype.many = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, false, options); - }; - - EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, true, options); - }; - - EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { - var self = this; - - if (typeof fn !== 'function') { - throw new Error('many only accepts instances of Function'); - } - - function listener() { - if (--ttl === 0) { - self.off(event, listener); - } - return fn.apply(this, arguments); - } - - listener._origin = fn; - - return this._on(event, listener, prepend, options); - }; - - EventEmitter.prototype.emit = function() { - var arguments$1 = arguments; - - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], ns, wildcard= this.wildcard; - var args,l,i,j, containsSymbol; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { - return false; - } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var al = arguments.length; - var handler; - - if (this._all && this._all.length) { - handler = this._all.slice(); - - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this, type); - break; - case 2: - handler[i].call(this, type, arguments$1[1]); - break; - case 3: - handler[i].call(this, type, arguments$1[1], arguments$1[2]); - break; - default: - handler[i].apply(this, arguments$1); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); - } else { - handler = this._events[type]; - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - handler.apply(this, args); - } - return true; - } else if (handler) { - // need to make copy of handlers because list can change in the middle - // of emit call - handler = handler.slice(); - } - } - - if (handler && handler.length) { - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this); - break; - case 2: - handler[i].call(this, arguments$1[1]); - break; - case 3: - handler[i].call(this, arguments$1[1], arguments$1[2]); - break; - default: - handler[i].apply(this, args); - } - } - return true; - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - } - - return !!this._all; - }; - - EventEmitter.prototype.emitAsync = function() { - var arguments$1 = arguments; - - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; - var args,l,i,j; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { return Promise.resolve([false]); } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var promises= []; - - var al = arguments.length; - var handler; - - if (this._all) { - for (i = 0, l = this._all.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(this._all[i].call(this, type)); - break; - case 2: - promises.push(this._all[i].call(this, type, arguments$1[1])); - break; - case 3: - promises.push(this._all[i].call(this, type, arguments$1[1], arguments$1[2])); - break; - default: - promises.push(this._all[i].apply(this, arguments$1)); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0); - } else { - handler = this._events[type]; - } - - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - promises.push(handler.call(this)); - break; - case 2: - promises.push(handler.call(this, arguments[1])); - break; - case 3: - promises.push(handler.call(this, arguments[1], arguments[2])); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - promises.push(handler.apply(this, args)); - } - } else if (handler && handler.length) { - handler = handler.slice(); - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) { args[j - 1] = arguments$1[j]; } - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(handler[i].call(this)); - break; - case 2: - promises.push(handler[i].call(this, arguments$1[1])); - break; - case 3: - promises.push(handler[i].call(this, arguments$1[1], arguments$1[2])); - break; - default: - promises.push(handler[i].apply(this, args)); - } - } - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - return Promise.reject(arguments[1]); // Unhandled 'error' event - } else { - return Promise.reject("Uncaught, unspecified 'error' event."); - } - } - - return Promise.all(promises); - }; - - EventEmitter.prototype.on = function(type, listener, options) { - return this._on(type, listener, false, options); - }; - - EventEmitter.prototype.prependListener = function(type, listener, options) { - return this._on(type, listener, true, options); - }; - - EventEmitter.prototype.onAny = function(fn) { - return this._onAny(fn, false); - }; - - EventEmitter.prototype.prependAny = function(fn) { - return this._onAny(fn, true); - }; - - EventEmitter.prototype.addListener = EventEmitter.prototype.on; - - EventEmitter.prototype._onAny = function(fn, prepend){ - if (typeof fn !== 'function') { - throw new Error('onAny only accepts instances of Function'); - } - - if (!this._all) { - this._all = []; - } - - // Add the function to the event listener collection. - if(prepend){ - this._all.unshift(fn); - }else { - this._all.push(fn); - } - - return this; - }; - - EventEmitter.prototype._on = function(type, listener, prepend, options) { - if (typeof type === 'function') { - this._onAny(type, listener); - return this; - } - - if (typeof listener !== 'function') { - throw new Error('on only accepts instances of Function'); - } - this._events || init.call(this); - - var returnValue= this, temp; - - if (options !== undefined$1) { - temp = setupListener.call(this, type, listener, options); - listener = temp[0]; - returnValue = temp[1]; - } - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._newListener) { - this.emit('newListener', type, listener); - } - - if (this.wildcard) { - growListenerTree.call(this, type, listener, prepend); - return returnValue; - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else { - if (typeof this._events[type] === 'function') { - // Change to array. - this._events[type] = [this._events[type]]; - } - - // If we've already got an array, just add - if(prepend){ - this._events[type].unshift(listener); - }else { - this._events[type].push(listener); - } - - // Check for listener leak - if ( - !this._events[type].warned && - this._maxListeners > 0 && - this._events[type].length > this._maxListeners - ) { - this._events[type].warned = true; - logPossibleMemoryLeak.call(this, this._events[type].length, type); - } - } - - return returnValue; - }; - - EventEmitter.prototype.off = function(type, listener) { - if (typeof listener !== 'function') { - throw new Error('removeListener only takes instances of Function'); - } - - var handlers,leafs=[]; - - if(this.wildcard) { - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); - if(!leafs) { return this; } - } else { - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events[type]) { return this; } - handlers = this._events[type]; - leafs.push({_listeners:handlers}); - } - - for (var iLeaf=0; iLeaf 0) { - fns = this._all; - for(i = 0, l = fns.length; i < l; i++) { - if(fn === fns[i]) { - fns.splice(i, 1); - if (this._removeListener) - { this.emit("removeListenerAny", fn); } - return this; - } - } - } else { - fns = this._all; - if (this._removeListener) { - for(i = 0, l = fns.length; i < l; i++) - { this.emit("removeListenerAny", fns[i]); } - } - this._all = []; - } - return this; - }; - - EventEmitter.prototype.removeListener = EventEmitter.prototype.off; - - EventEmitter.prototype.removeAllListeners = function (type) { - if (type === undefined$1) { - !this._events || init.call(this); - return this; - } - - if (this.wildcard) { - var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; - if (!leafs) { return this; } - for (i = 0; i < leafs.length; i++) { - leaf = leafs[i]; - leaf._listeners = null; - } - this.listenerTree && recursivelyGarbageCollect(this.listenerTree); - } else if (this._events) { - this._events[type] = null; - } - return this; - }; - - EventEmitter.prototype.listeners = function (type) { - var _events = this._events; - var keys, listeners, allListeners; - var i; - var listenerTree; - - if (type === undefined$1) { - if (this.wildcard) { - throw Error('event name required for wildcard emitter'); - } - - if (!_events) { - return []; - } - - keys = ownKeys(_events); - i = keys.length; - allListeners = []; - while (i-- > 0) { - listeners = _events[keys[i]]; - if (typeof listeners === 'function') { - allListeners.push(listeners); - } else { - allListeners.push.apply(allListeners, listeners); - } - } - return allListeners; - } else { - if (this.wildcard) { - listenerTree= this.listenerTree; - if(!listenerTree) { return []; } - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, listenerTree, 0); - return handlers; - } - - if (!_events) { - return []; - } - - listeners = _events[type]; - - if (!listeners) { - return []; - } - return typeof listeners === 'function' ? [listeners] : listeners; - } - }; - - EventEmitter.prototype.eventNames = function(nsAsArray){ - var _events= this._events; - return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); - }; - - EventEmitter.prototype.listenerCount = function(type) { - return this.listeners(type).length; - }; - - EventEmitter.prototype.hasListeners = function (type) { - if (this.wildcard) { - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); - return handlers.length > 0; - } - - var _events = this._events; - var _all = this._all; - - return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); - }; - - EventEmitter.prototype.listenersAny = function() { - - if(this._all) { - return this._all; - } - else { - return []; - } - - }; - - EventEmitter.prototype.waitFor = function (event, options) { - var self = this; - var type = typeof options; - if (type === 'number') { - options = {timeout: options}; - } else if (type === 'function') { - options = {filter: options}; - } - - options= resolveOptions(options, { - timeout: 0, - filter: undefined$1, - handleError: false, - Promise: Promise, - overload: false - }, { - filter: functionReducer, - Promise: constructorReducer - }); - - return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { - function listener() { - var filter= options.filter; - if (filter && !filter.apply(self, arguments)) { - return; - } - self.off(event, listener); - if (options.handleError) { - var err = arguments[0]; - err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); - } else { - resolve(toArray.apply(null, arguments)); - } - } - - onCancel(function(){ - self.off(event, listener); - }); - - self._on(event, listener, false); - }, { - timeout: options.timeout, - overload: options.overload - }) - }; - - function once(emitter, name, options) { - options= resolveOptions(options, { - Promise: Promise, - timeout: 0, - overload: false - }, { - Promise: constructorReducer - }); - - var _Promise= options.Promise; - - return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ - var handler; - if (typeof emitter.addEventListener === 'function') { - handler= function () { - resolve(toArray.apply(null, arguments)); - }; - - onCancel(function(){ - emitter.removeEventListener(name, handler); - }); - - emitter.addEventListener( - name, - handler, - {once: true} - ); - return; - } - - var eventListener = function(){ - errorListener && emitter.removeListener('error', errorListener); - resolve(toArray.apply(null, arguments)); - }; - - var errorListener; - - if (name !== 'error') { - errorListener = function (err){ - emitter.removeListener(name, eventListener); - reject(err); - }; - - emitter.once('error', errorListener); - } - - onCancel(function(){ - errorListener && emitter.removeListener('error', errorListener); - emitter.removeListener(name, eventListener); - }); - - emitter.once(name, eventListener); - }, { - timeout: options.timeout, - overload: options.overload - }); - } - - var prototype= EventEmitter.prototype; - - Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - get: function () { - return prototype._maxListeners; - }, - set: function (n) { - if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { - throw TypeError('n must be a non-negative number') - } - prototype._maxListeners = n; - }, - enumerable: true - }, - once: { - value: once, - writable: true, - configurable: true - } - }); - - Object.defineProperties(prototype, { - _maxListeners: { - value: defaultMaxListeners, - writable: true, - configurable: true - }, - _observers: {value: null, writable: true, configurable: true} - }); - - if (typeof undefined$1 === 'function' && undefined$1.amd) { - // AMD. Register as an anonymous module. - undefined$1(function() { - return EventEmitter; - }); - } else { - // CommonJS - module.exports = EventEmitter; - } - }(); -} (eventemitter2, eventemitter2.exports)); - -var eventemitter2Exports = eventemitter2.exports; -var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); - /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter2) { +var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter3) { function InteractiveMarkerHandle(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.message = options.message; this.feedbackTopic = options.feedbackTopic; @@ -54901,8 +53257,8 @@ var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter2) { this.tfUpdateBound = this.tfUpdate.bind(this); } - if ( EventEmitter2 ) InteractiveMarkerHandle.__proto__ = EventEmitter2; - InteractiveMarkerHandle.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) InteractiveMarkerHandle.__proto__ = EventEmitter3; + InteractiveMarkerHandle.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); InteractiveMarkerHandle.prototype.constructor = InteractiveMarkerHandle; /** * Subscribe to the TF associated with this interactive marker. @@ -55041,7 +53397,7 @@ var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter2) { }; return InteractiveMarkerHandle; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview @@ -55298,9 +53654,9 @@ var SceneNode = /*@__PURE__*/(function (superclass) { * @author Nils Berg - berg.nils@gmail.com */ -var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { +var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter3) { function MarkerArrayClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic; @@ -55316,8 +53672,8 @@ var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) MarkerArrayClient.__proto__ = EventEmitter2; - MarkerArrayClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) MarkerArrayClient.__proto__ = EventEmitter3; + MarkerArrayClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); MarkerArrayClient.prototype.constructor = MarkerArrayClient; MarkerArrayClient.prototype.subscribe = function subscribe (){ this.unsubscribe(); @@ -55393,16 +53749,16 @@ var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { }; return MarkerArrayClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { +var MarkerClient = /*@__PURE__*/(function (EventEmitter3) { function MarkerClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic; @@ -55420,8 +53776,8 @@ var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) MarkerClient.__proto__ = EventEmitter2; - MarkerClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) MarkerClient.__proto__ = EventEmitter3; + MarkerClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); MarkerClient.prototype.constructor = MarkerClient; MarkerClient.prototype.unsubscribe = function unsubscribe (){ if(this.rosTopic){ @@ -55493,7 +53849,7 @@ var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { }; return MarkerClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview @@ -55798,9 +54154,9 @@ var OccupancyGrid = /*@__PURE__*/(function (superclass) { * @author Russell Toris - rctoris@wpi.edu */ -var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter2) { +var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter3) { function OccupancyGridClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/map'; @@ -55821,8 +54177,8 @@ var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) OccupancyGridClient.__proto__ = EventEmitter2; - OccupancyGridClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) OccupancyGridClient.__proto__ = EventEmitter3; + OccupancyGridClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); OccupancyGridClient.prototype.constructor = OccupancyGridClient; OccupancyGridClient.prototype.unsubscribe = function unsubscribe (){ if(this.rosTopic){ @@ -55891,7 +54247,7 @@ var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter2) { }; return OccupancyGridClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview @@ -56558,9 +54914,9 @@ var ColorOcTree = /*@__PURE__*/(function (OcTree) { * @author Peter Sari - sari@photoneo.com */ -var OcTreeClient = /*@__PURE__*/(function (EventEmitter2) { +var OcTreeClient = /*@__PURE__*/(function (EventEmitter3) { function OcTreeClient(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/octomap'; @@ -56590,8 +54946,8 @@ var OcTreeClient = /*@__PURE__*/(function (EventEmitter2) { this.subscribe(); } - if ( EventEmitter2 ) OcTreeClient.__proto__ = EventEmitter2; - OcTreeClient.prototype = Object.create( EventEmitter2 && EventEmitter2.prototype ); + if ( EventEmitter3 ) OcTreeClient.__proto__ = EventEmitter3; + OcTreeClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); OcTreeClient.prototype.constructor = OcTreeClient; OcTreeClient.prototype.unsubscribe = function unsubscribe () { @@ -56701,7 +55057,7 @@ var OcTreeClient = /*@__PURE__*/(function (EventEmitter2) { }; return OcTreeClient; -}(EventEmitter2)); +}(EventEmitter3)); /** * @fileOverview diff --git a/build/ros3d.js b/build/ros3d.js index 33229259..5f80b819 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -53314,1650 +53314,12 @@ var ROS3D = (function (exports, ROSLIB) { }; } - function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; - } - - var eventemitter2 = {exports: {}}; - - /*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */ - eventemitter2.exports; - - (function (module, exports) { - !function(undefined$1) { - var hasOwnProperty= Object.hasOwnProperty; - var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - var defaultMaxListeners = 10; - var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; - var symbolsSupported= typeof Symbol==='function'; - var reflectSupported= typeof Reflect === 'object'; - var setImmediateSupported= typeof setImmediate === 'function'; - var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; - var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ - var arr= Object.getOwnPropertyNames(obj); - arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); - return arr; - }) : Object.keys; - - function init() { - this._events = {}; - if (this._conf) { - configure.call(this, this._conf); - } - } - - function configure(conf) { - if (conf) { - this._conf = conf; - - conf.delimiter && (this.delimiter = conf.delimiter); - - if(conf.maxListeners!==undefined$1){ - this._maxListeners= conf.maxListeners; - } - - conf.wildcard && (this.wildcard = conf.wildcard); - conf.newListener && (this._newListener = conf.newListener); - conf.removeListener && (this._removeListener = conf.removeListener); - conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); - conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); - - if (this.wildcard) { - this.listenerTree = {}; - } - } - } - - function logPossibleMemoryLeak(count, eventName) { - var errorMsg = '(node) warning: possible EventEmitter memory ' + - 'leak detected. ' + count + ' listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.'; - - if(this.verboseMemoryLeak){ - errorMsg += ' Event name: ' + eventName + '.'; - } - - if(typeof process !== 'undefined' && process.emitWarning){ - var e = new Error(errorMsg); - e.name = 'MaxListenersExceededWarning'; - e.emitter = this; - e.count = count; - process.emitWarning(e); - } else { - console.error(errorMsg); - - if (console.trace){ - console.trace(); - } - } - } - - var toArray = function (a, b, c) { - var n = arguments.length; - switch (n) { - case 0: - return []; - case 1: - return [a]; - case 2: - return [a, b]; - case 3: - return [a, b, c]; - default: - var arr = new Array(n); - while (n--) { - arr[n] = arguments[n]; - } - return arr; - } - }; - - function toObject(keys, values) { - var obj = {}; - var key; - var len = keys.length; - var valuesCount = values ? value.length : 0; - for (var i = 0; i < len; i++) { - key = keys[i]; - obj[key] = i < valuesCount ? values[i] : undefined$1; - } - return obj; - } - - function TargetObserver(emitter, target, options) { - this._emitter = emitter; - this._target = target; - this._listeners = {}; - this._listenersCount = 0; - - var on, off; - - if (options.on || options.off) { - on = options.on; - off = options.off; - } - - if (target.addEventListener) { - on = target.addEventListener; - off = target.removeEventListener; - } else if (target.addListener) { - on = target.addListener; - off = target.removeListener; - } else if (target.on) { - on = target.on; - off = target.off; - } - - if (!on && !off) { - throw Error('target does not implement any known event API'); - } - - if (typeof on !== 'function') { - throw TypeError('on method must be a function'); - } - - if (typeof off !== 'function') { - throw TypeError('off method must be a function'); - } - - this._on = on; - this._off = off; - - var _observers= emitter._observers; - if(_observers){ - _observers.push(this); - }else { - emitter._observers= [this]; - } - } - - Object.assign(TargetObserver.prototype, { - subscribe: function(event, localEvent, reducer){ - var observer= this; - var target= this._target; - var emitter= this._emitter; - var listeners= this._listeners; - var handler= function(){ - var args= toArray.apply(null, arguments); - var eventObj= { - data: args, - name: localEvent, - original: event - }; - if(reducer){ - var result= reducer.call(target, eventObj); - if(result!==false){ - emitter.emit.apply(emitter, [eventObj.name].concat(args)); - } - return; - } - emitter.emit.apply(emitter, [localEvent].concat(args)); - }; - - - if(listeners[event]){ - throw Error('Event \'' + event + '\' is already listening'); - } - - this._listenersCount++; - - if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ - - this._onNewListener = function (_event) { - if (_event === localEvent && listeners[event] === null) { - listeners[event] = handler; - observer._on.call(target, event, handler); - } - }; - - emitter.on('newListener', this._onNewListener); - - this._onRemoveListener= function(_event){ - if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ - listeners[event]= null; - observer._off.call(target, event, handler); - } - }; - - listeners[event]= null; - - emitter.on('removeListener', this._onRemoveListener); - }else { - listeners[event]= handler; - observer._on.call(target, event, handler); - } - }, - - unsubscribe: function(event){ - var observer= this; - var listeners= this._listeners; - var emitter= this._emitter; - var handler; - var events; - var off= this._off; - var target= this._target; - var i; - - if(event && typeof event!=='string'){ - throw TypeError('event must be a string'); - } - - function clearRefs(){ - if(observer._onNewListener){ - emitter.off('newListener', observer._onNewListener); - emitter.off('removeListener', observer._onRemoveListener); - observer._onNewListener= null; - observer._onRemoveListener= null; - } - var index= findTargetIndex.call(emitter, observer); - emitter._observers.splice(index, 1); - } - - if(event){ - handler= listeners[event]; - if(!handler) return; - off.call(target, event, handler); - delete listeners[event]; - if(!--this._listenersCount){ - clearRefs(); - } - }else { - events= ownKeys(listeners); - i= events.length; - while(i-->0){ - event= events[i]; - off.call(target, event, listeners[event]); - } - this._listeners= {}; - this._listenersCount= 0; - clearRefs(); - } - } - }); - - function resolveOptions(options, schema, reducers, allowUnknown) { - var computedOptions = Object.assign({}, schema); - - if (!options) return computedOptions; - - if (typeof options !== 'object') { - throw TypeError('options must be an object') - } - - var keys = Object.keys(options); - var length = keys.length; - var option, value; - var reducer; - - function reject(reason) { - throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) - } - - for (var i = 0; i < length; i++) { - option = keys[i]; - if (!allowUnknown && !hasOwnProperty.call(schema, option)) { - throw Error('Unknown "' + option + '" option'); - } - value = options[option]; - if (value !== undefined$1) { - reducer = reducers[option]; - computedOptions[option] = reducer ? reducer(value, reject) : value; - } - } - return computedOptions; - } - - function constructorReducer(value, reject) { - if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { - reject('value must be a constructor'); - } - return value; - } - - function makeTypeReducer(types) { - var message= 'value must be type of ' + types.join('|'); - var len= types.length; - var firstType= types[0]; - var secondType= types[1]; - - if (len === 1) { - return function (v, reject) { - if (typeof v === firstType) { - return v; - } - reject(message); - } - } - - if (len === 2) { - return function (v, reject) { - var kind= typeof v; - if (kind === firstType || kind === secondType) return v; - reject(message); - } - } - - return function (v, reject) { - var kind = typeof v; - var i = len; - while (i-- > 0) { - if (kind === types[i]) return v; - } - reject(message); - } - } - - var functionReducer= makeTypeReducer(['function']); - - var objectFunctionReducer= makeTypeReducer(['object', 'function']); - - function makeCancelablePromise(Promise, executor, options) { - var isCancelable; - var callbacks; - var timer= 0; - var subscriptionClosed; - - var promise = new Promise(function (resolve, reject, onCancel) { - options= resolveOptions(options, { - timeout: 0, - overload: false - }, { - timeout: function(value, reject){ - value*= 1; - if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { - reject('timeout must be a positive number'); - } - return value; - } - }); - - isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; - - function cleanup() { - if (callbacks) { - callbacks = null; - } - if (timer) { - clearTimeout(timer); - timer = 0; - } - } - - var _resolve= function(value){ - cleanup(); - resolve(value); - }; - - var _reject= function(err){ - cleanup(); - reject(err); - }; - - if (isCancelable) { - executor(_resolve, _reject, onCancel); - } else { - callbacks = [function(reason){ - _reject(reason || Error('canceled')); - }]; - executor(_resolve, _reject, function (cb) { - if (subscriptionClosed) { - throw Error('Unable to subscribe on cancel event asynchronously') - } - if (typeof cb !== 'function') { - throw TypeError('onCancel callback must be a function'); - } - callbacks.push(cb); - }); - subscriptionClosed= true; - } - - if (options.timeout > 0) { - timer= setTimeout(function(){ - var reason= Error('timeout'); - reason.code = 'ETIMEDOUT'; - timer= 0; - promise.cancel(reason); - reject(reason); - }, options.timeout); - } - }); - - if (!isCancelable) { - promise.cancel = function (reason) { - if (!callbacks) { - return; - } - var length = callbacks.length; - for (var i = 1; i < length; i++) { - callbacks[i](reason); - } - // internal callback to reject the promise - callbacks[0](reason); - callbacks = null; - }; - } - - return promise; - } - - function findTargetIndex(observer) { - var observers = this._observers; - if(!observers){ - return -1; - } - var len = observers.length; - for (var i = 0; i < len; i++) { - if (observers[i]._target === observer) return i; - } - return -1; - } - - // Attention, function return type now is array, always ! - // It has zero elements if no any matches found and one or more - // elements (leafs) if there are matches - // - function searchListenerTree(handlers, type, tree, i, typeLength) { - if (!tree) { - return null; - } - - if (i === 0) { - var kind = typeof type; - if (kind === 'string') { - var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; - if ((n = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[l++] = type.slice(j, n); - j = n + dl; - } while ((n = type.indexOf(delimiter, j)) !== -1); - - ns[l++] = type.slice(j); - type = ns; - typeLength = l; - } else { - type = [type]; - typeLength = 1; - } - } else if (kind === 'object') { - typeLength = type.length; - } else { - type = [type]; - typeLength = 1; - } - } - - var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], - nextType = type[i + 1], branches, _listeners; - - if (i === typeLength) { - // - // If at the end of the event(s) list and the tree has listeners - // invoke those listeners. - // - - if(tree._listeners) { - if (typeof tree._listeners === 'function') { - handlers && handlers.push(tree._listeners); - listeners = [tree]; - } else { - handlers && handlers.push.apply(handlers, tree._listeners); - listeners = [tree]; - } - } - } else { - - if (currentType === '*') { - // - // If the event emitted is '*' at this part - // or there is a concrete match at this patch - // - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (currentType === '**') { - endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); - if (endReached && tree._listeners) { - // The next element has a _listeners, add it to the handlers. - listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); - } - - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - if (branch === '*' || branch === '**') { - if (tree[branch]._listeners && !endReached) { - _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } else if (branch === nextType) { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); - } else { - // No match on this one, shift into the tree but not in the type array. - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (tree[currentType]) { - listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); - } - } - - xTree = tree['*']; - if (xTree) { - // - // If the listener tree will allow any match for this part, - // then recursively explore all branches of the tree - // - searchListenerTree(handlers, type, xTree, i + 1, typeLength); - } - - xxTree = tree['**']; - if (xxTree) { - if (i < typeLength) { - if (xxTree._listeners) { - // If we have a listener on a '**', it will catch all, so add its handler. - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } - - // Build arrays of matching next branches and others. - branches= ownKeys(xxTree); - n= branches.length; - while(n-->0){ - branch= branches[n]; - if (branch !== '_listeners') { - if (branch === nextType) { - // We know the next element will match, so jump twice. - searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); - } else if (branch === currentType) { - // Current node matches, move into the tree. - searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); - } else { - isolatedBranch = {}; - isolatedBranch[branch] = xxTree[branch]; - searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); - } - } - } - } else if (xxTree._listeners) { - // We have reached the end and still on a '**' - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } else if (xxTree['*'] && xxTree['*']._listeners) { - searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); - } - } - - return listeners; - } - - function growListenerTree(type, listener, prepend) { - var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; - - if(typeof type==='string') { - if ((i = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[len++] = type.slice(j, i); - j = i + dl; - } while ((i = type.indexOf(delimiter, j)) !== -1); - - ns[len++] = type.slice(j); - }else { - ns= [type]; - len= 1; - } - }else { - ns= type; - len= type.length; - } - - // - // Looks for two consecutive '**', if so, don't add the event at all. - // - if (len > 1) { - for (i = 0; i + 1 < len; i++) { - if (ns[i] === '**' && ns[i + 1] === '**') { - return; - } - } - } - - - - var tree = this.listenerTree, name; - - for (i = 0; i < len; i++) { - name = ns[i]; - - tree = tree[name] || (tree[name] = {}); - - if (i === len - 1) { - if (!tree._listeners) { - tree._listeners = listener; - } else { - if (typeof tree._listeners === 'function') { - tree._listeners = [tree._listeners]; - } - - if (prepend) { - tree._listeners.unshift(listener); - } else { - tree._listeners.push(listener); - } - - if ( - !tree._listeners.warned && - this._maxListeners > 0 && - tree._listeners.length > this._maxListeners - ) { - tree._listeners.warned = true; - logPossibleMemoryLeak.call(this, tree._listeners.length, name); - } - } - return true; - } - } - - return true; - } - - function collectTreeEvents(tree, events, root, asArray){ - var branches= ownKeys(tree); - var i= branches.length; - var branch, branchName, path; - var hasListeners= tree['_listeners']; - var isArrayPath; - - while(i-->0){ - branchName= branches[i]; - - branch= tree[branchName]; - - if(branchName==='_listeners'){ - path= root; - }else { - path = root ? root.concat(branchName) : [branchName]; - } - - isArrayPath= asArray || typeof branchName==='symbol'; - - hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); - - if(typeof branch==='object'){ - collectTreeEvents.call(this, branch, events, path, isArrayPath); - } - } - - return events; - } - - function recursivelyGarbageCollect(root) { - var keys = ownKeys(root); - var i= keys.length; - var obj, key, flag; - while(i-->0){ - key = keys[i]; - obj = root[key]; - - if(obj){ - flag= true; - if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ - delete root[key]; - } - } - } - - return flag; - } - - function Listener(emitter, event, listener){ - this.emitter= emitter; - this.event= event; - this.listener= listener; - } - - Listener.prototype.off= function(){ - this.emitter.off(this.event, this.listener); - return this; - }; - - function setupListener(event, listener, options){ - if (options === true) { - promisify = true; - } else if (options === false) { - async = true; - } else { - if (!options || typeof options !== 'object') { - throw TypeError('options should be an object or true'); - } - var async = options.async; - var promisify = options.promisify; - var nextTick = options.nextTick; - var objectify = options.objectify; - } - - if (async || nextTick || promisify) { - var _listener = listener; - var _origin = listener._origin || listener; - - if (nextTick && !nextTickSupported) { - throw Error('process.nextTick is not supported'); - } - - if (promisify === undefined$1) { - promisify = listener.constructor.name === 'AsyncFunction'; - } - - listener = function () { - var args = arguments; - var context = this; - var event = this.event; - - return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { - _setImmediate(resolve); - }).then(function () { - context.event = event; - return _listener.apply(context, args) - })) : (nextTick ? process.nextTick : _setImmediate)(function () { - context.event = event; - _listener.apply(context, args); - }); - }; - - listener._async = true; - listener._origin = _origin; - } - - return [listener, objectify? new Listener(this, event, listener): this]; - } - - function EventEmitter(conf) { - this._events = {}; - this._newListener = false; - this._removeListener = false; - this.verboseMemoryLeak = false; - configure.call(this, conf); - } - - EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property - - EventEmitter.prototype.listenTo= function(target, events, options){ - if(typeof target!=='object'){ - throw TypeError('target musts be an object'); - } - - var emitter= this; - - options = resolveOptions(options, { - on: undefined$1, - off: undefined$1, - reducers: undefined$1 - }, { - on: functionReducer, - off: functionReducer, - reducers: objectFunctionReducer - }); - - function listen(events){ - if(typeof events!=='object'){ - throw TypeError('events must be an object'); - } - - var reducers= options.reducers; - var index= findTargetIndex.call(emitter, target); - var observer; - - if(index===-1){ - observer= new TargetObserver(emitter, target, options); - }else { - observer= emitter._observers[index]; - } - - var keys= ownKeys(events); - var len= keys.length; - var event; - var isSingleReducer= typeof reducers==='function'; - - for(var i=0; i 0) { - observer = observers[i]; - if (!target || observer._target === target) { - observer.unsubscribe(event); - matched= true; - } - } - - return matched; - }; - - // By default EventEmitters will print a warning if more than - // 10 listeners are added to it. This is a useful default which - // helps finding memory leaks. - // - // Obviously not all Emitters should be limited to 10. This function allows - // that to be increased. Set to zero for unlimited. - - EventEmitter.prototype.delimiter = '.'; - - EventEmitter.prototype.setMaxListeners = function(n) { - if (n !== undefined$1) { - this._maxListeners = n; - if (!this._conf) this._conf = {}; - this._conf.maxListeners = n; - } - }; - - EventEmitter.prototype.getMaxListeners = function() { - return this._maxListeners; - }; - - EventEmitter.prototype.event = ''; - - EventEmitter.prototype.once = function(event, fn, options) { - return this._once(event, fn, false, options); - }; - - EventEmitter.prototype.prependOnceListener = function(event, fn, options) { - return this._once(event, fn, true, options); - }; - - EventEmitter.prototype._once = function(event, fn, prepend, options) { - return this._many(event, 1, fn, prepend, options); - }; - - EventEmitter.prototype.many = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, false, options); - }; - - EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, true, options); - }; - - EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { - var self = this; - - if (typeof fn !== 'function') { - throw new Error('many only accepts instances of Function'); - } - - function listener() { - if (--ttl === 0) { - self.off(event, listener); - } - return fn.apply(this, arguments); - } - - listener._origin = fn; - - return this._on(event, listener, prepend, options); - }; - - EventEmitter.prototype.emit = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], ns, wildcard= this.wildcard; - var args,l,i,j, containsSymbol; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { - return false; - } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var al = arguments.length; - var handler; - - if (this._all && this._all.length) { - handler = this._all.slice(); - - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this, type); - break; - case 2: - handler[i].call(this, type, arguments[1]); - break; - case 3: - handler[i].call(this, type, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, arguments); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); - } else { - handler = this._events[type]; - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - handler.apply(this, args); - } - return true; - } else if (handler) { - // need to make copy of handlers because list can change in the middle - // of emit call - handler = handler.slice(); - } - } - - if (handler && handler.length) { - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this); - break; - case 2: - handler[i].call(this, arguments[1]); - break; - case 3: - handler[i].call(this, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, args); - } - } - return true; - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - } - - return !!this._all; - }; - - EventEmitter.prototype.emitAsync = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; - var args,l,i,j; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { return Promise.resolve([false]); } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var promises= []; - - var al = arguments.length; - var handler; - - if (this._all) { - for (i = 0, l = this._all.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(this._all[i].call(this, type)); - break; - case 2: - promises.push(this._all[i].call(this, type, arguments[1])); - break; - case 3: - promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); - break; - default: - promises.push(this._all[i].apply(this, arguments)); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0); - } else { - handler = this._events[type]; - } - - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - promises.push(handler.call(this)); - break; - case 2: - promises.push(handler.call(this, arguments[1])); - break; - case 3: - promises.push(handler.call(this, arguments[1], arguments[2])); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - promises.push(handler.apply(this, args)); - } - } else if (handler && handler.length) { - handler = handler.slice(); - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(handler[i].call(this)); - break; - case 2: - promises.push(handler[i].call(this, arguments[1])); - break; - case 3: - promises.push(handler[i].call(this, arguments[1], arguments[2])); - break; - default: - promises.push(handler[i].apply(this, args)); - } - } - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - return Promise.reject(arguments[1]); // Unhandled 'error' event - } else { - return Promise.reject("Uncaught, unspecified 'error' event."); - } - } - - return Promise.all(promises); - }; - - EventEmitter.prototype.on = function(type, listener, options) { - return this._on(type, listener, false, options); - }; - - EventEmitter.prototype.prependListener = function(type, listener, options) { - return this._on(type, listener, true, options); - }; - - EventEmitter.prototype.onAny = function(fn) { - return this._onAny(fn, false); - }; - - EventEmitter.prototype.prependAny = function(fn) { - return this._onAny(fn, true); - }; - - EventEmitter.prototype.addListener = EventEmitter.prototype.on; - - EventEmitter.prototype._onAny = function(fn, prepend){ - if (typeof fn !== 'function') { - throw new Error('onAny only accepts instances of Function'); - } - - if (!this._all) { - this._all = []; - } - - // Add the function to the event listener collection. - if(prepend){ - this._all.unshift(fn); - }else { - this._all.push(fn); - } - - return this; - }; - - EventEmitter.prototype._on = function(type, listener, prepend, options) { - if (typeof type === 'function') { - this._onAny(type, listener); - return this; - } - - if (typeof listener !== 'function') { - throw new Error('on only accepts instances of Function'); - } - this._events || init.call(this); - - var returnValue= this, temp; - - if (options !== undefined$1) { - temp = setupListener.call(this, type, listener, options); - listener = temp[0]; - returnValue = temp[1]; - } - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._newListener) { - this.emit('newListener', type, listener); - } - - if (this.wildcard) { - growListenerTree.call(this, type, listener, prepend); - return returnValue; - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else { - if (typeof this._events[type] === 'function') { - // Change to array. - this._events[type] = [this._events[type]]; - } - - // If we've already got an array, just add - if(prepend){ - this._events[type].unshift(listener); - }else { - this._events[type].push(listener); - } - - // Check for listener leak - if ( - !this._events[type].warned && - this._maxListeners > 0 && - this._events[type].length > this._maxListeners - ) { - this._events[type].warned = true; - logPossibleMemoryLeak.call(this, this._events[type].length, type); - } - } - - return returnValue; - }; - - EventEmitter.prototype.off = function(type, listener) { - if (typeof listener !== 'function') { - throw new Error('removeListener only takes instances of Function'); - } - - var handlers,leafs=[]; - - if(this.wildcard) { - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); - if(!leafs) return this; - } else { - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events[type]) return this; - handlers = this._events[type]; - leafs.push({_listeners:handlers}); - } - - for (var iLeaf=0; iLeaf 0) { - fns = this._all; - for(i = 0, l = fns.length; i < l; i++) { - if(fn === fns[i]) { - fns.splice(i, 1); - if (this._removeListener) - this.emit("removeListenerAny", fn); - return this; - } - } - } else { - fns = this._all; - if (this._removeListener) { - for(i = 0, l = fns.length; i < l; i++) - this.emit("removeListenerAny", fns[i]); - } - this._all = []; - } - return this; - }; - - EventEmitter.prototype.removeListener = EventEmitter.prototype.off; - - EventEmitter.prototype.removeAllListeners = function (type) { - if (type === undefined$1) { - !this._events || init.call(this); - return this; - } - - if (this.wildcard) { - var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; - if (!leafs) return this; - for (i = 0; i < leafs.length; i++) { - leaf = leafs[i]; - leaf._listeners = null; - } - this.listenerTree && recursivelyGarbageCollect(this.listenerTree); - } else if (this._events) { - this._events[type] = null; - } - return this; - }; - - EventEmitter.prototype.listeners = function (type) { - var _events = this._events; - var keys, listeners, allListeners; - var i; - var listenerTree; - - if (type === undefined$1) { - if (this.wildcard) { - throw Error('event name required for wildcard emitter'); - } - - if (!_events) { - return []; - } - - keys = ownKeys(_events); - i = keys.length; - allListeners = []; - while (i-- > 0) { - listeners = _events[keys[i]]; - if (typeof listeners === 'function') { - allListeners.push(listeners); - } else { - allListeners.push.apply(allListeners, listeners); - } - } - return allListeners; - } else { - if (this.wildcard) { - listenerTree= this.listenerTree; - if(!listenerTree) return []; - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, listenerTree, 0); - return handlers; - } - - if (!_events) { - return []; - } - - listeners = _events[type]; - - if (!listeners) { - return []; - } - return typeof listeners === 'function' ? [listeners] : listeners; - } - }; - - EventEmitter.prototype.eventNames = function(nsAsArray){ - var _events= this._events; - return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); - }; - - EventEmitter.prototype.listenerCount = function(type) { - return this.listeners(type).length; - }; - - EventEmitter.prototype.hasListeners = function (type) { - if (this.wildcard) { - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); - return handlers.length > 0; - } - - var _events = this._events; - var _all = this._all; - - return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); - }; - - EventEmitter.prototype.listenersAny = function() { - - if(this._all) { - return this._all; - } - else { - return []; - } - - }; - - EventEmitter.prototype.waitFor = function (event, options) { - var self = this; - var type = typeof options; - if (type === 'number') { - options = {timeout: options}; - } else if (type === 'function') { - options = {filter: options}; - } - - options= resolveOptions(options, { - timeout: 0, - filter: undefined$1, - handleError: false, - Promise: Promise, - overload: false - }, { - filter: functionReducer, - Promise: constructorReducer - }); - - return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { - function listener() { - var filter= options.filter; - if (filter && !filter.apply(self, arguments)) { - return; - } - self.off(event, listener); - if (options.handleError) { - var err = arguments[0]; - err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); - } else { - resolve(toArray.apply(null, arguments)); - } - } - - onCancel(function(){ - self.off(event, listener); - }); - - self._on(event, listener, false); - }, { - timeout: options.timeout, - overload: options.overload - }) - }; - - function once(emitter, name, options) { - options= resolveOptions(options, { - Promise: Promise, - timeout: 0, - overload: false - }, { - Promise: constructorReducer - }); - - var _Promise= options.Promise; - - return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ - var handler; - if (typeof emitter.addEventListener === 'function') { - handler= function () { - resolve(toArray.apply(null, arguments)); - }; - - onCancel(function(){ - emitter.removeEventListener(name, handler); - }); - - emitter.addEventListener( - name, - handler, - {once: true} - ); - return; - } - - var eventListener = function(){ - errorListener && emitter.removeListener('error', errorListener); - resolve(toArray.apply(null, arguments)); - }; - - var errorListener; - - if (name !== 'error') { - errorListener = function (err){ - emitter.removeListener(name, eventListener); - reject(err); - }; - - emitter.once('error', errorListener); - } - - onCancel(function(){ - errorListener && emitter.removeListener('error', errorListener); - emitter.removeListener(name, eventListener); - }); - - emitter.once(name, eventListener); - }, { - timeout: options.timeout, - overload: options.overload - }); - } - - var prototype= EventEmitter.prototype; - - Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - get: function () { - return prototype._maxListeners; - }, - set: function (n) { - if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { - throw TypeError('n must be a non-negative number') - } - prototype._maxListeners = n; - }, - enumerable: true - }, - once: { - value: once, - writable: true, - configurable: true - } - }); - - Object.defineProperties(prototype, { - _maxListeners: { - value: defaultMaxListeners, - writable: true, - configurable: true - }, - _observers: {value: null, writable: true, configurable: true} - }); - - if (typeof undefined$1 === 'function' && undefined$1.amd) { - // AMD. Register as an anonymous module. - undefined$1(function() { - return EventEmitter; - }); - } else { - // CommonJS - module.exports = EventEmitter; - } - }(); - } (eventemitter2, eventemitter2.exports)); - - var eventemitter2Exports = eventemitter2.exports; - var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); - /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class InteractiveMarkerHandle extends EventEmitter2 { + class InteractiveMarkerHandle extends EventEmitter3 { /** * Handle with signals for a single interactive marker. @@ -55434,7 +53796,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Nils Berg - berg.nils@gmail.com */ - class MarkerArrayClient extends EventEmitter2 { + class MarkerArrayClient extends EventEmitter3 { /** * A MarkerArray client that listens to a given topic. @@ -55551,7 +53913,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Russell Toris - rctoris@wpi.edu */ - class MarkerClient extends EventEmitter2 { + class MarkerClient extends EventEmitter3 { /** * A marker client that listens to a given marker topic. @@ -56021,7 +54383,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Russell Toris - rctoris@wpi.edu */ - class OccupancyGridClient extends EventEmitter2 { + class OccupancyGridClient extends EventEmitter3 { /** * An occupancy grid client that listens to a given map topic. @@ -56846,7 +55208,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Peter Sari - sari@photoneo.com */ - class OcTreeClient extends EventEmitter2 { + class OcTreeClient extends EventEmitter3 { /** * An OcTree client that listens to a given OcTree topic. diff --git a/build/ros3d.min.js b/build/ros3d.min.js index d3b63366..35bd91a2 100644 --- a/build/ros3d.min.js +++ b/build/ros3d.min.js @@ -1,12 +1,5 @@ -var ROS3D=function(e,t){"use strict";function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(i){if("default"!==i){var r=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,r.get?r:{enumerable:!0,get:function(){return e[i]}})}})),t.default=e,Object.freeze(t)}var r=i(t);function n(){}void 0===Number.EPSILON&&(Number.EPSILON=Math.pow(2,-52)),void 0===Number.isInteger&&(Number.isInteger=function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}),void 0===Math.sign&&(Math.sign=function(e){return e<0?-1:e>0?1:+e}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),i=1;i>8&255]+e[t>>16&255]+e[t>>24&255]+"-"+e[255&i]+e[i>>8&255]+"-"+e[i>>16&15|64]+e[i>>24&255]+"-"+e[63&r|128]+e[r>>8&255]+"-"+e[r>>16&255]+e[r>>24&255]+e[255&n]+e[n>>8&255]+e[n>>16&255]+e[n>>24&255]}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,r,n){return r+(e-t)*(n-r)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*te.DEG2RAD},radToDeg:function(e){return e*te.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))}};function ie(e,t){this.x=e||0,this.y=t||0}function re(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}function ne(e,t,i,r){this._x=e||0,this._y=t||0,this._z=i||0,this._w=void 0!==r?r:1}function oe(e,t,i){this.x=e||0,this.y=t||0,this.z=i||0}function ae(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(ie.prototype,{width:{get:function(){return this.x},set:function(e){this.x=e}},height:{get:function(){return this.y},set:function(e){this.y=e}}}),Object.assign(ie.prototype,{isVector2:!0,set:function(e,t){return this.x=e,this.y=t,this},setScalar:function(e){return this.x=e,this.y=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(e){return this.x=e.x,this.y=e.y,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this)},addScalar:function(e){return this.x+=e,this.y+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this)},subScalar:function(e){return this.x-=e,this.y-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this},multiply:function(e){return this.x*=e.x,this.y*=e.y,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this},divide:function(e){return this.x/=e.x,this.y/=e.y,this},divideScalar:function(e){return this.multiplyScalar(1/e)},applyMatrix3:function(e){var t=this.x,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[7],this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this},clampScalar:(o=new ie,a=new ie,function(e,t){return o.set(e,e),a.set(t,t),this.clamp(o,a)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return 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},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(e){return this.x*e.x+this.y*e.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var e=Math.atan2(this.y,this.x);return e<0&&(e+=2*Math.PI),e},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y;return t*t+i*i},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},equals:function(e){return e.x===this.x&&e.y===this.y},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this},rotateAround:function(e,t){var i=Math.cos(t),r=Math.sin(t),n=this.x-e.x,o=this.y-e.y;return this.x=n*i-o*r+e.x,this.y=n*r+o*i+e.y,this}}),Object.assign(re.prototype,{isMatrix4:!0,set:function(e,t,i,r,n,o,a,s,c,h,l,u,p,d,f,m){var v=this.elements;return v[0]=e,v[4]=t,v[8]=i,v[12]=r,v[1]=n,v[5]=o,v[9]=a,v[13]=s,v[2]=c,v[6]=h,v[10]=l,v[14]=u,v[3]=p,v[7]=d,v[11]=f,v[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new re).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this},copyPosition:function(e){var t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this},extractBasis:function(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this},extractRotation:(p=new oe,function(e){var t=this.elements,i=e.elements,r=1/p.setFromMatrixColumn(e,0).length(),n=1/p.setFromMatrixColumn(e,1).length(),o=1/p.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[4]=i[4]*n,t[5]=i[5]*n,t[6]=i[6]*n,t[8]=i[8]*o,t[9]=i[9]*o,t[10]=i[10]*o,this}),makeRotationFromEuler:function(e){e&&e.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var t=this.elements,i=e.x,r=e.y,n=e.z,o=Math.cos(i),a=Math.sin(i),s=Math.cos(r),c=Math.sin(r),h=Math.cos(n),l=Math.sin(n);if("XYZ"===e.order){var u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=-s*l,t[8]=c,t[1]=p+d*c,t[5]=u-f*c,t[9]=-a*s,t[2]=f-u*c,t[6]=d+p*c,t[10]=o*s}else if("YXZ"===e.order){var m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m+y*a,t[4]=g*a-v,t[8]=o*c,t[1]=o*l,t[5]=o*h,t[9]=-a,t[2]=v*a-g,t[6]=y+m*a,t[10]=o*s}else if("ZXY"===e.order){m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m-y*a,t[4]=-o*l,t[8]=g+v*a,t[1]=v+g*a,t[5]=o*h,t[9]=y-m*a,t[2]=-o*c,t[6]=a,t[10]=o*s}else if("ZYX"===e.order){u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=d*c-p,t[8]=u*c+f,t[1]=s*l,t[5]=f*c+u,t[9]=p*c-d,t[2]=-c,t[6]=a*s,t[10]=o*s}else if("YZX"===e.order){var x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=_-x*l,t[8]=w*l+b,t[1]=l,t[5]=o*h,t[9]=-a*h,t[2]=-c*h,t[6]=b*l+w,t[10]=x-_*l}else if("XZY"===e.order){x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=-l,t[8]=c*h,t[1]=x*l+_,t[5]=o*h,t[9]=b*l-w,t[2]=w*l-b,t[6]=a*h,t[10]=_*l+x}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromQuaternion:function(e){var t=this.elements,i=e._x,r=e._y,n=e._z,o=e._w,a=i+i,s=r+r,c=n+n,h=i*a,l=i*s,u=i*c,p=r*s,d=r*c,f=n*c,m=o*a,v=o*s,g=o*c;return t[0]=1-(p+f),t[4]=l-g,t[8]=u+v,t[1]=l+g,t[5]=1-(h+f),t[9]=d-m,t[2]=u-v,t[6]=d+m,t[10]=1-(h+p),t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},lookAt:(h=new oe,l=new oe,u=new oe,function(e,t,i){var r=this.elements;return u.subVectors(e,t),0===u.lengthSq()&&(u.z=1),u.normalize(),h.crossVectors(i,u),0===h.lengthSq()&&(1===Math.abs(i.z)?u.x+=1e-4:u.z+=1e-4,u.normalize(),h.crossVectors(i,u)),h.normalize(),l.crossVectors(u,h),r[0]=h.x,r[4]=l.x,r[8]=u.x,r[1]=h.y,r[5]=l.y,r[9]=u.y,r[2]=h.z,r[6]=l.z,r[10]=u.z,this}),multiply:function(e,t){return void 0!==t?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(e,t)):this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var i=e.elements,r=t.elements,n=this.elements,o=i[0],a=i[4],s=i[8],c=i[12],h=i[1],l=i[5],u=i[9],p=i[13],d=i[2],f=i[6],m=i[10],v=i[14],g=i[3],y=i[7],x=i[11],b=i[15],w=r[0],_=r[4],M=r[8],E=r[12],T=r[1],S=r[5],A=r[9],L=r[13],R=r[2],C=r[6],P=r[10],N=r[14],O=r[3],I=r[7],D=r[11],U=r[15];return n[0]=o*w+a*T+s*R+c*O,n[4]=o*_+a*S+s*C+c*I,n[8]=o*M+a*A+s*P+c*D,n[12]=o*E+a*L+s*N+c*U,n[1]=h*w+l*T+u*R+p*O,n[5]=h*_+l*S+u*C+p*I,n[9]=h*M+l*A+u*P+p*D,n[13]=h*E+l*L+u*N+p*U,n[2]=d*w+f*T+m*R+v*O,n[6]=d*_+f*S+m*C+v*I,n[10]=d*M+f*A+m*P+v*D,n[14]=d*E+f*L+m*N+v*U,n[3]=g*w+y*T+x*R+b*O,n[7]=g*_+y*S+x*C+b*I,n[11]=g*M+y*A+x*P+b*D,n[15]=g*E+y*L+x*N+b*U,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i=0?1:-1,y=1-v*v;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,v*g);m=Math.sin(m*b)/x,a=Math.sin(a*b)/x}var w=a*g;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-a){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}e[t]=s,e[t+1]=c,e[t+2]=h,e[t+3]=l}}),Object.defineProperties(ne.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this.onChangeCallback()}}}),Object.assign(ne.prototype,{set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this.onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var i=e._x,r=e._y,n=e._z,o=e.order,a=Math.cos,s=Math.sin,c=a(i/2),h=a(r/2),l=a(n/2),u=s(i/2),p=s(r/2),d=s(n/2);return"XYZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===o&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],s=i[5],c=i[9],h=i[2],l=i[6],u=i[10],p=r+s+u;return p>0?(t=.5/Math.sqrt(p+1),this._w=.25/t,this._x=(l-c)*t,this._y=(o-h)*t,this._z=(a-n)*t):r>s&&r>u?(t=2*Math.sqrt(1+r-s-u),this._w=(l-c)/t,this._x=.25*t,this._y=(n+a)/t,this._z=(o+h)/t):s>u?(t=2*Math.sqrt(1+s-r-u),this._w=(o-h)/t,this._x=(n+a)/t,this._y=.25*t,this._z=(c+l)/t):(t=2*Math.sqrt(1+u-r-s),this._w=(a-n)/t,this._x=(o+h)/t,this._y=(c+l)/t,this._z=.25*t),this.onChangeCallback(),this},setFromUnitVectors:function(){var e,t=new oe;return function(i,r){return void 0===t&&(t=new oe),(e=i.dot(r)+1)<1e-6?(e=0,Math.abs(i.x)>Math.abs(i.z)?t.set(-i.y,i.x,0):t.set(0,-i.z,i.y)):t.crossVectors(i,r),this._x=t.x,this._y=t.y,this._z=t.z,this._w=e,this.normalize()}}(),inverse:function(){return this.conjugate().normalize()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this.onChangeCallback(),this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var i=e._x,r=e._y,n=e._z,o=e._w,a=t._x,s=t._y,c=t._z,h=t._w;return this._x=i*h+o*a+r*c-n*s,this._y=r*h+o*s+n*a-i*c,this._z=n*h+o*c+i*s-r*a,this._w=o*h-i*a-r*s-n*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,r=this._y,n=this._z,o=this._w,a=o*e._w+i*e._x+r*e._y+n*e._z;if(a<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,a=-a):this.copy(e),a>=1)return this._w=o,this._x=i,this._y=r,this._z=n,this;var s=Math.sqrt(1-a*a);if(Math.abs(s)<.001)return this._w=.5*(o+this._w),this._x=.5*(i+this._x),this._y=.5*(r+this._y),this._z=.5*(n+this._z),this;var c=Math.atan2(s,a),h=Math.sin((1-t)*c)/s,l=Math.sin(t*c)/s;return this._w=o*h+this._w*l,this._x=i*h+this._x*l,this._y=r*h+this._y*l,this._z=n*h+this._z*l,this.onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return void 0===t&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(oe.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:(d=new ne,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(d.setFromEuler(e))}),applyAxisAngle:function(){var e=new ne;return function(t,i){return this.applyQuaternion(e.setFromAxisAngle(t,i))}}(),applyMatrix3:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[3]*i+n[6]*r,this.y=n[1]*t+n[4]*i+n[7]*r,this.z=n[2]*t+n[5]*i+n[8]*r,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements,o=1/(n[3]*t+n[7]*i+n[11]*r+n[15]);return this.x=(n[0]*t+n[4]*i+n[8]*r+n[12])*o,this.y=(n[1]*t+n[5]*i+n[9]*r+n[13])*o,this.z=(n[2]*t+n[6]*i+n[10]*r+n[14])*o,this},applyQuaternion:function(e){var t=this.x,i=this.y,r=this.z,n=e.x,o=e.y,a=e.z,s=e.w,c=s*t+o*r-a*i,h=s*i+a*t-n*r,l=s*r+n*i-o*t,u=-n*t-o*i-a*r;return this.x=c*s+u*-n+h*-a-l*-o,this.y=h*s+u*-o+l*-n-c*-a,this.z=l*s+u*-a+c*-o-h*-n,this},project:function(){var e=new re;return function(t){return e.multiplyMatrices(t.projectionMatrix,e.getInverse(t.matrixWorld)),this.applyMatrix4(e)}}(),unproject:function(){var e=new re;return function(t){return e.multiplyMatrices(t.matrixWorld,e.getInverse(t.projectionMatrix)),this.applyMatrix4(e)}}(),transformDirection:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r,this.y=n[1]*t+n[5]*i+n[9]*r,this.z=n[2]*t+n[6]*i+n[10]*r,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:function(){var e=new oe,t=new oe;return function(i,r){return e.set(i,i,i),t.set(r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return 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},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},cross:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var i=e.x,r=e.y,n=e.z,o=t.x,a=t.y,s=t.z;return this.x=r*s-n*a,this.y=n*o-i*s,this.z=i*a-r*o,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:function(){var e=new oe;return function(t){return e.copy(this).projectOnVector(t),this.sub(e)}}(),reflect:function(){var e=new oe;return function(t){return this.sub(e.copy(t).multiplyScalar(2*this.dot(t)))}}(),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(te.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}}),Object.assign(ae.prototype,{isMatrix3:!0,set:function(e,t,i,r,n,o,a,s,c){var h=this.elements;return h[0]=e,h[1]=r,h[2]=a,h[3]=t,h[4]=n,h[5]=s,h[6]=i,h[7]=o,h[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")}(r)}),i.image=r.uuid}return t||(e.textures[this.uuid]=i),i},dispose:function(){this.dispatchEvent({type:"dispose"})},transformUv:function(e){if(this.mapping===f){if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case b:e.x=e.x-Math.floor(e.x);break;case w:e.x=e.x<0?0:1;break;case _:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case b:e.y=e.y-Math.floor(e.y);break;case w:e.y=e.y<0?0:1;break;case _:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}this.flipY&&(e.y=1-e.y)}}}),Object.defineProperty(ce.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(he.prototype,{isVector4:!0,set:function(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this.w=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setW:function(e){return this.w=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){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: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=this.w,o=e.elements;return this.x=o[0]*t+o[4]*i+o[8]*r+o[12]*n,this.y=o[1]*t+o[5]*i+o[9]*r+o[13]*n,this.z=o[2]*t+o[6]*i+o[10]*r+o[14]*n,this.w=o[3]*t+o[7]*i+o[11]*r+o[15]*n,this},divideScalar:function(e){return this.multiplyScalar(1/e)},setAxisAngleFromQuaternion:function(e){this.w=2*Math.acos(e.w);var t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this},setAxisAngleFromRotationMatrix:function(e){var t,i,r,n,o=.01,a=.1,s=e.elements,c=s[0],h=s[4],l=s[8],u=s[1],p=s[5],d=s[9],f=s[2],m=s[6],v=s[10];if(Math.abs(h-u)y&&g>x?gx?y0)return e;var n=t*i,o=ge[n];if(void 0===o&&(o=new Float32Array(n),ge[n]=o),0!==t){r.toArray(o,0);for(var a=1,s=0;a!==t;++a)s+=i,e[a].toArray(o,s)}return o}function _e(e,t){var i=ye[t];void 0===i&&(i=new Int32Array(t),ye[t]=i);for(var r=0;r!==t;++r)i[r]=e.allocTextureUnit();return i}function Me(e,t){e.uniform1f(this.addr,t)}function Ee(e,t){e.uniform1i(this.addr,t)}function Te(e,t){void 0===t.x?e.uniform2fv(this.addr,t):e.uniform2f(this.addr,t.x,t.y)}function Se(e,t){void 0!==t.x?e.uniform3f(this.addr,t.x,t.y,t.z):void 0!==t.r?e.uniform3f(this.addr,t.r,t.g,t.b):e.uniform3fv(this.addr,t)}function Ae(e,t){void 0===t.x?e.uniform4fv(this.addr,t):e.uniform4f(this.addr,t.x,t.y,t.z,t.w)}function Le(e,t){e.uniformMatrix2fv(this.addr,!1,t.elements||t)}function Re(e,t){void 0===t.elements?e.uniformMatrix3fv(this.addr,!1,t):(be.set(t.elements),e.uniformMatrix3fv(this.addr,!1,be))}function Ce(e,t){void 0===t.elements?e.uniformMatrix4fv(this.addr,!1,t):(xe.set(t.elements),e.uniformMatrix4fv(this.addr,!1,xe))}function Pe(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTexture2D(t||fe,r)}function Ne(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTextureCube(t||me,r)}function Oe(e,t){e.uniform2iv(this.addr,t)}function Ie(e,t){e.uniform3iv(this.addr,t)}function De(e,t){e.uniform4iv(this.addr,t)}function Ue(e,t){e.uniform1fv(this.addr,t)}function Be(e,t){e.uniform1iv(this.addr,t)}function Fe(e,t){e.uniform2fv(this.addr,we(t,this.size,2))}function ze(e,t){e.uniform3fv(this.addr,we(t,this.size,3))}function ke(e,t){e.uniform4fv(this.addr,we(t,this.size,4))}function Ge(e,t){e.uniformMatrix2fv(this.addr,!1,we(t,this.size,4))}function Ve(e,t){e.uniformMatrix3fv(this.addr,!1,we(t,this.size,9))}function je(e,t){e.uniformMatrix4fv(this.addr,!1,we(t,this.size,16))}function He(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTexture2D(t[o]||fe,n[o])}function We(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTextureCube(t[o]||me,n[o])}function Xe(e,t,i){this.id=e,this.addr=i,this.setValue=function(e){switch(e){case 5126:return Me;case 35664:return Te;case 35665:return Se;case 35666:return Ae;case 35674:return Le;case 35675:return Re;case 35676:return Ce;case 35678:case 36198:return Pe;case 35680:return Ne;case 5124:case 35670:return Ee;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function qe(e,t,i){this.id=e,this.addr=i,this.size=t.size,this.setValue=function(e){switch(e){case 5126:return Ue;case 35664:return Fe;case 35665:return ze;case 35666:return ke;case 35674:return Ge;case 35675:return Ve;case 35676:return je;case 35678:return He;case 35680:return We;case 5124:case 35670:return Be;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function Ye(e){this.id=e,ve.call(this)}Ye.prototype.setValue=function(e,t){for(var i=this.seq,r=0,n=i.length;r!==n;++r){var o=i[r];o.setValue(e,t[o.id])}};var Ze=/([\w\d_]+)(\])?(\[|\.)?/g;function Je(e,t){e.seq.push(t),e.map[t.id]=t}function Ke(e,t,i){var r=e.name,n=r.length;for(Ze.lastIndex=0;;){var o=Ze.exec(r),a=Ze.lastIndex,s=o[1],c="]"===o[2],h=o[3];if(c&&(s|=0),void 0===h||"["===h&&a+2===n){Je(i,void 0===h?new Xe(s,e,t):new qe(s,e,t));break}var l=i.map[s];void 0===l&&Je(i,l=new Ye(s)),i=l}}function Qe(e,t,i){ve.call(this),this.renderer=i;for(var r=e.getProgramParameter(t,e.ACTIVE_UNIFORMS),n=0;n>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function e(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+6*(t-e)*(2/3-i):e}return function(t,i,r){if(t=te.euclideanModulo(t,1),i=te.clamp(i,0,1),r=te.clamp(r,0,1),0===i)this.r=this.g=this.b=r;else{var n=r<=.5?r*(1+i):r+i-r*i,o=2*r-n;this.r=e(o,n,t+1/3),this.g=e(o,n,t),this.b=e(o,n,t-1/3)}return this}}(),setStyle:function(e){function t(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}var i;if(i=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var r,n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(255,parseInt(r[1],10))/255,this.g=Math.min(255,parseInt(r[2],10))/255,this.b=Math.min(255,parseInt(r[3],10))/255,t(r[5]),this;if(r=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(100,parseInt(r[1],10))/100,this.g=Math.min(100,parseInt(r[2],10))/100,this.b=Math.min(100,parseInt(r[3],10))/100,t(r[5]),this;break;case"hsl":case"hsla":if(r=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o)){var a=parseFloat(r[1])/360,s=parseInt(r[2],10)/100,c=parseInt(r[3],10)/100;return t(r[5]),this.setHSL(a,s,c)}}}else if(i=/^\#([A-Fa-f0-9]+)$/.exec(e)){var h,l=(h=i[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}e&&e.length>0&&(void 0!==(h=$e[e])?this.setHex(h):console.warn("THREE.Color: Unknown color "+e));return this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(e){return this.r=e.r,this.g=e.g,this.b=e.b,this},copyGammaToLinear:function(e,t){return void 0===t&&(t=2),this.r=Math.pow(e.r,t),this.g=Math.pow(e.g,t),this.b=Math.pow(e.b,t),this},copyLinearToGamma:function(e,t){void 0===t&&(t=2);var i=t>0?1/t:1;return this.r=Math.pow(e.r,i),this.g=Math.pow(e.g,i),this.b=Math.pow(e.b,i),this},convertGammaToLinear:function(){var e=this.r,t=this.g,i=this.b;return this.r=e*e,this.g=t*t,this.b=i*i,this},convertLinearToGamma:function(){return this.r=Math.sqrt(this.r),this.g=Math.sqrt(this.g),this.b=Math.sqrt(this.b),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(e){var t,i,r=e||{h:0,s:0,l:0},n=this.r,o=this.g,a=this.b,s=Math.max(n,o,a),c=Math.min(n,o,a),h=(c+s)/2;if(c===s)t=0,i=0;else{var l=s-c;switch(i=h<=.5?l/(s+c):l/(2-s-c),s){case n:t=(o-a)/l+(o 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n",lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 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\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",distanceRGBA_frag:"#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n",linedashed_frag:"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\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_frag:"#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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"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\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},nt={basic:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.fog]),vertexShader:rt.meshbasic_vert,fragmentShader:rt.meshbasic_frag},lambert:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.fog,tt.lights,{emissive:{value:new et(0)}}]),vertexShader:rt.meshlambert_vert,fragmentShader:rt.meshlambert_frag},phong:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.gradientmap,tt.fog,tt.lights,{emissive:{value:new et(0)},specular:{value:new et(1118481)},shininess:{value:30}}]),vertexShader:rt.meshphong_vert,fragmentShader:rt.meshphong_frag},standard:{uniforms:it.merge([tt.common,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.roughnessmap,tt.metalnessmap,tt.fog,tt.lights,{emissive:{value:new et(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},points:{uniforms:it.merge([tt.points,tt.fog]),vertexShader:rt.points_vert,fragmentShader:rt.points_frag},dashed:{uniforms:it.merge([tt.common,tt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rt.linedashed_vert,fragmentShader:rt.linedashed_frag},depth:{uniforms:it.merge([tt.common,tt.displacementmap]),vertexShader:rt.depth_vert,fragmentShader:rt.depth_frag},normal:{uniforms:it.merge([tt.common,tt.bumpmap,tt.normalmap,tt.displacementmap,{opacity:{value:1}}]),vertexShader:rt.normal_vert,fragmentShader:rt.normal_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:rt.cube_vert,fragmentShader:rt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rt.equirect_vert,fragmentShader:rt.equirect_frag},distanceRGBA:{uniforms:it.merge([tt.common,tt.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rt.distanceRGBA_vert,fragmentShader:rt.distanceRGBA_frag},shadow:{uniforms:it.merge([tt.lights,tt.fog,{color:{value:new et(0)},opacity:{value:1}}]),vertexShader:rt.shadow_vert,fragmentShader:rt.shadow_frag}};function ot(e,t){this.min=void 0!==e?e:new ie(1/0,1/0),this.max=void 0!==t?t:new ie(-1/0,-1/0)}function at(e,t,i,r,n){var o,a,s,c,h,l,u,p;function d(){var e=new Float32Array([-1,-1,0,0,1,-1,1,0,1,1,1,1,-1,1,0,1]),r=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,r,t.STATIC_DRAW),u=t.createTexture(),p=t.createTexture(),i.bindTexture(t.TEXTURE_2D,u),t.texImage2D(t.TEXTURE_2D,0,t.RGB,16,16,0,t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),i.bindTexture(t.TEXTURE_2D,p),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,16,16,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),s={vertexShader:["uniform lowp int renderType;","uniform vec3 screenPosition;","uniform vec2 scale;","uniform float rotation;","uniform sampler2D occlusionMap;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tvUV = uv;","\tvec2 pos = position;","\tif ( renderType == 2 ) {","\t\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );","\t\tvVisibility = visibility.r / 9.0;","\t\tvVisibility *= 1.0 - visibility.g / 9.0;","\t\tvVisibility *= visibility.b / 9.0;","\t\tvVisibility *= 1.0 - visibility.a / 9.0;","\t\tpos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;","\t\tpos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;","\t}","\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["uniform lowp int renderType;","uniform sampler2D map;","uniform float opacity;","uniform vec3 color;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tif ( renderType == 0 ) {","\t\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );","\t} else if ( renderType == 1 ) {","\t\tgl_FragColor = texture2D( map, vUV );","\t} else {","\t\tvec4 texture = texture2D( map, vUV );","\t\ttexture.a *= opacity * vVisibility;","\t\tgl_FragColor = texture;","\t\tgl_FragColor.rgb *= color;","\t}","}"].join("\n")},c=function(e){var i=t.createProgram(),r=t.createShader(t.FRAGMENT_SHADER),o=t.createShader(t.VERTEX_SHADER),a="precision "+n.precision+" float;\n";return t.shaderSource(r,a+e.fragmentShader),t.shaderSource(o,a+e.vertexShader),t.compileShader(r),t.compileShader(o),t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),i}(s),h={vertex:t.getAttribLocation(c,"position"),uv:t.getAttribLocation(c,"uv")},l={renderType:t.getUniformLocation(c,"renderType"),map:t.getUniformLocation(c,"map"),occlusionMap:t.getUniformLocation(c,"occlusionMap"),opacity:t.getUniformLocation(c,"opacity"),color:t.getUniformLocation(c,"color"),scale:t.getUniformLocation(c,"scale"),rotation:t.getUniformLocation(c,"rotation"),screenPosition:t.getUniformLocation(c,"screenPosition")}}this.render=function(e,n,s,f){if(0!==e.length){var m=new oe,v=f.w/f.z,g=.5*f.z,y=.5*f.w,x=16/f.w,b=new ie(x*v,x),w=new oe(1,1,0),_=new ie(1,1),M=new ot;M.min.set(f.x,f.y),M.max.set(f.x+(f.z-16),f.y+(f.w-16)),void 0===c&&d(),i.useProgram(c),i.initAttributes(),i.enableAttribute(h.vertex),i.enableAttribute(h.uv),i.disableUnusedAttributes(),t.uniform1i(l.occlusionMap,0),t.uniform1i(l.map,1),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(h.vertex,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(h.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),i.disable(t.CULL_FACE),i.buffers.depth.setMask(!1);for(var E=0,T=e.length;E.001&&R.scale>.001&&(w.x=R.x,w.y=R.y,w.z=R.z,x=R.size*R.scale/f.w,b.x=x*v,b.y=x,t.uniform3f(l.screenPosition,w.x,w.y,w.z),t.uniform2f(l.scale,b.x,b.y),t.uniform1f(l.rotation,R.rotation),t.uniform1f(l.opacity,R.opacity),t.uniform3f(l.color,R.color.r,R.color.g,R.color.b),i.setBlending(R.blending,R.blendEquation,R.blendSrc,R.blendDst),r.setTexture2D(R.texture,1),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0))}}}i.enable(t.CULL_FACE),i.enable(t.DEPTH_TEST),i.buffers.depth.setMask(!0),i.reset()}}}function st(e,t,i,r,n,o,a,s,c){ce.call(this,e,t,i,r,n,o,a,s,c),this.needsUpdate=!0}function ct(e,t,i,r,n){var o,a,s,c,h,l,u=new oe,p=new ne,d=new oe;function f(){var e=new Float32Array([-.5,-.5,0,0,.5,-.5,1,0,.5,.5,1,1,-.5,.5,0,1]),i=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s=function(){var e=t.createProgram(),i=t.createShader(t.VERTEX_SHADER),r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float rotation;","uniform vec2 scale;","uniform vec2 uvOffset;","uniform vec2 uvScale;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvUV = uvOffset + uv * uvScale;","\tvec2 alignedPosition = position * scale;","\tvec2 rotatedPosition;","\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;","\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;","\tvec4 mvPosition;","\tmvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );","\tmvPosition.xy += rotatedPosition;","\tgl_Position = projectionMatrix * mvPosition;","\tfogDepth = - mvPosition.z;","}"].join("\n")),t.shaderSource(r,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform vec3 color;","uniform sampler2D map;","uniform float opacity;","uniform int fogType;","uniform vec3 fogColor;","uniform float fogDensity;","uniform float fogNear;","uniform float fogFar;","uniform float alphaTest;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvec4 texture = texture2D( map, vUV );","\tgl_FragColor = vec4( color * texture.xyz, texture.a * opacity );","\tif ( gl_FragColor.a < alphaTest ) discard;","\tif ( fogType > 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),t.compileShader(i),t.compileShader(r),t.attachShader(e,i),t.attachShader(e,r),t.linkProgram(e),e}(),c={position:t.getAttribLocation(s,"position"),uv:t.getAttribLocation(s,"uv")},h={uvOffset:t.getUniformLocation(s,"uvOffset"),uvScale:t.getUniformLocation(s,"uvScale"),rotation:t.getUniformLocation(s,"rotation"),scale:t.getUniformLocation(s,"scale"),color:t.getUniformLocation(s,"color"),map:t.getUniformLocation(s,"map"),opacity:t.getUniformLocation(s,"opacity"),modelViewMatrix:t.getUniformLocation(s,"modelViewMatrix"),projectionMatrix:t.getUniformLocation(s,"projectionMatrix"),fogType:t.getUniformLocation(s,"fogType"),fogDensity:t.getUniformLocation(s,"fogDensity"),fogNear:t.getUniformLocation(s,"fogNear"),fogFar:t.getUniformLocation(s,"fogFar"),fogColor:t.getUniformLocation(s,"fogColor"),fogDepth:t.getUniformLocation(s,"fogDepth"),alphaTest:t.getUniformLocation(s,"alphaTest")};var r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");r.width=8,r.height=8;var u=r.getContext("2d");u.fillStyle="white",u.fillRect(0,0,8,8),l=new st(r)}function m(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(n,v,g){if(0!==n.length){void 0===s&&f(),i.useProgram(s),i.initAttributes(),i.enableAttribute(c.position),i.enableAttribute(c.uv),i.disableUnusedAttributes(),i.disable(t.CULL_FACE),i.enable(t.BLEND),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(c.position,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(c.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.uniformMatrix4fv(h.projectionMatrix,!1,g.projectionMatrix.elements),i.activeTexture(t.TEXTURE0),t.uniform1i(h.map,0);var y=0,x=0,b=v.fog;b?(t.uniform3f(h.fogColor,b.color.r,b.color.g,b.color.b),b.isFog?(t.uniform1f(h.fogNear,b.near),t.uniform1f(h.fogFar,b.far),t.uniform1i(h.fogType,1),y=1,x=1):b.isFogExp2&&(t.uniform1f(h.fogDensity,b.density),t.uniform1i(h.fogType,2),y=2,x=2)):(t.uniform1i(h.fogType,0),y=0,x=0);for(var w=0,_=n.length;w<_;w++){(E=n[w]).modelViewMatrix.multiplyMatrices(g.matrixWorldInverse,E.matrixWorld),E.z=-E.modelViewMatrix.elements[14]}n.sort(m);var M=[];for(w=0,_=n.length;w<_;w++){var E,T=(E=n[w]).material;if(!1!==T.visible){E.onBeforeRender(e,v,g,void 0,T,void 0),t.uniform1f(h.alphaTest,T.alphaTest),t.uniformMatrix4fv(h.modelViewMatrix,!1,E.modelViewMatrix.elements),E.matrixWorld.decompose(u,p,d),M[0]=d.x,M[1]=d.y;var S=0;v.fog&&T.fog&&(S=x),y!==S&&(t.uniform1i(h.fogType,S),y=S),null!==T.map?(t.uniform2f(h.uvOffset,T.map.offset.x,T.map.offset.y),t.uniform2f(h.uvScale,T.map.repeat.x,T.map.repeat.y)):(t.uniform2f(h.uvOffset,0,0),t.uniform2f(h.uvScale,1,1)),t.uniform1f(h.opacity,T.opacity),t.uniform3f(h.color,T.color.r,T.color.g,T.color.b),t.uniform1f(h.rotation,T.rotation),t.uniform2fv(h.scale,M),i.setBlending(T.blending,T.blendEquation,T.blendSrc,T.blendDst,T.blendEquationAlpha,T.blendSrcAlpha,T.blendDstAlpha,T.premultipliedAlpha),i.buffers.depth.setTest(T.depthTest),i.buffers.depth.setMask(T.depthWrite),i.buffers.color.setMask(T.colorWrite),r.setTexture2D(T.map||l,0),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0),E.onAfterRender(e,v,g,void 0,T,void 0)}}i.enable(t.CULL_FACE),i.reset()}}}nt.physical={uniforms:it.merge([nt.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},Object.assign(ot.prototype,{set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y},getParameter:function(e,t){return(t||new ie).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return(t||new ie).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new ie;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),st.prototype=Object.create(ce.prototype),st.prototype.constructor=st;var ht,lt,ut,pt,dt,ft,mt,vt=0;function gt(){Object.defineProperty(this,"id",{value:vt++}),this.uuid=te.generateUUID(),this.name="",this.type="Material",this.fog=!0,this.lights=!0,this.blending=1,this.side=0,this.flatShading=!1,this.vertexColors=0,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=100,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaTest=0,this.premultipliedAlpha=!1,this.overdraw=0,this.visible=!0,this.userData={},this.needsUpdate=!0}function yt(e){gt.call(this),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.setValues(e)}function xt(e){gt.call(this),this.type="MeshDistanceMaterial",this.referencePosition=new oe,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.lights=!1,this.setValues(e)}function bt(e,t){this.min=void 0!==e?e:new oe(1/0,1/0,1/0),this.max=void 0!==t?t:new oe(-1/0,-1/0,-1/0)}function wt(e,t){this.center=void 0!==e?e:new oe,this.radius=void 0!==t?t:0}function _t(e,t){this.normal=void 0!==e?e:new oe(1,0,0),this.constant=void 0!==t?t:0}function Mt(e,t,i,r,n,o){this.planes=[void 0!==e?e:new _t,void 0!==t?t:new _t,void 0!==i?i:new _t,void 0!==r?r:new _t,void 0!==n?n:new _t,void 0!==o?o:new _t]}function Et(e,t,i){for(var r=new Mt,n=new re,o=new ie,a=new ie(i,i),s=new oe,c=new oe,h=new Array(4),l=new Array(4),u={},p=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],d=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)],f=[new he,new he,new he,new he,new he,new he],m=0;4!==m;++m){var v=0!=(1&m),g=0!=(2&m),y=new yt({depthPacking:3201,morphTargets:v,skinning:g});h[m]=y;var x=new xt({morphTargets:v,skinning:g});l[m]=x}var b=this;function w(t,i,r,n,o,a){var s=t.geometry,c=null,p=h,d=t.customDepthMaterial;if(r&&(p=l,d=t.customDistanceMaterial),d)c=d;else{var f=!1;i.morphTargets&&(s&&s.isBufferGeometry?f=s.morphAttributes&&s.morphAttributes.position&&s.morphAttributes.position.length>0:s&&s.isGeometry&&(f=s.morphTargets&&s.morphTargets.length>0)),t.isSkinnedMesh&&!1===i.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t);var m=0;f&&(m|=1),t.isSkinnedMesh&&i.skinning&&(m|=2),c=p[m]}if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var v=c.uuid,g=i.uuid,y=u[v];void 0===y&&(y={},u[v]=y);var x=y[g];void 0===x&&(x=c.clone(),y[g]=x),c=x}c.visible=i.visible,c.wireframe=i.wireframe;var w=i.side;return b.renderSingleSided&&2==w&&(w=0),b.renderReverseSided&&(0===w?w=1:1===w&&(w=0)),c.side=w,c.clipShadows=i.clipShadows,c.clippingPlanes=i.clippingPlanes,c.clipIntersection=i.clipIntersection,c.wireframeLinewidth=i.wireframeLinewidth,c.linewidth=i.linewidth,r&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(n),c.nearDistance=o,c.farDistance=a),c}function _(i,n,o,a){if(!1!==i.visible){if(i.layers.test(n.layers)&&(i.isMesh||i.isLine||i.isPoints)&&i.castShadow&&(!i.frustumCulled||r.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(o.matrixWorldInverse,i.matrixWorld);var s=t.update(i),h=i.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u0&&(i.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(i.morphTargets=!0),!0===this.skinning&&(i.skinning=!0),!1===this.visible&&(i.visible=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),t){var n=r(e.textures),o=r(e.images);n.length>0&&(i.textures=n),o.length>0&&(i.images=o)}return i},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.lights=e.lights,this.blending=e.blending,this.side=e.side,this.flatShading=e.flatShading,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.premultipliedAlpha=e.premultipliedAlpha,this.overdraw=e.overdraw,this.visible=e.visible,this.userData=JSON.parse(JSON.stringify(e.userData)),this.clipShadows=e.clipShadows,this.clipIntersection=e.clipIntersection;var t=e.clippingPlanes,i=null;if(null!==t){var r=t.length;i=new Array(r);for(var n=0;n!==r;++n)i[n]=t[n].clone()}return this.clippingPlanes=i,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),yt.prototype=Object.create(gt.prototype),yt.prototype.constructor=yt,yt.prototype.isMeshDepthMaterial=!0,yt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.depthPacking=e.depthPacking,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this},xt.prototype=Object.create(gt.prototype),xt.prototype.constructor=xt,xt.prototype.isMeshDistanceMaterial=!0,xt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.referencePosition.copy(e.referencePosition),this.nearDistance=e.nearDistance,this.farDistance=e.farDistance,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this},Object.assign(bt.prototype,{isBox3:!0,set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromArray:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.length;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromBufferAttribute:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.count;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return(t||new oe).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:(lt=new oe,function(e){return this.clampPoint(e.center,lt),lt.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=e.constant&&i>=e.constant},clampPoint:function(e,t){return(t||new oe).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new oe;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),getBoundingSphere:function(){var e=new oe;return function(t){var i=t||new wt;return this.getCenter(i.center),i.radius=.5*this.getSize(e).length(),i}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:(ht=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],function(e){return this.isEmpty()||(ht[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),ht[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),ht[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),ht[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),ht[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),ht[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),ht[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),ht[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(ht)),this}),translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),Object.assign(wt.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(ut=new bt,function(e,t){var i=this.center;void 0!==t?i.copy(t):ut.setFromPoints(e).getCenter(i);for(var r=0,n=0,o=e.length;nthis.radius*this.radius&&(r.sub(this.center).normalize(),r.multiplyScalar(this.radius).add(this.center)),r},getBoundingBox:function(e){var t=e||new bt;return t.set(this.center,this.center),t.expandByScalar(this.radius),t},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}}),Object.assign(_t.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(){var e=new oe,t=new oe;return function(i,r,n){var o=e.subVectors(n,r).cross(t.subVectors(i,r)).normalize();return this.setFromNormalAndCoplanarPoint(o,i),this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return(t||new oe).copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(){var e=new oe;return function(t,i){var r=i||new oe,n=t.delta(e),o=this.normal.dot(n);if(0===o)return 0===this.distanceToPoint(t.start)?r.copy(t.start):void 0;var a=-(t.start.dot(this.normal)+this.constant)/o;return a<0||a>1?void 0:r.copy(n).multiplyScalar(a).add(t.start)}}(),intersectsLine:function(e){var t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return(e||new oe).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var e=new oe,t=new ae;return function(i,r){var n=r||t.getNormalMatrix(i),o=this.coplanarPoint(e).applyMatrix4(i),a=this.normal.applyMatrix3(n).normalize();return this.constant=-o.dot(a),this}}(),translate:function(e){return this.constant-=e.dot(this.normal),this},equals:function(e){return e.normal.equals(this.normal)&&e.constant===this.constant}}),Object.assign(Mt.prototype,{set:function(e,t,i,r,n,o){var a=this.planes;return a[0].copy(e),a[1].copy(t),a[2].copy(i),a[3].copy(r),a[4].copy(n),a[5].copy(o),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,i=0;i<6;i++)t[i].copy(e.planes[i]);return this},setFromMatrix:function(e){var t=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],s=i[4],c=i[5],h=i[6],l=i[7],u=i[8],p=i[9],d=i[10],f=i[11],m=i[12],v=i[13],g=i[14],y=i[15];return t[0].setComponents(a-r,l-s,f-u,y-m).normalize(),t[1].setComponents(a+r,l+s,f+u,y+m).normalize(),t[2].setComponents(a+n,l+c,f+p,y+v).normalize(),t[3].setComponents(a-n,l-c,f-p,y-v).normalize(),t[4].setComponents(a-o,l-h,f-d,y-g).normalize(),t[5].setComponents(a+o,l+h,f+d,y+g).normalize(),this},intersectsObject:(ft=new wt,function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),ft.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(ft)}),intersectsSprite:function(){var e=new wt;return function(t){return e.center.set(0,0,0),e.radius=.7071067811865476,e.applyMatrix4(t.matrixWorld),this.intersectsSphere(e)}}(),intersectsSphere:function(e){for(var t=this.planes,i=e.center,r=-e.radius,n=0;n<6;n++){if(t[n].distanceToPoint(i)0?e.min.x:e.max.x,dt.x=r.normal.x>0?e.max.x:e.min.x,pt.y=r.normal.y>0?e.min.y:e.max.y,dt.y=r.normal.y>0?e.max.y:e.min.y,pt.z=r.normal.z>0?e.min.z:e.max.z,dt.z=r.normal.z>0?e.max.z:e.min.z;var n=r.distanceToPoint(pt),o=r.distanceToPoint(dt);if(n<0&&o<0)return!1}return!0}),containsPoint:function(e){for(var t=this.planes,i=0;i<6;i++)if(t[i].distanceToPoint(e)<0)return!1;return!0}}),St.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],St.DefaultOrder="XYZ",Object.defineProperties(St.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},order:{get:function(){return this._order},set:function(e){this._order=e,this.onChangeCallback()}}}),Object.assign(St.prototype,{isEuler:!0,set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._order=r||this._order,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)},copy:function(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this.onChangeCallback(),this},setFromRotationMatrix:function(e,t,i){var r=te.clamp,n=e.elements,o=n[0],a=n[4],s=n[8],c=n[1],h=n[5],l=n[9],u=n[2],p=n[6],d=n[10];return"XYZ"===(t=t||this._order)?(this._y=Math.asin(r(s,-1,1)),Math.abs(s)<.99999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-a,o)):(this._x=Math.atan2(p,h),this._z=0)):"YXZ"===t?(this._x=Math.asin(-r(l,-1,1)),Math.abs(l)<.99999?(this._y=Math.atan2(s,d),this._z=Math.atan2(c,h)):(this._y=Math.atan2(-u,o),this._z=0)):"ZXY"===t?(this._x=Math.asin(r(p,-1,1)),Math.abs(p)<.99999?(this._y=Math.atan2(-u,d),this._z=Math.atan2(-a,h)):(this._y=0,this._z=Math.atan2(c,o))):"ZYX"===t?(this._y=Math.asin(-r(u,-1,1)),Math.abs(u)<.99999?(this._x=Math.atan2(p,d),this._z=Math.atan2(c,o)):(this._x=0,this._z=Math.atan2(-a,h))):"YZX"===t?(this._z=Math.asin(r(c,-1,1)),Math.abs(c)<.99999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-u,o)):(this._x=0,this._y=Math.atan2(s,d))):"XZY"===t?(this._z=Math.asin(-r(a,-1,1)),Math.abs(a)<.99999?(this._x=Math.atan2(p,h),this._y=Math.atan2(s,o)):(this._x=Math.atan2(-l,d),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+t),this._order=t,!1!==i&&this.onChangeCallback(),this},setFromQuaternion:function(){var e=new re;return function(t,i,r){return e.makeRotationFromQuaternion(t),this.setFromRotationMatrix(e,i,r)}}(),setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:(mt=new ne,function(e){return mt.setFromEuler(this),this.setFromQuaternion(mt,e)}),equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order},fromArray:function(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e},toVector3:function(e){return e?e.set(this._x,this._y,this._z):new oe(this._x,this._y,this._z)},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(At.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){r.children=[];for(s=0;s0&&(i.geometries=u),p.length>0&&(i.materials=p),d.length>0&&(i.textures=d),f.length>0&&(i.images=f),a.length>0&&(i.shapes=a)}return i.object=r,i;function m(e){var t=[];for(var i in e){var r=e[i];delete r.metadata,t.push(r)}return t}},clone:function(e){return(new this.constructor).copy(this,e)},copy:function(e,t){if(void 0===t&&(t=!0),this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(var i=0;it&&(t=e[i]);return t}zt.prototype=Object.assign(Object.create(n.prototype),{constructor:zt,isGeometry:!0,applyMatrix:function(e){for(var t=(new ae).getNormalMatrix(e),i=0,r=this.vertices.length;i0)for(p=0;p0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,i;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,i,r,n;for(i=0,r=this.faces.length;i0&&(e+=t[i].distanceTo(t[i-1])),this.lineDistances[i]=e},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt),this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new wt),this.boundingSphere.setFromPoints(this.vertices)},merge:function(e,t,i){if(e&&e.isGeometry){var r,n=this.vertices.length,o=this.vertices,a=e.vertices,s=this.faces,c=e.faces,h=this.faceVertexUvs[0],l=e.faceVertexUvs[0],u=this.colors,p=e.colors;void 0===i&&(i=0),void 0!==t&&(r=(new ae).getNormalMatrix(t));for(var d=0,f=a.length;d=0;i--){var f=p[i];for(this.faces.splice(f,1),a=0,s=this.faceVertexUvs.length;a0,v=d.vertexNormals.length>0,g=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,v),x=M(x,6,g),x=M(x,7,y),a.push(x),a.push(d.a,d.b,d.c),a.push(d.materialIndex),f){var b=this.faceVertexUvs[0][n];a.push(S(b[0]),S(b[1]),S(b[2]))}if(m&&a.push(E(d.normal)),v){var w=d.vertexNormals;a.push(E(w[0]),E(w[1]),E(w[2]))}if(g&&a.push(T(d.color)),y){var _=d.vertexColors;a.push(T(_[0]),T(_[1]),T(_[2]))}}function M(e,t,i){return i?e|1<0&&(e.data.colors=h),u.length>0&&(e.data.uvs=[u]),e.data.faces=a,e},clone:function(){return(new zt).copy(this)},copy:function(e){var t,i,r,n,o,a;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var s=e.vertices;for(t=0,i=s.length;t0,a=n[1]&&n[1].length>0,s=e.morphTargets,c=s.length;if(c>0){t=[];for(var h=0;h0){l=[];for(h=0;h0?1:-1,h.push(R.x,R.y,R.z),l.push(y/m),l.push(1-x/v),A+=1}}for(x=0;x1&&i.sort(yi),r.length>1&&r.sort(xi)}}}function wi(){var e={};return{get:function(t,i){var r=t.id+","+i.id,n=e[r];return void 0===n&&(n=new bi,e[r]=n),n},dispose:function(){e={}}}}function _i(e,t){return Math.abs(t[1])-Math.abs(e[1])}function Mi(e){var t={},i=new Float32Array(8);return{update:function(r,n,o,a){var s=r.morphTargetInfluences,c=s.length,h=t[n.id];if(void 0===h){h=[];for(var l=0;l65535?qt:Wt)(a,1),t.update(r,e.ELEMENT_ARRAY_BUFFER),n[i.id]=r,r}}}function Ai(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var i;switch(t.type){case"DirectionalLight":i={direction:new oe,color:new et,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"SpotLight":i={position:new oe,direction:new oe,color:new et,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"PointLight":i={position:new oe,color:new et,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":i={direction:new oe,skyColor:new et,groundColor:new et};break;case"RectAreaLight":i={color:new et,position:new oe,halfWidth:new oe,halfHeight:new oe}}return e[t.id]=i,i}}}function Li(){var e=new Ai,t={hash:"",ambient:[0,0,0],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},i=new oe,r=new re,n=new re;return{setup:function(o,a,s){for(var c=0,h=0,l=0,u=0,p=0,d=0,f=0,m=0,v=s.matrixWorldInverse,g=0,y=o.length;g65535?qt:Wt)(e,1):this.index=e},addAttribute:function(e,t){return t&&t.isBufferAttribute||t&&t.isInterleavedBufferAttribute?"index"===e?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),void this.setIndex(t)):(this.attributes[e]=t,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),void this.addAttribute(e,new kt(arguments[1],arguments[2])))},getAttribute:function(e){return this.attributes[e]},removeAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,i){this.groups.push({start:e,count:t,materialIndex:void 0!==i?i:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix:function(e){var t=this.attributes.position;void 0!==t&&(e.applyToBufferAttribute(t),t.needsUpdate=!0);var i=this.attributes.normal;void 0!==i&&((new ae).getNormalMatrix(e).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var e=new re;return function(t){return e.makeRotationX(t),this.applyMatrix(e),this}}(),rotateY:function(){var e=new re;return function(t){return e.makeRotationY(t),this.applyMatrix(e),this}}(),rotateZ:function(){var e=new re;return function(t){return e.makeRotationZ(t),this.applyMatrix(e),this}}(),translate:function(){var e=new re;return function(t,i,r){return e.makeTranslation(t,i,r),this.applyMatrix(e),this}}(),scale:function(){var e=new re;return function(t,i,r){return e.makeScale(t,i,r),this.applyMatrix(e),this}}(),lookAt:function(){var e=new Ot;return function(t){e.lookAt(t),e.updateMatrix(),this.applyMatrix(e.matrix)}}(),center:function(){this.computeBoundingBox();var e=this.boundingBox.getCenter().negate();return this.translate(e.x,e.y,e.z),e},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var i=new Yt(3*t.vertices.length,3),r=new Yt(3*t.colors.length,3);if(this.addAttribute("position",i.copyVector3sArray(t.vertices)),this.addAttribute("color",r.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var n=new Yt(t.lineDistances.length,1);this.addAttribute("lineDistance",n.copyArray(t.lineDistances))}null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone())}else e.isMesh&&t&&t.isGeometry&&this.fromGeometry(t);return this},setFromPoints:function(e){for(var t=[],i=0,r=e.length;i0){var i=new Float32Array(3*e.normals.length);this.addAttribute("normal",new kt(i,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var r=new Float32Array(3*e.colors.length);this.addAttribute("color",new kt(r,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var n=new Float32Array(2*e.uvs.length);this.addAttribute("uv",new kt(n,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var o=new Float32Array(2*e.uvs2.length);this.addAttribute("uv2",new kt(o,2).copyVector2sArray(e.uvs2))}if(e.indices.length>0){var a=new(Kt(e.indices)>65535?Uint32Array:Uint16Array)(3*e.indices.length);this.setIndex(new kt(a,1).copyIndicesArray(e.indices))}for(var s in this.groups=e.groups,e.morphTargets){for(var c=[],h=e.morphTargets[s],l=0,u=h.length;l0){var f=new Yt(4*e.skinIndices.length,4);this.addAttribute("skinIndex",f.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var m=new Yt(4*e.skinWeights.length,4);this.addAttribute("skinWeight",m.copyVector4sArray(e.skinWeights))}return null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone()),this},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt);var e=this.attributes.position;void 0!==e?this.boundingBox.setFromBufferAttribute(e):this.boundingBox.makeEmpty(),(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:function(){var e=new bt,t=new oe;return function(){null===this.boundingSphere&&(this.boundingSphere=new wt);var i=this.attributes.position;if(i){var r=this.boundingSphere.center;e.setFromBufferAttribute(i),e.getCenter(r);for(var n=0,o=0,a=i.count;o0&&(e.data.groups=JSON.parse(JSON.stringify(s)));var c=this.boundingSphere;return null!==c&&(e.data.boundingSphere={center:c.center.toArray(),radius:c.radius}),e},clone:function(){return(new ai).copy(this)},copy:function(e){var t,i,r;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var n=e.index;null!==n&&this.setIndex(n.clone());var o=e.attributes;for(t in o){var a=o[t];this.addAttribute(t,a.clone())}var s=e.morphAttributes;for(t in s){var c=[],h=s[t];for(i=0,r=h.length;i0)if(o=h*l-u,s=c*d,(n=h*u-l)>=0)if(o>=-s)if(o<=s){var f=1/d;a=(n*=f)*(n+h*(o*=f)+2*l)+o*(h*n+o+2*u)+p}else o=c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o=-c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o<=-s?a=-(n=Math.max(0,-(-h*c+l)))*n+(o=n>0?-c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p:o<=s?(n=0,a=(o=Math.min(Math.max(-c,-u),c))*(o+2*u)+p):a=-(n=Math.max(0,-(h*c+l)))*n+(o=n>0?c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p;else o=h>0?-c:c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;return i&&i.copy(this.direction).multiplyScalar(n).add(this.origin),r&&r.copy(ei).multiplyScalar(o).add($t),a}),intersectSphere:function(){var e=new oe;return function(t,i){e.subVectors(t.center,this.origin);var r=e.dot(this.direction),n=e.dot(e)-r*r,o=t.radius*t.radius;if(n>o)return null;var a=Math.sqrt(o-n),s=r-a,c=r+a;return s<0&&c<0?null:s<0?this.at(c,i):this.at(s,i)}}(),intersectsSphere:function(e){return this.distanceToPoint(e.center)<=e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null},intersectPlane:function(e,t){var i=this.distanceToPlane(e);return null===i?null:this.at(i,t)},intersectsPlane:function(e){var t=e.distanceToPoint(this.origin);return 0===t||e.normal.dot(this.direction)*t<0},intersectBox:function(e,t){var i,r,n,o,a,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(i=(e.min.x-u.x)*c,r=(e.max.x-u.x)*c):(i=(e.max.x-u.x)*c,r=(e.min.x-u.x)*c),h>=0?(n=(e.min.y-u.y)*h,o=(e.max.y-u.y)*h):(n=(e.max.y-u.y)*h,o=(e.min.y-u.y)*h),i>o||n>r?null:((n>i||i!=i)&&(i=n),(o=0?(a=(e.min.z-u.z)*l,s=(e.max.z-u.z)*l):(a=(e.max.z-u.z)*l,s=(e.min.z-u.z)*l),i>s||a>r?null:((a>i||i!=i)&&(i=a),(s=0?i:r,t)))},intersectsBox:(Qt=new oe,function(e){return null!==this.intersectBox(e,Qt)}),intersectTriangle:function(){var e=new oe,t=new oe,i=new oe,r=new oe;return function(n,o,a,s,c){t.subVectors(o,n),i.subVectors(a,n),r.crossVectors(t,i);var h,l=this.direction.dot(r);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}e.subVectors(this.origin,n);var u=h*this.direction.dot(i.crossVectors(e,i));if(u<0)return null;var p=h*this.direction.dot(t.cross(e));if(p<0)return null;if(u+p>l)return null;var d=-h*e.dot(r);return d<0?null:this.at(d/l,c)}}(),applyMatrix4:function(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this},equals:function(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}}),Object.assign(fi.prototype,{set:function(e,t){return this.start.copy(e),this.end.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.start.copy(e.start),this.end.copy(e.end),this},getCenter:function(e){return(e||new oe).addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(e){return(e||new oe).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(e,t){var i=t||new oe;return this.delta(i).multiplyScalar(e).add(this.start)},closestPointToPointParameter:(ii=new oe,ri=new oe,function(e,t){ii.subVectors(e,this.start),ri.subVectors(this.end,this.start);var i=ri.dot(ri),r=ri.dot(ii)/i;return t&&(r=te.clamp(r,0,1)),r}),closestPointToPoint:function(e,t,i){var r=this.closestPointToPointParameter(e,t),n=i||new oe;return this.delta(n).multiplyScalar(r).add(this.start)},applyMatrix4:function(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this},equals:function(e){return e.start.equals(this.start)&&e.end.equals(this.end)}}),Object.assign(mi,{normal:(ni=new oe,function(e,t,i,r){var n=r||new oe;n.subVectors(i,t),ni.subVectors(e,t),n.cross(ni);var o=n.lengthSq();return o>0?n.multiplyScalar(1/Math.sqrt(o)):n.set(0,0,0)}),barycoordFromPoint:function(){var e=new oe,t=new oe,i=new oe;return function(r,n,o,a,s){e.subVectors(a,n),t.subVectors(o,n),i.subVectors(r,n);var c=e.dot(e),h=e.dot(t),l=e.dot(i),u=t.dot(t),p=t.dot(i),d=c*u-h*h,f=s||new oe;if(0===d)return f.set(-2,-1,-1);var m=1/d,v=(u*l-h*p)*m,g=(c*p-h*l)*m;return f.set(1-v-g,g,v)}}(),containsPoint:function(){var e=new oe;return function(t,i,r,n){var o=mi.barycoordFromPoint(t,i,r,n,e);return o.x>=0&&o.y>=0&&o.x+o.y<=1}}()}),Object.assign(mi.prototype,{set:function(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this},setFromPointsAndIndices:function(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this},area:function(){var e=new oe,t=new oe;return function(){return e.subVectors(this.c,this.b),t.subVectors(this.a,this.b),.5*e.cross(t).length()}}(),midpoint:function(e){return(e||new oe).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(e){return mi.normal(this.a,this.b,this.c,e)},plane:function(e){return(e||new _t).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(e,t){return mi.barycoordFromPoint(e,this.a,this.b,this.c,t)},containsPoint:function(e){return mi.containsPoint(e,this.a,this.b,this.c)},closestPointToPoint:function(){var e=new _t,t=[new fi,new fi,new fi],i=new oe,r=new oe;return function(n,o){var a=o||new oe,s=1/0;if(e.setFromCoplanarPoints(this.a,this.b,this.c),e.projectPoint(n,i),!0===this.containsPoint(i))a.copy(i);else{t[0].set(this.a,this.b),t[1].set(this.b,this.c),t[2].set(this.c,this.a);for(var c=0;c0){var a=n[o[0]];if(void 0!==a)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=a.length;e0)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=s.length;ei.far?null:{distance:c,point:f.clone(),object:e}}function g(e,t,i,a,s,c,p,f){r.fromBufferAttribute(a,c),n.fromBufferAttribute(a,p),o.fromBufferAttribute(a,f);var g=v(e,e.material,t,i,r,n,o,d);return g&&(s&&(h.fromBufferAttribute(s,c),l.fromBufferAttribute(s,p),u.fromBufferAttribute(s,f),g.uv=m(d,r,n,o,h,l,u)),g.face=new Ut(c,p,f,mi.normal(r,n,o)),g.faceIndex=c),g}return function(p,f){var y,x=this.geometry,b=this.material,w=this.matrixWorld;if(void 0!==b&&(null===x.boundingSphere&&x.computeBoundingSphere(),i.copy(x.boundingSphere),i.applyMatrix4(w),!1!==p.ray.intersectsSphere(i)&&(e.getInverse(w),t.copy(p.ray).applyMatrix4(e),null===x.boundingBox||!1!==t.intersectsBox(x.boundingBox))))if(x.isBufferGeometry){var _,M,E,T,S,A=x.index,L=x.attributes.position,R=x.attributes.uv;if(null!==A)for(T=0,S=A.count;T0&&(O=B);for(var F=0,z=U.length;F/gm,(function(e,t){var i=rt[t];if(void 0===i)throw new Error("Can not resolve #include <"+t+">");return ji(i)}))}function Hi(e){return e.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,(function(e,t,i,r){for(var n="",o=parseInt(t);o0?e.gammaFactor:1,T=function(e,t,i){return[(e=e||{}).derivatives||t.envMapCubeUV||t.bumpMap||t.normalMap||t.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(e.fragDepth||t.logarithmicDepthBuffer)&&i.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",e.drawBuffers&&i.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(e.shaderTextureLOD||t.envMap)&&i.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Gi).join("\n")}(r.extensions,o,t),S=function(e){var t=[];for(var i in e){var r=e[i];!1!==r&&t.push("#define "+i+" "+r)}return t.join("\n")}(s),A=a.createProgram();r.isRawShaderMaterial?((f=[S].filter(Gi).join("\n")).length>0&&(f+="\n"),(b=[T,S].filter(Gi).join("\n")).length>0&&(b+="\n")):(f=["precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+E,"#define MAX_BONES "+o.maxBones,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+p:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.displacementMap&&o.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.flatShading?"#define FLAT_SHADED":"",o.skinning?"#define USE_SKINNING":"",o.useVertexTexture?"#define BONE_TEXTURE":"",o.morphTargets?"#define USE_MORPHTARGETS":"",o.morphNormals&&!1===o.flatShading?"#define USE_MORPHNORMALS":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.sizeAttenuation?"#define USE_SIZEATTENUATION":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Gi).join("\n"),b=[T,"precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.alphaTest?"#define ALPHATEST "+o.alphaTest:"","#define GAMMA_FACTOR "+E,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+u:"",o.envMap?"#define "+p:"",o.envMap?"#define "+d:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.gradientMap?"#define USE_GRADIENTMAP":"",o.flatShading?"#define FLAT_SHADED":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,"#define UNION_CLIPPING_PLANES "+(o.numClippingPlanes-o.numClipIntersection),o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",o.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"",o.envMap&&t.get("EXT_shader_texture_lod")?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",0!==o.toneMapping?"#define TONE_MAPPING":"",0!==o.toneMapping?rt.tonemapping_pars_fragment:"",0!==o.toneMapping?ki("toneMapping",o.toneMapping):"",o.dithering?"#define DITHERING":"",o.outputEncoding||o.mapEncoding||o.envMapEncoding||o.emissiveMapEncoding?rt.encodings_pars_fragment:"",o.mapEncoding?zi("mapTexelToLinear",o.mapEncoding):"",o.envMapEncoding?zi("envMapTexelToLinear",o.envMapEncoding):"",o.emissiveMapEncoding?zi("emissiveMapTexelToLinear",o.emissiveMapEncoding):"",o.outputEncoding?(w="linearToOutputTexel",_=o.outputEncoding,M=Fi(_),"vec4 "+w+"( vec4 value ) { return LinearTo"+M[0]+M[1]+"; }"):"",o.depthPacking?"#define DEPTH_PACKING "+r.depthPacking:"","\n"].filter(Gi).join("\n")),c=Vi(c=ji(c),o),h=Vi(h=ji(h),o),r.isShaderMaterial||(c=Hi(c),h=Hi(h));var L=f+c,R=b+h,C=Ci(a,a.VERTEX_SHADER,L),P=Ci(a,a.FRAGMENT_SHADER,R);a.attachShader(A,C),a.attachShader(A,P),void 0!==r.index0AttributeName?a.bindAttribLocation(A,0,r.index0AttributeName):!0===o.morphTargets&&a.bindAttribLocation(A,0,"position"),a.linkProgram(A);var N,O,I=a.getProgramInfoLog(A),D=a.getShaderInfoLog(C),U=a.getShaderInfoLog(P),B=!0,F=!0;return!1===a.getProgramParameter(A,a.LINK_STATUS)?(B=!1,console.error("THREE.WebGLProgram: shader error: ",a.getError(),"gl.VALIDATE_STATUS",a.getProgramParameter(A,a.VALIDATE_STATUS),"gl.getProgramInfoLog",I,D,U)):""!==I?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",I):""!==D&&""!==U||(F=!1),F&&(this.diagnostics={runnable:B,material:r,programLog:I,vertexShader:{log:D,prefix:f},fragmentShader:{log:U,prefix:b}}),a.deleteShader(C),a.deleteShader(P),this.getUniforms=function(){return void 0===N&&(N=new Qe(a,A,e)),N},this.getAttributes=function(){return void 0===O&&(O=function(e,t){for(var i={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;n0,maxBones:p,useVertexTexture:i.floatVertexTextures,morphTargets:t.morphTargets,morphNormals:t.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:r.directional.length,numPointLights:r.point.length,numSpotLights:r.spot.length,numRectAreaLights:r.rectArea.length,numHemiLights:r.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:t.dithering,shadowMapEnabled:e.shadowMap.enabled&&l.receiveShadow&&o.length>0,shadowMapType:e.shadowMap.type,toneMapping:e.toneMapping,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:t.premultipliedAlpha,alphaTest:t.alphaTest,doubleSided:2===t.side,flipSided:1===t.side,depthPacking:void 0!==t.depthPacking&&t.depthPacking}},this.getProgramCode=function(t,i){var r=[];if(i.shaderID?r.push(i.shaderID):(r.push(t.fragmentShader),r.push(t.vertexShader)),void 0!==t.defines)for(var n in t.defines)r.push(n),r.push(t.defines[n]);for(var a=0;at||e.height>t){var i=t/Math.max(e.width,e.height),r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return r.width=Math.floor(e.width*i),r.height=Math.floor(e.height*i),r.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,r.width,r.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+r.width+"x"+r.height,e),r}return e}function l(e){return te.isPowerOfTwo(e.width)&&te.isPowerOfTwo(e.height)}function u(e,t){return e.generateMipmaps&&t&&e.minFilter!==M&&e.minFilter!==S}function p(t){return t===M||t===E||t===T?e.NEAREST:e.LINEAR}function d(t){var i=t.target;i.removeEventListener("dispose",d),function(t){var i=r.get(t);if(t.image&&i.__image__webglTextureCube)e.deleteTexture(i.__image__webglTextureCube);else{if(void 0===i.__webglInit)return;e.deleteTexture(i.__webglTexture)}r.remove(t)}(i),i.isVideoTexture&&delete c[i.id],a.textures--}function f(t){var i=t.target;i.removeEventListener("dispose",f),function(t){var i=r.get(t),n=r.get(t.texture);if(!t)return;void 0!==n.__webglTexture&&e.deleteTexture(n.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLRenderTargetCube)for(var o=0;o<6;o++)e.deleteFramebuffer(i.__webglFramebuffer[o]),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer[o]);else e.deleteFramebuffer(i.__webglFramebuffer),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer);r.remove(t.texture),r.remove(t)}(i),a.textures--}function m(t,p){var f=r.get(t);if(t.version>0&&f.__version!==t.version){var m=t.image;if(void 0===m)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined",t);else{if(!1!==m.complete)return void function(t,r,p){void 0===t.__webglInit&&(t.__webglInit=!0,r.addEventListener("dispose",d),t.__webglTexture=e.createTexture(),r.isVideoTexture&&(c[r.id]=r),a.textures++);i.activeTexture(e.TEXTURE0+p),i.bindTexture(e.TEXTURE_2D,t.__webglTexture),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,r.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,r.unpackAlignment);var f=h(r.image,n.maxTextureSize);(function(e){return e.wrapS!==w||e.wrapT!==w||e.minFilter!==M&&e.minFilter!==S})(r)&&!1===l(f)&&(f=function(e){if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement||e instanceof ImageBitmap){var t=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return t.width=te.floorPowerOfTwo(e.width),t.height=te.floorPowerOfTwo(e.height),t.getContext("2d").drawImage(e,0,0,t.width,t.height),console.warn("THREE.WebGLRenderer: image is not power of two ("+e.width+"x"+e.height+"). Resized to "+t.width+"x"+t.height,e),t}return e}(f));var m=l(f),g=o.convert(r.format),y=o.convert(r.type);v(e.TEXTURE_2D,r,m);var x,b=r.mipmaps;if(r.isDepthTexture){var _=e.DEPTH_COMPONENT;if(r.type===N){if(!s)throw new Error("Float Depth Texture only supported in WebGL2.0");_=e.DEPTH_COMPONENT32F}else s&&(_=e.DEPTH_COMPONENT16);r.format===B&&_===e.DEPTH_COMPONENT&&r.type!==C&&r.type!==P&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=C,y=o.convert(r.type)),r.format===F&&(_=e.DEPTH_STENCIL,r.type!==I&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=I,y=o.convert(r.type))),i.texImage2D(e.TEXTURE_2D,0,_,f.width,f.height,0,g,y,null)}else if(r.isDataTexture)if(b.length>0&&m){for(var E=0,T=b.length;E-1?i.compressedTexImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):i.texImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,g,y,x.data);else if(b.length>0&&m){for(E=0,T=b.length;E1||r.get(a).__currentAnisotropy)&&(e.texParameterf(i,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,n.getMaxAnisotropy())),r.get(a).__currentAnisotropy=a.anisotropy)}}function g(t,n,a,s){var c=o.convert(n.texture.format),h=o.convert(n.texture.type);i.texImage2D(s,0,c,n.width,n.height,0,c,h,null),e.bindFramebuffer(e.FRAMEBUFFER,t),e.framebufferTexture2D(e.FRAMEBUFFER,a,s,r.get(n.texture).__webglTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}function y(t,i){e.bindRenderbuffer(e.RENDERBUFFER,t),i.depthBuffer&&!i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t)):i.depthBuffer&&i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t)):e.renderbufferStorage(e.RENDERBUFFER,e.RGBA4,i.width,i.height),e.bindRenderbuffer(e.RENDERBUFFER,null)}function x(t){var i=r.get(t),n=!0===t.isWebGLRenderTargetCube;if(t.depthTexture){if(n)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,i){if(i&&i.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(e.bindFramebuffer(e.FRAMEBUFFER,t),!i.depthTexture||!i.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");r.get(i.depthTexture).__webglTexture&&i.depthTexture.image.width===i.width&&i.depthTexture.image.height===i.height||(i.depthTexture.image.width=i.width,i.depthTexture.image.height=i.height,i.depthTexture.needsUpdate=!0),m(i.depthTexture,0);var n=r.get(i.depthTexture).__webglTexture;if(i.depthTexture.format===B)e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,n,0);else{if(i.depthTexture.format!==F)throw new Error("Unknown depthTexture format");e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,n,0)}}(i.__webglFramebuffer,t)}else if(n){i.__webglDepthbuffer=[];for(var o=0;o<6;o++)e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[o]),i.__webglDepthbuffer[o]=e.createRenderbuffer(),y(i.__webglDepthbuffer[o],t)}else e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer=e.createRenderbuffer(),y(i.__webglDepthbuffer,t);e.bindFramebuffer(e.FRAMEBUFFER,null)}this.setTexture2D=m,this.setTextureCube=function(t,s){var c=r.get(t);if(6===t.image.length)if(t.version>0&&c.__version!==t.version){c.__image__webglTextureCube||(t.addEventListener("dispose",d),c.__image__webglTextureCube=e.createTexture(),a.textures++),i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,t.flipY);for(var p=t&&t.isCompressedTexture,f=t.image[0]&&t.image[0].isDataTexture,m=[],g=0;g<6;g++)m[g]=p||f?f?t.image[g].image:t.image[g]:h(t.image[g],n.maxCubemapSize);var y=l(m[0]),x=o.convert(t.format),b=o.convert(t.type);v(e.TEXTURE_CUBE_MAP,t,y);for(g=0;g<6;g++)if(p)for(var w,_=m[g].mipmaps,M=0,E=_.length;M-1?i.compressedTexImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,w.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,x,b,w.data);else f?i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,m[g].width,m[g].height,0,x,b,m[g].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,x,b,m[g]);u(t,y)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),c.__version=t.version,t.onUpdate&&t.onUpdate(t)}else i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube)},this.setTextureCubeDynamic=function(t,n){i.activeTexture(e.TEXTURE0+n),i.bindTexture(e.TEXTURE_CUBE_MAP,r.get(t).__webglTexture)},this.setupRenderTarget=function(t){var n=r.get(t),o=r.get(t.texture);t.addEventListener("dispose",f),o.__webglTexture=e.createTexture(),a.textures++;var s=!0===t.isWebGLRenderTargetCube,c=l(t);if(s){n.__webglFramebuffer=[];for(var h=0;h<6;h++)n.__webglFramebuffer[h]=e.createFramebuffer()}else n.__webglFramebuffer=e.createFramebuffer();if(s){i.bindTexture(e.TEXTURE_CUBE_MAP,o.__webglTexture),v(e.TEXTURE_CUBE_MAP,t.texture,c);for(h=0;h<6;h++)g(n.__webglFramebuffer[h],t,e.COLOR_ATTACHMENT0,e.TEXTURE_CUBE_MAP_POSITIVE_X+h);u(t.texture,c)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),i.bindTexture(e.TEXTURE_CUBE_MAP,null)}else i.bindTexture(e.TEXTURE_2D,o.__webglTexture),v(e.TEXTURE_2D,t.texture,c),g(n.__webglFramebuffer,t,e.COLOR_ATTACHMENT0,e.TEXTURE_2D),u(t.texture,c)&&e.generateMipmap(e.TEXTURE_2D),i.bindTexture(e.TEXTURE_2D,null);t.depthBuffer&&x(t)},this.updateRenderTargetMipmap=function(t){var n=t.texture;if(u(n,l(t))){var o=t.isWebGLRenderTargetCube?e.TEXTURE_CUBE_MAP:e.TEXTURE_2D,a=r.get(n).__webglTexture;i.bindTexture(o,a),e.generateMipmap(o),i.bindTexture(o,null)}},this.updateVideoTextures=function(){for(var e in c)c[e].update()}}function Yi(){var e={};return{get:function(t){var i=t.uuid,r=e[i];return void 0===r&&(r={},e[i]=r),r},remove:function(t){delete e[t.uuid]},clear:function(){e={}}}}function Zi(e,t,i){var r=new function(){var t=!1,i=new he,r=null,n=new he(0,0,0,0);return{setMask:function(i){r===i||t||(e.colorMask(i,i,i,i),r=i)},setLocked:function(e){t=e},setClear:function(t,r,o,a,s){!0===s&&(t*=a,r*=a,o*=a),i.set(t,r,o,a),!1===n.equals(i)&&(e.clearColor(t,r,o,a),n.copy(i))},reset:function(){t=!1,r=null,n.set(-1,0,0,0)}}},n=new function(){var t=!1,i=null,r=null,n=null;return{setTest:function(t){t?D(e.DEPTH_TEST):U(e.DEPTH_TEST)},setMask:function(r){i===r||t||(e.depthMask(r),i=r)},setFunc:function(t){if(r!==t){if(t)switch(t){case 0:e.depthFunc(e.NEVER);break;case 1:e.depthFunc(e.ALWAYS);break;case 2:e.depthFunc(e.LESS);break;case 3:default:e.depthFunc(e.LEQUAL);break;case 4:e.depthFunc(e.EQUAL);break;case 5:e.depthFunc(e.GEQUAL);break;case 6:e.depthFunc(e.GREATER);break;case 7:e.depthFunc(e.NOTEQUAL)}else e.depthFunc(e.LEQUAL);r=t}},setLocked:function(e){t=e},setClear:function(t){n!==t&&(e.clearDepth(t),n=t)},reset:function(){t=!1,i=null,r=null,n=null}}},o=new function(){var t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null;return{setTest:function(t){t?D(e.STENCIL_TEST):U(e.STENCIL_TEST)},setMask:function(r){i===r||t||(e.stencilMask(r),i=r)},setFunc:function(t,i,a){r===t&&n===i&&o===a||(e.stencilFunc(t,i,a),r=t,n=i,o=a)},setOp:function(t,i,r){a===t&&s===i&&c===r||(e.stencilOp(t,i,r),a=t,s=i,c=r)},setLocked:function(e){t=e},setClear:function(t){h!==t&&(e.clearStencil(t),h=t)},reset:function(){t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null}}},a=e.getParameter(e.MAX_VERTEX_ATTRIBS),s=new Uint8Array(a),c=new Uint8Array(a),h=new Uint8Array(a),l={},u=null,p=null,d=null,f=null,m=null,v=null,g=null,y=null,x=null,b=!1,w=null,_=null,M=null,E=null,T=null,S=e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),A=parseFloat(/^WebGL\ ([0-9])/.exec(e.getParameter(e.VERSION))[1]),L=parseFloat(A)>=1,R=null,C={},P=new he,N=new he;function O(t,i,r){var n=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(var a=0;a0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}var o=void 0!==i.precision?i.precision:"highp",a=n(o);a!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",a,"instead."),o=a);var s=!0===i.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),l=e.getParameter(e.MAX_TEXTURE_SIZE),u=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),p=e.getParameter(e.MAX_VERTEX_ATTRIBS),d=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),f=e.getParameter(e.MAX_VARYING_VECTORS),m=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),v=h>0,g=!!t.get("OES_texture_float");return{getMaxAnisotropy:function(){if(void 0!==r)return r;var i=t.get("EXT_texture_filter_anisotropic");return r=null!==i?e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:n,precision:o,logarithmicDepthBuffer:s,maxTextures:c,maxVertexTextures:h,maxTextureSize:l,maxCubemapSize:u,maxAttributes:p,maxVertexUniforms:d,maxVaryings:f,maxFragmentUniforms:m,vertexTextures:v,floatFragmentTextures:g,floatVertexTextures:v&&g}}function Ki(e,t,i,r){It.call(this),this.type="PerspectiveCamera",this.fov=void 0!==e?e:50,this.zoom=1,this.near=void 0!==i?i:.1,this.far=void 0!==r?r:2e3,this.focus=10,this.aspect=void 0!==t?t:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qi(e){Ki.call(this),this.cameras=e||[]}function $i(e){var t=this,i=null,r=null,n=null;"undefined"!=typeof window&&"VRFrameData"in window&&(r=new window.VRFrameData);var o=new re,a=new Ki;a.bounds=new he(0,0,.5,1),a.layers.enable(1);var s=new Ki;s.bounds=new he(.5,0,.5,1),s.layers.enable(2);var c,h,l=new Qi([a,s]);function u(){if(null!==i&&i.isPresenting){var r=i.getEyeParameters("left"),n=r.renderWidth,o=r.renderHeight;h=e.getPixelRatio(),c=e.getSize(),e.setDrawingBufferSize(2*n,o,1)}else t.enabled&&e.setDrawingBufferSize(c.width,c.height,h)}l.layers.enable(1),l.layers.enable(2),"undefined"!=typeof window&&window.addEventListener("vrdisplaypresentchange",u,!1),this.enabled=!1,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e)},this.setPoseTarget=function(e){void 0!==e&&(n=e)},this.getCamera=function(e){if(null===i)return e;i.depthNear=e.near,i.depthFar=e.far,i.getFrameData(r);var t=r.pose,c=null!==n?n:e;if(null!==t.position?c.position.fromArray(t.position):c.position.set(0,0,0),null!==t.orientation&&c.quaternion.fromArray(t.orientation),c.updateMatrixWorld(),!1===i.isPresenting)return e;a.near=e.near,s.near=e.near,a.far=e.far,s.far=e.far,l.matrixWorld.copy(e.matrixWorld),l.matrixWorldInverse.copy(e.matrixWorldInverse),a.matrixWorldInverse.fromArray(r.leftViewMatrix),s.matrixWorldInverse.fromArray(r.rightViewMatrix);var h=c.parent;null!==h&&(o.getInverse(h.matrixWorld),a.matrixWorldInverse.multiply(o),s.matrixWorldInverse.multiply(o)),a.matrixWorld.getInverse(a.matrixWorldInverse),s.matrixWorld.getInverse(s.matrixWorldInverse),a.projectionMatrix.fromArray(r.leftProjectionMatrix),s.projectionMatrix.fromArray(r.rightProjectionMatrix),l.projectionMatrix.copy(a.projectionMatrix);var u=i.getLayers();if(u.length){var p=u[0];null!==p.leftBounds&&4===p.leftBounds.length&&a.bounds.fromArray(p.leftBounds),null!==p.rightBounds&&4===p.rightBounds.length&&s.bounds.fromArray(p.rightBounds)}return l},this.submitFrame=function(){i&&i.isPresenting&&i.submitFrame()},this.dispose=function(){"undefined"!=typeof window&&window.removeEventListener("vrdisplaypresentchange",u)}}function er(e){var t={};return{get:function(i){if(void 0!==t[i])return t[i];var r;switch(i){case"WEBGL_depth_texture":r=e.getExtension("WEBGL_depth_texture")||e.getExtension("MOZ_WEBGL_depth_texture")||e.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":r=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":r=e.getExtension("WEBGL_compressed_texture_s3tc")||e.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":r=e.getExtension("WEBGL_compressed_texture_pvrtc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;case"WEBGL_compressed_texture_etc1":r=e.getExtension("WEBGL_compressed_texture_etc1");break;default:r=e.getExtension(i)}return null===r&&console.warn("THREE.WebGLRenderer: "+i+" extension not supported."),t[i]=r,r}}}function tr(){var e=this,t=null,i=0,r=!1,n=!1,o=new _t,a=new ae,s={value:null,needsUpdate:!1};function c(){s.value!==t&&(s.value=t,s.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,i,r,n){var c=null!==t?t.length:0,h=null;if(0!==c){if(h=s.value,!0!==n||null===h){var l=r+4*c,u=i.matrixWorldInverse;a.getNormalMatrix(u),(null===h||h.length=0){var h=n[s];if(void 0!==h){var l=h.normalized,u=h.itemSize,p=w.get(h);if(void 0===p)continue;var d=p.buffer,f=p.type,g=p.bytesPerElement;if(h.isInterleavedBufferAttribute){var x=h.data,b=x.stride,_=h.offset;x&&x.isInstancedInterleavedBuffer?(y.enableAttributeAndDivisor(c,x.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=x.meshPerAttribute*x.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,b*g,(r*b+_)*g)}else h.isInstancedBufferAttribute?(y.enableAttributeAndDivisor(c,h.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=h.meshPerAttribute*h.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,0,r*u*g)}else if(void 0!==a){var M=a[s];if(void 0!==M)switch(M.length){case 2:m.vertexAttrib2fv(c,M);break;case 3:m.vertexAttrib3fv(c,M);break;case 4:m.vertexAttrib4fv(c,M);break;default:m.vertexAttrib1fv(c,M)}}}}y.disableUnusedAttributes()}(r,s,i),null!==u&&m.bindBuffer(m.ELEMENT_ARRAY_BUFFER,l.buffer));var g=0;null!==u?g=u.count:void 0!==p&&(g=p.count);var x=i.drawRange.start*d,b=i.drawRange.count*d,M=null!==o?o.start*d:0,E=null!==o?o.count*d:1/0,T=Math.max(x,M),S=Math.min(g,x+b,M+E)-1,A=Math.max(0,S-T+1);if(0!==A){if(n.isMesh)if(!0===r.wireframe)y.setLineWidth(r.wireframeLinewidth*me()),f.setMode(m.LINES);else switch(n.drawMode){case 0:f.setMode(m.TRIANGLES);break;case 1:f.setMode(m.TRIANGLE_STRIP);break;case 2:f.setMode(m.TRIANGLE_FAN)}else if(n.isLine){var R=r.linewidth;void 0===R&&(R=1),y.setLineWidth(R*me()),n.isLineSegments?f.setMode(m.LINES):n.isLineLoop?f.setMode(m.LINE_LOOP):f.setMode(m.LINE_STRIP)}else n.isPoints&&f.setMode(m.POINTS);i&&i.isInstancedBufferGeometry?i.maxInstancedCount>0&&f.renderInstances(i,T,A):f.render(T,A)}},this.compile=function(e,t){l.length=0,u.length=0,e.traverse((function(e){e.isLight&&(l.push(e),e.castShadow&&u.push(e))})),E.setup(l,u,t),e.traverse((function(t){if(t.material)if(Array.isArray(t.material))for(var i=0;i=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(l=0;l=0&&e.numSupportedMorphNormals++}var p=r.shader.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(r.numClippingPlanes=ae.numPlanes,r.numIntersection=ae.numIntersection,p.clippingPlanes=ae.uniform),r.fog=t,r.lightsHash=E.state.hash,e.lights&&(p.ambientLightColor.value=E.state.ambient,p.directionalLights.value=E.state.directional,p.spotLights.value=E.state.spot,p.rectAreaLights.value=E.state.rectArea,p.pointLights.value=E.state.point,p.hemisphereLights.value=E.state.hemi,p.directionalShadowMap.value=E.state.directionalShadowMap,p.directionalShadowMatrix.value=E.state.directionalShadowMatrix,p.spotShadowMap.value=E.state.spotShadowMap,p.spotShadowMatrix.value=E.state.spotShadowMatrix,p.pointShadowMap.value=E.state.pointShadowMap,p.pointShadowMatrix.value=E.state.pointShadowMatrix);var d=r.program.getUniforms(),f=Qe.seqWithValue(d.seq,p);r.uniformsList=f}function Ne(e,t,i,r){Z=0;var n=x.get(i);if(se&&(ce||e!==H)){var o=e===H&&i.id===V;ae.setState(i.clippingPlanes,i.clipIntersection,i.clipShadows,e,n,o)}!1===i.needsUpdate&&(void 0===n.program||i.fog&&n.fog!==t||i.lights&&n.lightsHash!==E.state.hash?i.needsUpdate=!0:void 0===n.numClippingPlanes||n.numClippingPlanes===ae.numPlanes&&n.numIntersection===ae.numIntersection||(i.needsUpdate=!0)),i.needsUpdate&&(Pe(i,t,r),i.needsUpdate=!1);var a=!1,s=!1,c=!1,h=n.program,l=h.getUniforms(),u=n.shader.uniforms;if(y.useProgram(h.program)&&(a=!0,s=!0,c=!0),i.id!==V&&(V=i.id,s=!0),a||e!==H){if(l.setValue(m,"projectionMatrix",e.projectionMatrix),g.logarithmicDepthBuffer&&l.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),H!==(W||e)&&(H=W||e,s=!0,c=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshStandardMaterial||i.envMap){var p=l.map.cameraPosition;void 0!==p&&p.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.skinning)&&l.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(i.skinning){l.setOptional(m,r,"bindMatrix"),l.setOptional(m,r,"bindMatrixInverse");var d=r.skeleton;if(d){var f=d.bones;if(g.floatVertexTextures){if(void 0===d.boneTexture){var v=Math.sqrt(4*f.length);v=te.ceilPowerOfTwo(v),v=Math.max(v,4);var b=new Float32Array(v*v*4);b.set(d.boneMatrices);var w=new pe(b,v,v,U,N);d.boneMatrices=b,d.boneTexture=w,d.boneTextureSize=v}l.setValue(m,"boneTexture",d.boneTexture),l.setValue(m,"boneTextureSize",d.boneTextureSize)}else l.setOptional(m,d,"boneMatrices")}}return s&&(l.setValue(m,"toneMappingExposure",F.toneMappingExposure),l.setValue(m,"toneMappingWhitePoint",F.toneMappingWhitePoint),i.lights&&function(e,t){e.ambientLightColor.needsUpdate=t,e.directionalLights.needsUpdate=t,e.pointLights.needsUpdate=t,e.spotLights.needsUpdate=t,e.rectAreaLights.needsUpdate=t,e.hemisphereLights.needsUpdate=t}(u,c),t&&i.fog&&function(e,t){e.fogColor.value=t.color,t.isFog?(e.fogNear.value=t.near,e.fogFar.value=t.far):t.isFogExp2&&(e.fogDensity.value=t.density)}(u,t),i.isMeshBasicMaterial?Oe(u,i):i.isMeshLambertMaterial?(Oe(u,i),function(e,t){t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap)}(u,i)):i.isMeshPhongMaterial?(Oe(u,i),i.isMeshToonMaterial?function(e,t){Ie(e,t),t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(u,i):Ie(u,i)):i.isMeshStandardMaterial?(Oe(u,i),i.isMeshPhysicalMaterial?function(e,t){e.clearCoat.value=t.clearCoat,e.clearCoatRoughness.value=t.clearCoatRoughness,De(e,t)}(u,i):De(u,i)):i.isMeshDepthMaterial?(Oe(u,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(u,i)):i.isMeshDistanceMaterial?(Oe(u,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias);e.referencePosition.value.copy(t.referencePosition),e.nearDistance.value=t.nearDistance,e.farDistance.value=t.farDistance}(u,i)):i.isMeshNormalMaterial?(Oe(u,i),function(e,t){t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale);t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale));t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(u,i)):i.isLineBasicMaterial?(function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity}(u,i),i.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(u,i)):i.isPointsMaterial?function(e,t){if(e.diffuse.value=t.color,e.opacity.value=t.opacity,e.size.value=t.size*Q,e.scale.value=.5*K,e.map.value=t.map,null!==t.map){if(!0===t.map.matrixAutoUpdate){var i=t.map.offset,r=t.map.repeat,n=t.map.rotation,o=t.map.center;t.map.matrix.setUvTransform(i.x,i.y,r.x,r.y,n,o.x,o.y)}e.uvTransform.value.copy(t.map.matrix)}}(u,i):i.isShadowMaterial&&(u.color.value=i.color,u.opacity.value=i.opacity),void 0!==u.ltcMat&&(u.ltcMat.value=tt.LTC_MAT_TEXTURE),void 0!==u.ltcMag&&(u.ltcMag.value=tt.LTC_MAG_TEXTURE),Qe.upload(m,n.uniformsList,u,F)),l.setValue(m,"modelViewMatrix",r.modelViewMatrix),l.setValue(m,"normalMatrix",r.normalMatrix),l.setValue(m,"modelMatrix",r.matrixWorld),h}function Oe(e,t){var i;if(e.opacity.value=t.opacity,t.color&&(e.diffuse.value=t.color),t.emissive&&e.emissive.value.copy(t.emissive).multiplyScalar(t.emissiveIntensity),t.map&&(e.map.value=t.map),t.alphaMap&&(e.alphaMap.value=t.alphaMap),t.specularMap&&(e.specularMap.value=t.specularMap),t.envMap&&(e.envMap.value=t.envMap,e.flipEnvMap.value=t.envMap&&t.envMap.isCubeTexture?-1:1,e.reflectivity.value=t.reflectivity,e.refractionRatio.value=t.refractionRatio),t.lightMap&&(e.lightMap.value=t.lightMap,e.lightMapIntensity.value=t.lightMapIntensity),t.aoMap&&(e.aoMap.value=t.aoMap,e.aoMapIntensity.value=t.aoMapIntensity),t.map?i=t.map:t.specularMap?i=t.specularMap:t.displacementMap?i=t.displacementMap:t.normalMap?i=t.normalMap:t.bumpMap?i=t.bumpMap:t.roughnessMap?i=t.roughnessMap:t.metalnessMap?i=t.metalnessMap:t.alphaMap?i=t.alphaMap:t.emissiveMap&&(i=t.emissiveMap),void 0!==i){if(i.isWebGLRenderTarget&&(i=i.texture),!0===i.matrixAutoUpdate){var r=i.offset,n=i.repeat,o=i.rotation,a=i.center;i.matrix.setUvTransform(r.x,r.y,n.x,n.y,o,a.x,a.y)}e.uvTransform.value.copy(i.matrix)}}function Ie(e,t){e.specular.value=t.specular,e.shininess.value=Math.max(t.shininess,1e-4),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}function De(e,t){e.roughness.value=t.roughness,e.metalness.value=t.metalness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap),t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}this.animate=function(e){Se=e,function(){if(!Te){var e=ye.getDevice();e&&e.isPresenting?e.requestAnimationFrame(Ae):window.requestAnimationFrame(Ae),Te=!0}}()},this.render=function(e,t,i,r){if(t&&t.isCamera){if(!z){j="",V=-1,H=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),ye.enabled&&(t=ye.getCamera(t)),le.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),ne.setFromMatrix(le),l.length=0,u.length=0,d.length=0,f.length=0,ce=this.localClippingEnabled,se=ae.init(this.clippingPlanes,ce,t),(p=S.get(e,t)).init(),Le(e,t,F.sortObjects),!0===F.sortObjects&&p.sort(),b.updateVideoTextures(),se&&ae.beginShadows(),xe.render(u,e,t),E.setup(l,u,t),se&&ae.endShadows(),fe.frame++,fe.calls=0,fe.vertices=0,fe.faces=0,fe.points=0,void 0===i&&(i=null),this.setRenderTarget(i),A.render(p,e,t,r);var n=p.opaque,o=p.transparent;if(e.overrideMaterial){var a=e.overrideMaterial;n.length&&Re(n,e,t,a),o.length&&Re(o,e,t,a)}else n.length&&Re(n,e,t),o.length&&Re(o,e,t);D.render(d,e,t),I.render(f,e,t,X),i&&b.updateRenderTargetMipmap(i),y.buffers.depth.setTest(!0),y.buffers.depth.setMask(!0),y.buffers.color.setMask(!0),y.setPolygonOffset(!1),ye.enabled&&ye.submitFrame()}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFaceCulling=function(e,t){y.setCullFace(e),y.setFlipSided(0===t)},this.allocTextureUnit=function(){var e=Z;return e>=g.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+g.maxTextures),Z+=1,e},this.setTexture2D=(Ee=!1,function(e,t){e&&e.isWebGLRenderTarget&&(Ee||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Ee=!0),e=e.texture),b.setTexture2D(e,t)}),this.setTexture=function(){var e=!1;return function(t,i){e||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),e=!0),b.setTexture2D(t,i)}}(),this.setTextureCube=function(){var e=!1;return function(t,i){t&&t.isWebGLRenderTargetCube&&(e||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),e=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?b.setTextureCube(t,i):b.setTextureCubeDynamic(t,i)}}(),this.getRenderTarget=function(){return k},this.setRenderTarget=function(e){k=e,e&&void 0===x.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var t=null,i=!1;if(e){var r=x.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=r[e.activeCubeFace],i=!0):t=r,X.copy(e.viewport),q.copy(e.scissor),Y=e.scissorTest}else X.copy($).multiplyScalar(Q),q.copy(ee).multiplyScalar(Q),Y=ie;if(G!==t&&(m.bindFramebuffer(m.FRAMEBUFFER,t),G=t),y.viewport(X),y.scissor(q),y.setScissorTest(Y),i){var n=x.get(e.texture);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,n.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,r,n,o){if(e&&e.isWebGLRenderTarget){var a=x.get(e).__webglFramebuffer;if(a){var s=!1;a!==G&&(m.bindFramebuffer(m.FRAMEBUFFER,a),s=!0);try{var c=e.texture,h=c.format,l=c.type;if(h!==U&&B.convert(h)!==m.getParameter(m.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(l===R||B.convert(l)===m.getParameter(m.IMPLEMENTATION_COLOR_READ_TYPE)||l===N&&(v.get("OES_texture_float")||v.get("WEBGL_color_buffer_float"))||l===O&&v.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?t>=0&&t<=e.width-r&&i>=0&&i<=e.height-n&&m.readPixels(t,i,r,n,B.convert(h),B.convert(l),o):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&m.bindFramebuffer(m.FRAMEBUFFER,G)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")}}function nr(e,t){this.name="",this.color=new et(e),this.density=void 0!==t?t:25e-5}function or(e,t,i){this.name="",this.color=new et(e),this.near=void 0!==t?t:1,this.far=void 0!==i?i:1e3}function ar(){Ot.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function sr(e,t,i,r,n){Ot.call(this),this.lensFlares=[],this.positionScreen=new oe,this.customUpdateCallback=void 0,void 0!==e&&this.add(e,t,i,r,n)}function cr(e){gt.call(this),this.type="SpriteMaterial",this.color=new et(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function hr(e){Ot.call(this),this.type="Sprite",this.material=void 0!==e?e:new cr}function lr(){Ot.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ur(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===t)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,r=this.bones.length;i=0?(p=e(g-h,v,p),d.subVectors(u,p)):(p=e(g+h,v,p),d.subVectors(p,u)),v-h>=0?(p=e(g,v-h,p),f.subVectors(u,p)):(p=e(g,v+h,p),f.subVectors(p,u)),l.crossVectors(d,f).normalize(),s.push(l.x,l.y,l.z),c.push(g,v)}}for(r=0;r.9&&a<.1&&(t<.2&&(o[e+0]+=1),i<.2&&(o[e+2]+=1),r<.2&&(o[e+4]+=1))}}()}(),this.addAttribute("position",new Yt(n,3)),this.addAttribute("normal",new Yt(n.slice(),3)),this.addAttribute("uv",new Yt(o,2)),0===r?this.computeVertexNormals():this.normalizeNormals()}function Rr(e,t){zt.call(this),this.type="TetrahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Cr(e,t)),this.mergeVertices()}function Cr(e,t){Lr.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],e,t),this.type="TetrahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Pr(e,t){zt.call(this),this.type="OctahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Nr(e,t)),this.mergeVertices()}function Nr(e,t){Lr.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],e,t),this.type="OctahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Or(e,t){zt.call(this),this.type="IcosahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ir(e,t)),this.mergeVertices()}function Ir(e,t){var i=(1+Math.sqrt(5))/2,r=[-1,i,0,1,i,0,-1,-i,0,1,-i,0,0,-1,i,0,1,i,0,-1,-i,0,1,-i,i,0,-1,i,0,1,-i,0,-1,-i,0,1];Lr.call(this,r,[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],e,t),this.type="IcosahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Dr(e,t){zt.call(this),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ur(e,t)),this.mergeVertices()}function Ur(e,t){var i=(1+Math.sqrt(5))/2,r=1/i,n=[-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,-i,0,-r,i,0,r,-i,0,r,i,-r,-i,0,-r,i,0,r,-i,0,r,i,0,-i,0,-r,i,0,-r,-i,0,r,i,0,r];Lr.call(this,n,[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],e,t),this.type="DodecahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Br(e,t,i,r,n,o){zt.call(this),this.type="TubeGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},void 0!==o&&console.warn("THREE.TubeGeometry: taper has been removed.");var a=new Fr(e,t,i,r,n);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals,this.fromBufferGeometry(a),this.mergeVertices()}function Fr(e,t,i,r,n){ai.call(this),this.type="TubeBufferGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},t=t||64,i=i||1,r=r||8,n=n||!1;var o=e.computeFrenetFrames(t,n);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals;var a,s,c=new oe,h=new oe,l=new ie,u=new oe,p=[],d=[],f=[],m=[];function v(n){u=e.getPointAt(n/t,u);var a=o.normals[n],l=o.binormals[n];for(s=0;s<=r;s++){var f=s/r*Math.PI*2,m=Math.sin(f),v=-Math.cos(f);h.x=v*a.x+m*l.x,h.y=v*a.y+m*l.y,h.z=v*a.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+i*h.x,c.y=u.y+i*h.y,c.z=u.z+i*h.z,p.push(c.x,c.y,c.z)}}!function(){for(a=0;ai)){var r=e.ray.origin.distanceTo(Pi);re.far||t.push({distance:r,point:Pi.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)}}),lr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:lr,copy:function(e){Ot.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,r=t.length;i1){e.setFromMatrixPosition(i.matrixWorld),t.setFromMatrixPosition(this.matrixWorld);var n=e.distanceTo(t);r[0].object.visible=!0;for(var o=1,a=r.length;o=r[o].distance;o++)r[o-1].object.visible=!1,r[o].object.visible=!0;for(;oa))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}else for(g=0,y=m.length/3-1;ga))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}else if(s.isGeometry){var w=s.vertices,_=w.length;for(g=0;g<_-1;g+=d){var M;if(!(t.distanceSqToSegment(w[g],w[g+1],p,u)>a))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),vr.prototype=Object.assign(Object.create(mr.prototype),{constructor:vr,isLineSegments:!0}),gr.prototype=Object.assign(Object.create(mr.prototype),{constructor:gr,isLineLoop:!0}),yr.prototype=Object.create(gt.prototype),yr.prototype.constructor=yr,yr.prototype.isPointsMaterial=!0,yr.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.size=e.size,this.sizeAttenuation=e.sizeAttenuation,this},xr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:xr,isPoints:!0,raycast:function(){var e=new re,t=new di,i=new wt;return function(r,n){var o=this,a=this.geometry,s=this.matrixWorld,c=r.params.Points.threshold;if(null===a.boundingSphere&&a.computeBoundingSphere(),i.copy(a.boundingSphere),i.applyMatrix4(s),i.radius+=c,!1!==r.ray.intersectsSphere(i)){e.getInverse(s),t.copy(r.ray).applyMatrix4(e);var h=c/((this.scale.x+this.scale.y+this.scale.z)/3),l=h*h,u=new oe;if(a.isBufferGeometry){var p=a.index,d=a.attributes.position.array;if(null!==p)for(var f=p.array,m=0,v=f.length;mr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:c.clone(),index:i,face:null,object:o})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),br.prototype=Object.assign(Object.create(Ot.prototype),{constructor:br,isGroup:!0}),wr.prototype=Object.assign(Object.create(ce.prototype),{constructor:wr,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),_r.prototype=Object.create(ce.prototype),_r.prototype.constructor=_r,_r.prototype.isCompressedTexture=!0,Mr.prototype=Object.create(ce.prototype),Mr.prototype.constructor=Mr,Mr.prototype.isDepthTexture=!0,Er.prototype=Object.create(ai.prototype),Er.prototype.constructor=Er,Tr.prototype=Object.create(zt.prototype),Tr.prototype.constructor=Tr,Sr.prototype=Object.create(ai.prototype),Sr.prototype.constructor=Sr,Ar.prototype=Object.create(zt.prototype),Ar.prototype.constructor=Ar,Lr.prototype=Object.create(ai.prototype),Lr.prototype.constructor=Lr,Rr.prototype=Object.create(zt.prototype),Rr.prototype.constructor=Rr,Cr.prototype=Object.create(Lr.prototype),Cr.prototype.constructor=Cr,Pr.prototype=Object.create(zt.prototype),Pr.prototype.constructor=Pr,Nr.prototype=Object.create(Lr.prototype),Nr.prototype.constructor=Nr,Or.prototype=Object.create(zt.prototype),Or.prototype.constructor=Or,Ir.prototype=Object.create(Lr.prototype),Ir.prototype.constructor=Ir,Dr.prototype=Object.create(zt.prototype),Dr.prototype.constructor=Dr,Ur.prototype=Object.create(Lr.prototype),Ur.prototype.constructor=Ur,Br.prototype=Object.create(zt.prototype),Br.prototype.constructor=Br,Fr.prototype=Object.create(ai.prototype),Fr.prototype.constructor=Fr,zr.prototype=Object.create(zt.prototype),zr.prototype.constructor=zr,kr.prototype=Object.create(ai.prototype),kr.prototype.constructor=kr,Gr.prototype=Object.create(zt.prototype),Gr.prototype.constructor=Gr,Vr.prototype=Object.create(ai.prototype),Vr.prototype.constructor=Vr;var jr=function(e,t,i){i=i||2;var r,n,o,a,s,c,h,l=t&&t.length,u=l?t[0]*i:e.length,p=Hr(e,0,u,i,!0),d=[];if(!p)return d;if(l&&(p=function(e,t,i,r){var n,o,a,s=[];for(n=0,o=t.length;n80*i){r=o=e[0],n=a=e[1];for(var f=i;fo&&(o=s),c>a&&(a=c);h=0!==(h=Math.max(o-r,a-n))?1/h:0}return Xr(p,d,i,r,n,h),d};function Hr(e,t,i,r,n){var o,a;if(n===function(e,t,i,r){for(var n=0,o=t,a=i-r;o0)for(o=t;o=t;o-=r)a=hn(o,e[o],e[o+1],a);return a&&on(a,a.next)&&(ln(a),a=a.next),a}function Wr(e,t){if(!e)return e;t||(t=e);var i,r=e;do{if(i=!1,r.steiner||!on(r,r.next)&&0!==nn(r.prev,r,r.next))r=r.next;else{if(ln(r),(r=t=r.prev)===r.next)break;i=!0}}while(i||r!==t);return t}function Xr(e,t,i,r,n,o,a){if(e){!a&&o&&function(e,t,i,r){var n=e;do{null===n.z&&(n.z=$r(n.x,n.y,t,i,r)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==e);n.prevZ.nextZ=null,n.prevZ=null,function(e){var t,i,r,n,o,a,s,c,h=1;do{for(i=e,e=null,o=null,a=0;i;){for(a++,r=i,s=0,t=0;t0||c>0&&r;)0!==s&&(0===c||!r||i.z<=r.z)?(n=i,i=i.nextZ,s--):(n=r,r=r.nextZ,c--),o?o.nextZ=n:e=n,n.prevZ=o,o=n;i=r}o.nextZ=null,h*=2}while(a>1)}(n)}(e,r,n,o);for(var s,c,h=e;e.prev!==e.next;)if(s=e.prev,c=e.next,o?Yr(e,r,n,o):qr(e))t.push(s.i/i),t.push(e.i/i),t.push(c.i/i),ln(e),e=c.next,h=c.next;else if((e=c)===h){a?1===a?Xr(e=Zr(e,t,i),t,i,r,n,o,2):2===a&&Jr(e,t,i,r,n,o):Xr(Wr(e),t,i,r,n,o,1);break}}}function qr(e){var t=e.prev,i=e,r=e.next;if(nn(t,i,r)>=0)return!1;for(var n=e.next.next;n!==e.prev;){if(tn(t.x,t.y,i.x,i.y,r.x,r.y,n.x,n.y)&&nn(n.prev,n,n.next)>=0)return!1;n=n.next}return!0}function Yr(e,t,i,r){var n=e.prev,o=e,a=e.next;if(nn(n,o,a)>=0)return!1;for(var s=n.xo.x?n.x>a.x?n.x:a.x:o.x>a.x?o.x:a.x,l=n.y>o.y?n.y>a.y?n.y:a.y:o.y>a.y?o.y:a.y,u=$r(s,c,t,i,r),p=$r(h,l,t,i,r),d=e.nextZ;d&&d.z<=p;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=e.prevZ;d&&d.z>=u;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function Zr(e,t,i){var r=e;do{var n=r.prev,o=r.next.next;!on(n,o)&&an(n,r,r.next,o)&&sn(n,o)&&sn(o,n)&&(t.push(n.i/i),t.push(r.i/i),t.push(o.i/i),ln(r),ln(r.next),r=e=o),r=r.next}while(r!==e);return r}function Jr(e,t,i,r,n,o){var a=e;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&rn(a,s)){var c=cn(a,s);return a=Wr(a,a.next),c=Wr(c,c.next),Xr(a,t,i,r,n,o),void Xr(c,t,i,r,n,o)}s=s.next}a=a.next}while(a!==e)}function Kr(e,t){return e.x-t.x}function Qr(e,t){if(t=function(e,t){var i,r=t,n=e.x,o=e.y,a=-1/0;do{if(o<=r.y&&o>=r.next.y&&r.next.y!==r.y){var s=r.x+(o-r.y)*(r.next.x-r.x)/(r.next.y-r.y);if(s<=n&&s>a){if(a=s,s===n){if(o===r.y)return r;if(o===r.next.y)return r.next}i=r.x=r.x&&r.x>=l&&n!==r.x&&tn(oi.x)&&sn(r,e)&&(i=r,p=c),r=r.next;return i}(e,t),t){var i=cn(t,e);Wr(i,i.next)}}function $r(e,t,i,r,n){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*n)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*n)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function en(e){var t=e,i=e;do{t.x=0&&(e-a)*(r-s)-(i-a)*(t-s)>=0&&(i-a)*(o-s)-(n-a)*(r-s)>=0}function rn(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&an(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(e,t)&&sn(e,t)&&sn(t,e)&&function(e,t){var i=e,r=!1,n=(e.x+t.x)/2,o=(e.y+t.y)/2;do{i.y>o!=i.next.y>o&&i.next.y!==i.y&&n<(i.next.x-i.x)*(o-i.y)/(i.next.y-i.y)+i.x&&(r=!r),i=i.next}while(i!==e);return r}(e,t)}function nn(e,t,i){return(t.y-e.y)*(i.x-t.x)-(t.x-e.x)*(i.y-t.y)}function on(e,t){return e.x===t.x&&e.y===t.y}function an(e,t,i,r){return!!(on(e,t)&&on(i,r)||on(e,r)&&on(i,t))||nn(e,t,i)>0!=nn(e,t,r)>0&&nn(i,r,e)>0!=nn(i,r,t)>0}function sn(e,t){return nn(e.prev,e,e.next)<0?nn(e,t,e.next)>=0&&nn(e,e.prev,t)>=0:nn(e,t,e.prev)<0||nn(e,e.next,t)<0}function cn(e,t){var i=new un(e.i,e.x,e.y),r=new un(t.i,t.x,t.y),n=e.next,o=t.prev;return e.next=t,t.prev=e,i.next=n,n.prev=i,r.next=i,i.prev=r,o.next=r,r.prev=o,r}function hn(e,t,i,r){var n=new un(e,t,i);return r?(n.next=r.next,n.prev=r,r.next.prev=n,r.next=n):(n.prev=n,n.next=n),n}function ln(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function un(e,t,i){this.i=e,this.x=t,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var pn={area:function(e){for(var t=e.length,i=0,r=t-1,n=0;n2&&e[t-1].equals(e[0])&&e.pop()}function r(e,t){for(var i=0;i0)&&f.push(w,_,E),(c!==i-1||h0&&g(!0),t>0&&g(!1)),this.setIndex(h),this.addAttribute("position",new Yt(l,3)),this.addAttribute("normal",new Yt(u,3)),this.addAttribute("uv",new Yt(p,2))}function Rn(e,t,i,r,n,o,a){An.call(this,0,e,t,i,r,n,o,a),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Cn(e,t,i,r,n,o,a){Ln.call(this,0,e,t,i,r,n,o,a),this.type="ConeBufferGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Pn(e,t,i,r){zt.call(this),this.type="CircleGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},this.fromBufferGeometry(new Nn(e,t,i,r)),this.mergeVertices()}function Nn(e,t,i,r){ai.call(this),this.type="CircleBufferGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},e=e||1,t=void 0!==t?Math.max(3,t):8,i=void 0!==i?i:0,r=void 0!==r?r:2*Math.PI;var n,o,a=[],s=[],c=[],h=[],l=new oe,u=new ie;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),o=0,n=3;o<=t;o++,n+=3){var p=i+o/t*r;l.x=e*Math.cos(p),l.y=e*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[n]/e+1)/2,u.y=(s[n+1]/e+1)/2,h.push(u.x,u.y)}for(n=1;n<=t;n++)a.push(n,n+1,0);this.setIndex(a),this.addAttribute("position",new Yt(s,3)),this.addAttribute("normal",new Yt(c,3)),this.addAttribute("uv",new Yt(h,2))}dn.prototype=Object.create(zt.prototype),dn.prototype.constructor=dn,fn.prototype=Object.create(ai.prototype),fn.prototype.constructor=fn,fn.prototype.getArrays=function(){var e=this.getAttribute("position"),t=e?Array.prototype.slice.call(e.array):[],i=this.getAttribute("uv"),r=i?Array.prototype.slice.call(i.array):[],n=this.index;return{position:t,uv:r,index:n?Array.prototype.slice.call(n.array):[]}},fn.prototype.addShapeList=function(e,t){var i=e.length;t.arrays=this.getArrays();for(var r=0;rNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=t.x-s/p,m=t.y+a/p,v=((i.x-h/d-f)*h-(i.y+c/d-m)*c)/(a*h-s*c),g=(r=f+a*v-e.x)*r+(n=m+s*v-e.y)*n;if(g<=2)return new ie(r,n);o=Math.sqrt(g/2)}else{var y=!1;a>Number.EPSILON?c>Number.EPSILON&&(y=!0):a<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(r=-s,n=a,o=Math.sqrt(l)):(r=a,n=s,o=Math.sqrt(l/2))}return new ie(r/o,n/o)}for(var G=[],V=0,j=C.length,H=j-1,W=V+1;V=0;N--){for(I=N/y,D=v*Math.cos(I*Math.PI/2),O=g*Math.sin(I*Math.PI/2),V=0,j=C.length;V=0;){i=V,(r=V-1)<0&&(r=e.length-1);var n=0,o=w+2*y;for(n=0;n0||0===e.search(/^data\:image\/jpeg/);n.format=r?D:U,n.needsUpdate=!0,void 0!==t&&t(n)}),i,r),n},setCrossOrigin:function(e){return this.crossOrigin=e,this},setPath:function(e){return this.path=e,this}}),Object.assign(eo.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(e,t){var i=this.getUtoTmapping(e);return this.getPoint(i,t)},getPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPoint(i/e));return t},getSpacedPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPointAt(i/e));return t},getLength:function(){var e=this.getLengths();return e[e.length-1]},getLengths:function(e){if(void 0===e&&(e=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var t,i,r=[],n=this.getPoint(0),o=0;for(r.push(0),i=1;i<=e;i++)o+=(t=this.getPoint(i/e)).distanceTo(n),r.push(o),n=t;return this.cacheArcLengths=r,r},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(e,t){var i,r=this.getLengths(),n=0,o=r.length;i=t||e*r[o-1];for(var a,s=0,c=o-1;s<=c;)if((a=r[n=Math.floor(s+(c-s)/2)]-i)<0)s=n+1;else{if(!(a>0)){c=n;break}c=n-1}if(r[n=c]===i)return n/(o-1);var h=r[n];return(n+(i-h)/(r[n+1]-h))/(o-1)},getTangent:function(e){var t=1e-4,i=e-t,r=e+t;i<0&&(i=0),r>1&&(r=1);var n=this.getPoint(i);return this.getPoint(r).clone().sub(n).normalize()},getTangentAt:function(e){var t=this.getUtoTmapping(e);return this.getTangent(t)},computeFrenetFrames:function(e,t){var i,r,n,o=new oe,a=[],s=[],c=[],h=new oe,l=new re;for(i=0;i<=e;i++)r=i/e,a[i]=this.getTangentAt(r),a[i].normalize();s[0]=new oe,c[0]=new oe;var u=Number.MAX_VALUE,p=Math.abs(a[0].x),d=Math.abs(a[0].y),f=Math.abs(a[0].z);for(p<=u&&(u=p,o.set(1,0,0)),d<=u&&(u=d,o.set(0,1,0)),f<=u&&o.set(0,0,1),h.crossVectors(a[0],o).normalize(),s[0].crossVectors(a[0],h),c[0].crossVectors(a[0],s[0]),i=1;i<=e;i++)s[i]=s[i-1].clone(),c[i]=c[i-1].clone(),h.crossVectors(a[i-1],a[i]),h.length()>Number.EPSILON&&(h.normalize(),n=Math.acos(te.clamp(a[i-1].dot(a[i]),-1,1)),s[i].applyMatrix4(l.makeRotationAxis(h,n))),c[i].crossVectors(a[i],s[i]);if(!0===t)for(n=Math.acos(te.clamp(s[0].dot(s[e]),-1,1)),n/=e,a[0].dot(h.crossVectors(s[0],s[e]))>0&&(n=-n),i=1;i<=e;i++)s[i].applyMatrix4(l.makeRotationAxis(a[i],n*i)),c[i].crossVectors(a[i],s[i]);return{tangents:a,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this},toJSON:function(){var e={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e},fromJSON:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}),to.prototype=Object.create(eo.prototype),to.prototype.constructor=to,to.prototype.isEllipseCurve=!0,to.prototype.getPoint=function(e,t){for(var i=t||new ie,r=2*Math.PI,n=this.aEndAngle-this.aStartAngle,o=Math.abs(n)r;)n-=r;n0?0:(Math.floor(Math.abs(l)/s.length)+1)*s.length:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?i=s[(l-1)%c]:(no.subVectors(s[0],s[1]).add(s[0]),i=no),r=s[l%c],n=s[(l+1)%c],this.closed||l+2r.length-2?r.length-1:o+1],l=r[o>r.length-3?r.length-1:o+2];return i.set(ho(a,s.x,c.x,h.x,l.x),ho(a,s.y,c.y,h.y,l.y)),i},xo.prototype.copy=function(e){eo.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var n=i[r]-t,o=this.curves[r],a=o.getLength(),s=0===a?0:1-n/a;return o.getPointAt(s)}r++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,r=this.curves.length;i1&&!i[i.length-1].equals(i[0])&&i.push(i[0]),i},copy:function(e){eo.prototype.copy.call(this,e),this.curves=[];for(var t=0,i=e.curves.length;t0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(e){return wo.prototype.copy.call(this,e),this.currentPoint.copy(e.currentPoint),this},toJSON:function(){var e=wo.prototype.toJSON.call(this);return e.currentPoint=this.currentPoint.toArray(),e},fromJSON:function(e){return wo.prototype.fromJSON.call(this,e),this.currentPoint.fromArray(e.currentPoint),this}}),Mo.prototype=Object.assign(Object.create(_o.prototype),{constructor:Mo,getPointsHoles:function(e){for(var t=[],i=0,r=this.holes.length;i=n)break e;var s=t[1];e=(n=t[--i-1]))break t}o=i,i=0}for(;i>>1;e0?1:+e}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),i=1;i>8&255]+e[t>>16&255]+e[t>>24&255]+"-"+e[255&i]+e[i>>8&255]+"-"+e[i>>16&15|64]+e[i>>24&255]+"-"+e[63&r|128]+e[r>>8&255]+"-"+e[r>>16&255]+e[r>>24&255]+e[255&n]+e[n>>8&255]+e[n>>16&255]+e[n>>24&255]}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,r,n){return r+(e-t)*(n-r)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*te.DEG2RAD},radToDeg:function(e){return e*te.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))}};function ie(e,t){this.x=e||0,this.y=t||0}function re(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}function ne(e,t,i,r){this._x=e||0,this._y=t||0,this._z=i||0,this._w=void 0!==r?r:1}function oe(e,t,i){this.x=e||0,this.y=t||0,this.z=i||0}function ae(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(ie.prototype,{width:{get:function(){return this.x},set:function(e){this.x=e}},height:{get:function(){return this.y},set:function(e){this.y=e}}}),Object.assign(ie.prototype,{isVector2:!0,set:function(e,t){return this.x=e,this.y=t,this},setScalar:function(e){return this.x=e,this.y=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(e){return this.x=e.x,this.y=e.y,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this)},addScalar:function(e){return this.x+=e,this.y+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this)},subScalar:function(e){return this.x-=e,this.y-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this},multiply:function(e){return this.x*=e.x,this.y*=e.y,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this},divide:function(e){return this.x/=e.x,this.y/=e.y,this},divideScalar:function(e){return this.multiplyScalar(1/e)},applyMatrix3:function(e){var t=this.x,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[7],this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this},clampScalar:(o=new ie,a=new ie,function(e,t){return o.set(e,e),a.set(t,t),this.clamp(o,a)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return 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},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(e){return this.x*e.x+this.y*e.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var e=Math.atan2(this.y,this.x);return e<0&&(e+=2*Math.PI),e},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y;return t*t+i*i},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},equals:function(e){return e.x===this.x&&e.y===this.y},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this},rotateAround:function(e,t){var i=Math.cos(t),r=Math.sin(t),n=this.x-e.x,o=this.y-e.y;return this.x=n*i-o*r+e.x,this.y=n*r+o*i+e.y,this}}),Object.assign(re.prototype,{isMatrix4:!0,set:function(e,t,i,r,n,o,a,s,c,h,l,u,p,d,f,m){var v=this.elements;return v[0]=e,v[4]=t,v[8]=i,v[12]=r,v[1]=n,v[5]=o,v[9]=a,v[13]=s,v[2]=c,v[6]=h,v[10]=l,v[14]=u,v[3]=p,v[7]=d,v[11]=f,v[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new re).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this},copyPosition:function(e){var t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this},extractBasis:function(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this},extractRotation:(p=new oe,function(e){var t=this.elements,i=e.elements,r=1/p.setFromMatrixColumn(e,0).length(),n=1/p.setFromMatrixColumn(e,1).length(),o=1/p.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[4]=i[4]*n,t[5]=i[5]*n,t[6]=i[6]*n,t[8]=i[8]*o,t[9]=i[9]*o,t[10]=i[10]*o,this}),makeRotationFromEuler:function(e){e&&e.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var t=this.elements,i=e.x,r=e.y,n=e.z,o=Math.cos(i),a=Math.sin(i),s=Math.cos(r),c=Math.sin(r),h=Math.cos(n),l=Math.sin(n);if("XYZ"===e.order){var u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=-s*l,t[8]=c,t[1]=p+d*c,t[5]=u-f*c,t[9]=-a*s,t[2]=f-u*c,t[6]=d+p*c,t[10]=o*s}else if("YXZ"===e.order){var m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m+y*a,t[4]=g*a-v,t[8]=o*c,t[1]=o*l,t[5]=o*h,t[9]=-a,t[2]=v*a-g,t[6]=y+m*a,t[10]=o*s}else if("ZXY"===e.order){m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m-y*a,t[4]=-o*l,t[8]=g+v*a,t[1]=v+g*a,t[5]=o*h,t[9]=y-m*a,t[2]=-o*c,t[6]=a,t[10]=o*s}else if("ZYX"===e.order){u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=d*c-p,t[8]=u*c+f,t[1]=s*l,t[5]=f*c+u,t[9]=p*c-d,t[2]=-c,t[6]=a*s,t[10]=o*s}else if("YZX"===e.order){var x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=_-x*l,t[8]=w*l+b,t[1]=l,t[5]=o*h,t[9]=-a*h,t[2]=-c*h,t[6]=b*l+w,t[10]=x-_*l}else if("XZY"===e.order){x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=-l,t[8]=c*h,t[1]=x*l+_,t[5]=o*h,t[9]=b*l-w,t[2]=w*l-b,t[6]=a*h,t[10]=_*l+x}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromQuaternion:function(e){var t=this.elements,i=e._x,r=e._y,n=e._z,o=e._w,a=i+i,s=r+r,c=n+n,h=i*a,l=i*s,u=i*c,p=r*s,d=r*c,f=n*c,m=o*a,v=o*s,g=o*c;return t[0]=1-(p+f),t[4]=l-g,t[8]=u+v,t[1]=l+g,t[5]=1-(h+f),t[9]=d-m,t[2]=u-v,t[6]=d+m,t[10]=1-(h+p),t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},lookAt:(h=new oe,l=new oe,u=new oe,function(e,t,i){var r=this.elements;return u.subVectors(e,t),0===u.lengthSq()&&(u.z=1),u.normalize(),h.crossVectors(i,u),0===h.lengthSq()&&(1===Math.abs(i.z)?u.x+=1e-4:u.z+=1e-4,u.normalize(),h.crossVectors(i,u)),h.normalize(),l.crossVectors(u,h),r[0]=h.x,r[4]=l.x,r[8]=u.x,r[1]=h.y,r[5]=l.y,r[9]=u.y,r[2]=h.z,r[6]=l.z,r[10]=u.z,this}),multiply:function(e,t){return void 0!==t?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(e,t)):this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var i=e.elements,r=t.elements,n=this.elements,o=i[0],a=i[4],s=i[8],c=i[12],h=i[1],l=i[5],u=i[9],p=i[13],d=i[2],f=i[6],m=i[10],v=i[14],g=i[3],y=i[7],x=i[11],b=i[15],w=r[0],_=r[4],M=r[8],E=r[12],T=r[1],S=r[5],A=r[9],R=r[13],L=r[2],C=r[6],P=r[10],N=r[14],O=r[3],I=r[7],D=r[11],U=r[15];return n[0]=o*w+a*T+s*L+c*O,n[4]=o*_+a*S+s*C+c*I,n[8]=o*M+a*A+s*P+c*D,n[12]=o*E+a*R+s*N+c*U,n[1]=h*w+l*T+u*L+p*O,n[5]=h*_+l*S+u*C+p*I,n[9]=h*M+l*A+u*P+p*D,n[13]=h*E+l*R+u*N+p*U,n[2]=d*w+f*T+m*L+v*O,n[6]=d*_+f*S+m*C+v*I,n[10]=d*M+f*A+m*P+v*D,n[14]=d*E+f*R+m*N+v*U,n[3]=g*w+y*T+x*L+b*O,n[7]=g*_+y*S+x*C+b*I,n[11]=g*M+y*A+x*P+b*D,n[15]=g*E+y*R+x*N+b*U,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i=0?1:-1,y=1-v*v;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,v*g);m=Math.sin(m*b)/x,a=Math.sin(a*b)/x}var w=a*g;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-a){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}e[t]=s,e[t+1]=c,e[t+2]=h,e[t+3]=l}}),Object.defineProperties(ne.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this.onChangeCallback()}}}),Object.assign(ne.prototype,{set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this.onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var i=e._x,r=e._y,n=e._z,o=e.order,a=Math.cos,s=Math.sin,c=a(i/2),h=a(r/2),l=a(n/2),u=s(i/2),p=s(r/2),d=s(n/2);return"XYZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===o&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],s=i[5],c=i[9],h=i[2],l=i[6],u=i[10],p=r+s+u;return p>0?(t=.5/Math.sqrt(p+1),this._w=.25/t,this._x=(l-c)*t,this._y=(o-h)*t,this._z=(a-n)*t):r>s&&r>u?(t=2*Math.sqrt(1+r-s-u),this._w=(l-c)/t,this._x=.25*t,this._y=(n+a)/t,this._z=(o+h)/t):s>u?(t=2*Math.sqrt(1+s-r-u),this._w=(o-h)/t,this._x=(n+a)/t,this._y=.25*t,this._z=(c+l)/t):(t=2*Math.sqrt(1+u-r-s),this._w=(a-n)/t,this._x=(o+h)/t,this._y=(c+l)/t,this._z=.25*t),this.onChangeCallback(),this},setFromUnitVectors:function(){var e,t=new oe;return function(i,r){return void 0===t&&(t=new oe),(e=i.dot(r)+1)<1e-6?(e=0,Math.abs(i.x)>Math.abs(i.z)?t.set(-i.y,i.x,0):t.set(0,-i.z,i.y)):t.crossVectors(i,r),this._x=t.x,this._y=t.y,this._z=t.z,this._w=e,this.normalize()}}(),inverse:function(){return this.conjugate().normalize()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this.onChangeCallback(),this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var i=e._x,r=e._y,n=e._z,o=e._w,a=t._x,s=t._y,c=t._z,h=t._w;return this._x=i*h+o*a+r*c-n*s,this._y=r*h+o*s+n*a-i*c,this._z=n*h+o*c+i*s-r*a,this._w=o*h-i*a-r*s-n*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,r=this._y,n=this._z,o=this._w,a=o*e._w+i*e._x+r*e._y+n*e._z;if(a<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,a=-a):this.copy(e),a>=1)return this._w=o,this._x=i,this._y=r,this._z=n,this;var s=Math.sqrt(1-a*a);if(Math.abs(s)<.001)return this._w=.5*(o+this._w),this._x=.5*(i+this._x),this._y=.5*(r+this._y),this._z=.5*(n+this._z),this;var c=Math.atan2(s,a),h=Math.sin((1-t)*c)/s,l=Math.sin(t*c)/s;return this._w=o*h+this._w*l,this._x=i*h+this._x*l,this._y=r*h+this._y*l,this._z=n*h+this._z*l,this.onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return void 0===t&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(oe.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:(d=new ne,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(d.setFromEuler(e))}),applyAxisAngle:function(){var e=new ne;return function(t,i){return this.applyQuaternion(e.setFromAxisAngle(t,i))}}(),applyMatrix3:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[3]*i+n[6]*r,this.y=n[1]*t+n[4]*i+n[7]*r,this.z=n[2]*t+n[5]*i+n[8]*r,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements,o=1/(n[3]*t+n[7]*i+n[11]*r+n[15]);return this.x=(n[0]*t+n[4]*i+n[8]*r+n[12])*o,this.y=(n[1]*t+n[5]*i+n[9]*r+n[13])*o,this.z=(n[2]*t+n[6]*i+n[10]*r+n[14])*o,this},applyQuaternion:function(e){var t=this.x,i=this.y,r=this.z,n=e.x,o=e.y,a=e.z,s=e.w,c=s*t+o*r-a*i,h=s*i+a*t-n*r,l=s*r+n*i-o*t,u=-n*t-o*i-a*r;return this.x=c*s+u*-n+h*-a-l*-o,this.y=h*s+u*-o+l*-n-c*-a,this.z=l*s+u*-a+c*-o-h*-n,this},project:function(){var e=new re;return function(t){return e.multiplyMatrices(t.projectionMatrix,e.getInverse(t.matrixWorld)),this.applyMatrix4(e)}}(),unproject:function(){var e=new re;return function(t){return e.multiplyMatrices(t.matrixWorld,e.getInverse(t.projectionMatrix)),this.applyMatrix4(e)}}(),transformDirection:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r,this.y=n[1]*t+n[5]*i+n[9]*r,this.z=n[2]*t+n[6]*i+n[10]*r,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:function(){var e=new oe,t=new oe;return function(i,r){return e.set(i,i,i),t.set(r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return 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},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},cross:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var i=e.x,r=e.y,n=e.z,o=t.x,a=t.y,s=t.z;return this.x=r*s-n*a,this.y=n*o-i*s,this.z=i*a-r*o,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:function(){var e=new oe;return function(t){return e.copy(this).projectOnVector(t),this.sub(e)}}(),reflect:function(){var e=new oe;return function(t){return this.sub(e.copy(t).multiplyScalar(2*this.dot(t)))}}(),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(te.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}}),Object.assign(ae.prototype,{isMatrix3:!0,set:function(e,t,i,r,n,o,a,s,c){var h=this.elements;return h[0]=e,h[1]=r,h[2]=a,h[3]=t,h[4]=n,h[5]=s,h[6]=i,h[7]=o,h[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")}(r)}),i.image=r.uuid}return t||(e.textures[this.uuid]=i),i},dispose:function(){this.dispatchEvent({type:"dispose"})},transformUv:function(e){if(this.mapping===f){if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case b:e.x=e.x-Math.floor(e.x);break;case w:e.x=e.x<0?0:1;break;case _:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case b:e.y=e.y-Math.floor(e.y);break;case w:e.y=e.y<0?0:1;break;case _:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}this.flipY&&(e.y=1-e.y)}}}),Object.defineProperty(ce.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(he.prototype,{isVector4:!0,set:function(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this.w=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setW:function(e){return this.w=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){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: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=this.w,o=e.elements;return this.x=o[0]*t+o[4]*i+o[8]*r+o[12]*n,this.y=o[1]*t+o[5]*i+o[9]*r+o[13]*n,this.z=o[2]*t+o[6]*i+o[10]*r+o[14]*n,this.w=o[3]*t+o[7]*i+o[11]*r+o[15]*n,this},divideScalar:function(e){return this.multiplyScalar(1/e)},setAxisAngleFromQuaternion:function(e){this.w=2*Math.acos(e.w);var t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this},setAxisAngleFromRotationMatrix:function(e){var t,i,r,n,o=.01,a=.1,s=e.elements,c=s[0],h=s[4],l=s[8],u=s[1],p=s[5],d=s[9],f=s[2],m=s[6],v=s[10];if(Math.abs(h-u)y&&g>x?gx?y0)return e;var n=t*i,o=ge[n];if(void 0===o&&(o=new Float32Array(n),ge[n]=o),0!==t){r.toArray(o,0);for(var a=1,s=0;a!==t;++a)s+=i,e[a].toArray(o,s)}return o}function _e(e,t){var i=ye[t];void 0===i&&(i=new Int32Array(t),ye[t]=i);for(var r=0;r!==t;++r)i[r]=e.allocTextureUnit();return i}function Me(e,t){e.uniform1f(this.addr,t)}function Ee(e,t){e.uniform1i(this.addr,t)}function Te(e,t){void 0===t.x?e.uniform2fv(this.addr,t):e.uniform2f(this.addr,t.x,t.y)}function Se(e,t){void 0!==t.x?e.uniform3f(this.addr,t.x,t.y,t.z):void 0!==t.r?e.uniform3f(this.addr,t.r,t.g,t.b):e.uniform3fv(this.addr,t)}function Ae(e,t){void 0===t.x?e.uniform4fv(this.addr,t):e.uniform4f(this.addr,t.x,t.y,t.z,t.w)}function Re(e,t){e.uniformMatrix2fv(this.addr,!1,t.elements||t)}function Le(e,t){void 0===t.elements?e.uniformMatrix3fv(this.addr,!1,t):(be.set(t.elements),e.uniformMatrix3fv(this.addr,!1,be))}function Ce(e,t){void 0===t.elements?e.uniformMatrix4fv(this.addr,!1,t):(xe.set(t.elements),e.uniformMatrix4fv(this.addr,!1,xe))}function Pe(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTexture2D(t||fe,r)}function Ne(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTextureCube(t||me,r)}function Oe(e,t){e.uniform2iv(this.addr,t)}function Ie(e,t){e.uniform3iv(this.addr,t)}function De(e,t){e.uniform4iv(this.addr,t)}function Ue(e,t){e.uniform1fv(this.addr,t)}function Be(e,t){e.uniform1iv(this.addr,t)}function Fe(e,t){e.uniform2fv(this.addr,we(t,this.size,2))}function ze(e,t){e.uniform3fv(this.addr,we(t,this.size,3))}function ke(e,t){e.uniform4fv(this.addr,we(t,this.size,4))}function Ge(e,t){e.uniformMatrix2fv(this.addr,!1,we(t,this.size,4))}function Ve(e,t){e.uniformMatrix3fv(this.addr,!1,we(t,this.size,9))}function je(e,t){e.uniformMatrix4fv(this.addr,!1,we(t,this.size,16))}function He(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTexture2D(t[o]||fe,n[o])}function We(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTextureCube(t[o]||me,n[o])}function Xe(e,t,i){this.id=e,this.addr=i,this.setValue=function(e){switch(e){case 5126:return Me;case 35664:return Te;case 35665:return Se;case 35666:return Ae;case 35674:return Re;case 35675:return Le;case 35676:return Ce;case 35678:case 36198:return Pe;case 35680:return Ne;case 5124:case 35670:return Ee;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function qe(e,t,i){this.id=e,this.addr=i,this.size=t.size,this.setValue=function(e){switch(e){case 5126:return Ue;case 35664:return Fe;case 35665:return ze;case 35666:return ke;case 35674:return Ge;case 35675:return Ve;case 35676:return je;case 35678:return He;case 35680:return We;case 5124:case 35670:return Be;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function Ye(e){this.id=e,ve.call(this)}Ye.prototype.setValue=function(e,t){for(var i=this.seq,r=0,n=i.length;r!==n;++r){var o=i[r];o.setValue(e,t[o.id])}};var Ze=/([\w\d_]+)(\])?(\[|\.)?/g;function Je(e,t){e.seq.push(t),e.map[t.id]=t}function Ke(e,t,i){var r=e.name,n=r.length;for(Ze.lastIndex=0;;){var o=Ze.exec(r),a=Ze.lastIndex,s=o[1],c="]"===o[2],h=o[3];if(c&&(s|=0),void 0===h||"["===h&&a+2===n){Je(i,void 0===h?new Xe(s,e,t):new qe(s,e,t));break}var l=i.map[s];void 0===l&&Je(i,l=new Ye(s)),i=l}}function Qe(e,t,i){ve.call(this),this.renderer=i;for(var r=e.getProgramParameter(t,e.ACTIVE_UNIFORMS),n=0;n>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function e(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+6*(t-e)*(2/3-i):e}return function(t,i,r){if(t=te.euclideanModulo(t,1),i=te.clamp(i,0,1),r=te.clamp(r,0,1),0===i)this.r=this.g=this.b=r;else{var n=r<=.5?r*(1+i):r+i-r*i,o=2*r-n;this.r=e(o,n,t+1/3),this.g=e(o,n,t),this.b=e(o,n,t-1/3)}return this}}(),setStyle:function(e){function t(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}var i;if(i=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var r,n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(255,parseInt(r[1],10))/255,this.g=Math.min(255,parseInt(r[2],10))/255,this.b=Math.min(255,parseInt(r[3],10))/255,t(r[5]),this;if(r=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(100,parseInt(r[1],10))/100,this.g=Math.min(100,parseInt(r[2],10))/100,this.b=Math.min(100,parseInt(r[3],10))/100,t(r[5]),this;break;case"hsl":case"hsla":if(r=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o)){var a=parseFloat(r[1])/360,s=parseInt(r[2],10)/100,c=parseInt(r[3],10)/100;return t(r[5]),this.setHSL(a,s,c)}}}else if(i=/^\#([A-Fa-f0-9]+)$/.exec(e)){var h,l=(h=i[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}e&&e.length>0&&(void 0!==(h=$e[e])?this.setHex(h):console.warn("THREE.Color: Unknown color "+e));return this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(e){return this.r=e.r,this.g=e.g,this.b=e.b,this},copyGammaToLinear:function(e,t){return void 0===t&&(t=2),this.r=Math.pow(e.r,t),this.g=Math.pow(e.g,t),this.b=Math.pow(e.b,t),this},copyLinearToGamma:function(e,t){void 0===t&&(t=2);var i=t>0?1/t:1;return this.r=Math.pow(e.r,i),this.g=Math.pow(e.g,i),this.b=Math.pow(e.b,i),this},convertGammaToLinear:function(){var e=this.r,t=this.g,i=this.b;return this.r=e*e,this.g=t*t,this.b=i*i,this},convertLinearToGamma:function(){return this.r=Math.sqrt(this.r),this.g=Math.sqrt(this.g),this.b=Math.sqrt(this.b),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(e){var t,i,r=e||{h:0,s:0,l:0},n=this.r,o=this.g,a=this.b,s=Math.max(n,o,a),c=Math.min(n,o,a),h=(c+s)/2;if(c===s)t=0,i=0;else{var l=s-c;switch(i=h<=.5?l/(s+c):l/(2-s-c),s){case n:t=(o-a)/l+(o 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n",lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 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\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",distanceRGBA_frag:"#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n",linedashed_frag:"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\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_frag:"#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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"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\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},nt={basic:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.fog]),vertexShader:rt.meshbasic_vert,fragmentShader:rt.meshbasic_frag},lambert:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.fog,tt.lights,{emissive:{value:new et(0)}}]),vertexShader:rt.meshlambert_vert,fragmentShader:rt.meshlambert_frag},phong:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.gradientmap,tt.fog,tt.lights,{emissive:{value:new et(0)},specular:{value:new et(1118481)},shininess:{value:30}}]),vertexShader:rt.meshphong_vert,fragmentShader:rt.meshphong_frag},standard:{uniforms:it.merge([tt.common,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.roughnessmap,tt.metalnessmap,tt.fog,tt.lights,{emissive:{value:new et(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},points:{uniforms:it.merge([tt.points,tt.fog]),vertexShader:rt.points_vert,fragmentShader:rt.points_frag},dashed:{uniforms:it.merge([tt.common,tt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rt.linedashed_vert,fragmentShader:rt.linedashed_frag},depth:{uniforms:it.merge([tt.common,tt.displacementmap]),vertexShader:rt.depth_vert,fragmentShader:rt.depth_frag},normal:{uniforms:it.merge([tt.common,tt.bumpmap,tt.normalmap,tt.displacementmap,{opacity:{value:1}}]),vertexShader:rt.normal_vert,fragmentShader:rt.normal_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:rt.cube_vert,fragmentShader:rt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rt.equirect_vert,fragmentShader:rt.equirect_frag},distanceRGBA:{uniforms:it.merge([tt.common,tt.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rt.distanceRGBA_vert,fragmentShader:rt.distanceRGBA_frag},shadow:{uniforms:it.merge([tt.lights,tt.fog,{color:{value:new et(0)},opacity:{value:1}}]),vertexShader:rt.shadow_vert,fragmentShader:rt.shadow_frag}};function ot(e,t){this.min=void 0!==e?e:new ie(1/0,1/0),this.max=void 0!==t?t:new ie(-1/0,-1/0)}function at(e,t,i,r,n){var o,a,s,c,h,l,u,p;function d(){var e=new Float32Array([-1,-1,0,0,1,-1,1,0,1,1,1,1,-1,1,0,1]),r=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,r,t.STATIC_DRAW),u=t.createTexture(),p=t.createTexture(),i.bindTexture(t.TEXTURE_2D,u),t.texImage2D(t.TEXTURE_2D,0,t.RGB,16,16,0,t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),i.bindTexture(t.TEXTURE_2D,p),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,16,16,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),s={vertexShader:["uniform lowp int renderType;","uniform vec3 screenPosition;","uniform vec2 scale;","uniform float rotation;","uniform sampler2D occlusionMap;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tvUV = uv;","\tvec2 pos = position;","\tif ( renderType == 2 ) {","\t\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );","\t\tvVisibility = visibility.r / 9.0;","\t\tvVisibility *= 1.0 - visibility.g / 9.0;","\t\tvVisibility *= visibility.b / 9.0;","\t\tvVisibility *= 1.0 - visibility.a / 9.0;","\t\tpos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;","\t\tpos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;","\t}","\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["uniform lowp int renderType;","uniform sampler2D map;","uniform float opacity;","uniform vec3 color;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tif ( renderType == 0 ) {","\t\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );","\t} else if ( renderType == 1 ) {","\t\tgl_FragColor = texture2D( map, vUV );","\t} else {","\t\tvec4 texture = texture2D( map, vUV );","\t\ttexture.a *= opacity * vVisibility;","\t\tgl_FragColor = texture;","\t\tgl_FragColor.rgb *= color;","\t}","}"].join("\n")},c=function(e){var i=t.createProgram(),r=t.createShader(t.FRAGMENT_SHADER),o=t.createShader(t.VERTEX_SHADER),a="precision "+n.precision+" float;\n";return t.shaderSource(r,a+e.fragmentShader),t.shaderSource(o,a+e.vertexShader),t.compileShader(r),t.compileShader(o),t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),i}(s),h={vertex:t.getAttribLocation(c,"position"),uv:t.getAttribLocation(c,"uv")},l={renderType:t.getUniformLocation(c,"renderType"),map:t.getUniformLocation(c,"map"),occlusionMap:t.getUniformLocation(c,"occlusionMap"),opacity:t.getUniformLocation(c,"opacity"),color:t.getUniformLocation(c,"color"),scale:t.getUniformLocation(c,"scale"),rotation:t.getUniformLocation(c,"rotation"),screenPosition:t.getUniformLocation(c,"screenPosition")}}this.render=function(e,n,s,f){if(0!==e.length){var m=new oe,v=f.w/f.z,g=.5*f.z,y=.5*f.w,x=16/f.w,b=new ie(x*v,x),w=new oe(1,1,0),_=new ie(1,1),M=new ot;M.min.set(f.x,f.y),M.max.set(f.x+(f.z-16),f.y+(f.w-16)),void 0===c&&d(),i.useProgram(c),i.initAttributes(),i.enableAttribute(h.vertex),i.enableAttribute(h.uv),i.disableUnusedAttributes(),t.uniform1i(l.occlusionMap,0),t.uniform1i(l.map,1),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(h.vertex,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(h.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),i.disable(t.CULL_FACE),i.buffers.depth.setMask(!1);for(var E=0,T=e.length;E.001&&L.scale>.001&&(w.x=L.x,w.y=L.y,w.z=L.z,x=L.size*L.scale/f.w,b.x=x*v,b.y=x,t.uniform3f(l.screenPosition,w.x,w.y,w.z),t.uniform2f(l.scale,b.x,b.y),t.uniform1f(l.rotation,L.rotation),t.uniform1f(l.opacity,L.opacity),t.uniform3f(l.color,L.color.r,L.color.g,L.color.b),i.setBlending(L.blending,L.blendEquation,L.blendSrc,L.blendDst),r.setTexture2D(L.texture,1),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0))}}}i.enable(t.CULL_FACE),i.enable(t.DEPTH_TEST),i.buffers.depth.setMask(!0),i.reset()}}}function st(e,t,i,r,n,o,a,s,c){ce.call(this,e,t,i,r,n,o,a,s,c),this.needsUpdate=!0}function ct(e,t,i,r,n){var o,a,s,c,h,l,u=new oe,p=new ne,d=new oe;function f(){var e=new Float32Array([-.5,-.5,0,0,.5,-.5,1,0,.5,.5,1,1,-.5,.5,0,1]),i=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s=function(){var e=t.createProgram(),i=t.createShader(t.VERTEX_SHADER),r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float rotation;","uniform vec2 scale;","uniform vec2 uvOffset;","uniform vec2 uvScale;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvUV = uvOffset + uv * uvScale;","\tvec2 alignedPosition = position * scale;","\tvec2 rotatedPosition;","\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;","\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;","\tvec4 mvPosition;","\tmvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );","\tmvPosition.xy += rotatedPosition;","\tgl_Position = projectionMatrix * mvPosition;","\tfogDepth = - mvPosition.z;","}"].join("\n")),t.shaderSource(r,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform vec3 color;","uniform sampler2D map;","uniform float opacity;","uniform int fogType;","uniform vec3 fogColor;","uniform float fogDensity;","uniform float fogNear;","uniform float fogFar;","uniform float alphaTest;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvec4 texture = texture2D( map, vUV );","\tgl_FragColor = vec4( color * texture.xyz, texture.a * opacity );","\tif ( gl_FragColor.a < alphaTest ) discard;","\tif ( fogType > 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),t.compileShader(i),t.compileShader(r),t.attachShader(e,i),t.attachShader(e,r),t.linkProgram(e),e}(),c={position:t.getAttribLocation(s,"position"),uv:t.getAttribLocation(s,"uv")},h={uvOffset:t.getUniformLocation(s,"uvOffset"),uvScale:t.getUniformLocation(s,"uvScale"),rotation:t.getUniformLocation(s,"rotation"),scale:t.getUniformLocation(s,"scale"),color:t.getUniformLocation(s,"color"),map:t.getUniformLocation(s,"map"),opacity:t.getUniformLocation(s,"opacity"),modelViewMatrix:t.getUniformLocation(s,"modelViewMatrix"),projectionMatrix:t.getUniformLocation(s,"projectionMatrix"),fogType:t.getUniformLocation(s,"fogType"),fogDensity:t.getUniformLocation(s,"fogDensity"),fogNear:t.getUniformLocation(s,"fogNear"),fogFar:t.getUniformLocation(s,"fogFar"),fogColor:t.getUniformLocation(s,"fogColor"),fogDepth:t.getUniformLocation(s,"fogDepth"),alphaTest:t.getUniformLocation(s,"alphaTest")};var r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");r.width=8,r.height=8;var u=r.getContext("2d");u.fillStyle="white",u.fillRect(0,0,8,8),l=new st(r)}function m(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(n,v,g){if(0!==n.length){void 0===s&&f(),i.useProgram(s),i.initAttributes(),i.enableAttribute(c.position),i.enableAttribute(c.uv),i.disableUnusedAttributes(),i.disable(t.CULL_FACE),i.enable(t.BLEND),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(c.position,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(c.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.uniformMatrix4fv(h.projectionMatrix,!1,g.projectionMatrix.elements),i.activeTexture(t.TEXTURE0),t.uniform1i(h.map,0);var y=0,x=0,b=v.fog;b?(t.uniform3f(h.fogColor,b.color.r,b.color.g,b.color.b),b.isFog?(t.uniform1f(h.fogNear,b.near),t.uniform1f(h.fogFar,b.far),t.uniform1i(h.fogType,1),y=1,x=1):b.isFogExp2&&(t.uniform1f(h.fogDensity,b.density),t.uniform1i(h.fogType,2),y=2,x=2)):(t.uniform1i(h.fogType,0),y=0,x=0);for(var w=0,_=n.length;w<_;w++){(E=n[w]).modelViewMatrix.multiplyMatrices(g.matrixWorldInverse,E.matrixWorld),E.z=-E.modelViewMatrix.elements[14]}n.sort(m);var M=[];for(w=0,_=n.length;w<_;w++){var E,T=(E=n[w]).material;if(!1!==T.visible){E.onBeforeRender(e,v,g,void 0,T,void 0),t.uniform1f(h.alphaTest,T.alphaTest),t.uniformMatrix4fv(h.modelViewMatrix,!1,E.modelViewMatrix.elements),E.matrixWorld.decompose(u,p,d),M[0]=d.x,M[1]=d.y;var S=0;v.fog&&T.fog&&(S=x),y!==S&&(t.uniform1i(h.fogType,S),y=S),null!==T.map?(t.uniform2f(h.uvOffset,T.map.offset.x,T.map.offset.y),t.uniform2f(h.uvScale,T.map.repeat.x,T.map.repeat.y)):(t.uniform2f(h.uvOffset,0,0),t.uniform2f(h.uvScale,1,1)),t.uniform1f(h.opacity,T.opacity),t.uniform3f(h.color,T.color.r,T.color.g,T.color.b),t.uniform1f(h.rotation,T.rotation),t.uniform2fv(h.scale,M),i.setBlending(T.blending,T.blendEquation,T.blendSrc,T.blendDst,T.blendEquationAlpha,T.blendSrcAlpha,T.blendDstAlpha,T.premultipliedAlpha),i.buffers.depth.setTest(T.depthTest),i.buffers.depth.setMask(T.depthWrite),i.buffers.color.setMask(T.colorWrite),r.setTexture2D(T.map||l,0),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0),E.onAfterRender(e,v,g,void 0,T,void 0)}}i.enable(t.CULL_FACE),i.reset()}}}nt.physical={uniforms:it.merge([nt.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},Object.assign(ot.prototype,{set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y},getParameter:function(e,t){return(t||new ie).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return(t||new ie).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new ie;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),st.prototype=Object.create(ce.prototype),st.prototype.constructor=st;var ht,lt,ut,pt,dt,ft,mt,vt=0;function gt(){Object.defineProperty(this,"id",{value:vt++}),this.uuid=te.generateUUID(),this.name="",this.type="Material",this.fog=!0,this.lights=!0,this.blending=1,this.side=0,this.flatShading=!1,this.vertexColors=0,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=100,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaTest=0,this.premultipliedAlpha=!1,this.overdraw=0,this.visible=!0,this.userData={},this.needsUpdate=!0}function yt(e){gt.call(this),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.setValues(e)}function xt(e){gt.call(this),this.type="MeshDistanceMaterial",this.referencePosition=new oe,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.lights=!1,this.setValues(e)}function bt(e,t){this.min=void 0!==e?e:new oe(1/0,1/0,1/0),this.max=void 0!==t?t:new oe(-1/0,-1/0,-1/0)}function wt(e,t){this.center=void 0!==e?e:new oe,this.radius=void 0!==t?t:0}function _t(e,t){this.normal=void 0!==e?e:new oe(1,0,0),this.constant=void 0!==t?t:0}function Mt(e,t,i,r,n,o){this.planes=[void 0!==e?e:new _t,void 0!==t?t:new _t,void 0!==i?i:new _t,void 0!==r?r:new _t,void 0!==n?n:new _t,void 0!==o?o:new _t]}function Et(e,t,i){for(var r=new Mt,n=new re,o=new ie,a=new ie(i,i),s=new oe,c=new oe,h=new Array(4),l=new Array(4),u={},p=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],d=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)],f=[new he,new he,new he,new he,new he,new he],m=0;4!==m;++m){var v=0!=(1&m),g=0!=(2&m),y=new yt({depthPacking:3201,morphTargets:v,skinning:g});h[m]=y;var x=new xt({morphTargets:v,skinning:g});l[m]=x}var b=this;function w(t,i,r,n,o,a){var s=t.geometry,c=null,p=h,d=t.customDepthMaterial;if(r&&(p=l,d=t.customDistanceMaterial),d)c=d;else{var f=!1;i.morphTargets&&(s&&s.isBufferGeometry?f=s.morphAttributes&&s.morphAttributes.position&&s.morphAttributes.position.length>0:s&&s.isGeometry&&(f=s.morphTargets&&s.morphTargets.length>0)),t.isSkinnedMesh&&!1===i.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t);var m=0;f&&(m|=1),t.isSkinnedMesh&&i.skinning&&(m|=2),c=p[m]}if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var v=c.uuid,g=i.uuid,y=u[v];void 0===y&&(y={},u[v]=y);var x=y[g];void 0===x&&(x=c.clone(),y[g]=x),c=x}c.visible=i.visible,c.wireframe=i.wireframe;var w=i.side;return b.renderSingleSided&&2==w&&(w=0),b.renderReverseSided&&(0===w?w=1:1===w&&(w=0)),c.side=w,c.clipShadows=i.clipShadows,c.clippingPlanes=i.clippingPlanes,c.clipIntersection=i.clipIntersection,c.wireframeLinewidth=i.wireframeLinewidth,c.linewidth=i.linewidth,r&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(n),c.nearDistance=o,c.farDistance=a),c}function _(i,n,o,a){if(!1!==i.visible){if(i.layers.test(n.layers)&&(i.isMesh||i.isLine||i.isPoints)&&i.castShadow&&(!i.frustumCulled||r.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(o.matrixWorldInverse,i.matrixWorld);var s=t.update(i),h=i.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u0&&(i.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(i.morphTargets=!0),!0===this.skinning&&(i.skinning=!0),!1===this.visible&&(i.visible=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),t){var n=r(e.textures),o=r(e.images);n.length>0&&(i.textures=n),o.length>0&&(i.images=o)}return i},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.lights=e.lights,this.blending=e.blending,this.side=e.side,this.flatShading=e.flatShading,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.premultipliedAlpha=e.premultipliedAlpha,this.overdraw=e.overdraw,this.visible=e.visible,this.userData=JSON.parse(JSON.stringify(e.userData)),this.clipShadows=e.clipShadows,this.clipIntersection=e.clipIntersection;var t=e.clippingPlanes,i=null;if(null!==t){var r=t.length;i=new Array(r);for(var n=0;n!==r;++n)i[n]=t[n].clone()}return this.clippingPlanes=i,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),yt.prototype=Object.create(gt.prototype),yt.prototype.constructor=yt,yt.prototype.isMeshDepthMaterial=!0,yt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.depthPacking=e.depthPacking,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this},xt.prototype=Object.create(gt.prototype),xt.prototype.constructor=xt,xt.prototype.isMeshDistanceMaterial=!0,xt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.referencePosition.copy(e.referencePosition),this.nearDistance=e.nearDistance,this.farDistance=e.farDistance,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this},Object.assign(bt.prototype,{isBox3:!0,set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromArray:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.length;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromBufferAttribute:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.count;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return(t||new oe).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:(lt=new oe,function(e){return this.clampPoint(e.center,lt),lt.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=e.constant&&i>=e.constant},clampPoint:function(e,t){return(t||new oe).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new oe;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),getBoundingSphere:function(){var e=new oe;return function(t){var i=t||new wt;return this.getCenter(i.center),i.radius=.5*this.getSize(e).length(),i}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:(ht=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],function(e){return this.isEmpty()||(ht[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),ht[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),ht[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),ht[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),ht[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),ht[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),ht[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),ht[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(ht)),this}),translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),Object.assign(wt.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(ut=new bt,function(e,t){var i=this.center;void 0!==t?i.copy(t):ut.setFromPoints(e).getCenter(i);for(var r=0,n=0,o=e.length;nthis.radius*this.radius&&(r.sub(this.center).normalize(),r.multiplyScalar(this.radius).add(this.center)),r},getBoundingBox:function(e){var t=e||new bt;return t.set(this.center,this.center),t.expandByScalar(this.radius),t},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}}),Object.assign(_t.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(){var e=new oe,t=new oe;return function(i,r,n){var o=e.subVectors(n,r).cross(t.subVectors(i,r)).normalize();return this.setFromNormalAndCoplanarPoint(o,i),this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return(t||new oe).copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(){var e=new oe;return function(t,i){var r=i||new oe,n=t.delta(e),o=this.normal.dot(n);if(0===o)return 0===this.distanceToPoint(t.start)?r.copy(t.start):void 0;var a=-(t.start.dot(this.normal)+this.constant)/o;return a<0||a>1?void 0:r.copy(n).multiplyScalar(a).add(t.start)}}(),intersectsLine:function(e){var t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return(e||new oe).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var e=new oe,t=new ae;return function(i,r){var n=r||t.getNormalMatrix(i),o=this.coplanarPoint(e).applyMatrix4(i),a=this.normal.applyMatrix3(n).normalize();return this.constant=-o.dot(a),this}}(),translate:function(e){return this.constant-=e.dot(this.normal),this},equals:function(e){return e.normal.equals(this.normal)&&e.constant===this.constant}}),Object.assign(Mt.prototype,{set:function(e,t,i,r,n,o){var a=this.planes;return a[0].copy(e),a[1].copy(t),a[2].copy(i),a[3].copy(r),a[4].copy(n),a[5].copy(o),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,i=0;i<6;i++)t[i].copy(e.planes[i]);return this},setFromMatrix:function(e){var t=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],s=i[4],c=i[5],h=i[6],l=i[7],u=i[8],p=i[9],d=i[10],f=i[11],m=i[12],v=i[13],g=i[14],y=i[15];return t[0].setComponents(a-r,l-s,f-u,y-m).normalize(),t[1].setComponents(a+r,l+s,f+u,y+m).normalize(),t[2].setComponents(a+n,l+c,f+p,y+v).normalize(),t[3].setComponents(a-n,l-c,f-p,y-v).normalize(),t[4].setComponents(a-o,l-h,f-d,y-g).normalize(),t[5].setComponents(a+o,l+h,f+d,y+g).normalize(),this},intersectsObject:(ft=new wt,function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),ft.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(ft)}),intersectsSprite:function(){var e=new wt;return function(t){return e.center.set(0,0,0),e.radius=.7071067811865476,e.applyMatrix4(t.matrixWorld),this.intersectsSphere(e)}}(),intersectsSphere:function(e){for(var t=this.planes,i=e.center,r=-e.radius,n=0;n<6;n++){if(t[n].distanceToPoint(i)0?e.min.x:e.max.x,dt.x=r.normal.x>0?e.max.x:e.min.x,pt.y=r.normal.y>0?e.min.y:e.max.y,dt.y=r.normal.y>0?e.max.y:e.min.y,pt.z=r.normal.z>0?e.min.z:e.max.z,dt.z=r.normal.z>0?e.max.z:e.min.z;var n=r.distanceToPoint(pt),o=r.distanceToPoint(dt);if(n<0&&o<0)return!1}return!0}),containsPoint:function(e){for(var t=this.planes,i=0;i<6;i++)if(t[i].distanceToPoint(e)<0)return!1;return!0}}),St.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],St.DefaultOrder="XYZ",Object.defineProperties(St.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},order:{get:function(){return this._order},set:function(e){this._order=e,this.onChangeCallback()}}}),Object.assign(St.prototype,{isEuler:!0,set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._order=r||this._order,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)},copy:function(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this.onChangeCallback(),this},setFromRotationMatrix:function(e,t,i){var r=te.clamp,n=e.elements,o=n[0],a=n[4],s=n[8],c=n[1],h=n[5],l=n[9],u=n[2],p=n[6],d=n[10];return"XYZ"===(t=t||this._order)?(this._y=Math.asin(r(s,-1,1)),Math.abs(s)<.99999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-a,o)):(this._x=Math.atan2(p,h),this._z=0)):"YXZ"===t?(this._x=Math.asin(-r(l,-1,1)),Math.abs(l)<.99999?(this._y=Math.atan2(s,d),this._z=Math.atan2(c,h)):(this._y=Math.atan2(-u,o),this._z=0)):"ZXY"===t?(this._x=Math.asin(r(p,-1,1)),Math.abs(p)<.99999?(this._y=Math.atan2(-u,d),this._z=Math.atan2(-a,h)):(this._y=0,this._z=Math.atan2(c,o))):"ZYX"===t?(this._y=Math.asin(-r(u,-1,1)),Math.abs(u)<.99999?(this._x=Math.atan2(p,d),this._z=Math.atan2(c,o)):(this._x=0,this._z=Math.atan2(-a,h))):"YZX"===t?(this._z=Math.asin(r(c,-1,1)),Math.abs(c)<.99999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-u,o)):(this._x=0,this._y=Math.atan2(s,d))):"XZY"===t?(this._z=Math.asin(-r(a,-1,1)),Math.abs(a)<.99999?(this._x=Math.atan2(p,h),this._y=Math.atan2(s,o)):(this._x=Math.atan2(-l,d),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+t),this._order=t,!1!==i&&this.onChangeCallback(),this},setFromQuaternion:function(){var e=new re;return function(t,i,r){return e.makeRotationFromQuaternion(t),this.setFromRotationMatrix(e,i,r)}}(),setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:(mt=new ne,function(e){return mt.setFromEuler(this),this.setFromQuaternion(mt,e)}),equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order},fromArray:function(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e},toVector3:function(e){return e?e.set(this._x,this._y,this._z):new oe(this._x,this._y,this._z)},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(At.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){r.children=[];for(s=0;s0&&(i.geometries=u),p.length>0&&(i.materials=p),d.length>0&&(i.textures=d),f.length>0&&(i.images=f),a.length>0&&(i.shapes=a)}return i.object=r,i;function m(e){var t=[];for(var i in e){var r=e[i];delete r.metadata,t.push(r)}return t}},clone:function(e){return(new this.constructor).copy(this,e)},copy:function(e,t){if(void 0===t&&(t=!0),this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(var i=0;it&&(t=e[i]);return t}zt.prototype=Object.assign(Object.create(n.prototype),{constructor:zt,isGeometry:!0,applyMatrix:function(e){for(var t=(new ae).getNormalMatrix(e),i=0,r=this.vertices.length;i0)for(p=0;p0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,i;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,i,r,n;for(i=0,r=this.faces.length;i0&&(e+=t[i].distanceTo(t[i-1])),this.lineDistances[i]=e},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt),this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new wt),this.boundingSphere.setFromPoints(this.vertices)},merge:function(e,t,i){if(e&&e.isGeometry){var r,n=this.vertices.length,o=this.vertices,a=e.vertices,s=this.faces,c=e.faces,h=this.faceVertexUvs[0],l=e.faceVertexUvs[0],u=this.colors,p=e.colors;void 0===i&&(i=0),void 0!==t&&(r=(new ae).getNormalMatrix(t));for(var d=0,f=a.length;d=0;i--){var f=p[i];for(this.faces.splice(f,1),a=0,s=this.faceVertexUvs.length;a0,v=d.vertexNormals.length>0,g=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,v),x=M(x,6,g),x=M(x,7,y),a.push(x),a.push(d.a,d.b,d.c),a.push(d.materialIndex),f){var b=this.faceVertexUvs[0][n];a.push(S(b[0]),S(b[1]),S(b[2]))}if(m&&a.push(E(d.normal)),v){var w=d.vertexNormals;a.push(E(w[0]),E(w[1]),E(w[2]))}if(g&&a.push(T(d.color)),y){var _=d.vertexColors;a.push(T(_[0]),T(_[1]),T(_[2]))}}function M(e,t,i){return i?e|1<0&&(e.data.colors=h),u.length>0&&(e.data.uvs=[u]),e.data.faces=a,e},clone:function(){return(new zt).copy(this)},copy:function(e){var t,i,r,n,o,a;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var s=e.vertices;for(t=0,i=s.length;t0,a=n[1]&&n[1].length>0,s=e.morphTargets,c=s.length;if(c>0){t=[];for(var h=0;h0){l=[];for(h=0;h0?1:-1,h.push(L.x,L.y,L.z),l.push(y/m),l.push(1-x/v),A+=1}}for(x=0;x1&&i.sort(yi),r.length>1&&r.sort(xi)}}}function wi(){var e={};return{get:function(t,i){var r=t.id+","+i.id,n=e[r];return void 0===n&&(n=new bi,e[r]=n),n},dispose:function(){e={}}}}function _i(e,t){return Math.abs(t[1])-Math.abs(e[1])}function Mi(e){var t={},i=new Float32Array(8);return{update:function(r,n,o,a){var s=r.morphTargetInfluences,c=s.length,h=t[n.id];if(void 0===h){h=[];for(var l=0;l65535?qt:Wt)(a,1),t.update(r,e.ELEMENT_ARRAY_BUFFER),n[i.id]=r,r}}}function Ai(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var i;switch(t.type){case"DirectionalLight":i={direction:new oe,color:new et,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"SpotLight":i={position:new oe,direction:new oe,color:new et,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"PointLight":i={position:new oe,color:new et,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":i={direction:new oe,skyColor:new et,groundColor:new et};break;case"RectAreaLight":i={color:new et,position:new oe,halfWidth:new oe,halfHeight:new oe}}return e[t.id]=i,i}}}function Ri(){var e=new Ai,t={hash:"",ambient:[0,0,0],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},i=new oe,r=new re,n=new re;return{setup:function(o,a,s){for(var c=0,h=0,l=0,u=0,p=0,d=0,f=0,m=0,v=s.matrixWorldInverse,g=0,y=o.length;g65535?qt:Wt)(e,1):this.index=e},addAttribute:function(e,t){return t&&t.isBufferAttribute||t&&t.isInterleavedBufferAttribute?"index"===e?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),void this.setIndex(t)):(this.attributes[e]=t,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),void this.addAttribute(e,new kt(arguments[1],arguments[2])))},getAttribute:function(e){return this.attributes[e]},removeAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,i){this.groups.push({start:e,count:t,materialIndex:void 0!==i?i:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix:function(e){var t=this.attributes.position;void 0!==t&&(e.applyToBufferAttribute(t),t.needsUpdate=!0);var i=this.attributes.normal;void 0!==i&&((new ae).getNormalMatrix(e).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var e=new re;return function(t){return e.makeRotationX(t),this.applyMatrix(e),this}}(),rotateY:function(){var e=new re;return function(t){return e.makeRotationY(t),this.applyMatrix(e),this}}(),rotateZ:function(){var e=new re;return function(t){return e.makeRotationZ(t),this.applyMatrix(e),this}}(),translate:function(){var e=new re;return function(t,i,r){return e.makeTranslation(t,i,r),this.applyMatrix(e),this}}(),scale:function(){var e=new re;return function(t,i,r){return e.makeScale(t,i,r),this.applyMatrix(e),this}}(),lookAt:function(){var e=new Ot;return function(t){e.lookAt(t),e.updateMatrix(),this.applyMatrix(e.matrix)}}(),center:function(){this.computeBoundingBox();var e=this.boundingBox.getCenter().negate();return this.translate(e.x,e.y,e.z),e},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var i=new Yt(3*t.vertices.length,3),r=new Yt(3*t.colors.length,3);if(this.addAttribute("position",i.copyVector3sArray(t.vertices)),this.addAttribute("color",r.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var n=new Yt(t.lineDistances.length,1);this.addAttribute("lineDistance",n.copyArray(t.lineDistances))}null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone())}else e.isMesh&&t&&t.isGeometry&&this.fromGeometry(t);return this},setFromPoints:function(e){for(var t=[],i=0,r=e.length;i0){var i=new Float32Array(3*e.normals.length);this.addAttribute("normal",new kt(i,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var r=new Float32Array(3*e.colors.length);this.addAttribute("color",new kt(r,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var n=new Float32Array(2*e.uvs.length);this.addAttribute("uv",new kt(n,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var o=new Float32Array(2*e.uvs2.length);this.addAttribute("uv2",new kt(o,2).copyVector2sArray(e.uvs2))}if(e.indices.length>0){var a=new(Kt(e.indices)>65535?Uint32Array:Uint16Array)(3*e.indices.length);this.setIndex(new kt(a,1).copyIndicesArray(e.indices))}for(var s in this.groups=e.groups,e.morphTargets){for(var c=[],h=e.morphTargets[s],l=0,u=h.length;l0){var f=new Yt(4*e.skinIndices.length,4);this.addAttribute("skinIndex",f.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var m=new Yt(4*e.skinWeights.length,4);this.addAttribute("skinWeight",m.copyVector4sArray(e.skinWeights))}return null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone()),this},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt);var e=this.attributes.position;void 0!==e?this.boundingBox.setFromBufferAttribute(e):this.boundingBox.makeEmpty(),(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:function(){var e=new bt,t=new oe;return function(){null===this.boundingSphere&&(this.boundingSphere=new wt);var i=this.attributes.position;if(i){var r=this.boundingSphere.center;e.setFromBufferAttribute(i),e.getCenter(r);for(var n=0,o=0,a=i.count;o0&&(e.data.groups=JSON.parse(JSON.stringify(s)));var c=this.boundingSphere;return null!==c&&(e.data.boundingSphere={center:c.center.toArray(),radius:c.radius}),e},clone:function(){return(new ai).copy(this)},copy:function(e){var t,i,r;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var n=e.index;null!==n&&this.setIndex(n.clone());var o=e.attributes;for(t in o){var a=o[t];this.addAttribute(t,a.clone())}var s=e.morphAttributes;for(t in s){var c=[],h=s[t];for(i=0,r=h.length;i0)if(o=h*l-u,s=c*d,(n=h*u-l)>=0)if(o>=-s)if(o<=s){var f=1/d;a=(n*=f)*(n+h*(o*=f)+2*l)+o*(h*n+o+2*u)+p}else o=c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o=-c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o<=-s?a=-(n=Math.max(0,-(-h*c+l)))*n+(o=n>0?-c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p:o<=s?(n=0,a=(o=Math.min(Math.max(-c,-u),c))*(o+2*u)+p):a=-(n=Math.max(0,-(h*c+l)))*n+(o=n>0?c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p;else o=h>0?-c:c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;return i&&i.copy(this.direction).multiplyScalar(n).add(this.origin),r&&r.copy(ei).multiplyScalar(o).add($t),a}),intersectSphere:function(){var e=new oe;return function(t,i){e.subVectors(t.center,this.origin);var r=e.dot(this.direction),n=e.dot(e)-r*r,o=t.radius*t.radius;if(n>o)return null;var a=Math.sqrt(o-n),s=r-a,c=r+a;return s<0&&c<0?null:s<0?this.at(c,i):this.at(s,i)}}(),intersectsSphere:function(e){return this.distanceToPoint(e.center)<=e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null},intersectPlane:function(e,t){var i=this.distanceToPlane(e);return null===i?null:this.at(i,t)},intersectsPlane:function(e){var t=e.distanceToPoint(this.origin);return 0===t||e.normal.dot(this.direction)*t<0},intersectBox:function(e,t){var i,r,n,o,a,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(i=(e.min.x-u.x)*c,r=(e.max.x-u.x)*c):(i=(e.max.x-u.x)*c,r=(e.min.x-u.x)*c),h>=0?(n=(e.min.y-u.y)*h,o=(e.max.y-u.y)*h):(n=(e.max.y-u.y)*h,o=(e.min.y-u.y)*h),i>o||n>r?null:((n>i||i!=i)&&(i=n),(o=0?(a=(e.min.z-u.z)*l,s=(e.max.z-u.z)*l):(a=(e.max.z-u.z)*l,s=(e.min.z-u.z)*l),i>s||a>r?null:((a>i||i!=i)&&(i=a),(s=0?i:r,t)))},intersectsBox:(Qt=new oe,function(e){return null!==this.intersectBox(e,Qt)}),intersectTriangle:function(){var e=new oe,t=new oe,i=new oe,r=new oe;return function(n,o,a,s,c){t.subVectors(o,n),i.subVectors(a,n),r.crossVectors(t,i);var h,l=this.direction.dot(r);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}e.subVectors(this.origin,n);var u=h*this.direction.dot(i.crossVectors(e,i));if(u<0)return null;var p=h*this.direction.dot(t.cross(e));if(p<0)return null;if(u+p>l)return null;var d=-h*e.dot(r);return d<0?null:this.at(d/l,c)}}(),applyMatrix4:function(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this},equals:function(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}}),Object.assign(fi.prototype,{set:function(e,t){return this.start.copy(e),this.end.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.start.copy(e.start),this.end.copy(e.end),this},getCenter:function(e){return(e||new oe).addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(e){return(e||new oe).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(e,t){var i=t||new oe;return this.delta(i).multiplyScalar(e).add(this.start)},closestPointToPointParameter:(ii=new oe,ri=new oe,function(e,t){ii.subVectors(e,this.start),ri.subVectors(this.end,this.start);var i=ri.dot(ri),r=ri.dot(ii)/i;return t&&(r=te.clamp(r,0,1)),r}),closestPointToPoint:function(e,t,i){var r=this.closestPointToPointParameter(e,t),n=i||new oe;return this.delta(n).multiplyScalar(r).add(this.start)},applyMatrix4:function(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this},equals:function(e){return e.start.equals(this.start)&&e.end.equals(this.end)}}),Object.assign(mi,{normal:(ni=new oe,function(e,t,i,r){var n=r||new oe;n.subVectors(i,t),ni.subVectors(e,t),n.cross(ni);var o=n.lengthSq();return o>0?n.multiplyScalar(1/Math.sqrt(o)):n.set(0,0,0)}),barycoordFromPoint:function(){var e=new oe,t=new oe,i=new oe;return function(r,n,o,a,s){e.subVectors(a,n),t.subVectors(o,n),i.subVectors(r,n);var c=e.dot(e),h=e.dot(t),l=e.dot(i),u=t.dot(t),p=t.dot(i),d=c*u-h*h,f=s||new oe;if(0===d)return f.set(-2,-1,-1);var m=1/d,v=(u*l-h*p)*m,g=(c*p-h*l)*m;return f.set(1-v-g,g,v)}}(),containsPoint:function(){var e=new oe;return function(t,i,r,n){var o=mi.barycoordFromPoint(t,i,r,n,e);return o.x>=0&&o.y>=0&&o.x+o.y<=1}}()}),Object.assign(mi.prototype,{set:function(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this},setFromPointsAndIndices:function(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this},area:function(){var e=new oe,t=new oe;return function(){return e.subVectors(this.c,this.b),t.subVectors(this.a,this.b),.5*e.cross(t).length()}}(),midpoint:function(e){return(e||new oe).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(e){return mi.normal(this.a,this.b,this.c,e)},plane:function(e){return(e||new _t).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(e,t){return mi.barycoordFromPoint(e,this.a,this.b,this.c,t)},containsPoint:function(e){return mi.containsPoint(e,this.a,this.b,this.c)},closestPointToPoint:function(){var e=new _t,t=[new fi,new fi,new fi],i=new oe,r=new oe;return function(n,o){var a=o||new oe,s=1/0;if(e.setFromCoplanarPoints(this.a,this.b,this.c),e.projectPoint(n,i),!0===this.containsPoint(i))a.copy(i);else{t[0].set(this.a,this.b),t[1].set(this.b,this.c),t[2].set(this.c,this.a);for(var c=0;c0){var a=n[o[0]];if(void 0!==a)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=a.length;e0)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=s.length;ei.far?null:{distance:c,point:f.clone(),object:e}}function g(e,t,i,a,s,c,p,f){r.fromBufferAttribute(a,c),n.fromBufferAttribute(a,p),o.fromBufferAttribute(a,f);var g=v(e,e.material,t,i,r,n,o,d);return g&&(s&&(h.fromBufferAttribute(s,c),l.fromBufferAttribute(s,p),u.fromBufferAttribute(s,f),g.uv=m(d,r,n,o,h,l,u)),g.face=new Ut(c,p,f,mi.normal(r,n,o)),g.faceIndex=c),g}return function(p,f){var y,x=this.geometry,b=this.material,w=this.matrixWorld;if(void 0!==b&&(null===x.boundingSphere&&x.computeBoundingSphere(),i.copy(x.boundingSphere),i.applyMatrix4(w),!1!==p.ray.intersectsSphere(i)&&(e.getInverse(w),t.copy(p.ray).applyMatrix4(e),null===x.boundingBox||!1!==t.intersectsBox(x.boundingBox))))if(x.isBufferGeometry){var _,M,E,T,S,A=x.index,R=x.attributes.position,L=x.attributes.uv;if(null!==A)for(T=0,S=A.count;T0&&(O=B);for(var F=0,z=U.length;F/gm,(function(e,t){var i=rt[t];if(void 0===i)throw new Error("Can not resolve #include <"+t+">");return ji(i)}))}function Hi(e){return e.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,(function(e,t,i,r){for(var n="",o=parseInt(t);o0?e.gammaFactor:1,T=function(e,t,i){return[(e=e||{}).derivatives||t.envMapCubeUV||t.bumpMap||t.normalMap||t.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(e.fragDepth||t.logarithmicDepthBuffer)&&i.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",e.drawBuffers&&i.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(e.shaderTextureLOD||t.envMap)&&i.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Gi).join("\n")}(r.extensions,o,t),S=function(e){var t=[];for(var i in e){var r=e[i];!1!==r&&t.push("#define "+i+" "+r)}return t.join("\n")}(s),A=a.createProgram();r.isRawShaderMaterial?((f=[S].filter(Gi).join("\n")).length>0&&(f+="\n"),(b=[T,S].filter(Gi).join("\n")).length>0&&(b+="\n")):(f=["precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+E,"#define MAX_BONES "+o.maxBones,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+p:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.displacementMap&&o.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.flatShading?"#define FLAT_SHADED":"",o.skinning?"#define USE_SKINNING":"",o.useVertexTexture?"#define BONE_TEXTURE":"",o.morphTargets?"#define USE_MORPHTARGETS":"",o.morphNormals&&!1===o.flatShading?"#define USE_MORPHNORMALS":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.sizeAttenuation?"#define USE_SIZEATTENUATION":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Gi).join("\n"),b=[T,"precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.alphaTest?"#define ALPHATEST "+o.alphaTest:"","#define GAMMA_FACTOR "+E,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+u:"",o.envMap?"#define "+p:"",o.envMap?"#define "+d:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.gradientMap?"#define USE_GRADIENTMAP":"",o.flatShading?"#define FLAT_SHADED":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,"#define UNION_CLIPPING_PLANES "+(o.numClippingPlanes-o.numClipIntersection),o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",o.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"",o.envMap&&t.get("EXT_shader_texture_lod")?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",0!==o.toneMapping?"#define TONE_MAPPING":"",0!==o.toneMapping?rt.tonemapping_pars_fragment:"",0!==o.toneMapping?ki("toneMapping",o.toneMapping):"",o.dithering?"#define DITHERING":"",o.outputEncoding||o.mapEncoding||o.envMapEncoding||o.emissiveMapEncoding?rt.encodings_pars_fragment:"",o.mapEncoding?zi("mapTexelToLinear",o.mapEncoding):"",o.envMapEncoding?zi("envMapTexelToLinear",o.envMapEncoding):"",o.emissiveMapEncoding?zi("emissiveMapTexelToLinear",o.emissiveMapEncoding):"",o.outputEncoding?(w="linearToOutputTexel",_=o.outputEncoding,M=Fi(_),"vec4 "+w+"( vec4 value ) { return LinearTo"+M[0]+M[1]+"; }"):"",o.depthPacking?"#define DEPTH_PACKING "+r.depthPacking:"","\n"].filter(Gi).join("\n")),c=Vi(c=ji(c),o),h=Vi(h=ji(h),o),r.isShaderMaterial||(c=Hi(c),h=Hi(h));var R=f+c,L=b+h,C=Ci(a,a.VERTEX_SHADER,R),P=Ci(a,a.FRAGMENT_SHADER,L);a.attachShader(A,C),a.attachShader(A,P),void 0!==r.index0AttributeName?a.bindAttribLocation(A,0,r.index0AttributeName):!0===o.morphTargets&&a.bindAttribLocation(A,0,"position"),a.linkProgram(A);var N,O,I=a.getProgramInfoLog(A),D=a.getShaderInfoLog(C),U=a.getShaderInfoLog(P),B=!0,F=!0;return!1===a.getProgramParameter(A,a.LINK_STATUS)?(B=!1,console.error("THREE.WebGLProgram: shader error: ",a.getError(),"gl.VALIDATE_STATUS",a.getProgramParameter(A,a.VALIDATE_STATUS),"gl.getProgramInfoLog",I,D,U)):""!==I?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",I):""!==D&&""!==U||(F=!1),F&&(this.diagnostics={runnable:B,material:r,programLog:I,vertexShader:{log:D,prefix:f},fragmentShader:{log:U,prefix:b}}),a.deleteShader(C),a.deleteShader(P),this.getUniforms=function(){return void 0===N&&(N=new Qe(a,A,e)),N},this.getAttributes=function(){return void 0===O&&(O=function(e,t){for(var i={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;n0,maxBones:p,useVertexTexture:i.floatVertexTextures,morphTargets:t.morphTargets,morphNormals:t.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:r.directional.length,numPointLights:r.point.length,numSpotLights:r.spot.length,numRectAreaLights:r.rectArea.length,numHemiLights:r.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:t.dithering,shadowMapEnabled:e.shadowMap.enabled&&l.receiveShadow&&o.length>0,shadowMapType:e.shadowMap.type,toneMapping:e.toneMapping,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:t.premultipliedAlpha,alphaTest:t.alphaTest,doubleSided:2===t.side,flipSided:1===t.side,depthPacking:void 0!==t.depthPacking&&t.depthPacking}},this.getProgramCode=function(t,i){var r=[];if(i.shaderID?r.push(i.shaderID):(r.push(t.fragmentShader),r.push(t.vertexShader)),void 0!==t.defines)for(var n in t.defines)r.push(n),r.push(t.defines[n]);for(var a=0;at||e.height>t){var i=t/Math.max(e.width,e.height),r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return r.width=Math.floor(e.width*i),r.height=Math.floor(e.height*i),r.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,r.width,r.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+r.width+"x"+r.height,e),r}return e}function l(e){return te.isPowerOfTwo(e.width)&&te.isPowerOfTwo(e.height)}function u(e,t){return e.generateMipmaps&&t&&e.minFilter!==M&&e.minFilter!==S}function p(t){return t===M||t===E||t===T?e.NEAREST:e.LINEAR}function d(t){var i=t.target;i.removeEventListener("dispose",d),function(t){var i=r.get(t);if(t.image&&i.__image__webglTextureCube)e.deleteTexture(i.__image__webglTextureCube);else{if(void 0===i.__webglInit)return;e.deleteTexture(i.__webglTexture)}r.remove(t)}(i),i.isVideoTexture&&delete c[i.id],a.textures--}function f(t){var i=t.target;i.removeEventListener("dispose",f),function(t){var i=r.get(t),n=r.get(t.texture);if(!t)return;void 0!==n.__webglTexture&&e.deleteTexture(n.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLRenderTargetCube)for(var o=0;o<6;o++)e.deleteFramebuffer(i.__webglFramebuffer[o]),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer[o]);else e.deleteFramebuffer(i.__webglFramebuffer),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer);r.remove(t.texture),r.remove(t)}(i),a.textures--}function m(t,p){var f=r.get(t);if(t.version>0&&f.__version!==t.version){var m=t.image;if(void 0===m)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined",t);else{if(!1!==m.complete)return void function(t,r,p){void 0===t.__webglInit&&(t.__webglInit=!0,r.addEventListener("dispose",d),t.__webglTexture=e.createTexture(),r.isVideoTexture&&(c[r.id]=r),a.textures++);i.activeTexture(e.TEXTURE0+p),i.bindTexture(e.TEXTURE_2D,t.__webglTexture),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,r.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,r.unpackAlignment);var f=h(r.image,n.maxTextureSize);(function(e){return e.wrapS!==w||e.wrapT!==w||e.minFilter!==M&&e.minFilter!==S})(r)&&!1===l(f)&&(f=function(e){if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement||e instanceof ImageBitmap){var t=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return t.width=te.floorPowerOfTwo(e.width),t.height=te.floorPowerOfTwo(e.height),t.getContext("2d").drawImage(e,0,0,t.width,t.height),console.warn("THREE.WebGLRenderer: image is not power of two ("+e.width+"x"+e.height+"). Resized to "+t.width+"x"+t.height,e),t}return e}(f));var m=l(f),g=o.convert(r.format),y=o.convert(r.type);v(e.TEXTURE_2D,r,m);var x,b=r.mipmaps;if(r.isDepthTexture){var _=e.DEPTH_COMPONENT;if(r.type===N){if(!s)throw new Error("Float Depth Texture only supported in WebGL2.0");_=e.DEPTH_COMPONENT32F}else s&&(_=e.DEPTH_COMPONENT16);r.format===B&&_===e.DEPTH_COMPONENT&&r.type!==C&&r.type!==P&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=C,y=o.convert(r.type)),r.format===F&&(_=e.DEPTH_STENCIL,r.type!==I&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=I,y=o.convert(r.type))),i.texImage2D(e.TEXTURE_2D,0,_,f.width,f.height,0,g,y,null)}else if(r.isDataTexture)if(b.length>0&&m){for(var E=0,T=b.length;E-1?i.compressedTexImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):i.texImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,g,y,x.data);else if(b.length>0&&m){for(E=0,T=b.length;E1||r.get(a).__currentAnisotropy)&&(e.texParameterf(i,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,n.getMaxAnisotropy())),r.get(a).__currentAnisotropy=a.anisotropy)}}function g(t,n,a,s){var c=o.convert(n.texture.format),h=o.convert(n.texture.type);i.texImage2D(s,0,c,n.width,n.height,0,c,h,null),e.bindFramebuffer(e.FRAMEBUFFER,t),e.framebufferTexture2D(e.FRAMEBUFFER,a,s,r.get(n.texture).__webglTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}function y(t,i){e.bindRenderbuffer(e.RENDERBUFFER,t),i.depthBuffer&&!i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t)):i.depthBuffer&&i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t)):e.renderbufferStorage(e.RENDERBUFFER,e.RGBA4,i.width,i.height),e.bindRenderbuffer(e.RENDERBUFFER,null)}function x(t){var i=r.get(t),n=!0===t.isWebGLRenderTargetCube;if(t.depthTexture){if(n)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,i){if(i&&i.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(e.bindFramebuffer(e.FRAMEBUFFER,t),!i.depthTexture||!i.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");r.get(i.depthTexture).__webglTexture&&i.depthTexture.image.width===i.width&&i.depthTexture.image.height===i.height||(i.depthTexture.image.width=i.width,i.depthTexture.image.height=i.height,i.depthTexture.needsUpdate=!0),m(i.depthTexture,0);var n=r.get(i.depthTexture).__webglTexture;if(i.depthTexture.format===B)e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,n,0);else{if(i.depthTexture.format!==F)throw new Error("Unknown depthTexture format");e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,n,0)}}(i.__webglFramebuffer,t)}else if(n){i.__webglDepthbuffer=[];for(var o=0;o<6;o++)e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[o]),i.__webglDepthbuffer[o]=e.createRenderbuffer(),y(i.__webglDepthbuffer[o],t)}else e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer=e.createRenderbuffer(),y(i.__webglDepthbuffer,t);e.bindFramebuffer(e.FRAMEBUFFER,null)}this.setTexture2D=m,this.setTextureCube=function(t,s){var c=r.get(t);if(6===t.image.length)if(t.version>0&&c.__version!==t.version){c.__image__webglTextureCube||(t.addEventListener("dispose",d),c.__image__webglTextureCube=e.createTexture(),a.textures++),i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,t.flipY);for(var p=t&&t.isCompressedTexture,f=t.image[0]&&t.image[0].isDataTexture,m=[],g=0;g<6;g++)m[g]=p||f?f?t.image[g].image:t.image[g]:h(t.image[g],n.maxCubemapSize);var y=l(m[0]),x=o.convert(t.format),b=o.convert(t.type);v(e.TEXTURE_CUBE_MAP,t,y);for(g=0;g<6;g++)if(p)for(var w,_=m[g].mipmaps,M=0,E=_.length;M-1?i.compressedTexImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,w.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,x,b,w.data);else f?i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,m[g].width,m[g].height,0,x,b,m[g].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,x,b,m[g]);u(t,y)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),c.__version=t.version,t.onUpdate&&t.onUpdate(t)}else i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube)},this.setTextureCubeDynamic=function(t,n){i.activeTexture(e.TEXTURE0+n),i.bindTexture(e.TEXTURE_CUBE_MAP,r.get(t).__webglTexture)},this.setupRenderTarget=function(t){var n=r.get(t),o=r.get(t.texture);t.addEventListener("dispose",f),o.__webglTexture=e.createTexture(),a.textures++;var s=!0===t.isWebGLRenderTargetCube,c=l(t);if(s){n.__webglFramebuffer=[];for(var h=0;h<6;h++)n.__webglFramebuffer[h]=e.createFramebuffer()}else n.__webglFramebuffer=e.createFramebuffer();if(s){i.bindTexture(e.TEXTURE_CUBE_MAP,o.__webglTexture),v(e.TEXTURE_CUBE_MAP,t.texture,c);for(h=0;h<6;h++)g(n.__webglFramebuffer[h],t,e.COLOR_ATTACHMENT0,e.TEXTURE_CUBE_MAP_POSITIVE_X+h);u(t.texture,c)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),i.bindTexture(e.TEXTURE_CUBE_MAP,null)}else i.bindTexture(e.TEXTURE_2D,o.__webglTexture),v(e.TEXTURE_2D,t.texture,c),g(n.__webglFramebuffer,t,e.COLOR_ATTACHMENT0,e.TEXTURE_2D),u(t.texture,c)&&e.generateMipmap(e.TEXTURE_2D),i.bindTexture(e.TEXTURE_2D,null);t.depthBuffer&&x(t)},this.updateRenderTargetMipmap=function(t){var n=t.texture;if(u(n,l(t))){var o=t.isWebGLRenderTargetCube?e.TEXTURE_CUBE_MAP:e.TEXTURE_2D,a=r.get(n).__webglTexture;i.bindTexture(o,a),e.generateMipmap(o),i.bindTexture(o,null)}},this.updateVideoTextures=function(){for(var e in c)c[e].update()}}function Yi(){var e={};return{get:function(t){var i=t.uuid,r=e[i];return void 0===r&&(r={},e[i]=r),r},remove:function(t){delete e[t.uuid]},clear:function(){e={}}}}function Zi(e,t,i){var r=new function(){var t=!1,i=new he,r=null,n=new he(0,0,0,0);return{setMask:function(i){r===i||t||(e.colorMask(i,i,i,i),r=i)},setLocked:function(e){t=e},setClear:function(t,r,o,a,s){!0===s&&(t*=a,r*=a,o*=a),i.set(t,r,o,a),!1===n.equals(i)&&(e.clearColor(t,r,o,a),n.copy(i))},reset:function(){t=!1,r=null,n.set(-1,0,0,0)}}},n=new function(){var t=!1,i=null,r=null,n=null;return{setTest:function(t){t?D(e.DEPTH_TEST):U(e.DEPTH_TEST)},setMask:function(r){i===r||t||(e.depthMask(r),i=r)},setFunc:function(t){if(r!==t){if(t)switch(t){case 0:e.depthFunc(e.NEVER);break;case 1:e.depthFunc(e.ALWAYS);break;case 2:e.depthFunc(e.LESS);break;case 3:default:e.depthFunc(e.LEQUAL);break;case 4:e.depthFunc(e.EQUAL);break;case 5:e.depthFunc(e.GEQUAL);break;case 6:e.depthFunc(e.GREATER);break;case 7:e.depthFunc(e.NOTEQUAL)}else e.depthFunc(e.LEQUAL);r=t}},setLocked:function(e){t=e},setClear:function(t){n!==t&&(e.clearDepth(t),n=t)},reset:function(){t=!1,i=null,r=null,n=null}}},o=new function(){var t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null;return{setTest:function(t){t?D(e.STENCIL_TEST):U(e.STENCIL_TEST)},setMask:function(r){i===r||t||(e.stencilMask(r),i=r)},setFunc:function(t,i,a){r===t&&n===i&&o===a||(e.stencilFunc(t,i,a),r=t,n=i,o=a)},setOp:function(t,i,r){a===t&&s===i&&c===r||(e.stencilOp(t,i,r),a=t,s=i,c=r)},setLocked:function(e){t=e},setClear:function(t){h!==t&&(e.clearStencil(t),h=t)},reset:function(){t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null}}},a=e.getParameter(e.MAX_VERTEX_ATTRIBS),s=new Uint8Array(a),c=new Uint8Array(a),h=new Uint8Array(a),l={},u=null,p=null,d=null,f=null,m=null,v=null,g=null,y=null,x=null,b=!1,w=null,_=null,M=null,E=null,T=null,S=e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),A=parseFloat(/^WebGL\ ([0-9])/.exec(e.getParameter(e.VERSION))[1]),R=parseFloat(A)>=1,L=null,C={},P=new he,N=new he;function O(t,i,r){var n=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(var a=0;a0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}var o=void 0!==i.precision?i.precision:"highp",a=n(o);a!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",a,"instead."),o=a);var s=!0===i.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),l=e.getParameter(e.MAX_TEXTURE_SIZE),u=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),p=e.getParameter(e.MAX_VERTEX_ATTRIBS),d=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),f=e.getParameter(e.MAX_VARYING_VECTORS),m=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),v=h>0,g=!!t.get("OES_texture_float");return{getMaxAnisotropy:function(){if(void 0!==r)return r;var i=t.get("EXT_texture_filter_anisotropic");return r=null!==i?e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:n,precision:o,logarithmicDepthBuffer:s,maxTextures:c,maxVertexTextures:h,maxTextureSize:l,maxCubemapSize:u,maxAttributes:p,maxVertexUniforms:d,maxVaryings:f,maxFragmentUniforms:m,vertexTextures:v,floatFragmentTextures:g,floatVertexTextures:v&&g}}function Ki(e,t,i,r){It.call(this),this.type="PerspectiveCamera",this.fov=void 0!==e?e:50,this.zoom=1,this.near=void 0!==i?i:.1,this.far=void 0!==r?r:2e3,this.focus=10,this.aspect=void 0!==t?t:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qi(e){Ki.call(this),this.cameras=e||[]}function $i(e){var t=this,i=null,r=null,n=null;"undefined"!=typeof window&&"VRFrameData"in window&&(r=new window.VRFrameData);var o=new re,a=new Ki;a.bounds=new he(0,0,.5,1),a.layers.enable(1);var s=new Ki;s.bounds=new he(.5,0,.5,1),s.layers.enable(2);var c,h,l=new Qi([a,s]);function u(){if(null!==i&&i.isPresenting){var r=i.getEyeParameters("left"),n=r.renderWidth,o=r.renderHeight;h=e.getPixelRatio(),c=e.getSize(),e.setDrawingBufferSize(2*n,o,1)}else t.enabled&&e.setDrawingBufferSize(c.width,c.height,h)}l.layers.enable(1),l.layers.enable(2),"undefined"!=typeof window&&window.addEventListener("vrdisplaypresentchange",u,!1),this.enabled=!1,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e)},this.setPoseTarget=function(e){void 0!==e&&(n=e)},this.getCamera=function(e){if(null===i)return e;i.depthNear=e.near,i.depthFar=e.far,i.getFrameData(r);var t=r.pose,c=null!==n?n:e;if(null!==t.position?c.position.fromArray(t.position):c.position.set(0,0,0),null!==t.orientation&&c.quaternion.fromArray(t.orientation),c.updateMatrixWorld(),!1===i.isPresenting)return e;a.near=e.near,s.near=e.near,a.far=e.far,s.far=e.far,l.matrixWorld.copy(e.matrixWorld),l.matrixWorldInverse.copy(e.matrixWorldInverse),a.matrixWorldInverse.fromArray(r.leftViewMatrix),s.matrixWorldInverse.fromArray(r.rightViewMatrix);var h=c.parent;null!==h&&(o.getInverse(h.matrixWorld),a.matrixWorldInverse.multiply(o),s.matrixWorldInverse.multiply(o)),a.matrixWorld.getInverse(a.matrixWorldInverse),s.matrixWorld.getInverse(s.matrixWorldInverse),a.projectionMatrix.fromArray(r.leftProjectionMatrix),s.projectionMatrix.fromArray(r.rightProjectionMatrix),l.projectionMatrix.copy(a.projectionMatrix);var u=i.getLayers();if(u.length){var p=u[0];null!==p.leftBounds&&4===p.leftBounds.length&&a.bounds.fromArray(p.leftBounds),null!==p.rightBounds&&4===p.rightBounds.length&&s.bounds.fromArray(p.rightBounds)}return l},this.submitFrame=function(){i&&i.isPresenting&&i.submitFrame()},this.dispose=function(){"undefined"!=typeof window&&window.removeEventListener("vrdisplaypresentchange",u)}}function er(e){var t={};return{get:function(i){if(void 0!==t[i])return t[i];var r;switch(i){case"WEBGL_depth_texture":r=e.getExtension("WEBGL_depth_texture")||e.getExtension("MOZ_WEBGL_depth_texture")||e.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":r=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":r=e.getExtension("WEBGL_compressed_texture_s3tc")||e.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":r=e.getExtension("WEBGL_compressed_texture_pvrtc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;case"WEBGL_compressed_texture_etc1":r=e.getExtension("WEBGL_compressed_texture_etc1");break;default:r=e.getExtension(i)}return null===r&&console.warn("THREE.WebGLRenderer: "+i+" extension not supported."),t[i]=r,r}}}function tr(){var e=this,t=null,i=0,r=!1,n=!1,o=new _t,a=new ae,s={value:null,needsUpdate:!1};function c(){s.value!==t&&(s.value=t,s.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,i,r,n){var c=null!==t?t.length:0,h=null;if(0!==c){if(h=s.value,!0!==n||null===h){var l=r+4*c,u=i.matrixWorldInverse;a.getNormalMatrix(u),(null===h||h.length=0){var h=n[s];if(void 0!==h){var l=h.normalized,u=h.itemSize,p=w.get(h);if(void 0===p)continue;var d=p.buffer,f=p.type,g=p.bytesPerElement;if(h.isInterleavedBufferAttribute){var x=h.data,b=x.stride,_=h.offset;x&&x.isInstancedInterleavedBuffer?(y.enableAttributeAndDivisor(c,x.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=x.meshPerAttribute*x.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,b*g,(r*b+_)*g)}else h.isInstancedBufferAttribute?(y.enableAttributeAndDivisor(c,h.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=h.meshPerAttribute*h.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,0,r*u*g)}else if(void 0!==a){var M=a[s];if(void 0!==M)switch(M.length){case 2:m.vertexAttrib2fv(c,M);break;case 3:m.vertexAttrib3fv(c,M);break;case 4:m.vertexAttrib4fv(c,M);break;default:m.vertexAttrib1fv(c,M)}}}}y.disableUnusedAttributes()}(r,s,i),null!==u&&m.bindBuffer(m.ELEMENT_ARRAY_BUFFER,l.buffer));var g=0;null!==u?g=u.count:void 0!==p&&(g=p.count);var x=i.drawRange.start*d,b=i.drawRange.count*d,M=null!==o?o.start*d:0,E=null!==o?o.count*d:1/0,T=Math.max(x,M),S=Math.min(g,x+b,M+E)-1,A=Math.max(0,S-T+1);if(0!==A){if(n.isMesh)if(!0===r.wireframe)y.setLineWidth(r.wireframeLinewidth*me()),f.setMode(m.LINES);else switch(n.drawMode){case 0:f.setMode(m.TRIANGLES);break;case 1:f.setMode(m.TRIANGLE_STRIP);break;case 2:f.setMode(m.TRIANGLE_FAN)}else if(n.isLine){var L=r.linewidth;void 0===L&&(L=1),y.setLineWidth(L*me()),n.isLineSegments?f.setMode(m.LINES):n.isLineLoop?f.setMode(m.LINE_LOOP):f.setMode(m.LINE_STRIP)}else n.isPoints&&f.setMode(m.POINTS);i&&i.isInstancedBufferGeometry?i.maxInstancedCount>0&&f.renderInstances(i,T,A):f.render(T,A)}},this.compile=function(e,t){l.length=0,u.length=0,e.traverse((function(e){e.isLight&&(l.push(e),e.castShadow&&u.push(e))})),E.setup(l,u,t),e.traverse((function(t){if(t.material)if(Array.isArray(t.material))for(var i=0;i=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(l=0;l=0&&e.numSupportedMorphNormals++}var p=r.shader.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(r.numClippingPlanes=ae.numPlanes,r.numIntersection=ae.numIntersection,p.clippingPlanes=ae.uniform),r.fog=t,r.lightsHash=E.state.hash,e.lights&&(p.ambientLightColor.value=E.state.ambient,p.directionalLights.value=E.state.directional,p.spotLights.value=E.state.spot,p.rectAreaLights.value=E.state.rectArea,p.pointLights.value=E.state.point,p.hemisphereLights.value=E.state.hemi,p.directionalShadowMap.value=E.state.directionalShadowMap,p.directionalShadowMatrix.value=E.state.directionalShadowMatrix,p.spotShadowMap.value=E.state.spotShadowMap,p.spotShadowMatrix.value=E.state.spotShadowMatrix,p.pointShadowMap.value=E.state.pointShadowMap,p.pointShadowMatrix.value=E.state.pointShadowMatrix);var d=r.program.getUniforms(),f=Qe.seqWithValue(d.seq,p);r.uniformsList=f}function Ne(e,t,i,r){Z=0;var n=x.get(i);if(se&&(ce||e!==H)){var o=e===H&&i.id===V;ae.setState(i.clippingPlanes,i.clipIntersection,i.clipShadows,e,n,o)}!1===i.needsUpdate&&(void 0===n.program||i.fog&&n.fog!==t||i.lights&&n.lightsHash!==E.state.hash?i.needsUpdate=!0:void 0===n.numClippingPlanes||n.numClippingPlanes===ae.numPlanes&&n.numIntersection===ae.numIntersection||(i.needsUpdate=!0)),i.needsUpdate&&(Pe(i,t,r),i.needsUpdate=!1);var a,s,c=!1,h=!1,l=!1,u=n.program,p=u.getUniforms(),d=n.shader.uniforms;if(y.useProgram(u.program)&&(c=!0,h=!0,l=!0),i.id!==V&&(V=i.id,h=!0),c||e!==H){if(p.setValue(m,"projectionMatrix",e.projectionMatrix),g.logarithmicDepthBuffer&&p.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),H!==(W||e)&&(H=W||e,h=!0,l=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshStandardMaterial||i.envMap){var f=p.map.cameraPosition;void 0!==f&&f.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.skinning)&&p.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(i.skinning){p.setOptional(m,r,"bindMatrix"),p.setOptional(m,r,"bindMatrixInverse");var v=r.skeleton;if(v){var b=v.bones;if(g.floatVertexTextures){if(void 0===v.boneTexture){var w=Math.sqrt(4*b.length);w=te.ceilPowerOfTwo(w),w=Math.max(w,4);var _=new Float32Array(w*w*4);_.set(v.boneMatrices);var M=new pe(_,w,w,U,N);v.boneMatrices=_,v.boneTexture=M,v.boneTextureSize=w}p.setValue(m,"boneTexture",v.boneTexture),p.setValue(m,"boneTextureSize",v.boneTextureSize)}else p.setOptional(m,v,"boneMatrices")}}return h&&(p.setValue(m,"toneMappingExposure",F.toneMappingExposure),p.setValue(m,"toneMappingWhitePoint",F.toneMappingWhitePoint),i.lights&&(s=l,(a=d).ambientLightColor.needsUpdate=s,a.directionalLights.needsUpdate=s,a.pointLights.needsUpdate=s,a.spotLights.needsUpdate=s,a.rectAreaLights.needsUpdate=s,a.hemisphereLights.needsUpdate=s),t&&i.fog&&function(e,t){e.fogColor.value=t.color,t.isFog?(e.fogNear.value=t.near,e.fogFar.value=t.far):t.isFogExp2&&(e.fogDensity.value=t.density)}(d,t),i.isMeshBasicMaterial?Oe(d,i):i.isMeshLambertMaterial?(Oe(d,i),function(e,t){t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap)}(d,i)):i.isMeshPhongMaterial?(Oe(d,i),i.isMeshToonMaterial?function(e,t){Ie(e,t),t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(d,i):Ie(d,i)):i.isMeshStandardMaterial?(Oe(d,i),i.isMeshPhysicalMaterial?function(e,t){e.clearCoat.value=t.clearCoat,e.clearCoatRoughness.value=t.clearCoatRoughness,De(e,t)}(d,i):De(d,i)):i.isMeshDepthMaterial?(Oe(d,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(d,i)):i.isMeshDistanceMaterial?(Oe(d,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias);e.referencePosition.value.copy(t.referencePosition),e.nearDistance.value=t.nearDistance,e.farDistance.value=t.farDistance}(d,i)):i.isMeshNormalMaterial?(Oe(d,i),function(e,t){t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale);t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale));t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(d,i)):i.isLineBasicMaterial?(function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity}(d,i),i.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(d,i)):i.isPointsMaterial?function(e,t){if(e.diffuse.value=t.color,e.opacity.value=t.opacity,e.size.value=t.size*Q,e.scale.value=.5*K,e.map.value=t.map,null!==t.map){if(!0===t.map.matrixAutoUpdate){var i=t.map.offset,r=t.map.repeat,n=t.map.rotation,o=t.map.center;t.map.matrix.setUvTransform(i.x,i.y,r.x,r.y,n,o.x,o.y)}e.uvTransform.value.copy(t.map.matrix)}}(d,i):i.isShadowMaterial&&(d.color.value=i.color,d.opacity.value=i.opacity),void 0!==d.ltcMat&&(d.ltcMat.value=tt.LTC_MAT_TEXTURE),void 0!==d.ltcMag&&(d.ltcMag.value=tt.LTC_MAG_TEXTURE),Qe.upload(m,n.uniformsList,d,F)),p.setValue(m,"modelViewMatrix",r.modelViewMatrix),p.setValue(m,"normalMatrix",r.normalMatrix),p.setValue(m,"modelMatrix",r.matrixWorld),u}function Oe(e,t){var i;if(e.opacity.value=t.opacity,t.color&&(e.diffuse.value=t.color),t.emissive&&e.emissive.value.copy(t.emissive).multiplyScalar(t.emissiveIntensity),t.map&&(e.map.value=t.map),t.alphaMap&&(e.alphaMap.value=t.alphaMap),t.specularMap&&(e.specularMap.value=t.specularMap),t.envMap&&(e.envMap.value=t.envMap,e.flipEnvMap.value=t.envMap&&t.envMap.isCubeTexture?-1:1,e.reflectivity.value=t.reflectivity,e.refractionRatio.value=t.refractionRatio),t.lightMap&&(e.lightMap.value=t.lightMap,e.lightMapIntensity.value=t.lightMapIntensity),t.aoMap&&(e.aoMap.value=t.aoMap,e.aoMapIntensity.value=t.aoMapIntensity),t.map?i=t.map:t.specularMap?i=t.specularMap:t.displacementMap?i=t.displacementMap:t.normalMap?i=t.normalMap:t.bumpMap?i=t.bumpMap:t.roughnessMap?i=t.roughnessMap:t.metalnessMap?i=t.metalnessMap:t.alphaMap?i=t.alphaMap:t.emissiveMap&&(i=t.emissiveMap),void 0!==i){if(i.isWebGLRenderTarget&&(i=i.texture),!0===i.matrixAutoUpdate){var r=i.offset,n=i.repeat,o=i.rotation,a=i.center;i.matrix.setUvTransform(r.x,r.y,n.x,n.y,o,a.x,a.y)}e.uvTransform.value.copy(i.matrix)}}function Ie(e,t){e.specular.value=t.specular,e.shininess.value=Math.max(t.shininess,1e-4),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}function De(e,t){e.roughness.value=t.roughness,e.metalness.value=t.metalness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap),t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}this.animate=function(e){Se=e,function(){if(!Te){var e=ye.getDevice();e&&e.isPresenting?e.requestAnimationFrame(Ae):window.requestAnimationFrame(Ae),Te=!0}}()},this.render=function(e,t,i,r){if(t&&t.isCamera){if(!z){j="",V=-1,H=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),ye.enabled&&(t=ye.getCamera(t)),le.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),ne.setFromMatrix(le),l.length=0,u.length=0,d.length=0,f.length=0,ce=this.localClippingEnabled,se=ae.init(this.clippingPlanes,ce,t),(p=S.get(e,t)).init(),Re(e,t,F.sortObjects),!0===F.sortObjects&&p.sort(),b.updateVideoTextures(),se&&ae.beginShadows(),xe.render(u,e,t),E.setup(l,u,t),se&&ae.endShadows(),fe.frame++,fe.calls=0,fe.vertices=0,fe.faces=0,fe.points=0,void 0===i&&(i=null),this.setRenderTarget(i),A.render(p,e,t,r);var n=p.opaque,o=p.transparent;if(e.overrideMaterial){var a=e.overrideMaterial;n.length&&Le(n,e,t,a),o.length&&Le(o,e,t,a)}else n.length&&Le(n,e,t),o.length&&Le(o,e,t);D.render(d,e,t),I.render(f,e,t,X),i&&b.updateRenderTargetMipmap(i),y.buffers.depth.setTest(!0),y.buffers.depth.setMask(!0),y.buffers.color.setMask(!0),y.setPolygonOffset(!1),ye.enabled&&ye.submitFrame()}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFaceCulling=function(e,t){y.setCullFace(e),y.setFlipSided(0===t)},this.allocTextureUnit=function(){var e=Z;return e>=g.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+g.maxTextures),Z+=1,e},this.setTexture2D=(Ee=!1,function(e,t){e&&e.isWebGLRenderTarget&&(Ee||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Ee=!0),e=e.texture),b.setTexture2D(e,t)}),this.setTexture=function(){var e=!1;return function(t,i){e||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),e=!0),b.setTexture2D(t,i)}}(),this.setTextureCube=function(){var e=!1;return function(t,i){t&&t.isWebGLRenderTargetCube&&(e||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),e=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?b.setTextureCube(t,i):b.setTextureCubeDynamic(t,i)}}(),this.getRenderTarget=function(){return k},this.setRenderTarget=function(e){k=e,e&&void 0===x.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var t=null,i=!1;if(e){var r=x.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=r[e.activeCubeFace],i=!0):t=r,X.copy(e.viewport),q.copy(e.scissor),Y=e.scissorTest}else X.copy($).multiplyScalar(Q),q.copy(ee).multiplyScalar(Q),Y=ie;if(G!==t&&(m.bindFramebuffer(m.FRAMEBUFFER,t),G=t),y.viewport(X),y.scissor(q),y.setScissorTest(Y),i){var n=x.get(e.texture);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,n.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,r,n,o){if(e&&e.isWebGLRenderTarget){var a=x.get(e).__webglFramebuffer;if(a){var s=!1;a!==G&&(m.bindFramebuffer(m.FRAMEBUFFER,a),s=!0);try{var c=e.texture,h=c.format,l=c.type;if(h!==U&&B.convert(h)!==m.getParameter(m.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(l===L||B.convert(l)===m.getParameter(m.IMPLEMENTATION_COLOR_READ_TYPE)||l===N&&(v.get("OES_texture_float")||v.get("WEBGL_color_buffer_float"))||l===O&&v.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?t>=0&&t<=e.width-r&&i>=0&&i<=e.height-n&&m.readPixels(t,i,r,n,B.convert(h),B.convert(l),o):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&m.bindFramebuffer(m.FRAMEBUFFER,G)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")}}function nr(e,t){this.name="",this.color=new et(e),this.density=void 0!==t?t:25e-5}function or(e,t,i){this.name="",this.color=new et(e),this.near=void 0!==t?t:1,this.far=void 0!==i?i:1e3}function ar(){Ot.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function sr(e,t,i,r,n){Ot.call(this),this.lensFlares=[],this.positionScreen=new oe,this.customUpdateCallback=void 0,void 0!==e&&this.add(e,t,i,r,n)}function cr(e){gt.call(this),this.type="SpriteMaterial",this.color=new et(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function hr(e){Ot.call(this),this.type="Sprite",this.material=void 0!==e?e:new cr}function lr(){Ot.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ur(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===t)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,r=this.bones.length;i=0?(p=e(g-h,v,p),d.subVectors(u,p)):(p=e(g+h,v,p),d.subVectors(p,u)),v-h>=0?(p=e(g,v-h,p),f.subVectors(u,p)):(p=e(g,v+h,p),f.subVectors(p,u)),l.crossVectors(d,f).normalize(),s.push(l.x,l.y,l.z),c.push(g,v)}}for(r=0;r.9&&a<.1&&(t<.2&&(o[e+0]+=1),i<.2&&(o[e+2]+=1),r<.2&&(o[e+4]+=1))}}()}(),this.addAttribute("position",new Yt(n,3)),this.addAttribute("normal",new Yt(n.slice(),3)),this.addAttribute("uv",new Yt(o,2)),0===r?this.computeVertexNormals():this.normalizeNormals()}function Lr(e,t){zt.call(this),this.type="TetrahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Cr(e,t)),this.mergeVertices()}function Cr(e,t){Rr.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],e,t),this.type="TetrahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Pr(e,t){zt.call(this),this.type="OctahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Nr(e,t)),this.mergeVertices()}function Nr(e,t){Rr.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],e,t),this.type="OctahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Or(e,t){zt.call(this),this.type="IcosahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ir(e,t)),this.mergeVertices()}function Ir(e,t){var i=(1+Math.sqrt(5))/2,r=[-1,i,0,1,i,0,-1,-i,0,1,-i,0,0,-1,i,0,1,i,0,-1,-i,0,1,-i,i,0,-1,i,0,1,-i,0,-1,-i,0,1];Rr.call(this,r,[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],e,t),this.type="IcosahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Dr(e,t){zt.call(this),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ur(e,t)),this.mergeVertices()}function Ur(e,t){var i=(1+Math.sqrt(5))/2,r=1/i,n=[-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,-i,0,-r,i,0,r,-i,0,r,i,-r,-i,0,-r,i,0,r,-i,0,r,i,0,-i,0,-r,i,0,-r,-i,0,r,i,0,r];Rr.call(this,n,[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],e,t),this.type="DodecahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Br(e,t,i,r,n,o){zt.call(this),this.type="TubeGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},void 0!==o&&console.warn("THREE.TubeGeometry: taper has been removed.");var a=new Fr(e,t,i,r,n);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals,this.fromBufferGeometry(a),this.mergeVertices()}function Fr(e,t,i,r,n){ai.call(this),this.type="TubeBufferGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},t=t||64,i=i||1,r=r||8,n=n||!1;var o=e.computeFrenetFrames(t,n);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals;var a,s,c=new oe,h=new oe,l=new ie,u=new oe,p=[],d=[],f=[],m=[];function v(n){u=e.getPointAt(n/t,u);var a=o.normals[n],l=o.binormals[n];for(s=0;s<=r;s++){var f=s/r*Math.PI*2,m=Math.sin(f),v=-Math.cos(f);h.x=v*a.x+m*l.x,h.y=v*a.y+m*l.y,h.z=v*a.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+i*h.x,c.y=u.y+i*h.y,c.z=u.z+i*h.z,p.push(c.x,c.y,c.z)}}!function(){for(a=0;ai)){var r=e.ray.origin.distanceTo(Pi);re.far||t.push({distance:r,point:Pi.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)}}),lr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:lr,copy:function(e){Ot.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,r=t.length;i1){e.setFromMatrixPosition(i.matrixWorld),t.setFromMatrixPosition(this.matrixWorld);var n=e.distanceTo(t);r[0].object.visible=!0;for(var o=1,a=r.length;o=r[o].distance;o++)r[o-1].object.visible=!1,r[o].object.visible=!0;for(;oa))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}else for(g=0,y=m.length/3-1;ga))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}else if(s.isGeometry){var w=s.vertices,_=w.length;for(g=0;g<_-1;g+=d){var M;if(!(t.distanceSqToSegment(w[g],w[g+1],p,u)>a))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),vr.prototype=Object.assign(Object.create(mr.prototype),{constructor:vr,isLineSegments:!0}),gr.prototype=Object.assign(Object.create(mr.prototype),{constructor:gr,isLineLoop:!0}),yr.prototype=Object.create(gt.prototype),yr.prototype.constructor=yr,yr.prototype.isPointsMaterial=!0,yr.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.size=e.size,this.sizeAttenuation=e.sizeAttenuation,this},xr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:xr,isPoints:!0,raycast:function(){var e=new re,t=new di,i=new wt;return function(r,n){var o=this,a=this.geometry,s=this.matrixWorld,c=r.params.Points.threshold;if(null===a.boundingSphere&&a.computeBoundingSphere(),i.copy(a.boundingSphere),i.applyMatrix4(s),i.radius+=c,!1!==r.ray.intersectsSphere(i)){e.getInverse(s),t.copy(r.ray).applyMatrix4(e);var h=c/((this.scale.x+this.scale.y+this.scale.z)/3),l=h*h,u=new oe;if(a.isBufferGeometry){var p=a.index,d=a.attributes.position.array;if(null!==p)for(var f=p.array,m=0,v=f.length;mr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:c.clone(),index:i,face:null,object:o})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),br.prototype=Object.assign(Object.create(Ot.prototype),{constructor:br,isGroup:!0}),wr.prototype=Object.assign(Object.create(ce.prototype),{constructor:wr,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),_r.prototype=Object.create(ce.prototype),_r.prototype.constructor=_r,_r.prototype.isCompressedTexture=!0,Mr.prototype=Object.create(ce.prototype),Mr.prototype.constructor=Mr,Mr.prototype.isDepthTexture=!0,Er.prototype=Object.create(ai.prototype),Er.prototype.constructor=Er,Tr.prototype=Object.create(zt.prototype),Tr.prototype.constructor=Tr,Sr.prototype=Object.create(ai.prototype),Sr.prototype.constructor=Sr,Ar.prototype=Object.create(zt.prototype),Ar.prototype.constructor=Ar,Rr.prototype=Object.create(ai.prototype),Rr.prototype.constructor=Rr,Lr.prototype=Object.create(zt.prototype),Lr.prototype.constructor=Lr,Cr.prototype=Object.create(Rr.prototype),Cr.prototype.constructor=Cr,Pr.prototype=Object.create(zt.prototype),Pr.prototype.constructor=Pr,Nr.prototype=Object.create(Rr.prototype),Nr.prototype.constructor=Nr,Or.prototype=Object.create(zt.prototype),Or.prototype.constructor=Or,Ir.prototype=Object.create(Rr.prototype),Ir.prototype.constructor=Ir,Dr.prototype=Object.create(zt.prototype),Dr.prototype.constructor=Dr,Ur.prototype=Object.create(Rr.prototype),Ur.prototype.constructor=Ur,Br.prototype=Object.create(zt.prototype),Br.prototype.constructor=Br,Fr.prototype=Object.create(ai.prototype),Fr.prototype.constructor=Fr,zr.prototype=Object.create(zt.prototype),zr.prototype.constructor=zr,kr.prototype=Object.create(ai.prototype),kr.prototype.constructor=kr,Gr.prototype=Object.create(zt.prototype),Gr.prototype.constructor=Gr,Vr.prototype=Object.create(ai.prototype),Vr.prototype.constructor=Vr;var jr=function(e,t,i){i=i||2;var r,n,o,a,s,c,h,l=t&&t.length,u=l?t[0]*i:e.length,p=Hr(e,0,u,i,!0),d=[];if(!p)return d;if(l&&(p=function(e,t,i,r){var n,o,a,s=[];for(n=0,o=t.length;n80*i){r=o=e[0],n=a=e[1];for(var f=i;fo&&(o=s),c>a&&(a=c);h=0!==(h=Math.max(o-r,a-n))?1/h:0}return Xr(p,d,i,r,n,h),d};function Hr(e,t,i,r,n){var o,a;if(n===function(e,t,i,r){for(var n=0,o=t,a=i-r;o0)for(o=t;o=t;o-=r)a=hn(o,e[o],e[o+1],a);return a&&on(a,a.next)&&(ln(a),a=a.next),a}function Wr(e,t){if(!e)return e;t||(t=e);var i,r=e;do{if(i=!1,r.steiner||!on(r,r.next)&&0!==nn(r.prev,r,r.next))r=r.next;else{if(ln(r),(r=t=r.prev)===r.next)break;i=!0}}while(i||r!==t);return t}function Xr(e,t,i,r,n,o,a){if(e){!a&&o&&function(e,t,i,r){var n=e;do{null===n.z&&(n.z=$r(n.x,n.y,t,i,r)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==e);n.prevZ.nextZ=null,n.prevZ=null,function(e){var t,i,r,n,o,a,s,c,h=1;do{for(i=e,e=null,o=null,a=0;i;){for(a++,r=i,s=0,t=0;t0||c>0&&r;)0!==s&&(0===c||!r||i.z<=r.z)?(n=i,i=i.nextZ,s--):(n=r,r=r.nextZ,c--),o?o.nextZ=n:e=n,n.prevZ=o,o=n;i=r}o.nextZ=null,h*=2}while(a>1)}(n)}(e,r,n,o);for(var s,c,h=e;e.prev!==e.next;)if(s=e.prev,c=e.next,o?Yr(e,r,n,o):qr(e))t.push(s.i/i),t.push(e.i/i),t.push(c.i/i),ln(e),e=c.next,h=c.next;else if((e=c)===h){a?1===a?Xr(e=Zr(e,t,i),t,i,r,n,o,2):2===a&&Jr(e,t,i,r,n,o):Xr(Wr(e),t,i,r,n,o,1);break}}}function qr(e){var t=e.prev,i=e,r=e.next;if(nn(t,i,r)>=0)return!1;for(var n=e.next.next;n!==e.prev;){if(tn(t.x,t.y,i.x,i.y,r.x,r.y,n.x,n.y)&&nn(n.prev,n,n.next)>=0)return!1;n=n.next}return!0}function Yr(e,t,i,r){var n=e.prev,o=e,a=e.next;if(nn(n,o,a)>=0)return!1;for(var s=n.xo.x?n.x>a.x?n.x:a.x:o.x>a.x?o.x:a.x,l=n.y>o.y?n.y>a.y?n.y:a.y:o.y>a.y?o.y:a.y,u=$r(s,c,t,i,r),p=$r(h,l,t,i,r),d=e.nextZ;d&&d.z<=p;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=e.prevZ;d&&d.z>=u;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function Zr(e,t,i){var r=e;do{var n=r.prev,o=r.next.next;!on(n,o)&&an(n,r,r.next,o)&&sn(n,o)&&sn(o,n)&&(t.push(n.i/i),t.push(r.i/i),t.push(o.i/i),ln(r),ln(r.next),r=e=o),r=r.next}while(r!==e);return r}function Jr(e,t,i,r,n,o){var a=e;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&rn(a,s)){var c=cn(a,s);return a=Wr(a,a.next),c=Wr(c,c.next),Xr(a,t,i,r,n,o),void Xr(c,t,i,r,n,o)}s=s.next}a=a.next}while(a!==e)}function Kr(e,t){return e.x-t.x}function Qr(e,t){if(t=function(e,t){var i,r=t,n=e.x,o=e.y,a=-1/0;do{if(o<=r.y&&o>=r.next.y&&r.next.y!==r.y){var s=r.x+(o-r.y)*(r.next.x-r.x)/(r.next.y-r.y);if(s<=n&&s>a){if(a=s,s===n){if(o===r.y)return r;if(o===r.next.y)return r.next}i=r.x=r.x&&r.x>=l&&n!==r.x&&tn(oi.x)&&sn(r,e)&&(i=r,p=c),r=r.next;return i}(e,t),t){var i=cn(t,e);Wr(i,i.next)}}function $r(e,t,i,r,n){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*n)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*n)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function en(e){var t=e,i=e;do{t.x=0&&(e-a)*(r-s)-(i-a)*(t-s)>=0&&(i-a)*(o-s)-(n-a)*(r-s)>=0}function rn(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&an(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(e,t)&&sn(e,t)&&sn(t,e)&&function(e,t){var i=e,r=!1,n=(e.x+t.x)/2,o=(e.y+t.y)/2;do{i.y>o!=i.next.y>o&&i.next.y!==i.y&&n<(i.next.x-i.x)*(o-i.y)/(i.next.y-i.y)+i.x&&(r=!r),i=i.next}while(i!==e);return r}(e,t)}function nn(e,t,i){return(t.y-e.y)*(i.x-t.x)-(t.x-e.x)*(i.y-t.y)}function on(e,t){return e.x===t.x&&e.y===t.y}function an(e,t,i,r){return!!(on(e,t)&&on(i,r)||on(e,r)&&on(i,t))||nn(e,t,i)>0!=nn(e,t,r)>0&&nn(i,r,e)>0!=nn(i,r,t)>0}function sn(e,t){return nn(e.prev,e,e.next)<0?nn(e,t,e.next)>=0&&nn(e,e.prev,t)>=0:nn(e,t,e.prev)<0||nn(e,e.next,t)<0}function cn(e,t){var i=new un(e.i,e.x,e.y),r=new un(t.i,t.x,t.y),n=e.next,o=t.prev;return e.next=t,t.prev=e,i.next=n,n.prev=i,r.next=i,i.prev=r,o.next=r,r.prev=o,r}function hn(e,t,i,r){var n=new un(e,t,i);return r?(n.next=r.next,n.prev=r,r.next.prev=n,r.next=n):(n.prev=n,n.next=n),n}function ln(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function un(e,t,i){this.i=e,this.x=t,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var pn={area:function(e){for(var t=e.length,i=0,r=t-1,n=0;n2&&e[t-1].equals(e[0])&&e.pop()}function r(e,t){for(var i=0;i0)&&f.push(w,_,E),(c!==i-1||h0&&g(!0),t>0&&g(!1)),this.setIndex(h),this.addAttribute("position",new Yt(l,3)),this.addAttribute("normal",new Yt(u,3)),this.addAttribute("uv",new Yt(p,2))}function Ln(e,t,i,r,n,o,a){An.call(this,0,e,t,i,r,n,o,a),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Cn(e,t,i,r,n,o,a){Rn.call(this,0,e,t,i,r,n,o,a),this.type="ConeBufferGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Pn(e,t,i,r){zt.call(this),this.type="CircleGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},this.fromBufferGeometry(new Nn(e,t,i,r)),this.mergeVertices()}function Nn(e,t,i,r){ai.call(this),this.type="CircleBufferGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},e=e||1,t=void 0!==t?Math.max(3,t):8,i=void 0!==i?i:0,r=void 0!==r?r:2*Math.PI;var n,o,a=[],s=[],c=[],h=[],l=new oe,u=new ie;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),o=0,n=3;o<=t;o++,n+=3){var p=i+o/t*r;l.x=e*Math.cos(p),l.y=e*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[n]/e+1)/2,u.y=(s[n+1]/e+1)/2,h.push(u.x,u.y)}for(n=1;n<=t;n++)a.push(n,n+1,0);this.setIndex(a),this.addAttribute("position",new Yt(s,3)),this.addAttribute("normal",new Yt(c,3)),this.addAttribute("uv",new Yt(h,2))}dn.prototype=Object.create(zt.prototype),dn.prototype.constructor=dn,fn.prototype=Object.create(ai.prototype),fn.prototype.constructor=fn,fn.prototype.getArrays=function(){var e=this.getAttribute("position"),t=e?Array.prototype.slice.call(e.array):[],i=this.getAttribute("uv"),r=i?Array.prototype.slice.call(i.array):[],n=this.index;return{position:t,uv:r,index:n?Array.prototype.slice.call(n.array):[]}},fn.prototype.addShapeList=function(e,t){var i=e.length;t.arrays=this.getArrays();for(var r=0;rNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=t.x-s/p,m=t.y+a/p,v=((i.x-h/d-f)*h-(i.y+c/d-m)*c)/(a*h-s*c),g=(r=f+a*v-e.x)*r+(n=m+s*v-e.y)*n;if(g<=2)return new ie(r,n);o=Math.sqrt(g/2)}else{var y=!1;a>Number.EPSILON?c>Number.EPSILON&&(y=!0):a<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(r=-s,n=a,o=Math.sqrt(l)):(r=a,n=s,o=Math.sqrt(l/2))}return new ie(r/o,n/o)}for(var G=[],V=0,j=C.length,H=j-1,W=V+1;V=0;N--){for(I=N/y,D=v*Math.cos(I*Math.PI/2),O=g*Math.sin(I*Math.PI/2),V=0,j=C.length;V=0;){i=V,(r=V-1)<0&&(r=e.length-1);var n=0,o=w+2*y;for(n=0;n0||0===e.search(/^data\:image\/jpeg/);n.format=r?D:U,n.needsUpdate=!0,void 0!==t&&t(n)}),i,r),n},setCrossOrigin:function(e){return this.crossOrigin=e,this},setPath:function(e){return this.path=e,this}}),Object.assign(eo.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(e,t){var i=this.getUtoTmapping(e);return this.getPoint(i,t)},getPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPoint(i/e));return t},getSpacedPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPointAt(i/e));return t},getLength:function(){var e=this.getLengths();return e[e.length-1]},getLengths:function(e){if(void 0===e&&(e=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var t,i,r=[],n=this.getPoint(0),o=0;for(r.push(0),i=1;i<=e;i++)o+=(t=this.getPoint(i/e)).distanceTo(n),r.push(o),n=t;return this.cacheArcLengths=r,r},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(e,t){var i,r=this.getLengths(),n=0,o=r.length;i=t||e*r[o-1];for(var a,s=0,c=o-1;s<=c;)if((a=r[n=Math.floor(s+(c-s)/2)]-i)<0)s=n+1;else{if(!(a>0)){c=n;break}c=n-1}if(r[n=c]===i)return n/(o-1);var h=r[n];return(n+(i-h)/(r[n+1]-h))/(o-1)},getTangent:function(e){var t=1e-4,i=e-t,r=e+t;i<0&&(i=0),r>1&&(r=1);var n=this.getPoint(i);return this.getPoint(r).clone().sub(n).normalize()},getTangentAt:function(e){var t=this.getUtoTmapping(e);return this.getTangent(t)},computeFrenetFrames:function(e,t){var i,r,n,o=new oe,a=[],s=[],c=[],h=new oe,l=new re;for(i=0;i<=e;i++)r=i/e,a[i]=this.getTangentAt(r),a[i].normalize();s[0]=new oe,c[0]=new oe;var u=Number.MAX_VALUE,p=Math.abs(a[0].x),d=Math.abs(a[0].y),f=Math.abs(a[0].z);for(p<=u&&(u=p,o.set(1,0,0)),d<=u&&(u=d,o.set(0,1,0)),f<=u&&o.set(0,0,1),h.crossVectors(a[0],o).normalize(),s[0].crossVectors(a[0],h),c[0].crossVectors(a[0],s[0]),i=1;i<=e;i++)s[i]=s[i-1].clone(),c[i]=c[i-1].clone(),h.crossVectors(a[i-1],a[i]),h.length()>Number.EPSILON&&(h.normalize(),n=Math.acos(te.clamp(a[i-1].dot(a[i]),-1,1)),s[i].applyMatrix4(l.makeRotationAxis(h,n))),c[i].crossVectors(a[i],s[i]);if(!0===t)for(n=Math.acos(te.clamp(s[0].dot(s[e]),-1,1)),n/=e,a[0].dot(h.crossVectors(s[0],s[e]))>0&&(n=-n),i=1;i<=e;i++)s[i].applyMatrix4(l.makeRotationAxis(a[i],n*i)),c[i].crossVectors(a[i],s[i]);return{tangents:a,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this},toJSON:function(){var e={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e},fromJSON:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}),to.prototype=Object.create(eo.prototype),to.prototype.constructor=to,to.prototype.isEllipseCurve=!0,to.prototype.getPoint=function(e,t){for(var i=t||new ie,r=2*Math.PI,n=this.aEndAngle-this.aStartAngle,o=Math.abs(n)r;)n-=r;n0?0:(Math.floor(Math.abs(l)/s.length)+1)*s.length:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?i=s[(l-1)%c]:(no.subVectors(s[0],s[1]).add(s[0]),i=no),r=s[l%c],n=s[(l+1)%c],this.closed||l+2r.length-2?r.length-1:o+1],l=r[o>r.length-3?r.length-1:o+2];return i.set(ho(a,s.x,c.x,h.x,l.x),ho(a,s.y,c.y,h.y,l.y)),i},xo.prototype.copy=function(e){eo.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var n=i[r]-t,o=this.curves[r],a=o.getLength(),s=0===a?0:1-n/a;return o.getPointAt(s)}r++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,r=this.curves.length;i1&&!i[i.length-1].equals(i[0])&&i.push(i[0]),i},copy:function(e){eo.prototype.copy.call(this,e),this.curves=[];for(var t=0,i=e.curves.length;t0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(e){return wo.prototype.copy.call(this,e),this.currentPoint.copy(e.currentPoint),this},toJSON:function(){var e=wo.prototype.toJSON.call(this);return e.currentPoint=this.currentPoint.toArray(),e},fromJSON:function(e){return wo.prototype.fromJSON.call(this,e),this.currentPoint.fromArray(e.currentPoint),this}}),Mo.prototype=Object.assign(Object.create(_o.prototype),{constructor:Mo,getPointsHoles:function(e){for(var t=[],i=0,r=this.holes.length;i=n)break e;var s=t[1];e=(n=t[--i-1]))break t}o=i,i=0}for(;i>>1;et;)--o;if(++o,0!==n||o!==r){n>=o&&(n=(o=Math.max(o,1))-1);var a=this.getValueSize();this.times=Ho.arraySlice(i,n,o),this.values=Ho.arraySlice(this.values,n*a,o*a)}return this},validate:function(){var e=!0,t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);var i=this.times,r=this.values,n=i.length;0===n&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);for(var o=null,a=0;a!==n;a++){var s=i[a];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,a,s),e=!1;break}if(null!==o&&o>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,a,s,o),e=!1;break}o=s}if(void 0!==r&&Ho.isTypedArray(r)){a=0;for(var c=r.length;a!==c;++a){var h=r[a];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,a,h),e=!1;break}}}return e},optimize:function(){for(var e=this.times,t=this.values,i=this.getValueSize(),r=this.getInterpolation()===Z,n=1,o=e.length-1,a=1;a0){e[n]=e[o];for(f=o*i,m=n*i,p=0;p!==i;++p)t[m+p]=t[f+p];++n}return n!==e.length&&(this.times=Ho.arraySlice(e,0,n),this.values=Ho.arraySlice(t,0,n*i)),this}}),Xo.prototype=Object.assign(Object.create(Wo.prototype),{constructor:Xo,ValueTypeName:"vector"}),Object.assign(qo,{parse:function(e){for(var t=[],i=e.tracks,r=1/(e.fps||1),n=0,o=i.length;n!==o;++n)t.push(Wo.parse(i[n]).scale(r));return new qo(e.name,e.duration,t)},toJSON:function(e){for(var t=[],i=e.tracks,r={name:e.name,duration:e.duration,tracks:t},n=0,o=i.length;n!==o;++n)t.push(Wo.toJSON(i[n]));return r},CreateFromMorphTargetSequence:function(e,t,i,r){for(var n=t.length,o=[],a=0;a1){var h=r[u=c[1]];h||(r[u]=h=[]),h.push(s)}}var l=[];for(var u in r)l.push(qo.CreateFromMorphTargetSequence(u,r[u],t,i));return l},parseAnimation:function(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var i=function(e,t,i,r,n){if(0!==i.length){var o=[],a=[];Ho.flattenJSON(i,o,a,r),0!==o.length&&n.push(new e(t,o,a))}},r=[],n=e.name||"default",o=e.length||-1,a=e.fps||30,s=e.hierarchy||[],c=0;c1?e.skinWeights[r+1]:0,s=i>2?e.skinWeights[r+2]:0,c=i>3?e.skinWeights[r+3]:0;t.skinWeights.push(new he(o,a,s,c))}if(e.skinIndices)for(r=0,n=e.skinIndices.length;r1?e.skinIndices[r+1]:0,u=i>2?e.skinIndices[r+2]:0,p=i>3?e.skinIndices[r+3]:0;t.skinIndices.push(new he(h,l,u,p))}t.bones=e.bones,t.bones&&t.bones.length>0&&(t.skinWeights.length!==t.skinIndices.length||t.skinIndices.length!==t.vertices.length)&&console.warn("When skinning, number of vertices ("+t.vertices.length+"), skinIndices ("+t.skinIndices.length+"), and skinWeights ("+t.skinWeights.length+") should match.")}(e,i),function(e,t){var i=e.scale;if(void 0!==e.morphTargets)for(var r=0,n=e.morphTargets.length;r0){console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');var l=t.faces,u=e.morphColors[0].colors;for(r=0,n=l.length;r0&&(t.animations=i)}(e,i),i.computeFaceNormals(),i.computeBoundingSphere(),void 0===e.materials||0===e.materials.length?{geometry:i}:{geometry:i,materials:ta.prototype.initMaterials(e.materials,t,this.crossOrigin)}}}),Object.assign(na.prototype,{load:function(e,t,i,r){""===this.texturePath&&(this.texturePath=e.substring(0,e.lastIndexOf("/")+1));var n=this;new Yn(n.manager).load(e,(function(i){var o=null;try{o=JSON.parse(i)}catch(t){return void 0!==r&&r(t),void console.error("THREE:ObjectLoader: Can't parse "+e+".",t.message)}var a=o.metadata;void 0!==a&&void 0!==a.type&&"geometry"!==a.type.toLowerCase()?n.parse(o,t):console.error("THREE.ObjectLoader: Can't load "+e+". Use THREE.JSONLoader instead.")}),i,r)},setTexturePath:function(e){this.texturePath=e},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){var i=this.parseShape(e.shapes),r=this.parseGeometries(e.geometries,i),n=this.parseImages(e.images,(function(){void 0!==t&&t(s)})),o=this.parseTextures(e.textures,n),a=this.parseMaterials(e.materials,o),s=this.parseObject(e.object,r,a);return e.animations&&(s.animations=this.parseAnimations(e.animations)),void 0!==e.images&&0!==e.images.length||void 0!==t&&t(s),s},parseShape:function(e){var t={};if(void 0!==e)for(var i=0,r=e.length;i0){var o=new Kn(new Wn(t));o.setCrossOrigin(this.crossOrigin);for(var a=0,s=e.length;a0?new dr(s,c):new vi(s,c);break;case"LOD":n=new lr;break;case"Line":n=new mr(o(t.geometry),a(t.material),t.mode);break;case"LineLoop":n=new gr(o(t.geometry),a(t.material));break;case"LineSegments":n=new vr(o(t.geometry),a(t.material));break;case"PointCloud":case"Points":n=new xr(o(t.geometry),a(t.material));break;case"Sprite":n=new hr(a(t.material));break;case"Group":n=new br;break;default:n=new Ot}if(n.uuid=t.uuid,void 0!==t.name&&(n.name=t.name),void 0!==t.matrix?(e.fromArray(t.matrix),e.decompose(n.position,n.quaternion,n.scale)):(void 0!==t.position&&n.position.fromArray(t.position),void 0!==t.rotation&&n.rotation.fromArray(t.rotation),void 0!==t.quaternion&&n.quaternion.fromArray(t.quaternion),void 0!==t.scale&&n.scale.fromArray(t.scale)),void 0!==t.castShadow&&(n.castShadow=t.castShadow),void 0!==t.receiveShadow&&(n.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.bias&&(n.shadow.bias=t.shadow.bias),void 0!==t.shadow.radius&&(n.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&n.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(n.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.children)for(var h=t.children,l=0;lNumber.EPSILON){if(h<0&&(a=t[o],c=-c,s=t[n],h=-h),e.ys.y)continue;if(e.y===a.y){if(e.x===a.x)return!0}else{var l=h*(e.x-a.x)-c*(e.y-a.y);if(0===l)return!0;if(l<0)continue;r=!r}}else{if(e.y!==a.y)continue;if(s.x<=e.x&&e.x<=a.x||a.x<=e.x&&e.x<=s.x)return!0}}return r}var n=pn.isClockWise,o=this.subPaths;if(0===o.length)return[];if(!0===t)return i(o);var a,s,c,h=[];if(1===o.length)return s=o[0],(c=new Mo).curves=s.curves,h.push(c),h;var l=!n(o[0].getPoints());l=e?!l:l;var u,p,d=[],f=[],m=[],v=0;f[v]=void 0,m[v]=[];for(var g=0,y=o.length;g1){for(var x=!1,b=[],w=0,_=f.length;w<_;w++)d[w]=[];for(w=0,_=f.length;w<_;w++)for(var M=m[w],E=0;E0&&(x||(m=d))}g=0;for(var L=f.length;g0){this.source.connect(this.filters[0]);for(var e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(var e=1,t=this.filters.length;e=.5)for(var o=0;o!==n;++o)e[t+o]=e[i+o]},_slerp:function(e,t,i,r){ne.slerpFlat(e,t,e,t,e,i,r)},_lerp:function(e,t,i,r,n){for(var o=1-r,a=0;a!==n;++a){var s=t+a;e[s]=e[s]*o+e[i+a]*r}}}),Object.assign(Fa.prototype,{getValue:function(e,t){this.bind();var i=this._targetGroup.nCachedObjects_,r=this._bindings[i];void 0!==r&&r.getValue(e,t)},setValue:function(e,t){for(var i=this._bindings,r=this._targetGroup.nCachedObjects_,n=i.length;r!==n;++r)i[r].setValue(e,t)},bind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].bind()},unbind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].unbind()}}),Object.assign(za,{Composite:Fa,create:function(e,t,i){return e&&e.isAnimationObjectGroup?new za.Composite(e,t,i):new za(e,t,i)},sanitizeNodeName:function(e){return e.replace(/\s/g,"_").replace(/[^\w-]/g,"")},parseTrackName:(Ma=new RegExp("^"+/((?:[\w-]+[\/:])*)/.source+/([\w-\.]+)?/.source+/(?:\.([\w-]+)(?:\[(.+)\])?)?/.source+/\.([\w-]+)(?:\[(.+)\])?/.source+"$"),Ea=["material","materials","bones"],function(e){var t=Ma.exec(e);if(!t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);var i={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},r=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==r&&-1!==r){var n=i.nodeName.substring(r+1);-1!==Ea.indexOf(n)&&(i.nodeName=i.nodeName.substring(0,r),i.objectName=n)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return i}),findNode:function(e,t){if(!t||""===t||"root"===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){var i=function(e){for(var i=0;it;)--o;if(++o,0!==n||o!==r){n>=o&&(n=(o=Math.max(o,1))-1);var a=this.getValueSize();this.times=Ho.arraySlice(i,n,o),this.values=Ho.arraySlice(this.values,n*a,o*a)}return this},validate:function(){var e=!0,t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);var i=this.times,r=this.values,n=i.length;0===n&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);for(var o=null,a=0;a!==n;a++){var s=i[a];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,a,s),e=!1;break}if(null!==o&&o>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,a,s,o),e=!1;break}o=s}if(void 0!==r&&Ho.isTypedArray(r)){a=0;for(var c=r.length;a!==c;++a){var h=r[a];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,a,h),e=!1;break}}}return e},optimize:function(){for(var e=this.times,t=this.values,i=this.getValueSize(),r=this.getInterpolation()===Z,n=1,o=e.length-1,a=1;a0){e[n]=e[o];for(f=o*i,m=n*i,p=0;p!==i;++p)t[m+p]=t[f+p];++n}return n!==e.length&&(this.times=Ho.arraySlice(e,0,n),this.values=Ho.arraySlice(t,0,n*i)),this}}),Xo.prototype=Object.assign(Object.create(Wo.prototype),{constructor:Xo,ValueTypeName:"vector"}),Object.assign(qo,{parse:function(e){for(var t=[],i=e.tracks,r=1/(e.fps||1),n=0,o=i.length;n!==o;++n)t.push(Wo.parse(i[n]).scale(r));return new qo(e.name,e.duration,t)},toJSON:function(e){for(var t=[],i=e.tracks,r={name:e.name,duration:e.duration,tracks:t},n=0,o=i.length;n!==o;++n)t.push(Wo.toJSON(i[n]));return r},CreateFromMorphTargetSequence:function(e,t,i,r){for(var n=t.length,o=[],a=0;a1){var h=r[u=c[1]];h||(r[u]=h=[]),h.push(s)}}var l=[];for(var u in r)l.push(qo.CreateFromMorphTargetSequence(u,r[u],t,i));return l},parseAnimation:function(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var i=function(e,t,i,r,n){if(0!==i.length){var o=[],a=[];Ho.flattenJSON(i,o,a,r),0!==o.length&&n.push(new e(t,o,a))}},r=[],n=e.name||"default",o=e.length||-1,a=e.fps||30,s=e.hierarchy||[],c=0;c1?e.skinWeights[r+1]:0,s=i>2?e.skinWeights[r+2]:0,c=i>3?e.skinWeights[r+3]:0;t.skinWeights.push(new he(o,a,s,c))}if(e.skinIndices)for(r=0,n=e.skinIndices.length;r1?e.skinIndices[r+1]:0,u=i>2?e.skinIndices[r+2]:0,p=i>3?e.skinIndices[r+3]:0;t.skinIndices.push(new he(h,l,u,p))}t.bones=e.bones,t.bones&&t.bones.length>0&&(t.skinWeights.length!==t.skinIndices.length||t.skinIndices.length!==t.vertices.length)&&console.warn("When skinning, number of vertices ("+t.vertices.length+"), skinIndices ("+t.skinIndices.length+"), and skinWeights ("+t.skinWeights.length+") should match.")}(e,i),function(e,t){var i=e.scale;if(void 0!==e.morphTargets)for(var r=0,n=e.morphTargets.length;r0){console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');var l=t.faces,u=e.morphColors[0].colors;for(r=0,n=l.length;r0&&(t.animations=i)}(e,i),i.computeFaceNormals(),i.computeBoundingSphere(),void 0===e.materials||0===e.materials.length?{geometry:i}:{geometry:i,materials:ta.prototype.initMaterials(e.materials,t,this.crossOrigin)}}}),Object.assign(na.prototype,{load:function(e,t,i,r){""===this.texturePath&&(this.texturePath=e.substring(0,e.lastIndexOf("/")+1));var n=this;new Yn(n.manager).load(e,(function(i){var o=null;try{o=JSON.parse(i)}catch(t){return void 0!==r&&r(t),void console.error("THREE:ObjectLoader: Can't parse "+e+".",t.message)}var a=o.metadata;void 0!==a&&void 0!==a.type&&"geometry"!==a.type.toLowerCase()?n.parse(o,t):console.error("THREE.ObjectLoader: Can't load "+e+". Use THREE.JSONLoader instead.")}),i,r)},setTexturePath:function(e){this.texturePath=e},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){var i=this.parseShape(e.shapes),r=this.parseGeometries(e.geometries,i),n=this.parseImages(e.images,(function(){void 0!==t&&t(s)})),o=this.parseTextures(e.textures,n),a=this.parseMaterials(e.materials,o),s=this.parseObject(e.object,r,a);return e.animations&&(s.animations=this.parseAnimations(e.animations)),void 0!==e.images&&0!==e.images.length||void 0!==t&&t(s),s},parseShape:function(e){var t={};if(void 0!==e)for(var i=0,r=e.length;i0){var o=new Kn(new Wn(t));o.setCrossOrigin(this.crossOrigin);for(var a=0,s=e.length;a0?new dr(s,c):new vi(s,c);break;case"LOD":n=new lr;break;case"Line":n=new mr(o(t.geometry),a(t.material),t.mode);break;case"LineLoop":n=new gr(o(t.geometry),a(t.material));break;case"LineSegments":n=new vr(o(t.geometry),a(t.material));break;case"PointCloud":case"Points":n=new xr(o(t.geometry),a(t.material));break;case"Sprite":n=new hr(a(t.material));break;case"Group":n=new br;break;default:n=new Ot}if(n.uuid=t.uuid,void 0!==t.name&&(n.name=t.name),void 0!==t.matrix?(e.fromArray(t.matrix),e.decompose(n.position,n.quaternion,n.scale)):(void 0!==t.position&&n.position.fromArray(t.position),void 0!==t.rotation&&n.rotation.fromArray(t.rotation),void 0!==t.quaternion&&n.quaternion.fromArray(t.quaternion),void 0!==t.scale&&n.scale.fromArray(t.scale)),void 0!==t.castShadow&&(n.castShadow=t.castShadow),void 0!==t.receiveShadow&&(n.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.bias&&(n.shadow.bias=t.shadow.bias),void 0!==t.shadow.radius&&(n.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&n.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(n.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.children)for(var h=t.children,l=0;lNumber.EPSILON){if(h<0&&(a=t[o],c=-c,s=t[n],h=-h),e.ys.y)continue;if(e.y===a.y){if(e.x===a.x)return!0}else{var l=h*(e.x-a.x)-c*(e.y-a.y);if(0===l)return!0;if(l<0)continue;r=!r}}else{if(e.y!==a.y)continue;if(s.x<=e.x&&e.x<=a.x||a.x<=e.x&&e.x<=s.x)return!0}}return r}var n=pn.isClockWise,o=this.subPaths;if(0===o.length)return[];if(!0===t)return i(o);var a,s,c,h=[];if(1===o.length)return s=o[0],(c=new Mo).curves=s.curves,h.push(c),h;var l=!n(o[0].getPoints());l=e?!l:l;var u,p,d=[],f=[],m=[],v=0;f[v]=void 0,m[v]=[];for(var g=0,y=o.length;g1){for(var x=!1,b=[],w=0,_=f.length;w<_;w++)d[w]=[];for(w=0,_=f.length;w<_;w++)for(var M=m[w],E=0;E0&&(x||(m=d))}g=0;for(var R=f.length;g0){this.source.connect(this.filters[0]);for(var e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(var e=1,t=this.filters.length;e=.5)for(var o=0;o!==n;++o)e[t+o]=e[i+o]},_slerp:function(e,t,i,r){ne.slerpFlat(e,t,e,t,e,i,r)},_lerp:function(e,t,i,r,n){for(var o=1-r,a=0;a!==n;++a){var s=t+a;e[s]=e[s]*o+e[i+a]*r}}}),Object.assign(Fa.prototype,{getValue:function(e,t){this.bind();var i=this._targetGroup.nCachedObjects_,r=this._bindings[i];void 0!==r&&r.getValue(e,t)},setValue:function(e,t){for(var i=this._bindings,r=this._targetGroup.nCachedObjects_,n=i.length;r!==n;++r)i[r].setValue(e,t)},bind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].bind()},unbind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].unbind()}}),Object.assign(za,{Composite:Fa,create:function(e,t,i){return e&&e.isAnimationObjectGroup?new za.Composite(e,t,i):new za(e,t,i)},sanitizeNodeName:function(e){return e.replace(/\s/g,"_").replace(/[^\w-]/g,"")},parseTrackName:(Ma=new RegExp("^"+/((?:[\w-]+[\/:])*)/.source+/([\w-\.]+)?/.source+/(?:\.([\w-]+)(?:\[(.+)\])?)?/.source+/\.([\w-]+)(?:\[(.+)\])?/.source+"$"),Ea=["material","materials","bones"],function(e){var t=Ma.exec(e);if(!t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);var i={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},r=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==r&&-1!==r){var n=i.nodeName.substring(r+1);-1!==Ea.indexOf(n)&&(i.nodeName=i.nodeName.substring(0,r),i.objectName=n)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return i}),findNode:function(e,t){if(!t||""===t||"root"===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){var i=function(e){for(var i=0;i=t){var l=t++,u=e[l];i[u.uuid]=h,e[h]=u,i[c]=l,e[l]=s;for(var p=0,d=n;p!==d;++p){var f=r[p],m=f[l],v=f[h];f[h]=m,f[l]=v}}}this.nCachedObjects_=t},uncache:function(){for(var e=this._objects,t=e.length,i=this.nCachedObjects_,r=this._indicesByUUID,n=this._bindings,o=n.length,a=0,s=arguments.length;a!==s;++a){var c=arguments[a],h=c.uuid,l=r[h];if(void 0!==l)if(delete r[h],l0)for(var c=this._interpolants,h=this._propertyBindings,l=0,u=c.length;l!==u;++l)c[l].evaluate(a),h[l].accumulate(r,s)}else this._updateWeight(e)},_updateWeight:function(e){var t=0;if(this.enabled){t=this.weight;var i=this._weightInterpolant;if(null!==i){var r=i.evaluate(e)[0];t*=r,e>i.parameterPositions[1]&&(this.stopFading(),0===r&&(this.enabled=!1))}}return this._effectiveWeight=t,t},_updateTimeScale:function(e){var t=0;if(!this.paused){t=this.timeScale;var i=this._timeScaleInterpolant;if(null!==i)t*=i.evaluate(e)[0],e>i.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}return this._effectiveTimeScale=t,t},_updateTime:function(e){var t=this.time+e;if(0===e)return t;var i=this._clip.duration,r=this.loop,n=this._loopCount;if(2200===r){-1===n&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(t>=i)t=i;else{if(!(t<0))break e;t=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{var o=2202===r;if(-1===n&&(e>=0?(n=0,this._setEndings(!0,0===this.repetitions,o)):this._setEndings(0===this.repetitions,!0,o)),t>=i||t<0){var a=Math.floor(t/i);t-=i*a,n+=Math.abs(a);var s=this.repetitions-n;if(s<0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,t=e>0?i:0,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(0===s){var c=e<0;this._setEndings(c,!c,o)}else this._setEndings(!1,!1,o);this._loopCount=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:a})}}if(o&&1==(1&n))return this.time=t,i-t}return this.time=t,t},_setEndings:function(e,t,i){var r=this._interpolantSettings;i?(r.endingStart=K,r.endingEnd=K):(r.endingStart=e?this.zeroSlopeAtStart?K:J:Q,r.endingEnd=t?this.zeroSlopeAtEnd?K:J:Q)},_scheduleFading:function(e,t,i){var r=this._mixer,n=r.time,o=this._weightInterpolant;null===o&&(o=r._lendControlInterpolant(),this._weightInterpolant=o);var a=o.parameterPositions,s=o.sampleValues;return a[0]=n,s[0]=t,a[1]=n+e,s[1]=i,this}}),Va.prototype=Object.assign(Object.create(n.prototype),{constructor:Va,_bindAction:function(e,t){var i=e._localRoot||this._root,r=e._clip.tracks,n=r.length,o=e._propertyBindings,a=e._interpolants,s=i.uuid,c=this._bindingsByRootAndName,h=c[s];void 0===h&&(h={},c[s]=h);for(var l=0;l!==n;++l){var u=r[l],p=u.name,d=h[p];if(void 0!==d)o[l]=d;else{if(void 0!==(d=o[l])){null===d._cacheIndex&&(++d.referenceCount,this._addInactiveBinding(d,s,p));continue}var f=t&&t._propertyBindings[l].binding.parsedPath;++(d=new Ba(za.create(i,p,f),u.ValueTypeName,u.getValueSize())).referenceCount,this._addInactiveBinding(d,s,p),o[l]=d}a[l].resultBuffer=d.buffer}},_activateAction:function(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){var t=(e._localRoot||this._root).uuid,i=e._clip.uuid,r=this._actionsByClip[i];this._bindAction(e,r&&r.knownActions[0]),this._addInactiveAction(e,i,t)}for(var n=e._propertyBindings,o=0,a=n.length;o!==a;++o){var s=n[o];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}},_deactivateAction:function(e){if(this._isActiveAction(e)){for(var t=e._propertyBindings,i=0,r=t.length;i!==r;++i){var n=t[i];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(e)}},_initMemoryManager:function(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;var e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}},_isActiveAction:function(e){var t=e._cacheIndex;return null!==t&&t.99999?this.quaternion.set(0,0,0,1):e.y<-.99999?this.quaternion.set(1,0,0,0):(La.set(e.z,0,-e.x).normalize(),Aa=Math.acos(e.y),this.quaternion.setFromAxisAngle(La,Aa))}),gs.prototype.setLength=function(e,t,i){void 0===t&&(t=.2*e),void 0===i&&(i=.2*t),this.line.scale.set(1,Math.max(0,e-t),1),this.line.updateMatrix(),this.cone.scale.set(i,t,i),this.cone.position.y=e,this.cone.updateMatrix()},gs.prototype.setColor=function(e){this.line.material.color.copy(e),this.cone.material.color.copy(e)},ys.prototype=Object.create(vr.prototype),ys.prototype.constructor=ys;var xs={createMultiMaterialObject:function(e,t){for(var i=new br,r=0,n=t.length;r0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),"," (- z + zOffset / 1000.0) * maxDepthPerTile,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),this.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n")}metaLoaded(){this.metaLoaded=!0,this.initStreamer()}initStreamer(){if(this.metaLoaded){this.texture=new Ss.Texture(this.video),this.geometry=new Ss.Geometry;for(var e=0,t=this.width*this.height;e{(this.isMjpeg||this.video.readyState===this.video.HAVE_ENOUGH_DATA)&&(this.texture.needsUpdate=!0)}),1e3/30)}}startStream(){this.isMjpeg||this.video.play()}stopStream(){this.isMjpeg||this.video.pause()}}class Ns extends Ss.Mesh{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1,n=e.headLength||.2,o=e.shaftDiameter||.05,a=e.headDiameter||.1,s=e.material||new Ss.MeshBasicMaterial,c=r-n,h=new Ss.CylinderGeometry(.5*o,.5*o,c,12,1),l=new Ss.Matrix4;l.setPosition(new Ss.Vector3(0,.5*c,0)),h.applyMatrix(l);var u=new Ss.CylinderGeometry(0,.5*a,n,12,1);l.setPosition(new Ss.Vector3(0,c+.5*n,0)),u.applyMatrix(l),h.merge(u),super(h,s),this.position.copy(t),this.setDirection(i)}setDirection(e){var t=new Ss.Vector3;0===e.x&&0===e.z?t.set(1,0,0):t.set(0,1,0).cross(e);var i=Math.acos(new Ss.Vector3(0,1,0).dot(e.clone().normalize()));this.matrix=(new Ss.Matrix4).makeRotationAxis(t.normalize(),i),this.rotation.setFromRotationMatrix(this.matrix,this.rotation.order)}setLength(e){this.scale.set(e,e,e)}setColor(e){this.material.color.setHex(e)}dispose(){void 0!==this.geometry&&this.geometry.dispose(),void 0!==this.material&&this.material.dispose()}}Ss.STLLoader=function(e){this.manager=void 0!==e?e:Ss.DefaultLoadingManager},Ss.STLLoader.prototype={constructor:Ss.STLLoader,load:function(e,t,i,r){var n=this,o=new Ss.FileLoader(n.manager);o.setResponseType("arraybuffer"),o.load(e,(function(e){t(n.parse(e))}),i,r)},parse:function(e){var t=function(e){if("string"==typeof e){for(var t=new Uint8Array(e.length),i=0;i>5&31)/31,r=(w>>10&31)/31):(t=o,i=a,r=s)}for(var _=1;_<=3;_++){var M=g+12*_;f.push(h.getFloat32(M,!0)),f.push(h.getFloat32(M+4,!0)),f.push(h.getFloat32(M+8,!0)),m.push(y,x,b),u&&n.push(t,i,r)}}return d.addAttribute("position",new Ss.BufferAttribute(new Float32Array(f),3)),d.addAttribute("normal",new Ss.BufferAttribute(new Float32Array(m),3)),u&&(d.addAttribute("color",new Ss.BufferAttribute(new Float32Array(n),3)),d.hasColors=!0,d.alpha=c),d}(t):function(e){for(var t,i=new Ss.BufferGeometry,r=/facet([\s\S]*?)endfacet/g,n=0,o=/[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source,a=new RegExp("vertex"+o+o+o,"g"),s=new RegExp("normal"+o+o+o,"g"),c=[],h=[],l=new Ss.Vector3;null!==(t=r.exec(e));){for(var u=0,p=0,d=t[0];null!==(t=s.exec(d));)l.x=parseFloat(t[1]),l.y=parseFloat(t[2]),l.z=parseFloat(t[3]),p++;for(;null!==(t=a.exec(d));)c.push(parseFloat(t[1]),parseFloat(t[2]),parseFloat(t[3])),h.push(l.x,l.y,l.z),u++;1!==p&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+n),3!==u&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+n),n++}return i.addAttribute("position",new Ss.Float32BufferAttribute(c,3)),i.addAttribute("normal",new Ss.Float32BufferAttribute(h,3)),i}(function(e){if("string"!=typeof e){var t=new Uint8Array(e);if(void 0!==window.TextDecoder)return(new TextDecoder).decode(t);for(var i="",r=0,n=e.byteLength;r0?t[t.length-1]:"",smooth:void 0!==i?i.smooth:this.smooth,groupStart:void 0!==i?i.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(e){var t={index:"number"==typeof e?e:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return t.clone=this.clone.bind(t),t}};return this.materials.push(r),r},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(e){var t=this.currentMaterial();if(t&&-1===t.groupEnd&&(t.groupEnd=this.geometry.vertices.length/3,t.groupCount=t.groupEnd-t.groupStart,t.inherited=!1),e&&this.materials.length>1)for(var i=this.materials.length-1;i>=0;i--)this.materials[i].groupCount<=0&&this.materials.splice(i,1);return e&&0===this.materials.length&&this.materials.push({name:"",smooth:this.smooth}),t}},i&&i.name&&"function"==typeof i.clone){var r=i.clone(0);r.inherited=!0,this.object.materials.push(r)}this.objects.push(this.object)},finalize:function(){this.object&&"function"==typeof this.object._finalize&&this.object._finalize(!0)},parseVertexIndex:function(e,t){var i=parseInt(e,10);return 3*(i>=0?i-1:i+t/3)},parseNormalIndex:function(e,t){var i=parseInt(e,10);return 3*(i>=0?i-1:i+t/3)},parseUVIndex:function(e,t){var i=parseInt(e,10);return 2*(i>=0?i-1:i+t/2)},addVertex:function(e,t,i){var r=this.vertices,n=this.object.geometry.vertices;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addVertexPoint:function(e){var t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){var t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,i){var r=this.normals,n=this.object.geometry.normals;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addColor:function(e,t,i){var r=this.colors,n=this.object.geometry.colors;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addUV:function(e,t,i){var r=this.uvs,n=this.object.geometry.uvs;n.push(r[e+0],r[e+1]),n.push(r[t+0],r[t+1]),n.push(r[i+0],r[i+1])},addUVLine:function(e){var t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,i,r,n,o,a,s,c){var h=this.vertices.length,l=this.parseVertexIndex(e,h),u=this.parseVertexIndex(t,h),p=this.parseVertexIndex(i,h);if(this.addVertex(l,u,p),void 0!==r&&""!==r){var d=this.uvs.length;l=this.parseUVIndex(r,d),u=this.parseUVIndex(n,d),p=this.parseUVIndex(o,d),this.addUV(l,u,p)}if(void 0!==a&&""!==a){var f=this.normals.length;l=this.parseNormalIndex(a,f),u=a===s?l:this.parseNormalIndex(s,f),p=a===c?l:this.parseNormalIndex(c,f),this.addNormal(l,u,p)}this.colors.length>0&&this.addColor(l,u,p)},addPointGeometry:function(e){this.object.geometry.type="Points";for(var t=this.vertices.length,i=0,r=e.length;i0){var m=f.split("/");u.push(m)}}var v=u[0];for(p=1,d=u.length-1;p1){var A=o[1].trim().toLowerCase();t.object.smooth="0"!==A&&"off"!==A}else t.object.smooth=!0;(G=t.object.currentMaterial())&&(G.smooth=t.object.smooth)}t.finalize();var L=new Ss.Object3D;L.materialLibraries=[].concat(t.materialLibraries);for(s=0,c=t.objects.length;s0?D.addAttribute("normal",new Ss.Float32BufferAttribute(C.normals,3)):D.computeVertexNormals(),C.colors.length>0&&(I=!0,D.addAttribute("color",new Ss.Float32BufferAttribute(C.colors,3))),C.uvs.length>0&&D.addAttribute("uv",new Ss.Float32BufferAttribute(C.uvs,2));for(var U,B=[],F=0,z=P.length;F1){for(F=0,z=P.length;F=0?s.substring(0,c):s;h=h.toLowerCase();var l=c>=0?s.substring(c+1):"";if(l=l.trim(),"newmtl"===h)r={name:l},o[l]=r;else if("ka"===h||"kd"===h||"ks"===h||"ke"===h){var u=l.split(n,3);r[h]=[parseFloat(u[0]),parseFloat(u[1]),parseFloat(u[2])]}else r[h]=l}}var p=new Ss.MTLLoader.MaterialCreator(this.resourcePath||t,this.materialOptions);return p.setCrossOrigin(this.crossOrigin),p.setManager(this.manager),p.setMaterials(o),p}},Ss.MTLLoader.MaterialCreator=function(e,t){this.baseUrl=e||"",this.options=t,this.materialsInfo={},this.materials={},this.materialsArray=[],this.nameLookup={},this.side=this.options&&this.options.side?this.options.side:Ss.FrontSide,this.wrap=this.options&&this.options.wrap?this.options.wrap:Ss.RepeatWrapping},Ss.MTLLoader.MaterialCreator.prototype={constructor:Ss.MTLLoader.MaterialCreator,crossOrigin:"anonymous",setCrossOrigin:function(e){return this.crossOrigin=e,this},setManager:function(e){this.manager=e},setMaterials:function(e){this.materialsInfo=this.convert(e),this.materials={},this.materialsArray=[],this.nameLookup={}},convert:function(e){if(!this.options)return e;var t={};for(var i in e){var r=e[i],n={};for(var o in t[i]=n,r){var a=!0,s=r[o],c=o.toLowerCase();switch(c){case"kd":case"ka":case"ks":this.options&&this.options.normalizeRGB&&(s=[s[0]/255,s[1]/255,s[2]/255]),this.options&&this.options.ignoreZeroRGBs&&0===s[0]&&0===s[1]&&0===s[2]&&(a=!1)}a&&(n[c]=s)}}return t},preload:function(){for(var e in this.materialsInfo)this.create(e)},getIndex:function(e){return this.nameLookup[e]},getAsArray:function(){var e=0;for(var t in this.materialsInfo)this.materialsArray[e]=this.create(t),this.nameLookup[t]=e,e++;return this.materialsArray},create:function(e){return void 0===this.materials[e]&&this.createMaterial_(e),this.materials[e]},createMaterial_:function(e){var t=this,i=this.materialsInfo[e],r={name:e,side:this.side};function n(e,i){if(!r[e]){var n,o,a=t.getTextureParams(i,r),s=t.loadTexture((n=t.baseUrl,"string"!=typeof(o=a.url)||""===o?"":/^https?:\/\//i.test(o)?o:n+o));s.repeat.copy(a.scale),s.offset.copy(a.offset),s.wrapS=t.wrap,s.wrapT=t.wrap,r[e]=s}}for(var o in i){var a,s=i[o];if(""!==s)switch(o.toLowerCase()){case"kd":r.color=(new Ss.Color).fromArray(s);break;case"ks":r.specular=(new Ss.Color).fromArray(s);break;case"ke":r.emissive=(new Ss.Color).fromArray(s);break;case"map_kd":n("map",s);break;case"map_ks":n("specularMap",s);break;case"map_ke":n("emissiveMap",s);break;case"norm":n("normalMap",s);break;case"map_bump":case"bump":n("bumpMap",s);break;case"map_d":n("alphaMap",s),r.transparent=!0;break;case"ns":r.shininess=parseFloat(s);break;case"d":(a=parseFloat(s))<1&&(r.opacity=a,r.transparent=!0);break;case"tr":a=parseFloat(s),this.options&&this.options.invertTrProperty&&(a=1-a),a>0&&(r.opacity=1-a,r.transparent=!0)}}return this.materials[e]=new Ss.MeshPhongMaterial(r),this.materials[e]},getTextureParams:function(e,t){var i,r={scale:new Ss.Vector2(1,1),offset:new Ss.Vector2(0,0)},n=e.split(/\s+/);return(i=n.indexOf("-bm"))>=0&&(t.bumpScale=parseFloat(n[i+1]),n.splice(i,2)),(i=n.indexOf("-s"))>=0&&(r.scale.set(parseFloat(n[i+1]),parseFloat(n[i+2])),n.splice(i,4)),(i=n.indexOf("-o"))>=0&&(r.offset.set(parseFloat(n[i+1]),parseFloat(n[i+2])),n.splice(i,4)),r.url=n.join(" ").trim(),r},loadTexture:function(e,t,i,r,n){var o,a=Ss.Loader.Handlers.get(e),s=void 0!==this.manager?this.manager:Ss.DefaultLoadingManager;return null===a&&(a=new Ss.TextureLoader(s)),a.setCrossOrigin&&a.setCrossOrigin(this.crossOrigin),o=a.load(e,i,r,n),void 0!==t&&(o.mapping=t),o}},Ss.ColladaLoader=function(e){this.manager=void 0!==e?e:Ss.DefaultLoadingManager},Ss.ColladaLoader.prototype={constructor:Ss.ColladaLoader,crossOrigin:"Anonymous",load:function(e,t,i,r){var n=this,o=Ss.Loader.prototype.extractUrlBase(e);new Ss.FileLoader(n.manager).load(e,(function(e){t(n.parse(e,o))}),i,r)},options:{set convertUpAxis(e){console.warn("THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.")}},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){function i(e,t){for(var i=[],r=e.childNodes,n=0,o=r.length;n0&&t.push(new Ss.VectorKeyframeTrack(r+".position",n,o)),a.length>0&&t.push(new Ss.QuaternionKeyframeTrack(r+".quaternion",n,a)),s.length>0&&t.push(new Ss.VectorKeyframeTrack(r+".scale",n,s)),t}function _(e,t,i){var r,n,o,a=!0;for(n=0,o=e.length;n=0;){var r=e[t];if(null!==r.value[i])return r;t--}return null}function E(e,t,i){for(;t0&&p.addAttribute("position",new Ss.Float32BufferAttribute(n.array,n.stride)),o.array.length>0&&p.addAttribute("normal",new Ss.Float32BufferAttribute(o.array,o.stride)),s.array.length>0&&p.addAttribute("color",new Ss.Float32BufferAttribute(s.array,s.stride)),a.array.length>0&&p.addAttribute("uv",new Ss.Float32BufferAttribute(a.array,a.stride)),c.length>0&&p.addAttribute("skinIndex",new Ss.Float32BufferAttribute(c,h)),l.length>0&&p.addAttribute("skinWeight",new Ss.Float32BufferAttribute(l,u)),r.data=p,r.type=e[0].type,r.materialKeys=d,r}function ne(e,t,i,r){var n=e.p,o=e.stride,a=e.vcount;function s(e){for(var t=n[e+i]*l,o=t+l;t0&&console.log("THREE.ColladaLoader: Geometry has faces with more than 4 vertices.")}else for(p=0,d=n.length;p=t.limits.max&&(t.static=!0),t.middlePosition=(t.limits.min+t.limits.max)/2,t}function le(e){for(var t={sid:e.getAttribute("sid"),name:e.getAttribute("name")||"",attachments:[],transforms:[]},i=0;ir.limits.max||t0){var q=this.msgColor,Y=document.createElement("canvas"),Z=Y.getContext("2d"),J="normal 100px sans-serif";Z.font=J;var K=Z.measureText(i.text).width;Y.width=K,Y.height=150,Z.font=J,Z.fillStyle="rgba("+Math.round(255*q.r)+", "+Math.round(255*q.g)+", "+Math.round(255*q.b)+", "+q.a+")",Z.textAlign="left",Z.textBaseline="middle",Z.fillText(i.text,0,Y.height/2);var Q=new Ss.Texture(Y);Q.needsUpdate=!0;var $=new Ss.SpriteMaterial({map:Q,useScreenCoordinates:!1}),ee=new Ss.Sprite($),te=i.scale.x;ee.scale.set(K/Y.height*te,te,1),this.add(ee)}break;case 10:var ie=null;0===i.color.r&&0===i.color.g&&0===i.color.b&&0===i.color.a||(ie=r),this.msgMesh=i.mesh_resource.substr(10);var re=new Fs({path:t,resource:this.msgMesh,material:ie});this.add(re);break;case 11:var ne=new zs({material:r,vertices:i.points,colors:i.colors});ne.scale.set(i.scale.x,i.scale.y,i.scale.z),this.add(ne);break;default:console.error("Currently unsupported marker type: "+i.type)}}setPose(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()}update(e){if(this.setPose(e.pose),e.color.r!==this.msgColor.r||e.color.g!==this.msgColor.g||e.color.b!==this.msgColor.b||e.color.a!==this.msgColor.a){var t=As(e.color.r,e.color.g,e.color.b,e.color.a);switch(e.type){case 4:case 5:case 8:break;case 0:case 1:case 2:case 3:case 11:case 9:this.traverse((function(e){e instanceof Ss.Mesh&&(e.material=t)}));break;case 10:var i=null;0===e.color.r&&0===e.color.g&&0===e.color.b&&0===e.color.a||(i=this.colorMaterial),this.traverse((function(e){e instanceof Ss.Mesh&&(e.material=i)}));break;default:return!1}this.msgColor=e.color}var r=Math.abs(this.msgScale[0]-e.scale.x)>1e-6||Math.abs(this.msgScale[1]-e.scale.y)>1e-6||Math.abs(this.msgScale[2]-e.scale.z)>1e-6;switch(this.msgScale=[e.scale.x,e.scale.y,e.scale.z],e.type){case 1:case 2:case 3:if(r)return!1;break;case 9:if(r||this.text!==e.text)return!1;break;case 10:if(e.mesh_resource.substr(10)!==this.msgMesh)return!1;if(r)return!1;break;case 0:case 4:case 5:case 6:case 7:case 8:case 11:return!1}return!0}dispose(){this.children.forEach((function(e){e instanceof Fs?e.children.forEach((function(t){void 0!==t.material&&t.material.dispose(),t.children.forEach((function(e){void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose(),t.remove(e)})),e.remove(t)})):(void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose()),e.parent.remove(e)}))}}class Gs extends Ss.Object3D{constructor(e){super();var t=this;e=e||{},this.parent=e.parent;var i=e.handle,n=e.message;this.message=n,this.name=n.name,this.camera=e.camera,this.path=e.path||"/",this.loader=e.loader,this.dragging=!1,this.startMousePos=new Ss.Vector2,this.isShift=!1;var o=new Ss.Quaternion(n.orientation.x,n.orientation.y,n.orientation.z,n.orientation.w);o.normalize();var a=new Ss.Vector3(1,0,0);switch(a.applyQuaternion(o),this.currentControlOri=new Ss.Quaternion,n.interaction_mode){case 9:case 7:this.addEventListener("mousemove",this.parent.move3d.bind(this.parent,this,a));break;case 3:this.addEventListener("mousemove",this.parent.moveAxis.bind(this.parent,this,a)),this.addEventListener("touchmove",this.parent.moveAxis.bind(this.parent,this,a));break;case 5:this.addEventListener("mousemove",this.parent.rotateAxis.bind(this.parent,this,o));break;case 4:this.addEventListener("mousemove",this.parent.movePlane.bind(this.parent,this,a));break;case 2:this.addEventListener("click",this.parent.buttonClick.bind(this.parent,this))}function s(e){e.stopPropagation()}0!==n.interaction_mode&&(this.addEventListener("mousedown",this.parent.startDrag.bind(this.parent,this)),this.addEventListener("mouseup",this.parent.stopDrag.bind(this.parent,this)),this.addEventListener("contextmenu",this.parent.showMenu.bind(this.parent,this)),this.addEventListener("mouseup",(function(e){0===t.startMousePos.distanceToSquared(e.mousePos)&&(e.type="contextmenu",t.dispatchEvent(e))})),this.addEventListener("mouseover",s),this.addEventListener("mouseout",s),this.addEventListener("click",s),this.addEventListener("mousedown",(function(e){t.startMousePos=e.mousePos})),this.addEventListener("touchstart",(function(e){1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,t.dispatchEvent(e))})),this.addEventListener("touchmove",(function(e){1===e.domEvent.touches.length&&(e.type="mousemove",e.domEvent.button=0,t.dispatchEvent(e))})),this.addEventListener("touchend",(function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",t.dispatchEvent(e),e.type="click",t.dispatchEvent(e))})),window.addEventListener("keydown",(function(e){16===e.keyCode&&(t.isShift=!0)})),window.addEventListener("keyup",(function(e){16===e.keyCode&&(t.isShift=!1)})));var c=new Ss.Quaternion,h=this.parent.position.clone().multiplyScalar(-1);switch(n.orientation_mode){case 0:c=this.parent.quaternion.clone().inverse();break;case 1:case 2:break;default:console.error("Unkown orientation mode: "+n.orientation_mode)}var l=new r.TFClient({ros:i.tfClient.ros,fixedFrame:i.message.header.frame_id,serverName:i.tfClient.serverName});n.markers.forEach((function(e){var i=function(i){var n=new ks({message:e,path:t.path,loader:t.loader});if(null!==i){var o=new r.Pose({position:n.position,orientation:n.quaternion});o.applyTransform(new r.Transform(i));var a=new ks({message:e,path:t.path,loader:t.loader});a.position.add(h),a.position.applyQuaternion(c),a.quaternion.multiplyQuaternions(c,a.quaternion);var s=new Ss.Vector3(a.position.x,a.position.y,a.position.z),u=new r.Transform({translation:s,orientation:a.quaternion});o.applyTransform(u),n.setPose(o),n.updateMatrixWorld(),l.unsubscribe(e.header.frame_id)}t.add(n)};""!==e.header.frame_id?l.subscribe(e.header.frame_id,i):i(null)}))}updateMatrixWorld(e){var t=this,i=this.message;switch(i.orientation_mode){case 0:super.updateMatrixWorld(e),t.currentControlOri.copy(t.quaternion),t.currentControlOri.normalize();break;case 1:t.quaternion.copy(t.parent.quaternion.clone().inverse()),t.updateMatrix(),t.matrixWorldNeedsUpdate=!0,super.updateMatrixWorld(e),t.currentControlOri.copy(t.quaternion);break;case 2:t.camera.updateMatrixWorld();var r=(new Ss.Matrix4).extractRotation(t.camera.matrixWorld),n=new Ss.Matrix4,o=.5*Math.PI,a=new Ss.Euler(-o,0,o);n.makeRotationFromEuler(a);var s=new Ss.Matrix4;s.getInverse(t.parent.matrixWorld),r.multiplyMatrices(r,n),r.multiplyMatrices(s,r),t.currentControlOri.setFromRotationMatrix(r),i.independent_marker_orientation||(t.quaternion.copy(t.currentControlOri),t.updateMatrix(),t.matrixWorldNeedsUpdate=!0),super.updateMatrixWorld(e);break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}}}class Vs extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).menuEntries,r=e.className||"default-interactive-marker-menu";e.entryClassName;var n,o,a,s=e.overlayClassName||"default-interactive-marker-overlay",c=e.menuFontSize||"0.8em",h=[];if(h[0]={children:[]},null===document.getElementById("default-interactive-marker-menu-css")){var l=document.createElement("style");l.id="default-interactive-marker-menu-css",l.type="text/css",l.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: "+c+";z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(l)}for(this.menuDomElem=document.createElement("div"),this.menuDomElem.style.position="absolute",this.menuDomElem.className=r,this.menuDomElem.addEventListener("contextmenu",(function(e){e.preventDefault()})),this.overlayDomElem=document.createElement("div"),this.overlayDomElem.className=s,this.hideListener=this.hide.bind(this),this.overlayDomElem.addEventListener("contextmenu",this.hideListener),this.overlayDomElem.addEventListener("click",this.hideListener),this.overlayDomElem.addEventListener("touchstart",this.hideListener),n=0;n0?(e(s,o[a]),c.addEventListener("click",t.hide.bind(t)),c.addEventListener("touchstart",t.hide.bind(t))):(c.addEventListener("click",p.bind(t,o[a])),c.addEventListener("touchstart",p.bind(t,o[a])),c.className="default-interactive-marker-menu-entry")}}(this.menuDomElem,h[0])}show(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,void 0!==t.domEvent.changedTouches?(this.menuDomElem.style.left=t.domEvent.changedTouches[0].pageX+"px",this.menuDomElem.style.top=t.domEvent.changedTouches[0].pageY+"px"):(this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px"),document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)}hide(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)}}class js extends Ss.Object3D{constructor(e){super();var t=(e=e||{}).handle;this.name=t.name;var i=e.camera,r=e.path||"/",n=e.loader;this.dragging=!1,this.onServerSetPose({pose:t.pose}),this.dragStart={position:new Ss.Vector3,orientation:new Ss.Quaternion,positionWorld:new Ss.Vector3,orientationWorld:new Ss.Quaternion,event3d:{}},t.controls.forEach(function(e){this.add(new Gs({parent:this,handle:t,message:e,camera:i,path:r,loader:n}))}.bind(this)),t.menuEntries.length>0&&(this.menu=new Vs({menuEntries:t.menuEntries,menuFontSize:t.menuFontSize}),this.menu.addEventListener("menu-select",function(e){this.dispatchEvent(e)}.bind(this)))}showMenu(e,t){this.menu&&this.menu.show(e,t)}moveAxis(e,t,i){if(this.dragging){var r=e.currentControlOri,n=t.clone().applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),s=new Ss.Ray(o,a),c=Cs(s,i.camera,i.mousePos),h=new Ss.Vector3;h.addVectors(this.dragStart.position,n.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(c)),this.setPosition(e,h),i.stopPropagation()}}move3d(e,t,i){if(this.dragging)if(e.isShift);else{var r=e.camera.getWorldDirection(),n=Math.abs(r.x),o=Math.abs(r.y),a=Math.abs(r.z),s=new Ss.Quaternion(1,0,0,1);o>n&&o>a?s=new Ss.Quaternion(0,0,1,1):a>n&&a>o&&(s=new Ss.Quaternion(0,1,0,1)),s.normalize(),(t=new Ss.Vector3(1,0,0)).applyQuaternion(s),this.movePlane(e,t,i)}}movePlane(e,t,i){if(this.dragging){var r=e.currentControlOri,n=t.clone().applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.clone().applyQuaternion(this.dragStart.orientationWorld),s=Ls(i.mouseRay,o,a),c=new Ss.Vector3;c.subVectors(s,o),c.add(this.dragStart.positionWorld),this.setPosition(e,c),i.stopPropagation()}}rotateAxis(e,t,i){if(this.dragging){e.updateMatrixWorld();var r=e.currentControlOri.clone().multiply(t.clone()),n=new Ss.Vector3(1,0,0).applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.applyQuaternion(this.dragStart.orientationWorld),s=Ls(i.mouseRay,o,a),c=new Ss.Ray(this.dragStart.positionWorld,a),h=Ls(c,o,a),l=this.dragStart.orientationWorld.clone().multiply(r).clone().inverse();s.sub(h),s.applyQuaternion(l);var u=this.dragStart.event3d.intersection.point.clone();u.sub(h),u.applyQuaternion(l);var p=Math.atan2(s.y,s.z),d=Math.atan2(u.y,u.z)-p,f=new Ss.Quaternion;f.setFromAxisAngle(n,d),this.setOrientation(e,f.multiply(this.dragStart.orientationWorld)),i.stopPropagation()}}feedbackEvent(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})}startDrag(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var i=new Ss.Vector3;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,i),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}}stopDrag(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))}buttonClick(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)}setPosition(e,t){this.position.copy(t),this.feedbackEvent("user-pose-change",e)}setOrientation(e,t){t.normalize(),this.quaternion.copy(t),this.feedbackEvent("user-pose-change",e)}onServerSetPose(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.copy(t.position),this.quaternion.copy(t.orientation),this.updateMatrixWorld(!0)}}dispose(){this.children.forEach(function(e){e.children.forEach((function(t){t.dispose(),e.remove(t)})),this.remove(e)}.bind(this))}}function Hs(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Ws,Xs={exports:{}}; -/*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */Ws=Xs,function(e){var t=Object.hasOwnProperty,i=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},r="object"==typeof process&&"function"==typeof process.nextTick,n="function"==typeof Symbol,o="object"==typeof Reflect,a="function"==typeof setImmediate?setImmediate:setTimeout,s=n?o&&"function"==typeof Reflect.ownKeys?Reflect.ownKeys:function(e){var t=Object.getOwnPropertyNames(e);return t.push.apply(t,Object.getOwnPropertySymbols(e)),t}:Object.keys;function c(){this._events={},this._conf&&h.call(this,this._conf)}function h(t){t&&(this._conf=t,t.delimiter&&(this.delimiter=t.delimiter),t.maxListeners!==e&&(this._maxListeners=t.maxListeners),t.wildcard&&(this.wildcard=t.wildcard),t.newListener&&(this._newListener=t.newListener),t.removeListener&&(this._removeListener=t.removeListener),t.verboseMemoryLeak&&(this.verboseMemoryLeak=t.verboseMemoryLeak),t.ignoreErrors&&(this.ignoreErrors=t.ignoreErrors),this.wildcard&&(this.listenerTree={}))}function l(e,t){var i="(node) warning: possible EventEmitter memory leak detected. "+e+" listeners added. Use emitter.setMaxListeners() to increase limit.";if(this.verboseMemoryLeak&&(i+=" Event name: "+t+"."),"undefined"!=typeof process&&process.emitWarning){var r=new Error(i);r.name="MaxListenersExceededWarning",r.emitter=this,r.count=e,process.emitWarning(r)}else console.error(i),console.trace&&console.trace()}var u=function(e,t,i){var r=arguments.length;switch(r){case 0:return[];case 1:return[e];case 2:return[e,t];case 3:return[e,t,i];default:for(var n=new Array(r);r--;)n[r]=arguments[r];return n}};function p(t,i){for(var r={},n=t.length,o=i?value.length:0,a=0;a0;)if(o===e[a])return r;n(t)}}Object.assign(d.prototype,{subscribe:function(e,t,i){var r=this,n=this._target,o=this._emitter,a=this._listeners,s=function(){var r=u.apply(null,arguments),a={data:r,name:t,original:e};if(i){var s=i.call(n,a);!1!==s&&o.emit.apply(o,[a.name].concat(r))}else o.emit.apply(o,[t].concat(r))};if(a[e])throw Error("Event '"+e+"' is already listening");this._listenersCount++,o._newListener&&o._removeListener&&!r._onNewListener?(this._onNewListener=function(i){i===t&&null===a[e]&&(a[e]=s,r._on.call(n,e,s))},o.on("newListener",this._onNewListener),this._onRemoveListener=function(i){i===t&&!o.hasListeners(i)&&a[e]&&(a[e]=null,r._off.call(n,e,s))},a[e]=null,o.on("removeListener",this._onRemoveListener)):(a[e]=s,r._on.call(n,e,s))},unsubscribe:function(e){var t,i,r,n=this,o=this._listeners,a=this._emitter,c=this._off,h=this._target;if(e&&"string"!=typeof e)throw TypeError("event must be a string");function l(){n._onNewListener&&(a.off("newListener",n._onNewListener),a.off("removeListener",n._onRemoveListener),n._onNewListener=null,n._onRemoveListener=null);var e=b.call(a,n);a._observers.splice(e,1)}if(e){if(!(t=o[e]))return;c.call(h,e,t),delete o[e],--this._listenersCount||l()}else{for(r=(i=s(o)).length;r-- >0;)e=i[r],c.call(h,e,o[e]);this._listeners={},this._listenersCount=0,l()}}});var g=v(["function"]),y=v(["object","function"]);function x(e,t,i){var r,n,o,a=0,s=new e((function(c,h,l){function u(){n&&(n=null),a&&(clearTimeout(a),a=0)}i=f(i,{timeout:0,overload:!1},{timeout:function(e,t){return("number"!=typeof(e*=1)||e<0||!Number.isFinite(e))&&t("timeout must be a positive number"),e}}),r=!i.overload&&"function"==typeof e.prototype.cancel&&"function"==typeof l;var p=function(e){u(),c(e)},d=function(e){u(),h(e)};r?t(p,d,l):(n=[function(e){d(e||Error("canceled"))}],t(p,d,(function(e){if(o)throw Error("Unable to subscribe on cancel event asynchronously");if("function"!=typeof e)throw TypeError("onCancel callback must be a function");n.push(e)})),o=!0),i.timeout>0&&(a=setTimeout((function(){var e=Error("timeout");e.code="ETIMEDOUT",a=0,s.cancel(e),h(e)}),i.timeout))}));return r||(s.cancel=function(e){if(n){for(var t=n.length,i=1;i0;)"_listeners"!==(d=y[c])&&(x=w(e,t,i[d],r+1,n))&&(b?b.push.apply(b,x):b=x);return b}if("**"===_){for((g=r+1===n||r+2===n&&"*"===M)&&i._listeners&&(b=w(e,t,i,n,n)),c=(y=s(i)).length;c-- >0;)"_listeners"!==(d=y[c])&&("*"===d||"**"===d?(i[d]._listeners&&!g&&(x=w(e,t,i[d],n,n))&&(b?b.push.apply(b,x):b=x),x=w(e,t,i[d],r,n)):x=w(e,t,i[d],d===M?r+2:r,n),x&&(b?b.push.apply(b,x):b=x));return b}i[_]&&(b=w(e,t,i[_],r+1,n))}if((f=i["*"])&&w(e,t,f,r+1,n),m=i["**"])if(r0;)"_listeners"!==(d=y[c])&&(d===M?w(e,t,m[d],r+2,n):d===_?w(e,t,m[d],r+1,n):((v={})[d]=m[d],w(e,t,{"**":v},r+1,n)));else m._listeners?w(e,t,m,n,n):m["*"]&&m["*"]._listeners&&w(e,t,m["*"],n,n);return b}function _(e,t,i){var r,n,o=0,a=0,s=this.delimiter,c=s.length;if("string"==typeof e)if(-1!==(r=e.indexOf(s))){n=new Array(5);do{n[o++]=e.slice(a,r),a=r+c}while(-1!==(r=e.indexOf(s,a)));n[o++]=e.slice(a)}else n=[e],o=1;else n=e,o=e.length;if(o>1)for(r=0;r+10&&u._listeners.length>this._maxListeners&&(u._listeners.warned=!0,l.call(this,u._listeners.length,h))):u._listeners=t,!0;return!0}function M(e,t,i,r){for(var n,o,a,c,h=s(e),l=h.length,u=e._listeners;l-- >0;)n=e[o=h[l]],a="_listeners"===o?i:i?i.concat(o):[o],c=r||"symbol"==typeof o,u&&t.push(c?a:a.join(this.delimiter)),"object"==typeof n&&M.call(this,n,t,a,c);return t}function E(e){for(var t,i,r,n=s(e),o=n.length;o-- >0;)(t=e[i=n[o]])&&(r=!0,"_listeners"===i||E(t)||delete e[i]);return r}function T(e,t,i){this.emitter=e,this.event=t,this.listener=i}function S(t,i,n){if(!0===n)s=!0;else if(!1===n)o=!0;else{if(!n||"object"!=typeof n)throw TypeError("options should be an object or true");var o=n.async,s=n.promisify,c=n.nextTick,h=n.objectify}if(o||c||s){var l=i,u=i._origin||i;if(c&&!r)throw Error("process.nextTick is not supported");s===e&&(s="AsyncFunction"===i.constructor.name),i=function(){var e=arguments,t=this,i=this.event;return s?c?Promise.resolve():new Promise((function(e){a(e)})).then((function(){return t.event=i,l.apply(t,e)})):(c?process.nextTick:a)((function(){t.event=i,l.apply(t,e)}))},i._async=!0,i._origin=u}return[i,h?new T(this,t,i):this]}function A(e){this._events={},this._newListener=!1,this._removeListener=!1,this.verboseMemoryLeak=!1,h.call(this,e)}T.prototype.off=function(){return this.emitter.off(this.event,this.listener),this},A.EventEmitter2=A,A.prototype.listenTo=function(t,r,n){if("object"!=typeof t)throw TypeError("target musts be an object");var o=this;function a(e){if("object"!=typeof e)throw TypeError("events must be an object");var i,r=n.reducers,a=b.call(o,t);i=-1===a?new d(o,t,n):o._observers[a];for(var c,h=s(e),l=h.length,u="function"==typeof r,p=0;p0;)r=i[n],e&&r._target!==e||(r.unsubscribe(t),o=!0);return o},A.prototype.delimiter=".",A.prototype.setMaxListeners=function(t){t!==e&&(this._maxListeners=t,this._conf||(this._conf={}),this._conf.maxListeners=t)},A.prototype.getMaxListeners=function(){return this._maxListeners},A.prototype.event="",A.prototype.once=function(e,t,i){return this._once(e,t,!1,i)},A.prototype.prependOnceListener=function(e,t,i){return this._once(e,t,!0,i)},A.prototype._once=function(e,t,i,r){return this._many(e,1,t,i,r)},A.prototype.many=function(e,t,i,r){return this._many(e,t,i,!1,r)},A.prototype.prependMany=function(e,t,i,r){return this._many(e,t,i,!0,r)},A.prototype._many=function(e,t,i,r,n){var o=this;if("function"!=typeof i)throw new Error("many only accepts instances of Function");function a(){return 0==--t&&o.off(e,a),i.apply(this,arguments)}return a._origin=i,this._on(e,a,r,n)},A.prototype.emit=function(){if(!this._events&&!this._all)return!1;this._events||c.call(this);var e,t,i,r,o,a,s=arguments[0],h=this.wildcard;if("newListener"===s&&!this._newListener&&!this._events.newListener)return!1;if(h&&(e=s,"newListener"!==s&&"removeListener"!==s&&"object"==typeof s)){if(i=s.length,n)for(r=0;r3)for(t=new Array(u-1),o=1;o3)for(i=new Array(p-1),a=1;a0&&this._events[t].length>this._maxListeners&&(this._events[t].warned=!0,l.call(this,this._events[t].length,t))):this._events[t]=i,a)},A.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var r,n=[];if(this.wildcard){var o="string"==typeof e?e.split(this.delimiter):e.slice();if(!(n=w.call(this,null,o,this.listenerTree,0)))return this}else{if(!this._events[e])return this;r=this._events[e],n.push({_listeners:r})}for(var a=0;a0){for(i=0,r=(t=this._all).length;i0;)"function"==typeof(r=c[i[o]])?n.push(r):n.push.apply(n,r);return n}if(this.wildcard){if(!(a=this.listenerTree))return[];var h=[],l="string"==typeof t?t.split(this.delimiter):t.slice();return w.call(this,h,l,a,0),h}return c&&(r=c[t])?"function"==typeof r?[r]:r:[]},A.prototype.eventNames=function(e){var t=this._events;return this.wildcard?M.call(this,this.listenerTree,[],null,e):t?s(t):[]},A.prototype.listenerCount=function(e){return this.listeners(e).length},A.prototype.hasListeners=function(t){if(this.wildcard){var i=[],r="string"==typeof t?t.split(this.delimiter):t.slice();return w.call(this,i,r,this.listenerTree,0),i.length>0}var n=this._events,o=this._all;return!!(o&&o.length||n&&(t===e?s(n).length:n[t]))},A.prototype.listenersAny=function(){return this._all?this._all:[]},A.prototype.waitFor=function(t,i){var r=this,n=typeof i;return"number"===n?i={timeout:i}:"function"===n&&(i={filter:i}),x((i=f(i,{timeout:0,filter:e,handleError:!1,Promise:Promise,overload:!1},{filter:g,Promise:m})).Promise,(function(e,n,o){function a(){var o=i.filter;if(!o||o.apply(r,arguments))if(r.off(t,a),i.handleError){var s=arguments[0];s?n(s):e(u.apply(null,arguments).slice(1))}else e(u.apply(null,arguments))}o((function(){r.off(t,a)})),r._on(t,a,!1)}),{timeout:i.timeout,overload:i.overload})};var L=A.prototype;Object.defineProperties(A,{defaultMaxListeners:{get:function(){return L._maxListeners},set:function(e){if("number"!=typeof e||e<0||Number.isNaN(e))throw TypeError("n must be a non-negative number");L._maxListeners=e},enumerable:!0},once:{value:function(e,t,i){return x((i=f(i,{Promise:Promise,timeout:0,overload:!1},{Promise:m})).Promise,(function(i,r,n){var o;if("function"==typeof e.addEventListener)return o=function(){i(u.apply(null,arguments))},n((function(){e.removeEventListener(t,o)})),void e.addEventListener(t,o,{once:!0});var a,s=function(){a&&e.removeListener("error",a),i(u.apply(null,arguments))};"error"!==t&&(a=function(i){e.removeListener(t,s),r(i)},e.once("error",a)),n((function(){a&&e.removeListener("error",a),e.removeListener(t,s)})),e.once(t,s)}),{timeout:i.timeout,overload:i.overload})},writable:!0,configurable:!0}}),Object.defineProperties(L,{_maxListeners:{value:10,writable:!0,configurable:!0},_observers:{value:null,writable:!0,configurable:!0}}),Ws.exports=A}();var qs=Hs(Xs.exports);class Ys extends qs{constructor(e){super(),e=e||{},this.message=e.message,this.feedbackTopic=e.feedbackTopic,this.tfClient=e.tfClient,this.menuFontSize=e.menuFontSize||"0.8em",this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new r.Transform,this.pose=new r.Pose,this.setPoseFromClientBound=this.setPoseFromClient.bind(this),this.onMouseDownBound=this.onMouseDown.bind(this),this.onMouseUpBound=this.onMouseUp.bind(this),this.onButtonClickBound=this.onButtonClick.bind(this),this.onMenuSelectBound=this.onMenuSelect.bind(this),this.setPoseFromServer(this.message.pose),this.tfUpdateBound=this.tfUpdate.bind(this)}subscribeTf(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}unsubscribeTf(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}emitServerPoseUpdate(){var e=new r.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}setPoseFromServer(e){this.pose=new r.Pose(e),this.emitServerPoseUpdate()}tfUpdate(e){this.tfTransform=new r.Transform(e),this.emitServerPoseUpdate()}setPoseFromClient(e){this.pose=new r.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}onButtonClick(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}onMouseDown(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}onMouseUp(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}onMenuSelect(e){this.sendFeedback(2,void 0,e.id,e.controlName)}sendFeedback(e,t,i,r){var n=void 0!==t;t=t||{x:0,y:0,z:0};var o={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:r,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:n,menu_entry_id:i};this.feedbackTopic.publish(o)}}class Zs extends Ss.Object3D{constructor(e){super(),e=e||{},this.tfClient=e.tfClient,this.frameID=e.frameID;var t=e.object;this.pose=e.pose||new r.Pose,this.visible=!1,this.add(t),this.updatePose(this.pose),this.tfUpdate=function(e){var t=new r.Transform(e),i=new r.Pose(this.pose);i.applyTransform(t),this.updatePose(i),this.visible=!0},this.tfUpdateBound=this.tfUpdate.bind(this),this.tfClient.subscribe(this.frameID,this.tfUpdateBound)}updatePose(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}unsubscribeTf(){this.tfClient.unsubscribe(this.frameID,this.tfUpdateBound)}}class Js extends Ss.ArrowHelper{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1;e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Ss.MeshBasicMaterial,super(i,t,r,16711680)}dispose(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}class Ks extends Ss.Object3D{constructor(e){super();var t=this,i=(e=e||{}).shaftRadius||.008,r=e.headRadius||.023,n=e.headLength||.1,o=e.scale||1,a=e.lineType||"full",s=e.lineDashLength||.1;function c(e){var r=new Ss.Color;r.setRGB(e.x,e.y,e.z);var n=new Ss.MeshBasicMaterial({color:r.getHex()}),o=new Ss.Vector3;o.crossVectors(e,new Ss.Vector3(0,-1,0));var c=new Ss.Quaternion;c.setFromAxisAngle(o,.5*Math.PI);var h,l=new Ss.Mesh(t.headGeom,n);if(l.position.copy(e),l.position.multiplyScalar(.95),l.quaternion.copy(c),l.updateMatrix(),t.add(l),"dashed"===a)for(var u=s,p=0;u/2+3*u*p+u/2<=1;++p){var d=new Ss.CylinderGeometry(i,i,u);(h=new Ss.Mesh(d,n)).position.copy(e),h.position.multiplyScalar(u/2+3*u*p),h.quaternion.copy(c),h.updateMatrix(),t.add(h)}else"full"===a?((h=new Ss.Mesh(t.lineGeom,n)).position.copy(e),h.position.multiplyScalar(.45),h.quaternion.copy(c),h.updateMatrix(),t.add(h)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}this.scale.set(o,o,o),this.lineGeom=new Ss.CylinderGeometry(i,i,1-n),this.headGeom=new Ss.CylinderGeometry(0,r,n),c(new Ss.Vector3(1,0,0)),c(new Ss.Vector3(0,1,0)),c(new Ss.Vector3(0,0,1))}}class Qs extends Ss.Object3D{constructor(e){var t=(e=e||{}).num_cells||10,i=e.color||"#cccccc",r=e.lineWidth||1,n=e.cellSize||1;super();for(var o=new Ss.LineBasicMaterial({color:i,linewidth:r}),a=0;a<=t;++a){var s=n*t/2,c=s-a*n,h=new Ss.Geometry;h.vertices.push(new Ss.Vector3(-s,c,0),new Ss.Vector3(s,c,0));var l=new Ss.Geometry;l.vertices.push(new Ss.Vector3(c,-s,0),new Ss.Vector3(c,s,0)),this.add(new Ss.Line(h,o)),this.add(new Ss.Line(l,o))}}}class $s extends Ss.Mesh{constructor(e){var t=(e=e||{}).message,i=e.opacity||1,r=e.color||{r:255,g:255,b:255,a:255},n=t.info,o=n.origin,a=n.width,s=n.height,c=new Ss.PlaneBufferGeometry(a,s),h=new Uint8Array(a*s*4),l=new Ss.DataTexture(h,a,s,Ss.RGBAFormat);l.flipY=!0,l.minFilter=Ss.NearestFilter,l.magFilter=Ss.NearestFilter,l.needsUpdate=!0;var u=new Ss.MeshBasicMaterial({map:l,transparent:i<1,opacity:i});u.side=Ss.DoubleSide,super(c,u),Object.assign(this,e),this.quaternion.copy(new Ss.Quaternion(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),this.position.x=a*n.resolution/2+o.position.x,this.position.y=s*n.resolution/2+o.position.y,this.position.z=o.position.z,this.scale.x=n.resolution,this.scale.y=n.resolution;var p=t.data;this.color=r,this.material=u,this.texture=l;for(var d=0;d{const t="read"+e.kind,i="get"+e.kind;this[t]=()=>{if(this._cursor+e.width>this.length)throw new Error("Cannot read data stream. Overflow. Len="+this.length+" crsr="+this._cursor);const t=this._dataView[i](this._cursor,this.isLittleEndian);return this._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:()=>this.cursor>=this.data.length}),this}class ac{constructor(e){this.resolution=void 0!==e.resolution?e.resolution:1,this.color=new Ss.Color(void 0!==e.color?e.color:"green"),this.opacity=void 0!==e.opacity?e.opacity:1,this.voxelRenderMode=void 0!==e.voxelRenderMode?e.voxelRenderMode:tc,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);let t=this.resolution;for(let e=this._treeDepth-1;e>=0;--e)this.nodeSizeTable[e]=t,t*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}searchAtDepth(e,t){t=void 0!==t&&t>0?t:this._treeDepth;const i=this._adjustKeyAtDepth(e,t),r=this._treeDepth-t;let n=this._rootNode;for(let e=this._treeDepth-1;e>=r;--e){const t=this._computeChildIdx(i,e);if(!n.hasChildAt(t))return n.hasChildren()?null:n;n=n.getChildAt(t)}return n}_computeCoordFromKey(e){return e.map((e=>this.resolution*(e-this._treeMaxKeyVal)))}_computeChildIdx(e,t){let i=0;return e[0]&1<(e-this._treeMaxKeyVal>>i<0;){let e=i.pop();const r=t.readUint16();let n=8;for(;0!==n;){--n;const t=(r&3<<2*n)>>2*n;if(t!==this._BINARY_UNALLOCATED){let r=this._newNode();this._BINARY_CHILD_BUILD_TABLE[t].bind(this)(r),e.createChildNodeAt(r,n),t===this._BINARY_HAS_CHILDREN&&i.push(r)}}}}read(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();let t=new oc(e,!0),i=new Array;for(i.push(this._rootNode);i.length>0;){let e=i.pop();this._readNodeData(t,e);const r=t.readUint8();let n=8;for(;0!==n;){--n;if(r&1<0;){let i=t.pop();if(i.node.isLeafNode())e(i.node,i.key,i.depth-1);else for(let e=0;e<8;++e)if(i.node.hasChildAt(e)){const r=this._computeKeyFromChildIdx(e,i.key,i.depth);t.push({node:i.node.getChildAt(e),depth:i.depth+1,key:r})}}}_obtainColor(e){return this.color}_checkOccupied(e){return!1!==e.value}_buildFaces(){let e={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,i,r){const n=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*i,t[1]+e[1]*i,t[2]+e[2]*i)}));const o=[r.r,r.g,r.b];this.colors.push(...o,...o,...o,...o),this.normals.push(...e.normal,...e.normal,...e.normal,...e.normal),this.indices.push(n,n+1,n+2,n+2,n+1,n+3)},_checkNeighborsTouchingFace:function(e,t,i){let r=new Array;for(r.push(t);0!==r.length;){const t=r.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;{const n=t.getChildAt(e),o=this._checkOccupied(t);(o&&i===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!o&&i===ic)&&r.push(n)}}))}return!1}};return this._traverseLeaves(((t,i,r)=>{const n=this._computeCoordFromKey(i),o=this.nodeSizeTable[r],a=this._treeDepth-r,s=this._checkOccupied(t);(s||this.voxelRenderMode!==tc)&&(s&&this.voxelRenderMode===ic||this._FACES.forEach((function(s){const c=[i[0]+s.normal[0]*a*a,i[1]+s.normal[1]*a*a,i[2]+s.normal[2]*a*a],h=this.searchAtDepth(c);null===h?e._insertFace(s,n,o,this._obtainColor(t)):rnew Ss.Color(e))):[{r:0,g:0,b:128},{r:0,g:255,b:0},{r:255,g:255,b:0},{r:255,g:128,b:0},{r:255,g:0,b:0}],this.paletteScale=void 0!==e.paletteScale?e.paletteScale:1}_readNodeData(e,t){t.value=e.readFloat32()}_obtainColor(e){if(this.useFlatColoring)return this.color;const t=1/(1+Math.exp(-e.value*this.paletteScale))*this.palette.length,i=Math.trunc(t),r=t-i;return i<0?this.palette[0]:i>=this.palette.length-1?this.palette[this.palette.length-1]:{r:r*this.palette[i].r+(1-r)*this.palette[i+1].r,g:r*this.palette[i].g+(1-r)*this.palette[i+1].g,b:r*this.palette[i].b+(1-r)*this.palette[i+1].b}}_checkOccupied(e){return e.value>=this.occupancyThreshold}}class cc extends sc{constructor(e){super(e),this.useOwnColor=void 0!==e.palette&&e.colorMode===nc}_readNodeData(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}_obtainColor(e){return this.useOwnColor?e.color:sc.prototype._obtainColor.call(this,e)}}class hc extends Ss.Object3D{constructor(e){super(),this.options=e||{},this.ros=e.ros,this.topicName=e.topic||"/particlecloud",this.tfClient=e.tfClient,this.color=e.color||13369599,this.length=e.length||1,this.rootObject=e.rootObject||new Ss.Object3D,this.keep=e.keep||1,this.sns=[],this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new Ss.Vector3(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new Ss.Quaternion(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new Ss.Vector3(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Ss.MeshBasicMaterial({color:this.color});var i=new Ns(this.options);this.sns.push(new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:i})),this.rootObject.add(this.sns[this.sns.length-1])}}class lc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/path",this.tfClient=e.tfClient,this.color=e.color||13369599,this.rootObject=e.rootObject||new Ss.Object3D,this.sn=null,this.line=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new Ss.Geometry,i=0;i=e.range_min&&n<=e.range_max){var o=e.angle_min+r*e.angle_increment;this.points.positions.array[i++]=n*Math.cos(o),this.points.positions.array[i++]=n*Math.sin(o),this.points.positions.array[i++]=0}}this.points.update(i/3)}}}class yc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/gps/fix",this.rootObject=e.rootObject||new Ss.Object3D,this.object3d=e.object3d||new Ss.Object3D;var t=e.material||{};this.altitudeNaN=e.altitudeNaN||0,this.keep=e.keep||100,this.convert=e.convert||function(e,t,i){return new Ss.Vector3(e,t,i)},this.count=0,this.next1=0,this.next2=this.keep,this.geom=new Ss.BufferGeometry,this.vertices=new Ss.BufferAttribute(new Float32Array(6*this.keep),3),this.geom.addAttribute("position",this.vertices),this.material=t.isMaterial?t:new Ss.LineBasicMaterial(t),this.line=new Ss.Line(this.geom,this.material),this.rootObject.add(this.object3d),this.rootObject.add(this.line),this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,i=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(i),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=i.x,this.vertices.array[3*this.next1+1]=i.y,this.vertices.array[3*this.next1+2]=i.z,this.vertices.array[3*this.next2]=i.x,this.vertices.array[3*this.next2+1]=i.y,this.vertices.array[3*this.next2+2]=i.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}function xc(e,t,i,r){var n,o=0,a=0,s=0,c=e.length,h=t.length,l=((r=r||1)-1)*(i=i||h)*8;for(n=0;n=8&&(a-=8,t[s++]=o>>>a&255,s%i==0&&(n+=Math.ceil((l-a)/6),(a%=8)>0&&(o=xc.e[e.charAt(n)])));return Math.floor(s/i)}xc.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",xc.e={};for(var bc=0;bc<64;bc++)xc.e[xc.S.charAt(bc)]=bc;class wc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/points",this.throttle_rate=e.throttle_rate||null,this.compression=e.compression||"cbor",this.max_pts=e.max_pts||1e4,this.points=new vc(e),this.rosTopic=void 0,this.buffer=null,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,i=this.points.pointRatio,r=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,r)),t=Math.min(e.height*e.width/i,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(r=d[0].object,p.intersection=this.lastIntersection=d[0]):r=this.fallbackTarget,r!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(r,"mouseover",p);0===f?this.notify(this.lastTarget,"mouseout",p):1===f&&(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(r,"mouseover",p),this.notify(this.lastTarget,"mouseout",p))}r!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(r,e.type,p)?(this.notify(this.lastTarget,"touchleave",p),this.notify(this.lastTarget,"touchend",p)):(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",p),this.notify(this.lastTarget,"touchend",p)));this.notify(r,e.type,p),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=r}notify(e,t,i){for(i.type=t,i.cancelBubble=!1,i.continueBubble=!1,i.stopPropagation=function(){i.cancelBubble=!0},i.continuePropagation=function(){i.continueBubble=!0},i.currentTarget=e;i.currentTarget;){if(i.currentTarget.dispatchEvent&&i.currentTarget.dispatchEvent instanceof Function){if(i.currentTarget.dispatchEvent(i),i.cancelBubble)return this.dispatchEvent(i),0;if(i.continueBubble)return 2}i.currentTarget=i.currentTarget.parent}return 1}}class Sc extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).scene;this.camera=e.camera,this.center=new Ss.Vector3,this.userZoom=!0,this.userZoomSpeed=e.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=e.userRotateSpeed||1,this.autoRotate=e.autoRotate,this.autoRotateSpeed=e.autoRotateSpeed||2,this.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,this.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",this.camera.up=new Ss.Vector3(0,0,1);var r=1800,n=new Ss.Vector2,o=new Ss.Vector2,a=new Ss.Vector2,s=new Ss.Vector2,c=new Ss.Vector2,h=new Ss.Vector2,l=new Ss.Vector3,u=new Ss.Vector3,p=new Ss.Vector3,d=new Ss.Vector3,f=new Array(2),m=new Array(2);this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new Ss.Vector3;var v=-1,g=0,y=1,x=2,b=v;function w(e,t,i){var r=new Ss.Vector3;new Ss.Vector3;r.subVectors(t,e.origin);var n=e.direction.dot(i);if(Math.abs(n)0?t.zoomIn():t.zoomOut(),this.showAxes()}}this.axes=new Ks({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:this.lineTypePanAndZoomFrame}),this.displayPanAndZoomFrame&&(i.add(this.axes),this.axes.traverse((function(e){e.visible=!1}))),this.addEventListener("mousedown",(function(e){var i=e.domEvent;switch(i.preventDefault(),i.button){case 0:b=g,n.set(i.clientX,i.clientY);break;case 1:b=x,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u);break;case 2:b=y,s.set(i.clientX,i.clientY)}this.showAxes()})),this.addEventListener("mouseup",(function(e){t.userRotate&&(b=v)})),this.addEventListener("mousemove",(function(e){var i=e.domEvent;if(b===g)o.set(i.clientX,i.clientY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else if(b===y)c.set(i.clientX,i.clientY),h.subVectors(c,s),h.y>0?t.zoomIn():t.zoomOut(),s.copy(c),this.showAxes();else if(b===x){var f=w(e.mouseRay,t.center,u);if(!f)return;var m=(new Ss.Vector3).subVectors(d.clone(),f.clone());t.center.addVectors(l.clone(),m.clone()),t.camera.position.addVectors(p.clone(),m.clone()),t.update(),t.camera.updateMatrixWorld(),this.showAxes()}})),this.addEventListener("touchstart",(function(e){var i=e.domEvent;switch(i.touches.length){case 1:b=g,n.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY);break;case 2:b=v,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u),f[0]=new Ss.Vector2(i.touches[0].pageX,i.touches[0].pageY),f[1]=new Ss.Vector2(i.touches[1].pageX,i.touches[1].pageY),m[0]=new Ss.Vector2(0,0),m[1]=new Ss.Vector2(0,0)}this.showAxes(),i.preventDefault()})),this.addEventListener("touchmove",(function(e){var i=e.domEvent;if(b===g)o.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else{if(m[0].set(f[0].x-i.touches[0].pageX,f[0].y-i.touches[0].pageY),m[1].set(f[1].x-i.touches[1].pageX,f[1].y-i.touches[1].pageY),m[0].lengthSq()>10&&m[1].lengthSq()>10&&(f[0].set(i.touches[0].pageX,i.touches[0].pageY),f[1].set(i.touches[1].pageX,i.touches[1].pageY),m[0].dot(m[1])>0&&b!==y?b=x:m[0].dot(m[1])<0&&b!==x&&(b=y),b===y)){var s=new Ss.Vector2;s.subVectors(f[0],f[1]),m[0].dot(s)<0&&m[1].dot(s)>0?t.zoomOut():m[0].dot(s)>0&&m[1].dot(s)<0&&t.zoomIn()}if(b===x){var c=w(e.mouseRay,t.center,u);if(!c)return;var h=(new Ss.Vector3).subVectors(d.clone(),c.clone());t.center.addVectors(l.clone(),h.clone()),t.camera.position.addVectors(p.clone(),h.clone()),t.update(),t.camera.updateMatrixWorld()}this.showAxes(),i.preventDefault()}})),this.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&b!==g?(b=g,n.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):b=v})),this.addEventListener("mousewheel",_),this.addEventListener("DOMMouseScroll",_)}showAxes(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}rotateLeft(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}rotateRight(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}rotateUp(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}rotateDown(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}zoomIn(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}zoomOut(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}update(){var e=this.camera.position,t=e.clone().sub(this.center),i=Math.atan2(t.y,t.x),r=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),i+=this.thetaDelta,r+=this.phiDelta;var n=1e-6;r=Math.max(n,Math.min(Math.PI-n,r));var o=t.length();t.set(o*Math.sin(r)*Math.cos(i),o*Math.sin(r)*Math.sin(i),o*Math.cos(r)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),o=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*o,.05*o,.05*o),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}return e.Arrow=Ns,e.Arrow2=Js,e.Axes=Ks,e.ColorOcTree=cc,e.DepthCloud=Ps,e.Grid=Qs,e.Highlighter=Ec,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=js,e.InteractiveMarkerClient=class{constructor(e){e=e||{},this.ros=e.ros,this.tfClient=e.tfClient,this.topicName=e.topic,this.path=e.path||"/",this.camera=e.camera,this.rootObject=e.rootObject||new Ss.Object3D,this.loader=e.loader,this.menuFontSize=e.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.processUpdateBound=this.processUpdate.bind(this),this.topicName&&this.subscribe(this.topicName)}subscribe(e){this.unsubscribe(),this.updateTopic=new r.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdateBound),this.feedbackTopic=new r.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new r.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new r.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}unsubscribe(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdateBound),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}processInit(e){var t=e.msg;for(var i in t.erases=[],this.interactiveMarkers)t.erases.push(i);t.poses=[],this.processUpdate(t)}processUpdate(e){e.erases.forEach((function(e){this.eraseIntMarker(e)})),e.poses.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&t.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&this.eraseIntMarker(t.name);var i=new Ys({message:e,feedbackTopic:this.feedbackTopic,tfClient:this.tfClient,menuFontSize:this.menuFontSize});this.interactiveMarkers[e.name]=i;var r=new js({handle:i,camera:this.camera,path:this.path,loader:this.loader});r.name=e.name,this.rootObject.add(r),i.on("pose",(function(e){r.onServerSetPose({pose:e})})),r.addEventListener("user-pose-change",i.setPoseFromClientBound),r.addEventListener("user-mousedown",i.onMouseDownBound),r.addEventListener("user-mouseup",i.onMouseUpBound),r.addEventListener("user-button-click",i.onButtonClickBound),r.addEventListener("menu-select",i.onMenuSelectBound),i.subscribeTf()}))}eraseIntMarker(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var i=this.interactiveMarkers[e];i.unsubscribeTf(),t.removeEventListener("user-pose-change",i.setPoseFromClientBound),t.removeEventListener("user-mousedown",i.onMouseDownBound),t.removeEventListener("user-mouseup",i.onMouseUpBound),t.removeEventListener("user-button-click",i.onButtonClickBound),t.removeEventListener("menu-select",i.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}},e.InteractiveMarkerControl=Gs,e.InteractiveMarkerHandle=Ys,e.InteractiveMarkerMenu=Vs,e.LaserScan=gc,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=ks,e.MarkerArrayClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.markers={},this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var i=!1;if(t in this.markers&&((i=this.markers[t].children[0].update(e))||this.removeMarker(t)),!i){var r=new ks({message:e,path:this.path});this.markers[t]=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var n in this.markers)this.removeMarker(n);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}},e.MarkerClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.lifetime=e.lifetime||0,this.markers={},this.rosTopic=void 0,this.updatedTime={},this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}checkTime(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){var t=e.ns+e.id,i=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),i?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var r=new ks({message:e,path:this.path});this.markers[t]=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}this.emit("change")}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}},e.MeshLoader=Bs,e.MeshResource=Fs,e.MouseHandler=Tc,e.NavSatFix=yc,e.OcTree=sc,e.OcTreeClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/octomap",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.options={},void 0!==e.color&&(this.options.color=e.color),void 0!==e.opacity&&(this.options.opacity=e.opacity),void 0!==e.colorMode&&(this.options.colorMode=e.colorMode),void 0!==e.palette&&(this.options.palette=e.palette),void 0!==e.paletteScale&&(this.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(this.options.voxelRenderMode=e.voxelRenderMode),this.currentMap=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}_loadOcTree(e){return new Promise(function(t,i){const r=Object.assign({resolution:e.resolution},this.options);let n=null;if(e.binary)n=new ac(r),n.readBinary(e.data);else{const t={OcTree:sc,ColorOcTree:cc};e.id in t&&(console.log(e.id,t),n=new t[e.id](r),n.read(e.data))}n.buildGeometry(),t(n)}.bind(this))}_processMessagePrivate(e){this._loadOcTree(e).then(function(t){const i=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(i),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}},e.OccupancyGrid=$s,e.OccupancyGridClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/map",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.color=e.color||{r:255,g:255,b:255},this.opacity=e.opacity||1,this.currentGrid=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"nav_msgs/OccupancyGrid",queue_length:1,compression:this.compression}),this.sceneNode=null,this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.currentGrid&&(this.tfClient?(this.sceneNode.unsubscribeTf(),this.sceneNode.remove(this.currentGrid)):this.rootObject.remove(this.currentGrid),this.currentGrid.dispose());var t=new $s({message:e,color:this.color,opacity:this.opacity});this.tfClient?(this.currentGrid=t,null===this.sceneNode?(this.sceneNode=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:t,pose:this.offsetPose}),this.rootObject.add(this.sceneNode)):this.sceneNode.add(this.currentGrid)):(this.sceneNode=this.currentGrid=t,this.rootObject.add(this.currentGrid)),this.emit("change"),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}},e.Odometry=hc,e.OrbitControls=Sc,e.Path=lc,e.Point=uc,e.PointCloud2=wc,e.Points=vc,e.Polygon=pc,e.Pose=dc,e.PoseArray=fc,e.PoseWithCovariance=mc,e.SceneNode=Zs,e.TFAxes=_c,e.TriangleList=zs,e.Urdf=Mc,e.UrdfClient=class{constructor(e){var t=(e=e||{}).ros;this.param=e.param||"robot_description",this.path=e.path||"/",this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.tfPrefix=e.tfPrefix||"",this.loader=e.loader,new r.Param({ros:t,name:this.param}).get(function(e){var t=new r.UrdfModel({string:e});this.urdf=new Mc({urdfModel:t,path:this.path,tfClient:this.tfClient,tfPrefix:this.tfPrefix,loader:this.loader}),this.rootObject.add(this.urdf)}.bind(this))}},e.Viewer=class{constructor(e){var t=(e=e||{}).divID,i=e.elem,r=e.width,n=e.height,o=e.background||"#111111",a=e.antialias,s=e.intensity||.66,c=e.near||.01,h=e.far||1e3,l=e.alpha||1,u=e.cameraPose||{x:3,y:3,z:3},p=e.cameraZoomSpeed||.5,d=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,f=e.lineTypePanAndZoomFrame||"full";this.renderer=new Ss.WebGLRenderer({antialias:a,alpha:!0}),this.renderer.setClearColor(parseInt(o.replace("#","0x"),16),l),this.renderer.sortObjects=!1,this.renderer.setSize(r,n),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ss.Scene,this.camera=new Ss.PerspectiveCamera(40,r/n,c,h),this.camera.position.x=u.x,this.camera.position.y=u.y,this.camera.position.z=u.z,this.cameraControls=new Sc({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:d,lineTypePanAndZoomFrame:f}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Ss.AmbientLight(5592405)),this.directionalLight=new Ss.DirectionalLight(16777215,s),this.scene.add(this.directionalLight),this.selectableObjects=new Ss.Group,this.scene.add(this.selectableObjects);var m=new Tc({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ec({mouseHandler:m}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(t)).appendChild(this.renderer.domElement),this.start()}start(){this.stopped=!1,this.draw()}draw(){this.stopped||(this.cameraControls.update(),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}stop(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}addObject(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}},e.closestAxisPoint=Cs,e.findClosestPoint=Rs,e.intersectPlane=Ls,e.makeColorMaterial=As,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); +Object.assign(za.prototype,{_getValue_unbound:za.prototype.getValue,_setValue_unbound:za.prototype.setValue}),Object.assign(ka.prototype,{isAnimationObjectGroup:!0,add:function(){for(var e=this._objects,t=e.length,i=this.nCachedObjects_,r=this._indicesByUUID,n=this._paths,o=this._parsedPaths,a=this._bindings,s=a.length,c=0,h=arguments.length;c!==h;++c){var l=arguments[c],u=l.uuid,p=r[u],d=void 0;if(void 0===p){p=t++,r[u]=p,e.push(l);for(var f=0,m=s;f!==m;++f)a[f].push(new za(l,n[f],o[f]))}else if(p=t){var l=t++,u=e[l];i[u.uuid]=h,e[h]=u,i[c]=l,e[l]=s;for(var p=0,d=n;p!==d;++p){var f=r[p],m=f[l],v=f[h];f[h]=m,f[l]=v}}}this.nCachedObjects_=t},uncache:function(){for(var e=this._objects,t=e.length,i=this.nCachedObjects_,r=this._indicesByUUID,n=this._bindings,o=n.length,a=0,s=arguments.length;a!==s;++a){var c=arguments[a],h=c.uuid,l=r[h];if(void 0!==l)if(delete r[h],l0)for(var c=this._interpolants,h=this._propertyBindings,l=0,u=c.length;l!==u;++l)c[l].evaluate(a),h[l].accumulate(r,s)}else this._updateWeight(e)},_updateWeight:function(e){var t=0;if(this.enabled){t=this.weight;var i=this._weightInterpolant;if(null!==i){var r=i.evaluate(e)[0];t*=r,e>i.parameterPositions[1]&&(this.stopFading(),0===r&&(this.enabled=!1))}}return this._effectiveWeight=t,t},_updateTimeScale:function(e){var t=0;if(!this.paused){t=this.timeScale;var i=this._timeScaleInterpolant;if(null!==i)t*=i.evaluate(e)[0],e>i.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}return this._effectiveTimeScale=t,t},_updateTime:function(e){var t=this.time+e;if(0===e)return t;var i=this._clip.duration,r=this.loop,n=this._loopCount;if(2200===r){-1===n&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(t>=i)t=i;else{if(!(t<0))break e;t=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{var o=2202===r;if(-1===n&&(e>=0?(n=0,this._setEndings(!0,0===this.repetitions,o)):this._setEndings(0===this.repetitions,!0,o)),t>=i||t<0){var a=Math.floor(t/i);t-=i*a,n+=Math.abs(a);var s=this.repetitions-n;if(s<0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,t=e>0?i:0,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(0===s){var c=e<0;this._setEndings(c,!c,o)}else this._setEndings(!1,!1,o);this._loopCount=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:a})}}if(o&&1==(1&n))return this.time=t,i-t}return this.time=t,t},_setEndings:function(e,t,i){var r=this._interpolantSettings;i?(r.endingStart=K,r.endingEnd=K):(r.endingStart=e?this.zeroSlopeAtStart?K:J:Q,r.endingEnd=t?this.zeroSlopeAtEnd?K:J:Q)},_scheduleFading:function(e,t,i){var r=this._mixer,n=r.time,o=this._weightInterpolant;null===o&&(o=r._lendControlInterpolant(),this._weightInterpolant=o);var a=o.parameterPositions,s=o.sampleValues;return a[0]=n,s[0]=t,a[1]=n+e,s[1]=i,this}}),Va.prototype=Object.assign(Object.create(n.prototype),{constructor:Va,_bindAction:function(e,t){var i=e._localRoot||this._root,r=e._clip.tracks,n=r.length,o=e._propertyBindings,a=e._interpolants,s=i.uuid,c=this._bindingsByRootAndName,h=c[s];void 0===h&&(h={},c[s]=h);for(var l=0;l!==n;++l){var u=r[l],p=u.name,d=h[p];if(void 0!==d)o[l]=d;else{if(void 0!==(d=o[l])){null===d._cacheIndex&&(++d.referenceCount,this._addInactiveBinding(d,s,p));continue}var f=t&&t._propertyBindings[l].binding.parsedPath;++(d=new Ba(za.create(i,p,f),u.ValueTypeName,u.getValueSize())).referenceCount,this._addInactiveBinding(d,s,p),o[l]=d}a[l].resultBuffer=d.buffer}},_activateAction:function(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){var t=(e._localRoot||this._root).uuid,i=e._clip.uuid,r=this._actionsByClip[i];this._bindAction(e,r&&r.knownActions[0]),this._addInactiveAction(e,i,t)}for(var n=e._propertyBindings,o=0,a=n.length;o!==a;++o){var s=n[o];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}},_deactivateAction:function(e){if(this._isActiveAction(e)){for(var t=e._propertyBindings,i=0,r=t.length;i!==r;++i){var n=t[i];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(e)}},_initMemoryManager:function(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;var e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}},_isActiveAction:function(e){var t=e._cacheIndex;return null!==t&&t.99999?this.quaternion.set(0,0,0,1):e.y<-.99999?this.quaternion.set(1,0,0,0):(Ra.set(e.z,0,-e.x).normalize(),Aa=Math.acos(e.y),this.quaternion.setFromAxisAngle(Ra,Aa))}),gs.prototype.setLength=function(e,t,i){void 0===t&&(t=.2*e),void 0===i&&(i=.2*t),this.line.scale.set(1,Math.max(0,e-t),1),this.line.updateMatrix(),this.cone.scale.set(i,t,i),this.cone.position.y=e,this.cone.updateMatrix()},gs.prototype.setColor=function(e){this.line.material.color.copy(e),this.cone.material.color.copy(e)},ys.prototype=Object.create(vr.prototype),ys.prototype.constructor=ys;var xs={createMultiMaterialObject:function(e,t){for(var i=new br,r=0,n=t.length;r0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),"," (- z + zOffset / 1000.0) * maxDepthPerTile,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),this.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n")}metaLoaded(){this.metaLoaded=!0,this.initStreamer()}initStreamer(){if(this.metaLoaded){this.texture=new Ss.Texture(this.video),this.geometry=new Ss.Geometry;for(var e=0,t=this.width*this.height;e{(this.isMjpeg||this.video.readyState===this.video.HAVE_ENOUGH_DATA)&&(this.texture.needsUpdate=!0)}),1e3/30)}}startStream(){this.isMjpeg||this.video.play()}stopStream(){this.isMjpeg||this.video.pause()}}class Ns extends Ss.Mesh{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1,n=e.headLength||.2,o=e.shaftDiameter||.05,a=e.headDiameter||.1,s=e.material||new Ss.MeshBasicMaterial,c=r-n,h=new Ss.CylinderGeometry(.5*o,.5*o,c,12,1),l=new Ss.Matrix4;l.setPosition(new Ss.Vector3(0,.5*c,0)),h.applyMatrix(l);var u=new Ss.CylinderGeometry(0,.5*a,n,12,1);l.setPosition(new Ss.Vector3(0,c+.5*n,0)),u.applyMatrix(l),h.merge(u),super(h,s),this.position.copy(t),this.setDirection(i)}setDirection(e){var t=new Ss.Vector3;0===e.x&&0===e.z?t.set(1,0,0):t.set(0,1,0).cross(e);var i=Math.acos(new Ss.Vector3(0,1,0).dot(e.clone().normalize()));this.matrix=(new Ss.Matrix4).makeRotationAxis(t.normalize(),i),this.rotation.setFromRotationMatrix(this.matrix,this.rotation.order)}setLength(e){this.scale.set(e,e,e)}setColor(e){this.material.color.setHex(e)}dispose(){void 0!==this.geometry&&this.geometry.dispose(),void 0!==this.material&&this.material.dispose()}}Ss.STLLoader=function(e){this.manager=void 0!==e?e:Ss.DefaultLoadingManager},Ss.STLLoader.prototype={constructor:Ss.STLLoader,load:function(e,t,i,r){var n=this,o=new Ss.FileLoader(n.manager);o.setResponseType("arraybuffer"),o.load(e,(function(e){t(n.parse(e))}),i,r)},parse:function(e){var t=function(e){if("string"==typeof e){for(var t=new Uint8Array(e.length),i=0;i>5&31)/31,r=(w>>10&31)/31):(t=o,i=a,r=s)}for(var _=1;_<=3;_++){var M=g+12*_;f.push(h.getFloat32(M,!0)),f.push(h.getFloat32(M+4,!0)),f.push(h.getFloat32(M+8,!0)),m.push(y,x,b),u&&n.push(t,i,r)}}return d.addAttribute("position",new Ss.BufferAttribute(new Float32Array(f),3)),d.addAttribute("normal",new Ss.BufferAttribute(new Float32Array(m),3)),u&&(d.addAttribute("color",new Ss.BufferAttribute(new Float32Array(n),3)),d.hasColors=!0,d.alpha=c),d}(t):function(e){for(var t,i=new Ss.BufferGeometry,r=/facet([\s\S]*?)endfacet/g,n=0,o=/[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source,a=new RegExp("vertex"+o+o+o,"g"),s=new RegExp("normal"+o+o+o,"g"),c=[],h=[],l=new Ss.Vector3;null!==(t=r.exec(e));){for(var u=0,p=0,d=t[0];null!==(t=s.exec(d));)l.x=parseFloat(t[1]),l.y=parseFloat(t[2]),l.z=parseFloat(t[3]),p++;for(;null!==(t=a.exec(d));)c.push(parseFloat(t[1]),parseFloat(t[2]),parseFloat(t[3])),h.push(l.x,l.y,l.z),u++;1!==p&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+n),3!==u&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+n),n++}return i.addAttribute("position",new Ss.Float32BufferAttribute(c,3)),i.addAttribute("normal",new Ss.Float32BufferAttribute(h,3)),i}(function(e){if("string"!=typeof e){var t=new Uint8Array(e);if(void 0!==window.TextDecoder)return(new TextDecoder).decode(t);for(var i="",r=0,n=e.byteLength;r0?t[t.length-1]:"",smooth:void 0!==i?i.smooth:this.smooth,groupStart:void 0!==i?i.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(e){var t={index:"number"==typeof e?e:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return t.clone=this.clone.bind(t),t}};return this.materials.push(r),r},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(e){var t=this.currentMaterial();if(t&&-1===t.groupEnd&&(t.groupEnd=this.geometry.vertices.length/3,t.groupCount=t.groupEnd-t.groupStart,t.inherited=!1),e&&this.materials.length>1)for(var i=this.materials.length-1;i>=0;i--)this.materials[i].groupCount<=0&&this.materials.splice(i,1);return e&&0===this.materials.length&&this.materials.push({name:"",smooth:this.smooth}),t}},i&&i.name&&"function"==typeof i.clone){var r=i.clone(0);r.inherited=!0,this.object.materials.push(r)}this.objects.push(this.object)},finalize:function(){this.object&&"function"==typeof this.object._finalize&&this.object._finalize(!0)},parseVertexIndex:function(e,t){var i=parseInt(e,10);return 3*(i>=0?i-1:i+t/3)},parseNormalIndex:function(e,t){var i=parseInt(e,10);return 3*(i>=0?i-1:i+t/3)},parseUVIndex:function(e,t){var i=parseInt(e,10);return 2*(i>=0?i-1:i+t/2)},addVertex:function(e,t,i){var r=this.vertices,n=this.object.geometry.vertices;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addVertexPoint:function(e){var t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){var t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,i){var r=this.normals,n=this.object.geometry.normals;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addColor:function(e,t,i){var r=this.colors,n=this.object.geometry.colors;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addUV:function(e,t,i){var r=this.uvs,n=this.object.geometry.uvs;n.push(r[e+0],r[e+1]),n.push(r[t+0],r[t+1]),n.push(r[i+0],r[i+1])},addUVLine:function(e){var t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,i,r,n,o,a,s,c){var h=this.vertices.length,l=this.parseVertexIndex(e,h),u=this.parseVertexIndex(t,h),p=this.parseVertexIndex(i,h);if(this.addVertex(l,u,p),void 0!==r&&""!==r){var d=this.uvs.length;l=this.parseUVIndex(r,d),u=this.parseUVIndex(n,d),p=this.parseUVIndex(o,d),this.addUV(l,u,p)}if(void 0!==a&&""!==a){var f=this.normals.length;l=this.parseNormalIndex(a,f),u=a===s?l:this.parseNormalIndex(s,f),p=a===c?l:this.parseNormalIndex(c,f),this.addNormal(l,u,p)}this.colors.length>0&&this.addColor(l,u,p)},addPointGeometry:function(e){this.object.geometry.type="Points";for(var t=this.vertices.length,i=0,r=e.length;i0){var m=f.split("/");u.push(m)}}var v=u[0];for(p=1,d=u.length-1;p1){var A=o[1].trim().toLowerCase();t.object.smooth="0"!==A&&"off"!==A}else t.object.smooth=!0;(G=t.object.currentMaterial())&&(G.smooth=t.object.smooth)}t.finalize();var R=new Ss.Object3D;R.materialLibraries=[].concat(t.materialLibraries);for(s=0,c=t.objects.length;s0?D.addAttribute("normal",new Ss.Float32BufferAttribute(C.normals,3)):D.computeVertexNormals(),C.colors.length>0&&(I=!0,D.addAttribute("color",new Ss.Float32BufferAttribute(C.colors,3))),C.uvs.length>0&&D.addAttribute("uv",new Ss.Float32BufferAttribute(C.uvs,2));for(var U,B=[],F=0,z=P.length;F1){for(F=0,z=P.length;F=0?s.substring(0,c):s;h=h.toLowerCase();var l=c>=0?s.substring(c+1):"";if(l=l.trim(),"newmtl"===h)r={name:l},o[l]=r;else if("ka"===h||"kd"===h||"ks"===h||"ke"===h){var u=l.split(n,3);r[h]=[parseFloat(u[0]),parseFloat(u[1]),parseFloat(u[2])]}else r[h]=l}}var p=new Ss.MTLLoader.MaterialCreator(this.resourcePath||t,this.materialOptions);return p.setCrossOrigin(this.crossOrigin),p.setManager(this.manager),p.setMaterials(o),p}},Ss.MTLLoader.MaterialCreator=function(e,t){this.baseUrl=e||"",this.options=t,this.materialsInfo={},this.materials={},this.materialsArray=[],this.nameLookup={},this.side=this.options&&this.options.side?this.options.side:Ss.FrontSide,this.wrap=this.options&&this.options.wrap?this.options.wrap:Ss.RepeatWrapping},Ss.MTLLoader.MaterialCreator.prototype={constructor:Ss.MTLLoader.MaterialCreator,crossOrigin:"anonymous",setCrossOrigin:function(e){return this.crossOrigin=e,this},setManager:function(e){this.manager=e},setMaterials:function(e){this.materialsInfo=this.convert(e),this.materials={},this.materialsArray=[],this.nameLookup={}},convert:function(e){if(!this.options)return e;var t={};for(var i in e){var r=e[i],n={};for(var o in t[i]=n,r){var a=!0,s=r[o],c=o.toLowerCase();switch(c){case"kd":case"ka":case"ks":this.options&&this.options.normalizeRGB&&(s=[s[0]/255,s[1]/255,s[2]/255]),this.options&&this.options.ignoreZeroRGBs&&0===s[0]&&0===s[1]&&0===s[2]&&(a=!1)}a&&(n[c]=s)}}return t},preload:function(){for(var e in this.materialsInfo)this.create(e)},getIndex:function(e){return this.nameLookup[e]},getAsArray:function(){var e=0;for(var t in this.materialsInfo)this.materialsArray[e]=this.create(t),this.nameLookup[t]=e,e++;return this.materialsArray},create:function(e){return void 0===this.materials[e]&&this.createMaterial_(e),this.materials[e]},createMaterial_:function(e){var t=this,i=this.materialsInfo[e],r={name:e,side:this.side};function n(e,i){if(!r[e]){var n,o,a=t.getTextureParams(i,r),s=t.loadTexture((n=t.baseUrl,"string"!=typeof(o=a.url)||""===o?"":/^https?:\/\//i.test(o)?o:n+o));s.repeat.copy(a.scale),s.offset.copy(a.offset),s.wrapS=t.wrap,s.wrapT=t.wrap,r[e]=s}}for(var o in i){var a,s=i[o];if(""!==s)switch(o.toLowerCase()){case"kd":r.color=(new Ss.Color).fromArray(s);break;case"ks":r.specular=(new Ss.Color).fromArray(s);break;case"ke":r.emissive=(new Ss.Color).fromArray(s);break;case"map_kd":n("map",s);break;case"map_ks":n("specularMap",s);break;case"map_ke":n("emissiveMap",s);break;case"norm":n("normalMap",s);break;case"map_bump":case"bump":n("bumpMap",s);break;case"map_d":n("alphaMap",s),r.transparent=!0;break;case"ns":r.shininess=parseFloat(s);break;case"d":(a=parseFloat(s))<1&&(r.opacity=a,r.transparent=!0);break;case"tr":a=parseFloat(s),this.options&&this.options.invertTrProperty&&(a=1-a),a>0&&(r.opacity=1-a,r.transparent=!0)}}return this.materials[e]=new Ss.MeshPhongMaterial(r),this.materials[e]},getTextureParams:function(e,t){var i,r={scale:new Ss.Vector2(1,1),offset:new Ss.Vector2(0,0)},n=e.split(/\s+/);return(i=n.indexOf("-bm"))>=0&&(t.bumpScale=parseFloat(n[i+1]),n.splice(i,2)),(i=n.indexOf("-s"))>=0&&(r.scale.set(parseFloat(n[i+1]),parseFloat(n[i+2])),n.splice(i,4)),(i=n.indexOf("-o"))>=0&&(r.offset.set(parseFloat(n[i+1]),parseFloat(n[i+2])),n.splice(i,4)),r.url=n.join(" ").trim(),r},loadTexture:function(e,t,i,r,n){var o,a=Ss.Loader.Handlers.get(e),s=void 0!==this.manager?this.manager:Ss.DefaultLoadingManager;return null===a&&(a=new Ss.TextureLoader(s)),a.setCrossOrigin&&a.setCrossOrigin(this.crossOrigin),o=a.load(e,i,r,n),void 0!==t&&(o.mapping=t),o}},Ss.ColladaLoader=function(e){this.manager=void 0!==e?e:Ss.DefaultLoadingManager},Ss.ColladaLoader.prototype={constructor:Ss.ColladaLoader,crossOrigin:"Anonymous",load:function(e,t,i,r){var n=this,o=Ss.Loader.prototype.extractUrlBase(e);new Ss.FileLoader(n.manager).load(e,(function(e){t(n.parse(e,o))}),i,r)},options:{set convertUpAxis(e){console.warn("THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.")}},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){function i(e,t){for(var i=[],r=e.childNodes,n=0,o=r.length;n0&&t.push(new Ss.VectorKeyframeTrack(r+".position",n,o)),a.length>0&&t.push(new Ss.QuaternionKeyframeTrack(r+".quaternion",n,a)),s.length>0&&t.push(new Ss.VectorKeyframeTrack(r+".scale",n,s)),t}function _(e,t,i){var r,n,o,a=!0;for(n=0,o=e.length;n=0;){var r=e[t];if(null!==r.value[i])return r;t--}return null}function E(e,t,i){for(;t0&&p.addAttribute("position",new Ss.Float32BufferAttribute(n.array,n.stride)),o.array.length>0&&p.addAttribute("normal",new Ss.Float32BufferAttribute(o.array,o.stride)),s.array.length>0&&p.addAttribute("color",new Ss.Float32BufferAttribute(s.array,s.stride)),a.array.length>0&&p.addAttribute("uv",new Ss.Float32BufferAttribute(a.array,a.stride)),c.length>0&&p.addAttribute("skinIndex",new Ss.Float32BufferAttribute(c,h)),l.length>0&&p.addAttribute("skinWeight",new Ss.Float32BufferAttribute(l,u)),r.data=p,r.type=e[0].type,r.materialKeys=d,r}function ne(e,t,i,r){var n=e.p,o=e.stride,a=e.vcount;function s(e){for(var t=n[e+i]*l,o=t+l;t0&&console.log("THREE.ColladaLoader: Geometry has faces with more than 4 vertices.")}else for(p=0,d=n.length;p=t.limits.max&&(t.static=!0),t.middlePosition=(t.limits.min+t.limits.max)/2,t}function le(e){for(var t={sid:e.getAttribute("sid"),name:e.getAttribute("name")||"",attachments:[],transforms:[]},i=0;ir.limits.max||t0){var q=this.msgColor,Y=document.createElement("canvas"),Z=Y.getContext("2d"),J="normal 100px sans-serif";Z.font=J;var K=Z.measureText(i.text).width;Y.width=K,Y.height=150,Z.font=J,Z.fillStyle="rgba("+Math.round(255*q.r)+", "+Math.round(255*q.g)+", "+Math.round(255*q.b)+", "+q.a+")",Z.textAlign="left",Z.textBaseline="middle",Z.fillText(i.text,0,Y.height/2);var Q=new Ss.Texture(Y);Q.needsUpdate=!0;var $=new Ss.SpriteMaterial({map:Q,useScreenCoordinates:!1}),ee=new Ss.Sprite($),te=i.scale.x;ee.scale.set(K/Y.height*te,te,1),this.add(ee)}break;case 10:var ie=null;0===i.color.r&&0===i.color.g&&0===i.color.b&&0===i.color.a||(ie=r),this.msgMesh=i.mesh_resource.substr(10);var re=new Fs({path:t,resource:this.msgMesh,material:ie});this.add(re);break;case 11:var ne=new zs({material:r,vertices:i.points,colors:i.colors});ne.scale.set(i.scale.x,i.scale.y,i.scale.z),this.add(ne);break;default:console.error("Currently unsupported marker type: "+i.type)}}setPose(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()}update(e){if(this.setPose(e.pose),e.color.r!==this.msgColor.r||e.color.g!==this.msgColor.g||e.color.b!==this.msgColor.b||e.color.a!==this.msgColor.a){var t=As(e.color.r,e.color.g,e.color.b,e.color.a);switch(e.type){case 4:case 5:case 8:break;case 0:case 1:case 2:case 3:case 11:case 9:this.traverse((function(e){e instanceof Ss.Mesh&&(e.material=t)}));break;case 10:var i=null;0===e.color.r&&0===e.color.g&&0===e.color.b&&0===e.color.a||(i=this.colorMaterial),this.traverse((function(e){e instanceof Ss.Mesh&&(e.material=i)}));break;default:return!1}this.msgColor=e.color}var r=Math.abs(this.msgScale[0]-e.scale.x)>1e-6||Math.abs(this.msgScale[1]-e.scale.y)>1e-6||Math.abs(this.msgScale[2]-e.scale.z)>1e-6;switch(this.msgScale=[e.scale.x,e.scale.y,e.scale.z],e.type){case 1:case 2:case 3:if(r)return!1;break;case 9:if(r||this.text!==e.text)return!1;break;case 10:if(e.mesh_resource.substr(10)!==this.msgMesh)return!1;if(r)return!1;break;case 0:case 4:case 5:case 6:case 7:case 8:case 11:return!1}return!0}dispose(){this.children.forEach((function(e){e instanceof Fs?e.children.forEach((function(t){void 0!==t.material&&t.material.dispose(),t.children.forEach((function(e){void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose(),t.remove(e)})),e.remove(t)})):(void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose()),e.parent.remove(e)}))}}class Gs extends Ss.Object3D{constructor(e){super();var t=this;e=e||{},this.parent=e.parent;var i=e.handle,n=e.message;this.message=n,this.name=n.name,this.camera=e.camera,this.path=e.path||"/",this.loader=e.loader,this.dragging=!1,this.startMousePos=new Ss.Vector2,this.isShift=!1;var o=new Ss.Quaternion(n.orientation.x,n.orientation.y,n.orientation.z,n.orientation.w);o.normalize();var a=new Ss.Vector3(1,0,0);switch(a.applyQuaternion(o),this.currentControlOri=new Ss.Quaternion,n.interaction_mode){case 9:case 7:this.addEventListener("mousemove",this.parent.move3d.bind(this.parent,this,a));break;case 3:this.addEventListener("mousemove",this.parent.moveAxis.bind(this.parent,this,a)),this.addEventListener("touchmove",this.parent.moveAxis.bind(this.parent,this,a));break;case 5:this.addEventListener("mousemove",this.parent.rotateAxis.bind(this.parent,this,o));break;case 4:this.addEventListener("mousemove",this.parent.movePlane.bind(this.parent,this,a));break;case 2:this.addEventListener("click",this.parent.buttonClick.bind(this.parent,this))}function s(e){e.stopPropagation()}0!==n.interaction_mode&&(this.addEventListener("mousedown",this.parent.startDrag.bind(this.parent,this)),this.addEventListener("mouseup",this.parent.stopDrag.bind(this.parent,this)),this.addEventListener("contextmenu",this.parent.showMenu.bind(this.parent,this)),this.addEventListener("mouseup",(function(e){0===t.startMousePos.distanceToSquared(e.mousePos)&&(e.type="contextmenu",t.dispatchEvent(e))})),this.addEventListener("mouseover",s),this.addEventListener("mouseout",s),this.addEventListener("click",s),this.addEventListener("mousedown",(function(e){t.startMousePos=e.mousePos})),this.addEventListener("touchstart",(function(e){1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,t.dispatchEvent(e))})),this.addEventListener("touchmove",(function(e){1===e.domEvent.touches.length&&(e.type="mousemove",e.domEvent.button=0,t.dispatchEvent(e))})),this.addEventListener("touchend",(function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",t.dispatchEvent(e),e.type="click",t.dispatchEvent(e))})),window.addEventListener("keydown",(function(e){16===e.keyCode&&(t.isShift=!0)})),window.addEventListener("keyup",(function(e){16===e.keyCode&&(t.isShift=!1)})));var c=new Ss.Quaternion,h=this.parent.position.clone().multiplyScalar(-1);switch(n.orientation_mode){case 0:c=this.parent.quaternion.clone().inverse();break;case 1:case 2:break;default:console.error("Unkown orientation mode: "+n.orientation_mode)}var l=new r.TFClient({ros:i.tfClient.ros,fixedFrame:i.message.header.frame_id,serverName:i.tfClient.serverName});n.markers.forEach((function(e){var i=function(i){var n=new ks({message:e,path:t.path,loader:t.loader});if(null!==i){var o=new r.Pose({position:n.position,orientation:n.quaternion});o.applyTransform(new r.Transform(i));var a=new ks({message:e,path:t.path,loader:t.loader});a.position.add(h),a.position.applyQuaternion(c),a.quaternion.multiplyQuaternions(c,a.quaternion);var s=new Ss.Vector3(a.position.x,a.position.y,a.position.z),u=new r.Transform({translation:s,orientation:a.quaternion});o.applyTransform(u),n.setPose(o),n.updateMatrixWorld(),l.unsubscribe(e.header.frame_id)}t.add(n)};""!==e.header.frame_id?l.subscribe(e.header.frame_id,i):i(null)}))}updateMatrixWorld(e){var t=this,i=this.message;switch(i.orientation_mode){case 0:super.updateMatrixWorld(e),t.currentControlOri.copy(t.quaternion),t.currentControlOri.normalize();break;case 1:t.quaternion.copy(t.parent.quaternion.clone().inverse()),t.updateMatrix(),t.matrixWorldNeedsUpdate=!0,super.updateMatrixWorld(e),t.currentControlOri.copy(t.quaternion);break;case 2:t.camera.updateMatrixWorld();var r=(new Ss.Matrix4).extractRotation(t.camera.matrixWorld),n=new Ss.Matrix4,o=.5*Math.PI,a=new Ss.Euler(-o,0,o);n.makeRotationFromEuler(a);var s=new Ss.Matrix4;s.getInverse(t.parent.matrixWorld),r.multiplyMatrices(r,n),r.multiplyMatrices(s,r),t.currentControlOri.setFromRotationMatrix(r),i.independent_marker_orientation||(t.quaternion.copy(t.currentControlOri),t.updateMatrix(),t.matrixWorldNeedsUpdate=!0),super.updateMatrixWorld(e);break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}}}class Vs extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).menuEntries,r=e.className||"default-interactive-marker-menu";e.entryClassName;var n,o,a,s=e.overlayClassName||"default-interactive-marker-overlay",c=e.menuFontSize||"0.8em",h=[];if(h[0]={children:[]},null===document.getElementById("default-interactive-marker-menu-css")){var l=document.createElement("style");l.id="default-interactive-marker-menu-css",l.type="text/css",l.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: "+c+";z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(l)}for(this.menuDomElem=document.createElement("div"),this.menuDomElem.style.position="absolute",this.menuDomElem.className=r,this.menuDomElem.addEventListener("contextmenu",(function(e){e.preventDefault()})),this.overlayDomElem=document.createElement("div"),this.overlayDomElem.className=s,this.hideListener=this.hide.bind(this),this.overlayDomElem.addEventListener("contextmenu",this.hideListener),this.overlayDomElem.addEventListener("click",this.hideListener),this.overlayDomElem.addEventListener("touchstart",this.hideListener),n=0;n0?(e(s,o[a]),c.addEventListener("click",t.hide.bind(t)),c.addEventListener("touchstart",t.hide.bind(t))):(c.addEventListener("click",p.bind(t,o[a])),c.addEventListener("touchstart",p.bind(t,o[a])),c.className="default-interactive-marker-menu-entry")}}(this.menuDomElem,h[0])}show(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,void 0!==t.domEvent.changedTouches?(this.menuDomElem.style.left=t.domEvent.changedTouches[0].pageX+"px",this.menuDomElem.style.top=t.domEvent.changedTouches[0].pageY+"px"):(this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px"),document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)}hide(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)}}class js extends Ss.Object3D{constructor(e){super();var t=(e=e||{}).handle;this.name=t.name;var i=e.camera,r=e.path||"/",n=e.loader;this.dragging=!1,this.onServerSetPose({pose:t.pose}),this.dragStart={position:new Ss.Vector3,orientation:new Ss.Quaternion,positionWorld:new Ss.Vector3,orientationWorld:new Ss.Quaternion,event3d:{}},t.controls.forEach(function(e){this.add(new Gs({parent:this,handle:t,message:e,camera:i,path:r,loader:n}))}.bind(this)),t.menuEntries.length>0&&(this.menu=new Vs({menuEntries:t.menuEntries,menuFontSize:t.menuFontSize}),this.menu.addEventListener("menu-select",function(e){this.dispatchEvent(e)}.bind(this)))}showMenu(e,t){this.menu&&this.menu.show(e,t)}moveAxis(e,t,i){if(this.dragging){var r=e.currentControlOri,n=t.clone().applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),s=new Ss.Ray(o,a),c=Cs(s,i.camera,i.mousePos),h=new Ss.Vector3;h.addVectors(this.dragStart.position,n.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(c)),this.setPosition(e,h),i.stopPropagation()}}move3d(e,t,i){if(this.dragging)if(e.isShift);else{var r=e.camera.getWorldDirection(),n=Math.abs(r.x),o=Math.abs(r.y),a=Math.abs(r.z),s=new Ss.Quaternion(1,0,0,1);o>n&&o>a?s=new Ss.Quaternion(0,0,1,1):a>n&&a>o&&(s=new Ss.Quaternion(0,1,0,1)),s.normalize(),(t=new Ss.Vector3(1,0,0)).applyQuaternion(s),this.movePlane(e,t,i)}}movePlane(e,t,i){if(this.dragging){var r=e.currentControlOri,n=t.clone().applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.clone().applyQuaternion(this.dragStart.orientationWorld),s=Rs(i.mouseRay,o,a),c=new Ss.Vector3;c.subVectors(s,o),c.add(this.dragStart.positionWorld),this.setPosition(e,c),i.stopPropagation()}}rotateAxis(e,t,i){if(this.dragging){e.updateMatrixWorld();var r=e.currentControlOri.clone().multiply(t.clone()),n=new Ss.Vector3(1,0,0).applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.applyQuaternion(this.dragStart.orientationWorld),s=Rs(i.mouseRay,o,a),c=new Ss.Ray(this.dragStart.positionWorld,a),h=Rs(c,o,a),l=this.dragStart.orientationWorld.clone().multiply(r).clone().inverse();s.sub(h),s.applyQuaternion(l);var u=this.dragStart.event3d.intersection.point.clone();u.sub(h),u.applyQuaternion(l);var p=Math.atan2(s.y,s.z),d=Math.atan2(u.y,u.z)-p,f=new Ss.Quaternion;f.setFromAxisAngle(n,d),this.setOrientation(e,f.multiply(this.dragStart.orientationWorld)),i.stopPropagation()}}feedbackEvent(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})}startDrag(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var i=new Ss.Vector3;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,i),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}}stopDrag(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))}buttonClick(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)}setPosition(e,t){this.position.copy(t),this.feedbackEvent("user-pose-change",e)}setOrientation(e,t){t.normalize(),this.quaternion.copy(t),this.feedbackEvent("user-pose-change",e)}onServerSetPose(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.copy(t.position),this.quaternion.copy(t.orientation),this.updateMatrixWorld(!0)}}dispose(){this.children.forEach(function(e){e.children.forEach((function(t){t.dispose(),e.remove(t)})),this.remove(e)}.bind(this))}}class Hs extends EventEmitter3{constructor(e){super(),e=e||{},this.message=e.message,this.feedbackTopic=e.feedbackTopic,this.tfClient=e.tfClient,this.menuFontSize=e.menuFontSize||"0.8em",this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new r.Transform,this.pose=new r.Pose,this.setPoseFromClientBound=this.setPoseFromClient.bind(this),this.onMouseDownBound=this.onMouseDown.bind(this),this.onMouseUpBound=this.onMouseUp.bind(this),this.onButtonClickBound=this.onButtonClick.bind(this),this.onMenuSelectBound=this.onMenuSelect.bind(this),this.setPoseFromServer(this.message.pose),this.tfUpdateBound=this.tfUpdate.bind(this)}subscribeTf(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}unsubscribeTf(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}emitServerPoseUpdate(){var e=new r.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}setPoseFromServer(e){this.pose=new r.Pose(e),this.emitServerPoseUpdate()}tfUpdate(e){this.tfTransform=new r.Transform(e),this.emitServerPoseUpdate()}setPoseFromClient(e){this.pose=new r.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}onButtonClick(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}onMouseDown(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}onMouseUp(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}onMenuSelect(e){this.sendFeedback(2,void 0,e.id,e.controlName)}sendFeedback(e,t,i,r){var n=void 0!==t;t=t||{x:0,y:0,z:0};var o={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:r,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:n,menu_entry_id:i};this.feedbackTopic.publish(o)}}class Ws extends Ss.Object3D{constructor(e){super(),e=e||{},this.tfClient=e.tfClient,this.frameID=e.frameID;var t=e.object;this.pose=e.pose||new r.Pose,this.visible=!1,this.add(t),this.updatePose(this.pose),this.tfUpdate=function(e){var t=new r.Transform(e),i=new r.Pose(this.pose);i.applyTransform(t),this.updatePose(i),this.visible=!0},this.tfUpdateBound=this.tfUpdate.bind(this),this.tfClient.subscribe(this.frameID,this.tfUpdateBound)}updatePose(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}unsubscribeTf(){this.tfClient.unsubscribe(this.frameID,this.tfUpdateBound)}}class Xs extends EventEmitter3{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.markers={},this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var i=!1;if(t in this.markers&&((i=this.markers[t].children[0].update(e))||this.removeMarker(t)),!i){var r=new ks({message:e,path:this.path});this.markers[t]=new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var n in this.markers)this.removeMarker(n);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}}class qs extends EventEmitter3{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.lifetime=e.lifetime||0,this.markers={},this.rosTopic=void 0,this.updatedTime={},this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}checkTime(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){var t=e.ns+e.id,i=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),i?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var r=new ks({message:e,path:this.path});this.markers[t]=new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}this.emit("change")}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}}class Ys extends Ss.ArrowHelper{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1;e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Ss.MeshBasicMaterial,super(i,t,r,16711680)}dispose(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}class Zs extends Ss.Object3D{constructor(e){super();var t=this,i=(e=e||{}).shaftRadius||.008,r=e.headRadius||.023,n=e.headLength||.1,o=e.scale||1,a=e.lineType||"full",s=e.lineDashLength||.1;function c(e){var r=new Ss.Color;r.setRGB(e.x,e.y,e.z);var n=new Ss.MeshBasicMaterial({color:r.getHex()}),o=new Ss.Vector3;o.crossVectors(e,new Ss.Vector3(0,-1,0));var c=new Ss.Quaternion;c.setFromAxisAngle(o,.5*Math.PI);var h,l=new Ss.Mesh(t.headGeom,n);if(l.position.copy(e),l.position.multiplyScalar(.95),l.quaternion.copy(c),l.updateMatrix(),t.add(l),"dashed"===a)for(var u=s,p=0;u/2+3*u*p+u/2<=1;++p){var d=new Ss.CylinderGeometry(i,i,u);(h=new Ss.Mesh(d,n)).position.copy(e),h.position.multiplyScalar(u/2+3*u*p),h.quaternion.copy(c),h.updateMatrix(),t.add(h)}else"full"===a?((h=new Ss.Mesh(t.lineGeom,n)).position.copy(e),h.position.multiplyScalar(.45),h.quaternion.copy(c),h.updateMatrix(),t.add(h)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}this.scale.set(o,o,o),this.lineGeom=new Ss.CylinderGeometry(i,i,1-n),this.headGeom=new Ss.CylinderGeometry(0,r,n),c(new Ss.Vector3(1,0,0)),c(new Ss.Vector3(0,1,0)),c(new Ss.Vector3(0,0,1))}}class Js extends Ss.Object3D{constructor(e){var t=(e=e||{}).num_cells||10,i=e.color||"#cccccc",r=e.lineWidth||1,n=e.cellSize||1;super();for(var o=new Ss.LineBasicMaterial({color:i,linewidth:r}),a=0;a<=t;++a){var s=n*t/2,c=s-a*n,h=new Ss.Geometry;h.vertices.push(new Ss.Vector3(-s,c,0),new Ss.Vector3(s,c,0));var l=new Ss.Geometry;l.vertices.push(new Ss.Vector3(c,-s,0),new Ss.Vector3(c,s,0)),this.add(new Ss.Line(h,o)),this.add(new Ss.Line(l,o))}}}class Ks extends Ss.Mesh{constructor(e){var t=(e=e||{}).message,i=e.opacity||1,r=e.color||{r:255,g:255,b:255,a:255},n=t.info,o=n.origin,a=n.width,s=n.height,c=new Ss.PlaneBufferGeometry(a,s),h=new Uint8Array(a*s*4),l=new Ss.DataTexture(h,a,s,Ss.RGBAFormat);l.flipY=!0,l.minFilter=Ss.NearestFilter,l.magFilter=Ss.NearestFilter,l.needsUpdate=!0;var u=new Ss.MeshBasicMaterial({map:l,transparent:i<1,opacity:i});u.side=Ss.DoubleSide,super(c,u),Object.assign(this,e),this.quaternion.copy(new Ss.Quaternion(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),this.position.x=a*n.resolution/2+o.position.x,this.position.y=s*n.resolution/2+o.position.y,this.position.z=o.position.z,this.scale.x=n.resolution,this.scale.y=n.resolution;var p=t.data;this.color=r,this.material=u,this.texture=l;for(var d=0;d{const t="read"+e.kind,i="get"+e.kind;this[t]=()=>{if(this._cursor+e.width>this.length)throw new Error("Cannot read data stream. Overflow. Len="+this.length+" crsr="+this._cursor);const t=this._dataView[i](this._cursor,this.isLittleEndian);return this._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:()=>this.cursor>=this.data.length}),this}class oc{constructor(e){this.resolution=void 0!==e.resolution?e.resolution:1,this.color=new Ss.Color(void 0!==e.color?e.color:"green"),this.opacity=void 0!==e.opacity?e.opacity:1,this.voxelRenderMode=void 0!==e.voxelRenderMode?e.voxelRenderMode:ec,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);let t=this.resolution;for(let e=this._treeDepth-1;e>=0;--e)this.nodeSizeTable[e]=t,t*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}searchAtDepth(e,t){t=void 0!==t&&t>0?t:this._treeDepth;const i=this._adjustKeyAtDepth(e,t),r=this._treeDepth-t;let n=this._rootNode;for(let e=this._treeDepth-1;e>=r;--e){const t=this._computeChildIdx(i,e);if(!n.hasChildAt(t))return n.hasChildren()?null:n;n=n.getChildAt(t)}return n}_computeCoordFromKey(e){return e.map((e=>this.resolution*(e-this._treeMaxKeyVal)))}_computeChildIdx(e,t){let i=0;return e[0]&1<(e-this._treeMaxKeyVal>>i<0;){let e=i.pop();const r=t.readUint16();let n=8;for(;0!==n;){--n;const t=(r&3<<2*n)>>2*n;if(t!==this._BINARY_UNALLOCATED){let r=this._newNode();this._BINARY_CHILD_BUILD_TABLE[t].bind(this)(r),e.createChildNodeAt(r,n),t===this._BINARY_HAS_CHILDREN&&i.push(r)}}}}read(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();let t=new nc(e,!0),i=new Array;for(i.push(this._rootNode);i.length>0;){let e=i.pop();this._readNodeData(t,e);const r=t.readUint8();let n=8;for(;0!==n;){--n;if(r&1<0;){let i=t.pop();if(i.node.isLeafNode())e(i.node,i.key,i.depth-1);else for(let e=0;e<8;++e)if(i.node.hasChildAt(e)){const r=this._computeKeyFromChildIdx(e,i.key,i.depth);t.push({node:i.node.getChildAt(e),depth:i.depth+1,key:r})}}}_obtainColor(e){return this.color}_checkOccupied(e){return!1!==e.value}_buildFaces(){let e={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,i,r){const n=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*i,t[1]+e[1]*i,t[2]+e[2]*i)}));const o=[r.r,r.g,r.b];this.colors.push(...o,...o,...o,...o),this.normals.push(...e.normal,...e.normal,...e.normal,...e.normal),this.indices.push(n,n+1,n+2,n+2,n+1,n+3)},_checkNeighborsTouchingFace:function(e,t,i){let r=new Array;for(r.push(t);0!==r.length;){const t=r.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;{const n=t.getChildAt(e),o=this._checkOccupied(t);(o&&i===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!o&&i===tc)&&r.push(n)}}))}return!1}};return this._traverseLeaves(((t,i,r)=>{const n=this._computeCoordFromKey(i),o=this.nodeSizeTable[r],a=this._treeDepth-r,s=this._checkOccupied(t);(s||this.voxelRenderMode!==ec)&&(s&&this.voxelRenderMode===tc||this._FACES.forEach((function(s){const c=[i[0]+s.normal[0]*a*a,i[1]+s.normal[1]*a*a,i[2]+s.normal[2]*a*a],h=this.searchAtDepth(c);null===h?e._insertFace(s,n,o,this._obtainColor(t)):rnew Ss.Color(e))):[{r:0,g:0,b:128},{r:0,g:255,b:0},{r:255,g:255,b:0},{r:255,g:128,b:0},{r:255,g:0,b:0}],this.paletteScale=void 0!==e.paletteScale?e.paletteScale:1}_readNodeData(e,t){t.value=e.readFloat32()}_obtainColor(e){if(this.useFlatColoring)return this.color;const t=1/(1+Math.exp(-e.value*this.paletteScale))*this.palette.length,i=Math.trunc(t),r=t-i;return i<0?this.palette[0]:i>=this.palette.length-1?this.palette[this.palette.length-1]:{r:r*this.palette[i].r+(1-r)*this.palette[i+1].r,g:r*this.palette[i].g+(1-r)*this.palette[i+1].g,b:r*this.palette[i].b+(1-r)*this.palette[i+1].b}}_checkOccupied(e){return e.value>=this.occupancyThreshold}}class sc extends ac{constructor(e){super(e),this.useOwnColor=void 0!==e.palette&&e.colorMode===rc}_readNodeData(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}_obtainColor(e){return this.useOwnColor?e.color:ac.prototype._obtainColor.call(this,e)}}class cc extends EventEmitter3{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/octomap",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.options={},void 0!==e.color&&(this.options.color=e.color),void 0!==e.opacity&&(this.options.opacity=e.opacity),void 0!==e.colorMode&&(this.options.colorMode=e.colorMode),void 0!==e.palette&&(this.options.palette=e.palette),void 0!==e.paletteScale&&(this.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(this.options.voxelRenderMode=e.voxelRenderMode),this.currentMap=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}_loadOcTree(e){return new Promise(function(t,i){const r=Object.assign({resolution:e.resolution},this.options);let n=null;if(e.binary)n=new oc(r),n.readBinary(e.data);else{const t={OcTree:ac,ColorOcTree:sc};e.id in t&&(console.log(e.id,t),n=new t[e.id](r),n.read(e.data))}n.buildGeometry(),t(n)}.bind(this))}_processMessagePrivate(e){this._loadOcTree(e).then(function(t){const i=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(i),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}}class hc extends Ss.Object3D{constructor(e){super(),this.options=e||{},this.ros=e.ros,this.topicName=e.topic||"/particlecloud",this.tfClient=e.tfClient,this.color=e.color||13369599,this.length=e.length||1,this.rootObject=e.rootObject||new Ss.Object3D,this.keep=e.keep||1,this.sns=[],this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new Ss.Vector3(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new Ss.Quaternion(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new Ss.Vector3(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Ss.MeshBasicMaterial({color:this.color});var i=new Ns(this.options);this.sns.push(new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:i})),this.rootObject.add(this.sns[this.sns.length-1])}}class lc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/path",this.tfClient=e.tfClient,this.color=e.color||13369599,this.rootObject=e.rootObject||new Ss.Object3D,this.sn=null,this.line=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new Ss.Geometry,i=0;i=e.range_min&&n<=e.range_max){var o=e.angle_min+r*e.angle_increment;this.points.positions.array[i++]=n*Math.cos(o),this.points.positions.array[i++]=n*Math.sin(o),this.points.positions.array[i++]=0}}this.points.update(i/3)}}}class yc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/gps/fix",this.rootObject=e.rootObject||new Ss.Object3D,this.object3d=e.object3d||new Ss.Object3D;var t=e.material||{};this.altitudeNaN=e.altitudeNaN||0,this.keep=e.keep||100,this.convert=e.convert||function(e,t,i){return new Ss.Vector3(e,t,i)},this.count=0,this.next1=0,this.next2=this.keep,this.geom=new Ss.BufferGeometry,this.vertices=new Ss.BufferAttribute(new Float32Array(6*this.keep),3),this.geom.addAttribute("position",this.vertices),this.material=t.isMaterial?t:new Ss.LineBasicMaterial(t),this.line=new Ss.Line(this.geom,this.material),this.rootObject.add(this.object3d),this.rootObject.add(this.line),this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,i=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(i),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=i.x,this.vertices.array[3*this.next1+1]=i.y,this.vertices.array[3*this.next1+2]=i.z,this.vertices.array[3*this.next2]=i.x,this.vertices.array[3*this.next2+1]=i.y,this.vertices.array[3*this.next2+2]=i.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}function xc(e,t,i,r){var n,o=0,a=0,s=0,c=e.length,h=t.length,l=((r=r||1)-1)*(i=i||h)*8;for(n=0;n=8&&(a-=8,t[s++]=o>>>a&255,s%i==0&&(n+=Math.ceil((l-a)/6),(a%=8)>0&&(o=xc.e[e.charAt(n)])));return Math.floor(s/i)}xc.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",xc.e={};for(var bc=0;bc<64;bc++)xc.e[xc.S.charAt(bc)]=bc;class wc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/points",this.throttle_rate=e.throttle_rate||null,this.compression=e.compression||"cbor",this.max_pts=e.max_pts||1e4,this.points=new vc(e),this.rosTopic=void 0,this.buffer=null,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,i=this.points.pointRatio,r=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,r)),t=Math.min(e.height*e.width/i,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(r=d[0].object,p.intersection=this.lastIntersection=d[0]):r=this.fallbackTarget,r!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(r,"mouseover",p);0===f?this.notify(this.lastTarget,"mouseout",p):1===f&&(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(r,"mouseover",p),this.notify(this.lastTarget,"mouseout",p))}r!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(r,e.type,p)?(this.notify(this.lastTarget,"touchleave",p),this.notify(this.lastTarget,"touchend",p)):(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",p),this.notify(this.lastTarget,"touchend",p)));this.notify(r,e.type,p),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=r}notify(e,t,i){for(i.type=t,i.cancelBubble=!1,i.continueBubble=!1,i.stopPropagation=function(){i.cancelBubble=!0},i.continuePropagation=function(){i.continueBubble=!0},i.currentTarget=e;i.currentTarget;){if(i.currentTarget.dispatchEvent&&i.currentTarget.dispatchEvent instanceof Function){if(i.currentTarget.dispatchEvent(i),i.cancelBubble)return this.dispatchEvent(i),0;if(i.continueBubble)return 2}i.currentTarget=i.currentTarget.parent}return 1}}class Sc extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).scene;this.camera=e.camera,this.center=new Ss.Vector3,this.userZoom=!0,this.userZoomSpeed=e.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=e.userRotateSpeed||1,this.autoRotate=e.autoRotate,this.autoRotateSpeed=e.autoRotateSpeed||2,this.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,this.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",this.camera.up=new Ss.Vector3(0,0,1);var r=1800,n=new Ss.Vector2,o=new Ss.Vector2,a=new Ss.Vector2,s=new Ss.Vector2,c=new Ss.Vector2,h=new Ss.Vector2,l=new Ss.Vector3,u=new Ss.Vector3,p=new Ss.Vector3,d=new Ss.Vector3,f=new Array(2),m=new Array(2);this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new Ss.Vector3;var v=-1,g=0,y=1,x=2,b=v;function w(e,t,i){var r=new Ss.Vector3;new Ss.Vector3;r.subVectors(t,e.origin);var n=e.direction.dot(i);if(Math.abs(n)0?t.zoomIn():t.zoomOut(),this.showAxes()}}this.axes=new Zs({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:this.lineTypePanAndZoomFrame}),this.displayPanAndZoomFrame&&(i.add(this.axes),this.axes.traverse((function(e){e.visible=!1}))),this.addEventListener("mousedown",(function(e){var i=e.domEvent;switch(i.preventDefault(),i.button){case 0:b=g,n.set(i.clientX,i.clientY);break;case 1:b=x,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u);break;case 2:b=y,s.set(i.clientX,i.clientY)}this.showAxes()})),this.addEventListener("mouseup",(function(e){t.userRotate&&(b=v)})),this.addEventListener("mousemove",(function(e){var i=e.domEvent;if(b===g)o.set(i.clientX,i.clientY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else if(b===y)c.set(i.clientX,i.clientY),h.subVectors(c,s),h.y>0?t.zoomIn():t.zoomOut(),s.copy(c),this.showAxes();else if(b===x){var f=w(e.mouseRay,t.center,u);if(!f)return;var m=(new Ss.Vector3).subVectors(d.clone(),f.clone());t.center.addVectors(l.clone(),m.clone()),t.camera.position.addVectors(p.clone(),m.clone()),t.update(),t.camera.updateMatrixWorld(),this.showAxes()}})),this.addEventListener("touchstart",(function(e){var i=e.domEvent;switch(i.touches.length){case 1:b=g,n.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY);break;case 2:b=v,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u),f[0]=new Ss.Vector2(i.touches[0].pageX,i.touches[0].pageY),f[1]=new Ss.Vector2(i.touches[1].pageX,i.touches[1].pageY),m[0]=new Ss.Vector2(0,0),m[1]=new Ss.Vector2(0,0)}this.showAxes(),i.preventDefault()})),this.addEventListener("touchmove",(function(e){var i=e.domEvent;if(b===g)o.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else{if(m[0].set(f[0].x-i.touches[0].pageX,f[0].y-i.touches[0].pageY),m[1].set(f[1].x-i.touches[1].pageX,f[1].y-i.touches[1].pageY),m[0].lengthSq()>10&&m[1].lengthSq()>10&&(f[0].set(i.touches[0].pageX,i.touches[0].pageY),f[1].set(i.touches[1].pageX,i.touches[1].pageY),m[0].dot(m[1])>0&&b!==y?b=x:m[0].dot(m[1])<0&&b!==x&&(b=y),b===y)){var s=new Ss.Vector2;s.subVectors(f[0],f[1]),m[0].dot(s)<0&&m[1].dot(s)>0?t.zoomOut():m[0].dot(s)>0&&m[1].dot(s)<0&&t.zoomIn()}if(b===x){var c=w(e.mouseRay,t.center,u);if(!c)return;var h=(new Ss.Vector3).subVectors(d.clone(),c.clone());t.center.addVectors(l.clone(),h.clone()),t.camera.position.addVectors(p.clone(),h.clone()),t.update(),t.camera.updateMatrixWorld()}this.showAxes(),i.preventDefault()}})),this.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&b!==g?(b=g,n.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):b=v})),this.addEventListener("mousewheel",_),this.addEventListener("DOMMouseScroll",_)}showAxes(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}rotateLeft(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}rotateRight(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}rotateUp(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}rotateDown(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}zoomIn(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}zoomOut(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}update(){var e=this.camera.position,t=e.clone().sub(this.center),i=Math.atan2(t.y,t.x),r=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),i+=this.thetaDelta,r+=this.phiDelta;var n=1e-6;r=Math.max(n,Math.min(Math.PI-n,r));var o=t.length();t.set(o*Math.sin(r)*Math.cos(i),o*Math.sin(r)*Math.sin(i),o*Math.cos(r)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),o=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*o,.05*o,.05*o),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}return e.Arrow=Ns,e.Arrow2=Ys,e.Axes=Zs,e.ColorOcTree=sc,e.DepthCloud=Ps,e.Grid=Js,e.Highlighter=Ec,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=js,e.InteractiveMarkerClient=class{constructor(e){e=e||{},this.ros=e.ros,this.tfClient=e.tfClient,this.topicName=e.topic,this.path=e.path||"/",this.camera=e.camera,this.rootObject=e.rootObject||new Ss.Object3D,this.loader=e.loader,this.menuFontSize=e.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.processUpdateBound=this.processUpdate.bind(this),this.topicName&&this.subscribe(this.topicName)}subscribe(e){this.unsubscribe(),this.updateTopic=new r.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdateBound),this.feedbackTopic=new r.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new r.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new r.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}unsubscribe(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdateBound),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}processInit(e){var t=e.msg;for(var i in t.erases=[],this.interactiveMarkers)t.erases.push(i);t.poses=[],this.processUpdate(t)}processUpdate(e){e.erases.forEach((function(e){this.eraseIntMarker(e)})),e.poses.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&t.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&this.eraseIntMarker(t.name);var i=new Hs({message:e,feedbackTopic:this.feedbackTopic,tfClient:this.tfClient,menuFontSize:this.menuFontSize});this.interactiveMarkers[e.name]=i;var r=new js({handle:i,camera:this.camera,path:this.path,loader:this.loader});r.name=e.name,this.rootObject.add(r),i.on("pose",(function(e){r.onServerSetPose({pose:e})})),r.addEventListener("user-pose-change",i.setPoseFromClientBound),r.addEventListener("user-mousedown",i.onMouseDownBound),r.addEventListener("user-mouseup",i.onMouseUpBound),r.addEventListener("user-button-click",i.onButtonClickBound),r.addEventListener("menu-select",i.onMenuSelectBound),i.subscribeTf()}))}eraseIntMarker(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var i=this.interactiveMarkers[e];i.unsubscribeTf(),t.removeEventListener("user-pose-change",i.setPoseFromClientBound),t.removeEventListener("user-mousedown",i.onMouseDownBound),t.removeEventListener("user-mouseup",i.onMouseUpBound),t.removeEventListener("user-button-click",i.onButtonClickBound),t.removeEventListener("menu-select",i.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}},e.InteractiveMarkerControl=Gs,e.InteractiveMarkerHandle=Hs,e.InteractiveMarkerMenu=Vs,e.LaserScan=gc,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=ks,e.MarkerArrayClient=Xs,e.MarkerClient=qs,e.MeshLoader=Bs,e.MeshResource=Fs,e.MouseHandler=Tc,e.NavSatFix=yc,e.OcTree=ac,e.OcTreeClient=cc,e.OccupancyGrid=Ks,e.OccupancyGridClient=Qs,e.Odometry=hc,e.OrbitControls=Sc,e.Path=lc,e.Point=uc,e.PointCloud2=wc,e.Points=vc,e.Polygon=pc,e.Pose=dc,e.PoseArray=fc,e.PoseWithCovariance=mc,e.SceneNode=Ws,e.TFAxes=_c,e.TriangleList=zs,e.Urdf=Mc,e.UrdfClient=class{constructor(e){var t=(e=e||{}).ros;this.param=e.param||"robot_description",this.path=e.path||"/",this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.tfPrefix=e.tfPrefix||"",this.loader=e.loader,new r.Param({ros:t,name:this.param}).get(function(e){var t=new r.UrdfModel({string:e});this.urdf=new Mc({urdfModel:t,path:this.path,tfClient:this.tfClient,tfPrefix:this.tfPrefix,loader:this.loader}),this.rootObject.add(this.urdf)}.bind(this))}},e.Viewer=class{constructor(e){var t=(e=e||{}).divID,i=e.elem,r=e.width,n=e.height,o=e.background||"#111111",a=e.antialias,s=e.intensity||.66,c=e.near||.01,h=e.far||1e3,l=e.alpha||1,u=e.cameraPose||{x:3,y:3,z:3},p=e.cameraZoomSpeed||.5,d=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,f=e.lineTypePanAndZoomFrame||"full";this.renderer=new Ss.WebGLRenderer({antialias:a,alpha:!0}),this.renderer.setClearColor(parseInt(o.replace("#","0x"),16),l),this.renderer.sortObjects=!1,this.renderer.setSize(r,n),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ss.Scene,this.camera=new Ss.PerspectiveCamera(40,r/n,c,h),this.camera.position.x=u.x,this.camera.position.y=u.y,this.camera.position.z=u.z,this.cameraControls=new Sc({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:d,lineTypePanAndZoomFrame:f}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Ss.AmbientLight(5592405)),this.directionalLight=new Ss.DirectionalLight(16777215,s),this.scene.add(this.directionalLight),this.selectableObjects=new Ss.Group,this.scene.add(this.selectableObjects);var m=new Tc({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ec({mouseHandler:m}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(t)).appendChild(this.renderer.domElement),this.start()}start(){this.stopped=!1,this.draw()}draw(){this.stopped||(this.cameraControls.update(),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}stop(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}addObject(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}},e.closestAxisPoint=Cs,e.findClosestPoint=Ls,e.intersectPlane=Rs,e.makeColorMaterial=As,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); diff --git a/package-lock.json b/package-lock.json index 985683c3..633ec816 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.1.0", "license": "BSD-3-Clause", "dependencies": { - "eventemitter2": "^6.4.0", + "eventemitter3": "^5.0.1", "roslib": "^1.0.0", "three": "^0.89.0" }, @@ -2483,10 +2483,9 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" }, "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/exit": { "version": "0.1.2", @@ -3807,6 +3806,12 @@ "node": ">= 6" } }, + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -7322,8 +7327,7 @@ "node_modules/three": { "version": "0.89.0", "resolved": "https://registry.npmjs.org/three/-/three-0.89.0.tgz", - "integrity": "sha512-Evv3JolLQtag/lCWu1o3cgz2E5UYCSZHbh9lfBjeLz7nlK8DMmASID680Odl++ZPYk63rrZjPAMq88IrMP3GCA==", - "license": "MIT" + "integrity": "sha512-Evv3JolLQtag/lCWu1o3cgz2E5UYCSZHbh9lfBjeLz7nlK8DMmASID680Odl++ZPYk63rrZjPAMq88IrMP3GCA==" }, "node_modules/through": { "version": "2.3.8", @@ -10117,10 +10121,9 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" }, "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "exit": { "version": "0.1.2", @@ -11099,6 +11102,14 @@ "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + } } }, "http-proxy-agent": { diff --git a/package.json b/package.json index 6a79c284..411fbf4e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "main": "./build/ros3d.cjs.js", "module": "./build/ros3d.esm.js", "dependencies": { - "eventemitter2": "^6.4.0", + "eventemitter3": "^5.0.1", "roslib": "^1.0.0", "three": "^0.89.0" }, diff --git a/src/interactivemarkers/InteractiveMarkerHandle.js b/src/interactivemarkers/InteractiveMarkerHandle.js index c9c75484..af2ed1d4 100644 --- a/src/interactivemarkers/InteractiveMarkerHandle.js +++ b/src/interactivemarkers/InteractiveMarkerHandle.js @@ -43,7 +43,7 @@ ROS3D.InteractiveMarkerHandle = function(options) { this.setPoseFromServer(this.message.pose); this.tfUpdateBound = this.tfUpdate.bind(this); }; -ROS3D.InteractiveMarkerHandle.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.InteractiveMarkerHandle.prototype.__proto__ = EventEmitter3.prototype; /** * Subscribe to the TF associated with this interactive marker. diff --git a/src/markers/MarkerArrayClient.js b/src/markers/MarkerArrayClient.js index 6353c176..00be1831 100644 --- a/src/markers/MarkerArrayClient.js +++ b/src/markers/MarkerArrayClient.js @@ -35,7 +35,7 @@ ROS3D.MarkerArrayClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.MarkerArrayClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.MarkerArrayClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.MarkerArrayClient.prototype.subscribe = function(){ this.unsubscribe(); diff --git a/src/markers/MarkerClient.js b/src/markers/MarkerClient.js index 896f01f4..9cb5d4ed 100644 --- a/src/markers/MarkerClient.js +++ b/src/markers/MarkerClient.js @@ -37,7 +37,7 @@ ROS3D.MarkerClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.MarkerClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.MarkerClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.MarkerClient.prototype.unsubscribe = function(){ if(this.rosTopic){ diff --git a/src/navigation/OcTreeClient.js b/src/navigation/OcTreeClient.js index 1983b2b0..722e1dad 100644 --- a/src/navigation/OcTreeClient.js +++ b/src/navigation/OcTreeClient.js @@ -30,7 +30,7 @@ */ ROS3D.OcTreeClient = function(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/octomap'; @@ -60,7 +60,7 @@ ROS3D.OcTreeClient = function(options) { this.subscribe(); }; -ROS3D.OcTreeClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.OcTreeClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.OcTreeClient.prototype.unsubscribe = function () { if (this.rosTopic) { diff --git a/src/navigation/OccupancyGridClient.js b/src/navigation/OccupancyGridClient.js index 493831e2..011e69d4 100644 --- a/src/navigation/OccupancyGridClient.js +++ b/src/navigation/OccupancyGridClient.js @@ -24,7 +24,7 @@ * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) */ ROS3D.OccupancyGridClient = function(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/map'; @@ -44,7 +44,7 @@ ROS3D.OccupancyGridClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.OccupancyGridClient.prototype.unsubscribe = function(){ if(this.rosTopic){ From 185c3c0d3bec3fcdb17eea0eb25f8f9b3984b9ee Mon Sep 17 00:00:00 2001 From: Anna-Maria Meer Date: Tue, 13 Aug 2024 17:12:40 +0200 Subject: [PATCH 3/8] update ros3djs with new three version --- README.md | 4 + build/ros3d.cjs.js | 70841 +++++++--------- build/ros3d.esm.js | 70841 +++++++--------- build/ros3d.js | 69715 +++++++-------- build/ros3d.min.js | 18 +- es6-transpiler.js | 26 +- examples/html-import/yarn.lock | 4 +- package-lock.json | 14821 ++-- package.json | 11 +- rollup.config.js | 46 +- shims/three/ColladaLoader.js | 4803 +- shims/three/ColladaTest.html | 62 + shims/three/MTLLoader.js | 588 - shims/three/OBJLoader.js | 795 - shims/three/STLLoader.js | 325 - shims/three/core.js | 4 +- src/depthcloud/DepthCloud.js | 4 +- .../InteractiveMarkerHandle.js | 2 +- src/markers/Marker.js | 6 +- src/markers/MarkerArrayClient.js | 2 +- src/markers/MarkerClient.js | 2 +- src/models/Grid.js | 31 +- src/models/MeshLoader.js | 225 +- src/models/TriangleList.js | 66 +- src/navigation/OcTreeBase.js | 2 +- src/navigation/OcTreeClient.js | 4 +- src/navigation/OccupancyGrid.js | 3 +- src/navigation/OccupancyGridClient.js | 4 +- src/navigation/Path.js | 2 +- src/navigation/Polygon.js | 2 +- src/navigation/PoseArray.js | 2 +- src/sensors/Points.js | 35 +- src/urdf/Urdf.js | 8 +- src/visualization/Viewer.js | 6 + 34 files changed, 106156 insertions(+), 127154 deletions(-) create mode 100644 shims/three/ColladaTest.html delete mode 100644 shims/three/MTLLoader.js delete mode 100644 shims/three/OBJLoader.js delete mode 100644 shims/three/STLLoader.js diff --git a/README.md b/README.md index a0b230ea..1858c1c0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# update three before usage! + +npm install three@latest + # ros3djs [![CI](https://github.com/RobotWebTools/ros3djs/actions/workflows/main.yml/badge.svg)](https://github.com/RobotWebTools/ros3djs/actions/workflows/main.yml) diff --git a/build/ros3d.cjs.js b/build/ros3d.cjs.js index b6caaa3f..2a8c74da 100644 --- a/build/ros3d.cjs.js +++ b/build/ros3d.cjs.js @@ -24,552 +24,675 @@ function _interopNamespace(e) { var ROSLIB__namespace = /*#__PURE__*/_interopNamespace(ROSLIB); -// Polyfills +/** + * @license + * Copyright 2010-2024 Three.js Authors + * SPDX-License-Identifier: MIT + */ +const REVISION = '167'; +const CullFaceNone = 0; +const CullFaceBack = 1; +const CullFaceFront = 2; +const PCFShadowMap = 1; +const PCFSoftShadowMap = 2; +const VSMShadowMap = 3; +const FrontSide = 0; +const BackSide = 1; +const DoubleSide = 2; +const NoBlending = 0; +const NormalBlending = 1; +const AdditiveBlending = 2; +const SubtractiveBlending = 3; +const MultiplyBlending = 4; +const CustomBlending = 5; +const AddEquation = 100; +const SubtractEquation = 101; +const ReverseSubtractEquation = 102; +const MinEquation = 103; +const MaxEquation = 104; +const ZeroFactor = 200; +const OneFactor = 201; +const SrcColorFactor = 202; +const OneMinusSrcColorFactor = 203; +const SrcAlphaFactor = 204; +const OneMinusSrcAlphaFactor = 205; +const DstAlphaFactor = 206; +const OneMinusDstAlphaFactor = 207; +const DstColorFactor = 208; +const OneMinusDstColorFactor = 209; +const SrcAlphaSaturateFactor = 210; +const ConstantColorFactor = 211; +const OneMinusConstantColorFactor = 212; +const ConstantAlphaFactor = 213; +const OneMinusConstantAlphaFactor = 214; +const NeverDepth = 0; +const AlwaysDepth = 1; +const LessDepth = 2; +const LessEqualDepth = 3; +const EqualDepth = 4; +const GreaterEqualDepth = 5; +const GreaterDepth = 6; +const NotEqualDepth = 7; +const MultiplyOperation = 0; +const MixOperation = 1; +const AddOperation = 2; +const NoToneMapping = 0; +const LinearToneMapping = 1; +const ReinhardToneMapping = 2; +const CineonToneMapping = 3; +const ACESFilmicToneMapping = 4; +const CustomToneMapping = 5; +const AgXToneMapping = 6; +const NeutralToneMapping = 7; +const AttachedBindMode = 'attached'; +const DetachedBindMode = 'detached'; + +const UVMapping = 300; +const CubeReflectionMapping = 301; +const CubeRefractionMapping = 302; +const EquirectangularReflectionMapping = 303; +const EquirectangularRefractionMapping = 304; +const CubeUVReflectionMapping = 306; +const RepeatWrapping = 1000; +const ClampToEdgeWrapping = 1001; +const MirroredRepeatWrapping = 1002; +const NearestFilter = 1003; +const NearestMipmapNearestFilter = 1004; +const NearestMipmapLinearFilter = 1005; +const LinearFilter = 1006; +const LinearMipmapNearestFilter = 1007; +const LinearMipmapLinearFilter = 1008; +const UnsignedByteType = 1009; +const ByteType = 1010; +const ShortType = 1011; +const UnsignedShortType = 1012; +const IntType = 1013; +const UnsignedIntType = 1014; +const FloatType = 1015; +const HalfFloatType = 1016; +const UnsignedShort4444Type = 1017; +const UnsignedShort5551Type = 1018; +const UnsignedInt248Type = 1020; +const UnsignedInt5999Type = 35902; +const AlphaFormat = 1021; +const RGBFormat = 1022; +const RGBAFormat = 1023; +const LuminanceFormat = 1024; +const LuminanceAlphaFormat = 1025; +const DepthFormat = 1026; +const DepthStencilFormat = 1027; +const RedFormat = 1028; +const RedIntegerFormat = 1029; +const RGFormat = 1030; +const RGIntegerFormat = 1031; +const RGBAIntegerFormat = 1033; + +const RGB_S3TC_DXT1_Format = 33776; +const RGBA_S3TC_DXT1_Format = 33777; +const RGBA_S3TC_DXT3_Format = 33778; +const RGBA_S3TC_DXT5_Format = 33779; +const RGB_PVRTC_4BPPV1_Format = 35840; +const RGB_PVRTC_2BPPV1_Format = 35841; +const RGBA_PVRTC_4BPPV1_Format = 35842; +const RGBA_PVRTC_2BPPV1_Format = 35843; +const RGB_ETC1_Format = 36196; +const RGB_ETC2_Format = 37492; +const RGBA_ETC2_EAC_Format = 37496; +const RGBA_ASTC_4x4_Format = 37808; +const RGBA_ASTC_5x4_Format = 37809; +const RGBA_ASTC_5x5_Format = 37810; +const RGBA_ASTC_6x5_Format = 37811; +const RGBA_ASTC_6x6_Format = 37812; +const RGBA_ASTC_8x5_Format = 37813; +const RGBA_ASTC_8x6_Format = 37814; +const RGBA_ASTC_8x8_Format = 37815; +const RGBA_ASTC_10x5_Format = 37816; +const RGBA_ASTC_10x6_Format = 37817; +const RGBA_ASTC_10x8_Format = 37818; +const RGBA_ASTC_10x10_Format = 37819; +const RGBA_ASTC_12x10_Format = 37820; +const RGBA_ASTC_12x12_Format = 37821; +const RGBA_BPTC_Format = 36492; +const RGB_BPTC_SIGNED_Format = 36494; +const RGB_BPTC_UNSIGNED_Format = 36495; +const RED_RGTC1_Format = 36283; +const SIGNED_RED_RGTC1_Format = 36284; +const RED_GREEN_RGTC2_Format = 36285; +const SIGNED_RED_GREEN_RGTC2_Format = 36286; +const InterpolateDiscrete = 2300; +const InterpolateLinear = 2301; +const InterpolateSmooth = 2302; +const ZeroCurvatureEnding = 2400; +const ZeroSlopeEnding = 2401; +const WrapAroundEnding = 2402; +const NormalAnimationBlendMode = 2500; +const BasicDepthPacking = 3200; +const RGBADepthPacking = 3201; +const TangentSpaceNormalMap = 0; +const ObjectSpaceNormalMap = 1; + +// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. +const NoColorSpace = ''; +const SRGBColorSpace = 'srgb'; +const LinearSRGBColorSpace = 'srgb-linear'; +const DisplayP3ColorSpace = 'display-p3'; +const LinearDisplayP3ColorSpace = 'display-p3-linear'; + +const LinearTransfer = 'linear'; +const SRGBTransfer = 'srgb'; + +const Rec709Primaries = 'rec709'; +const P3Primaries = 'p3'; +const KeepStencilOp = 7680; +const AlwaysStencilFunc = 519; + +const NeverCompare = 512; +const LessCompare = 513; +const EqualCompare = 514; +const LessEqualCompare = 515; +const GreaterCompare = 516; +const NotEqualCompare = 517; +const GreaterEqualCompare = 518; +const AlwaysCompare = 519; + +const StaticDrawUsage = 35044; +const DynamicDrawUsage = 35048; +const GLSL3 = '300 es'; + +const WebGLCoordinateSystem = 2000; +const WebGPUCoordinateSystem = 2001; -if ( Number.EPSILON === undefined ) { +/** + * https://github.com/mrdoob/eventdispatcher.js/ + */ - Number.EPSILON = Math.pow( 2, - 52 ); +class EventDispatcher { -} + addEventListener( type, listener ) { -if ( Number.isInteger === undefined ) { + if ( this._listeners === undefined ) this._listeners = {}; - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger + const listeners = this._listeners; - Number.isInteger = function ( value ) { + if ( listeners[ type ] === undefined ) { - return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value; + listeners[ type ] = []; - }; + } -} + if ( listeners[ type ].indexOf( listener ) === - 1 ) { -// + listeners[ type ].push( listener ); -if ( Math.sign === undefined ) { + } - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign + } - Math.sign = function ( x ) { + hasEventListener( type, listener ) { - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x; + if ( this._listeners === undefined ) return false; - }; + const listeners = this._listeners; -} + return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; + + } -if ( 'name' in Function.prototype === false ) { + removeEventListener( type, listener ) { + + if ( this._listeners === undefined ) return; + + const listeners = this._listeners; + const listenerArray = listeners[ type ]; + + if ( listenerArray !== undefined ) { - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + const index = listenerArray.indexOf( listener ); - Object.defineProperty( Function.prototype, 'name', { + if ( index !== - 1 ) { - get: function () { + listenerArray.splice( index, 1 ); - return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ]; + } } - } ); + } -} + dispatchEvent( event ) { -if ( Object.assign === undefined ) { + if ( this._listeners === undefined ) return; - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign + const listeners = this._listeners; + const listenerArray = listeners[ event.type ]; - ( function () { + if ( listenerArray !== undefined ) { - Object.assign = function ( target ) { - var arguments$1 = arguments; + event.target = this; + // Make a copy, in case listeners are removed while iterating. + const array = listenerArray.slice( 0 ); - if ( target === undefined || target === null ) { + for ( let i = 0, l = array.length; i < l; i ++ ) { - throw new TypeError( 'Cannot convert undefined or null to object' ); + array[ i ].call( this, event ); } - var output = Object( target ); + event.target = null; - for ( var index = 1; index < arguments.length; index ++ ) { + } - var source = arguments$1[ index ]; + } - if ( source !== undefined && source !== null ) { +} - for ( var nextKey in source ) { +const _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' ]; - if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) { +let _seed = 1234567; - output[ nextKey ] = source[ nextKey ]; - } +const DEG2RAD = Math.PI / 180; +const RAD2DEG = 180 / Math.PI; - } +// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 +function generateUUID() { - } + const d0 = Math.random() * 0xffffffff | 0; + const d1 = Math.random() * 0xffffffff | 0; + const d2 = Math.random() * 0xffffffff | 0; + const d3 = Math.random() * 0xffffffff | 0; + const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + + _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + + _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + + _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; - } + // .toLowerCase() here flattens concatenated strings to save heap memory space. + return uuid.toLowerCase(); - return output; +} - }; +function clamp( value, min, max ) { - } )(); + return Math.max( min, Math.min( max, value ) ); } -/** - * https://github.com/mrdoob/eventdispatcher.js/ - */ +// compute euclidean modulo of m % n +// https://en.wikipedia.org/wiki/Modulo_operation +function euclideanModulo( n, m ) { -function EventDispatcher() {} + return ( ( n % m ) + m ) % m; -Object.assign( EventDispatcher.prototype, { +} - addEventListener: function ( type, listener ) { +// Linear mapping from range to range +function mapLinear( x, a1, a2, b1, b2 ) { - if ( this._listeners === undefined ) { this._listeners = {}; } + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); - var listeners = this._listeners; +} - if ( listeners[ type ] === undefined ) { +// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ +function inverseLerp( x, y, value ) { - listeners[ type ] = []; + if ( x !== y ) { - } + return ( value - x ) / ( y - x ); - if ( listeners[ type ].indexOf( listener ) === - 1 ) { + } else { - listeners[ type ].push( listener ); + return 0; - } + } - }, +} - hasEventListener: function ( type, listener ) { +// https://en.wikipedia.org/wiki/Linear_interpolation +function lerp( x, y, t ) { - if ( this._listeners === undefined ) { return false; } + return ( 1 - t ) * x + t * y; - var listeners = this._listeners; +} - return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; +// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ +function damp( x, y, lambda, dt ) { - }, + return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); - removeEventListener: function ( type, listener ) { +} - if ( this._listeners === undefined ) { return; } +// https://www.desmos.com/calculator/vcsjnyz7x4 +function pingpong( x, length = 1 ) { - var listeners = this._listeners; - var listenerArray = listeners[ type ]; + return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); - if ( listenerArray !== undefined ) { +} - var index = listenerArray.indexOf( listener ); +// http://en.wikipedia.org/wiki/Smoothstep +function smoothstep( x, min, max ) { - if ( index !== - 1 ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - listenerArray.splice( index, 1 ); + x = ( x - min ) / ( max - min ); - } + return x * x * ( 3 - 2 * x ); - } +} - }, +function smootherstep( x, min, max ) { - dispatchEvent: function ( event ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - if ( this._listeners === undefined ) { return; } + x = ( x - min ) / ( max - min ); - var listeners = this._listeners; - var listenerArray = listeners[ event.type ]; + return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); - if ( listenerArray !== undefined ) { +} - event.target = this; +// Random integer from interval +function randInt( low, high ) { - var array = listenerArray.slice( 0 ); + return low + Math.floor( Math.random() * ( high - low + 1 ) ); - for ( var i = 0, l = array.length; i < l; i ++ ) { +} - array[ i ].call( this, event ); +// Random float from interval +function randFloat( low, high ) { - } + return low + Math.random() * ( high - low ); - } +} - } +// Random float from <-range/2, range/2> interval +function randFloatSpread( range ) { -} ); - -var REVISION = '89'; -var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; -var CullFaceNone = 0; -var CullFaceBack = 1; -var CullFaceFront = 2; -var CullFaceFrontBack = 3; -var FrontFaceDirectionCW = 0; -var FrontFaceDirectionCCW = 1; -var BasicShadowMap = 0; -var PCFShadowMap = 1; -var PCFSoftShadowMap = 2; -var FrontSide = 0; -var BackSide = 1; -var DoubleSide = 2; -var FlatShading = 1; -var SmoothShading = 2; -var NoColors = 0; -var FaceColors = 1; -var VertexColors = 2; -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 Uncharted2ToneMapping = 3; -var CineonToneMapping = 4; -var UVMapping = 300; -var CubeReflectionMapping = 301; -var CubeRefractionMapping = 302; -var EquirectangularReflectionMapping = 303; -var EquirectangularRefractionMapping = 304; -var SphericalReflectionMapping = 305; -var CubeUVReflectionMapping = 306; -var CubeUVRefractionMapping = 307; -var RepeatWrapping = 1000; -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 UnsignedShort565Type = 1019; -var UnsignedInt248Type = 1020; -var AlphaFormat = 1021; -var RGBFormat = 1022; -var RGBAFormat = 1023; -var LuminanceFormat = 1024; -var LuminanceAlphaFormat = 1025; -var RGBEFormat = RGBAFormat; -var DepthFormat = 1026; -var DepthStencilFormat = 1027; -var RGB_S3TC_DXT1_Format = 2001; -var RGBA_S3TC_DXT1_Format = 2002; -var RGBA_S3TC_DXT3_Format = 2003; -var RGBA_S3TC_DXT5_Format = 2004; -var RGB_PVRTC_4BPPV1_Format = 2100; -var RGB_PVRTC_2BPPV1_Format = 2101; -var RGBA_PVRTC_4BPPV1_Format = 2102; -var RGBA_PVRTC_2BPPV1_Format = 2103; -var RGB_ETC1_Format = 2151; -var LoopOnce = 2200; -var LoopRepeat = 2201; -var LoopPingPong = 2202; -var InterpolateDiscrete = 2300; -var InterpolateLinear = 2301; -var InterpolateSmooth = 2302; -var ZeroCurvatureEnding = 2400; -var ZeroSlopeEnding = 2401; -var WrapAroundEnding = 2402; -var TrianglesDrawMode = 0; -var TriangleStripDrawMode = 1; -var TriangleFanDrawMode = 2; -var LinearEncoding = 3000; -var sRGBEncoding = 3001; -var GammaEncoding = 3007; -var RGBEEncoding = 3002; -var LogLuvEncoding = 3003; -var RGBM7Encoding = 3004; -var RGBM16Encoding = 3005; -var RGBDEncoding = 3006; -var BasicDepthPacking = 3200; -var RGBADepthPacking = 3201; + return range * ( 0.5 - Math.random() ); -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ +} -var _Math = { +// Deterministic pseudo-random float in the interval [ 0, 1 ] +function seededRandom( s ) { - DEG2RAD: Math.PI / 180, - RAD2DEG: 180 / Math.PI, + if ( s !== undefined ) _seed = s; - generateUUID: ( function () { + // Mulberry32 generator - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 + let t = _seed += 0x6D2B79F5; - var lut = []; + t = Math.imul( t ^ t >>> 15, t | 1 ); - for ( var i = 0; i < 256; i ++ ) { + t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); - lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 ).toUpperCase(); + return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; - } +} - return function () { +function degToRad( degrees ) { - var d0 = Math.random() * 0xffffffff | 0; - var d1 = Math.random() * 0xffffffff | 0; - var d2 = Math.random() * 0xffffffff | 0; - var d3 = Math.random() * 0xffffffff | 0; - return lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' + - lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' + - lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] + - lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ]; + return degrees * DEG2RAD; - }; +} - } )(), +function radToDeg( radians ) { - clamp: function ( value, min, max ) { + return radians * RAD2DEG; - return Math.max( min, Math.min( max, value ) ); +} - }, +function isPowerOfTwo( value ) { - // compute euclidian modulo of m % n - // https://en.wikipedia.org/wiki/Modulo_operation + return ( value & ( value - 1 ) ) === 0 && value !== 0; - euclideanModulo: function ( n, m ) { +} - return ( ( n % m ) + m ) % m; +function ceilPowerOfTwo( value ) { - }, + return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); - // Linear mapping from range to range +} - mapLinear: function ( x, a1, a2, b1, b2 ) { +function floorPowerOfTwo( value ) { - return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); + return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); - }, +} - // https://en.wikipedia.org/wiki/Linear_interpolation +function setQuaternionFromProperEuler( q, a, b, c, order ) { - lerp: function ( x, y, t ) { + // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles - return ( 1 - t ) * x + t * y; + // rotations are applied to the axes in the order specified by 'order' + // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' + // angles are in radians - }, + const cos = Math.cos; + const sin = Math.sin; - // http://en.wikipedia.org/wiki/Smoothstep + const c2 = cos( b / 2 ); + const s2 = sin( b / 2 ); - smoothstep: function ( x, min, max ) { + const c13 = cos( ( a + c ) / 2 ); + const s13 = sin( ( a + c ) / 2 ); - if ( x <= min ) { return 0; } - if ( x >= max ) { return 1; } + const c1_3 = cos( ( a - c ) / 2 ); + const s1_3 = sin( ( a - c ) / 2 ); - x = ( x - min ) / ( max - min ); + const c3_1 = cos( ( c - a ) / 2 ); + const s3_1 = sin( ( c - a ) / 2 ); - return x * x * ( 3 - 2 * x ); + switch ( order ) { - }, + case 'XYX': + q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); + break; - smootherstep: function ( x, min, max ) { + case 'YZY': + q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); + break; - if ( x <= min ) { return 0; } - if ( x >= max ) { return 1; } + case 'ZXZ': + q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); + break; - x = ( x - min ) / ( max - min ); + case 'XZX': + q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); + break; - return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); + case 'YXY': + q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); + break; - }, + case 'ZYZ': + q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); + break; - // Random integer from interval + default: + console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); - randInt: function ( low, high ) { + } - return low + Math.floor( Math.random() * ( high - low + 1 ) ); +} - }, +function denormalize( value, array ) { - // Random float from interval + switch ( array.constructor ) { - randFloat: function ( low, high ) { + case Float32Array: - return low + Math.random() * ( high - low ); + return value; - }, + case Uint32Array: - // Random float from <-range/2, range/2> interval + return value / 4294967295.0; - randFloatSpread: function ( range ) { + case Uint16Array: - return range * ( 0.5 - Math.random() ); + return value / 65535.0; - }, + case Uint8Array: - degToRad: function ( degrees ) { + return value / 255.0; - return degrees * _Math.DEG2RAD; + case Int32Array: - }, + return Math.max( value / 2147483647.0, - 1.0 ); - radToDeg: function ( radians ) { + case Int16Array: - return radians * _Math.RAD2DEG; + return Math.max( value / 32767.0, - 1.0 ); - }, + case Int8Array: - isPowerOfTwo: function ( value ) { + return Math.max( value / 127.0, - 1.0 ); - return ( value & ( value - 1 ) ) === 0 && value !== 0; + default: - }, + throw new Error( 'Invalid component type.' ); - ceilPowerOfTwo: function ( value ) { + } - return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); +} - }, +function normalize( value, array ) { - floorPowerOfTwo: function ( value ) { + switch ( array.constructor ) { - return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); + case Float32Array: - } + return value; -}; + case Uint32Array: -/** - * @author mrdoob / http://mrdoob.com/ - * @author philogb / http://blog.thejit.org/ - * @author egraether / http://egraether.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - */ + return Math.round( value * 4294967295.0 ); -function Vector2( x, y ) { + case Uint16Array: - this.x = x || 0; - this.y = y || 0; + return Math.round( value * 65535.0 ); -} + case Uint8Array: -Object.defineProperties( Vector2.prototype, { + return Math.round( value * 255.0 ); - "width": { + case Int32Array: - get: function () { + return Math.round( value * 2147483647.0 ); - return this.x; + case Int16Array: - }, + return Math.round( value * 32767.0 ); - set: function ( value ) { + case Int8Array: - this.x = value; + return Math.round( value * 127.0 ); - } + default: - }, + throw new Error( 'Invalid component type.' ); + + } + +} + +const MathUtils = { + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler, + normalize: normalize, + denormalize: denormalize +}; - "height": { +class Vector2 { - get: function () { + constructor( x = 0, y = 0 ) { - return this.y; + Vector2.prototype.isVector2 = true; - }, + this.x = x; + this.y = y; - set: function ( value ) { + } - this.y = value; + get width() { - } + return this.x; + + } + + set width( value ) { + + this.x = value; + + } + + get height() { + + return this.y; } -} ); + set height( value ) { -Object.assign( Vector2.prototype, { + this.y = value; - isVector2: true, + } - set: function ( x, y ) { + set( x, y ) { this.x = x; this.y = y; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { @@ -581,9 +704,9 @@ Object.assign( Vector2.prototype, { return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { @@ -593,164 +716,150 @@ Object.assign( Vector2.prototype, { } - }, + } - clone: function () { + clone() { return new this.constructor( this.x, this.y ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; return this; - }, + } - addScaledVector: function ( v, s ) { + addScaledVector( v, s ) { this.x += v.x * s; this.y += v.y * s; return this; - }, - - sub: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; return this; - }, + } - multiply: function ( v ) { + multiply( v ) { this.x *= v.x; this.y *= v.y; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; return this; - }, + } - divide: function ( v ) { + divide( v ) { this.x /= v.x; this.y /= v.y; return this; - }, + } - divideScalar: function ( scalar ) { + divideScalar( scalar ) { return this.multiplyScalar( 1 / scalar ); - }, + } - applyMatrix3: function ( m ) { + applyMatrix3( m ) { - var x = this.x, y = this.y; - var e = m.elements; + const x = this.x, y = this.y; + const e = m.elements; this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; return this; - }, + } - min: function ( v ) { + min( v ) { this.x = Math.min( this.x, v.x ); this.y = Math.min( this.y, v.y ); return this; - }, + } - max: function ( v ) { + max( v ) { this.x = Math.max( this.x, v.x ); this.y = Math.max( this.y, v.y ); return this; - }, + } - clamp: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise @@ -759,209 +868,212 @@ Object.assign( Vector2.prototype, { return this; - }, - - clampScalar: function () { - - var min = new Vector2(); - var max = new Vector2(); - - return function clampScalar( minVal, maxVal ) { + } - min.set( minVal, minVal ); - max.set( maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - }; + return this; - }(), + } - clampLength: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + floor() { this.x = Math.floor( this.x ); this.y = Math.floor( this.y ); return this; - }, + } - ceil: function () { + ceil() { this.x = Math.ceil( this.x ); this.y = Math.ceil( this.y ); return this; - }, + } - round: function () { + round() { this.x = Math.round( this.x ); this.y = Math.round( this.y ); return this; - }, + } - roundToZero: function () { + 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.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; return this; - }, + } - dot: function ( v ) { + dot( v ) { return this.x * v.x + this.y * v.y; - }, + } + + cross( v ) { + + return this.x * v.y - this.y * v.x; + + } - lengthSq: function () { + lengthSq() { return this.x * this.x + this.y * this.y; - }, + } - length: function () { + length() { return Math.sqrt( this.x * this.x + this.y * this.y ); - }, + } - manhattanLength: function () { + manhattanLength() { return Math.abs( this.x ) + Math.abs( this.y ); - }, + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - angle: function () { + angle() { // computes the angle in radians with respect to the positive x-axis - var angle = Math.atan2( this.y, this.x ); - - if ( angle < 0 ) { angle += 2 * Math.PI; } + const angle = Math.atan2( - this.y, - this.x ) + Math.PI; return angle; - }, + } + + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; - distanceTo: function ( v ) { + // clamp, to handle numerical problems + + return Math.acos( clamp( theta, - 1, 1 ) ); + + } + + distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); - }, + } - distanceToSquared: function ( v ) { + distanceToSquared( v ) { - var dx = this.x - v.x, dy = this.y - v.y; + const dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; - }, + } - manhattanDistanceTo: function ( v ) { + manhattanDistanceTo( v ) { return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + lerp( v, alpha ) { this.x += ( v.x - this.x ) * alpha; this.y += ( v.y - this.y ) * alpha; return this; - }, + } - lerpVectors: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; - }, + return this; - equals: function ( v ) { + } - return ( ( v.x === this.x ) && ( v.y === this.y ) ); + equals( v ) { - }, + return ( ( v.x === this.x ) && ( v.y === this.y ) ); - fromArray: function ( array, offset ) { + } - if ( offset === undefined ) { offset = 0; } + fromArray( array, offset = 0 ) { this.x = array[ offset ]; this.y = array[ offset + 1 ]; return this; - }, + } - toArray: function ( array, offset ) { - - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + toArray( array = [], offset = 0 ) { array[ offset ] = this.x; array[ offset + 1 ] = this.y; return array; - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' ); + } - } + fromBufferAttribute( attribute, index ) { this.x = attribute.getX( index ); this.y = attribute.getY( index ); return this; - }, + } - rotateAround: function ( center, angle ) { + rotateAround( center, angle ) { - var c = Math.cos( angle ), s = Math.sin( angle ); + const c = Math.cos( angle ), s = Math.sin( angle ); - var x = this.x - center.x; - var y = this.y - center.y; + const x = this.x - center.x; + const y = this.y - center.y; this.x = x * c - y * s + center.x; this.y = x * s + y * c + center.y; @@ -970,21197 +1082,10283 @@ Object.assign( Vector2.prototype, { } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author jordi_ros / http://plattsoft.com - * @author D1plo1d / http://github.com/D1plo1d - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author timknip / http://www.floorplanner.com/ - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - */ - -function Matrix4() { + random() { - this.elements = [ + this.x = Math.random(); + this.y = Math.random(); - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + return this; - ]; + } - if ( arguments.length > 0 ) { + *[ Symbol.iterator ]() { - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + yield this.x; + yield this.y; } } -Object.assign( Matrix4.prototype, { +class Matrix3 { - isMatrix4: true, + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + Matrix3.prototype.isMatrix3 = true; - var te = this.elements; + 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; + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 - return this; + ]; - }, + if ( n11 !== undefined ) { - identity: function () { + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); - this.set( + } - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + } - ); + set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - return this; + 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; - clone: function () { + return this; - return new Matrix4().fromArray( this.elements ); + } - }, + identity() { - copy: function ( m ) { + this.set( - var te = this.elements; - var me = m.elements; + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 - 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: function ( m ) { + copy( m ) { - var te = this.elements, me = m.elements; + const te = this.elements; + const me = m.elements; - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; + 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: function ( xAxis, yAxis, zAxis ) { + extractBasis( xAxis, yAxis, zAxis ) { - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); + xAxis.setFromMatrix3Column( this, 0 ); + yAxis.setFromMatrix3Column( this, 1 ); + zAxis.setFromMatrix3Column( this, 2 ); return this; - }, + } + + setFromMatrix4( m ) { - makeBasis: function ( xAxis, yAxis, zAxis ) { + const me = m.elements; 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; + me[ 0 ], me[ 4 ], me[ 8 ], + me[ 1 ], me[ 5 ], me[ 9 ], + me[ 2 ], me[ 6 ], me[ 10 ] - }, + ); - extractRotation: function () { + return this; - var v1 = new Vector3(); + } - return function extractRotation( m ) { + multiply( m ) { - var te = this.elements; - var me = m.elements; + return this.multiplyMatrices( this, m ); - var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); - var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); - var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); + } - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; + premultiply( m ) { - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; + return this.multiplyMatrices( m, this ); - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; + } - return this; + multiplyMatrices( a, b ) { - }; + const ae = a.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 ]; - makeRotationFromEuler: function ( euler ) { + 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 ]; - if ( ! ( euler && euler.isEuler ) ) { + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; + te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; + te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + 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; - var te = this.elements; + return this; - var x = euler.x, y = euler.y, z = euler.z; - var a = Math.cos( x ), b = Math.sin( x ); - var c = Math.cos( y ), d = Math.sin( y ); - var e = Math.cos( z ), f = Math.sin( z ); + } - if ( euler.order === 'XYZ' ) { + multiplyScalar( s ) { - var ae = a * e, af = a * f, be = b * e, bf = b * f; + const te = this.elements; - te[ 0 ] = c * e; - te[ 4 ] = - c * f; - te[ 8 ] = d; + 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; - te[ 1 ] = af + be * d; - te[ 5 ] = ae - bf * d; - te[ 9 ] = - b * c; + return this; - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'YXZ' ) { + determinant() { - var ce = c * e, cf = c * f, de = d * e, df = d * f; + const te = this.elements; - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; + const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], + d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], + g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'ZXY' ) { + invert() { - var ce = c * e, cf = c * f, de = d * e, df = d * f; + const te = this.elements, - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; + 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 ], - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; + t11 = n33 * n22 - n32 * n23, + t12 = n32 * n13 - n33 * n12, + t13 = n23 * n12 - n22 * n13, - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; + det = n11 * t11 + n21 * t12 + n31 * t13; - } else if ( euler.order === 'ZYX' ) { + if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var ae = a * e, af = a * f, be = b * e, bf = b * f; + const detInv = 1 / det; - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; + te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; + te[ 3 ] = t12 * detInv; + te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; + te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; + te[ 6 ] = t13 * detInv; + te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; + te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; - } else if ( euler.order === 'YZX' ) { + return this; - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + } - te[ 0 ] = c * e; - te[ 4 ] = bd - ac * f; - te[ 8 ] = bc * f + ad; + transpose() { - te[ 1 ] = f; - te[ 5 ] = a * e; - te[ 9 ] = - b * e; + let tmp; + const m = this.elements; - te[ 2 ] = - d * e; - te[ 6 ] = ad * f + bc; - te[ 10 ] = ac - bd * f; + tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; + tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; + tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; - } else if ( euler.order === 'XZY' ) { + return this; - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + } - te[ 0 ] = c * e; - te[ 4 ] = - f; - te[ 8 ] = d * e; + getNormalMatrix( matrix4 ) { - te[ 1 ] = ac * f + bd; - te[ 5 ] = a * e; - te[ 9 ] = ad * f - bc; + return this.setFromMatrix4( matrix4 ).invert().transpose(); - te[ 2 ] = bc * f - ad; - te[ 6 ] = b * e; - te[ 10 ] = bd * f + ac; + } - } + transposeIntoArray( r ) { - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + const m = this.elements; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + r[ 0 ] = m[ 0 ]; + r[ 1 ] = m[ 3 ]; + r[ 2 ] = m[ 6 ]; + r[ 3 ] = m[ 1 ]; + r[ 4 ] = m[ 4 ]; + r[ 5 ] = m[ 7 ]; + r[ 6 ] = m[ 2 ]; + r[ 7 ] = m[ 5 ]; + r[ 8 ] = m[ 8 ]; return this; - }, + } - makeRotationFromQuaternion: function ( q ) { + setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { - var te = this.elements; + const c = Math.cos( rotation ); + const s = Math.sin( rotation ); - var x = q._x, y = q._y, z = q._z, w = q._w; - var x2 = x + x, y2 = y + y, z2 = z + z; - var xx = x * x2, xy = x * y2, xz = x * z2; - var yy = y * y2, yz = y * z2, zz = z * z2; - var wx = w * x2, wy = w * y2, wz = w * z2; + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 1 + ); - te[ 0 ] = 1 - ( yy + zz ); - te[ 4 ] = xy - wz; - te[ 8 ] = xz + wy; + return this; - te[ 1 ] = xy + wz; - te[ 5 ] = 1 - ( xx + zz ); - te[ 9 ] = yz - wx; + } - te[ 2 ] = xz - wy; - te[ 6 ] = yz + wx; - te[ 10 ] = 1 - ( xx + yy ); + // - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + scale( sx, sy ) { - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + this.premultiply( _m3.makeScale( sx, sy ) ); return this; - }, + } - lookAt: function () { + rotate( theta ) { - var x = new Vector3(); - var y = new Vector3(); - var z = new Vector3(); + this.premultiply( _m3.makeRotation( - theta ) ); - return function lookAt( eye, target, up ) { + return this; - var te = this.elements; + } - z.subVectors( eye, target ); + translate( tx, ty ) { - if ( z.lengthSq() === 0 ) { + this.premultiply( _m3.makeTranslation( tx, ty ) ); - // eye and target are in the same position + return this; - z.z = 1; + } - } + // for 2D Transforms - z.normalize(); - x.crossVectors( up, z ); + makeTranslation( x, y ) { - if ( x.lengthSq() === 0 ) { + if ( x.isVector2 ) { - // up and z are parallel + this.set( - if ( Math.abs( up.z ) === 1 ) { + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 - z.x += 0.0001; + ); - } else { + } else { - z.z += 0.0001; + this.set( - } + 1, 0, x, + 0, 1, y, + 0, 0, 1 - z.normalize(); - x.crossVectors( up, z ); + ); - } + } - x.normalize(); - y.crossVectors( z, x ); + return this; - 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; + makeRotation( theta ) { - }; + // counterclockwise - }(), + const c = Math.cos( theta ); + const s = Math.sin( theta ); - multiply: function ( m, n ) { + this.set( - if ( n !== undefined ) { + c, - s, 0, + s, c, 0, + 0, 0, 1 - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); - return this.multiplyMatrices( m, n ); + ); - } + return this; - return this.multiplyMatrices( this, m ); + } - }, + makeScale( x, y ) { - premultiply: function ( m ) { + this.set( - return this.multiplyMatrices( m, this ); + x, 0, 0, + 0, y, 0, + 0, 0, 1 - }, + ); - multiplyMatrices: function ( a, b ) { + return this; - var ae = a.elements; - var be = b.elements; - var te = this.elements; + } - var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; - var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; - var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; - var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; + // - var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; - var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; - var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; - var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; + equals( matrix ) { - 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; + const te = this.elements; + const me = matrix.elements; - 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; + for ( let i = 0; i < 9; i ++ ) { - 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; + if ( te[ i ] !== me[ i ] ) return false; - 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; + return true; - }, + } - multiplyScalar: function ( s ) { + fromArray( array, offset = 0 ) { - var te = this.elements; + for ( let i = 0; i < 9; i ++ ) { - 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; + this.elements[ i ] = array[ i + offset ]; + + } return this; - }, + } - applyToBufferAttribute: function () { + toArray( array = [], offset = 0 ) { - var v1 = new Vector3(); + const te = this.elements; - return function applyToBufferAttribute( attribute ) { + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + array[ offset + 3 ] = te[ 3 ]; + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; + array[ offset + 8 ] = te[ 8 ]; - v1.applyMatrix4( this ); + return array; - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + } - } + clone() { - return attribute; + return new this.constructor().fromArray( this.elements ); - }; + } - }(), +} - determinant: function () { +const _m3 = /*@__PURE__*/ new Matrix3(); - var te = this.elements; +function arrayNeedsUint32( array ) { - var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; - var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; - var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; - var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; + // assumes larger values usually on last - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + for ( let i = array.length - 1; i >= 0; -- i ) { - 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 - ) + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 - ); + } - }, + return false; - transpose: function () { +} - var te = this.elements; - var tmp; +function createElementNS( name ) { - 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; + return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); - 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; +function createCanvasElement() { - }, + const canvas = createElementNS( 'canvas' ); + canvas.style.display = 'block'; + return canvas; - setPosition: function ( v ) { +} - var te = this.elements; +const _cache = {}; - te[ 12 ] = v.x; - te[ 13 ] = v.y; - te[ 14 ] = v.z; +function warnOnce( message ) { - return this; + if ( message in _cache ) return; - }, + _cache[ message ] = true; - getInverse: function ( m, throwOnDegenerate ) { + console.warn( message ); - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - var te = this.elements, - me = m.elements, +} - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ], - n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ], - n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ], - n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ], +function probeAsync( gl, sync, interval ) { - 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; + return new Promise( function ( resolve, reject ) { - var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + function probe() { - if ( det === 0 ) { + switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) { - var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; + case gl.WAIT_FAILED: + reject(); + break; - if ( throwOnDegenerate === true ) { + case gl.TIMEOUT_EXPIRED: + setTimeout( probe, interval ); + break; - throw new Error( msg ); + default: + resolve(); - } else { + } - console.warn( msg ); + } - } + setTimeout( probe, interval ); - return this.identity(); + } ); - } +} - var detInv = 1 / det; +/** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + +const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( + 0.8224621, 0.177538, 0.0, + 0.0331941, 0.9668058, 0.0, + 0.0170827, 0.0723974, 0.9105199, +); + +const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( + 1.2249401, - 0.2249404, 0.0, + - 0.0420569, 1.0420571, 0.0, + - 0.0196376, - 0.0786361, 1.0982735 +); + +/** + * Defines supported color spaces by transfer function and primaries, + * and provides conversions to/from the Linear-sRGB reference space. + */ +const COLOR_SPACES = { + [ LinearSRGBColorSpace ]: { + transfer: LinearTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color, + fromReference: ( color ) => color, + }, + [ SRGBColorSpace ]: { + transfer: SRGBTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color.convertSRGBToLinear(), + fromReference: ( color ) => color.convertLinearToSRGB(), + }, + [ LinearDisplayP3ColorSpace ]: { + transfer: LinearTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), + }, + [ DisplayP3ColorSpace ]: { + transfer: SRGBTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), + }, +}; - 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; +const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); - 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; +const ColorManagement = { - 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; + enabled: true, - 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; + _workingColorSpace: LinearSRGBColorSpace, - return this; + get workingColorSpace() { + + return this._workingColorSpace; }, - scale: function ( v ) { + set workingColorSpace( colorSpace ) { - var te = this.elements; - var x = v.x, y = v.y, z = v.z; + if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { - te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; - te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; - te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; - te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; + throw new Error( `Unsupported working color space, "${ colorSpace }".` ); - return this; + } + + this._workingColorSpace = colorSpace; }, - getMaxScaleOnAxis: function () { + convert: function ( color, sourceColorSpace, targetColorSpace ) { - var te = this.elements; + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { - var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; - var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; - var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; + return color; - return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); + } + + const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; + const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; + + return targetFromReference( sourceToReference( color ) ); }, - makeTranslation: function ( x, y, z ) { + fromWorkingColorSpace: function ( color, targetColorSpace ) { - this.set( + return this.convert( color, this._workingColorSpace, targetColorSpace ); - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + }, - ); + toWorkingColorSpace: function ( color, sourceColorSpace ) { - return this; + return this.convert( color, sourceColorSpace, this._workingColorSpace ); }, - makeRotationX: function ( theta ) { + getPrimaries: function ( colorSpace ) { - var c = Math.cos( theta ), s = Math.sin( theta ); + return COLOR_SPACES[ colorSpace ].primaries; - this.set( + }, - 1, 0, 0, 0, - 0, c, - s, 0, - 0, s, c, 0, - 0, 0, 0, 1 + getTransfer: function ( colorSpace ) { - ); + if ( colorSpace === NoColorSpace ) return LinearTransfer; - return this; + return COLOR_SPACES[ colorSpace ].transfer; }, - makeRotationY: function ( theta ) { + getLuminanceCoefficients: function ( target, colorSpace = this._workingColorSpace ) { - var c = Math.cos( theta ), s = Math.sin( theta ); + return target.fromArray( COLOR_SPACES[ colorSpace ].luminanceCoefficients ); - this.set( + }, - c, 0, s, 0, - 0, 1, 0, 0, - - s, 0, c, 0, - 0, 0, 0, 1 +}; - ); - return this; +function SRGBToLinear( c ) { - }, + return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); - makeRotationZ: function ( theta ) { +} - var c = Math.cos( theta ), s = Math.sin( theta ); +function LinearToSRGB( c ) { - this.set( + return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; - c, - s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 +} - ); +let _canvas; - return this; +class ImageUtils { - }, + static getDataURL( image ) { - makeRotationAxis: function ( axis, angle ) { + if ( /^data:/i.test( image.src ) ) { - // Based on http://www.gamedev.net/reference/articles/article1199.asp + return image.src; - var c = Math.cos( angle ); - var s = Math.sin( angle ); - var t = 1 - c; - var x = axis.x, y = axis.y, z = axis.z; - var tx = t * x, ty = t * y; + } - this.set( + if ( typeof HTMLCanvasElement === 'undefined' ) { - tx * x + c, tx * y - s * z, tx * z + s * y, 0, - tx * y + s * z, ty * y + c, ty * z - s * x, 0, - tx * z - s * y, ty * z + s * x, t * z * z + c, 0, - 0, 0, 0, 1 + return image.src; - ); + } - return this; + let canvas; - }, + if ( image instanceof HTMLCanvasElement ) { - makeScale: function ( x, y, z ) { + canvas = image; - this.set( + } else { - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - ); + _canvas.width = image.width; + _canvas.height = image.height; - return this; + const context = _canvas.getContext( '2d' ); - }, + if ( image instanceof ImageData ) { - makeShear: function ( x, y, z ) { + context.putImageData( image, 0, 0 ); - this.set( + } else { - 1, y, z, 0, - x, 1, z, 0, - x, y, 1, 0, - 0, 0, 0, 1 + context.drawImage( image, 0, 0, image.width, image.height ); - ); + } - return this; + canvas = _canvas; - }, + } - compose: function ( position, quaternion, scale ) { + if ( canvas.width > 2048 || canvas.height > 2048 ) { - this.makeRotationFromQuaternion( quaternion ); - this.scale( scale ); - this.setPosition( position ); + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - return this; + return canvas.toDataURL( 'image/jpeg', 0.6 ); - }, + } else { - decompose: function () { + return canvas.toDataURL( 'image/png' ); - var vector = new Vector3(); - var matrix = new Matrix4(); + } - return function decompose( position, quaternion, scale ) { + } - var te = this.elements; + static sRGBToLinear( image ) { - var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); - var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); - var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - // if determine is negative, we need to invert one scale - var det = this.determinant(); - if ( det < 0 ) { sx = - sx; } + const canvas = createElementNS( 'canvas' ); - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; + canvas.width = image.width; + canvas.height = image.height; - // scale the rotation part - matrix.copy( this ); + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - matrix.elements[ 0 ] *= invSX; - matrix.elements[ 1 ] *= invSX; - matrix.elements[ 2 ] *= invSX; + for ( let i = 0; i < data.length; i ++ ) { - matrix.elements[ 4 ] *= invSY; - matrix.elements[ 5 ] *= invSY; - matrix.elements[ 6 ] *= invSY; + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - matrix.elements[ 8 ] *= invSZ; - matrix.elements[ 9 ] *= invSZ; - matrix.elements[ 10 ] *= invSZ; + } - quaternion.setFromRotationMatrix( matrix ); + context.putImageData( imageData, 0, 0 ); - scale.x = sx; - scale.y = sy; - scale.z = sz; + return canvas; - return this; + } else if ( image.data ) { - }; + const data = image.data.slice( 0 ); - }(), + for ( let i = 0; i < data.length; i ++ ) { - makePerspective: function ( left, right, top, bottom, near, far ) { + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - if ( far === undefined ) { + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); + } else { - } + // assuming float - var te = this.elements; - var x = 2 * near / ( right - left ); - var y = 2 * near / ( top - bottom ); + data[ i ] = SRGBToLinear( data[ i ] ); - var a = ( right + left ) / ( right - left ); - var b = ( top + bottom ) / ( top - bottom ); - var c = - ( far + near ) / ( far - near ); - var d = - 2 * far * near / ( far - near ); + } - te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; - te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; - te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; - te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; + } - return this; + return { + data: data, + width: image.width, + height: image.height + }; - }, + } else { - makeOrthographic: function ( left, right, top, bottom, near, far ) { + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; + + } - var te = this.elements; - var w = 1.0 / ( right - left ); - var h = 1.0 / ( top - bottom ); - var p = 1.0 / ( far - near ); + } - var x = ( right + left ) * w; - var y = ( top + bottom ) * h; - var z = ( far + near ) * p; +} - te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; - te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; - 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; +let _sourceId = 0; - return this; +class Source { - }, + constructor( data = null ) { - equals: function ( matrix ) { + this.isSource = true; - var te = this.elements; - var me = matrix.elements; + Object.defineProperty( this, 'id', { value: _sourceId ++ } ); - for ( var i = 0; i < 16; i ++ ) { + this.uuid = generateUUID(); - if ( te[ i ] !== me[ i ] ) { return false; } + this.data = data; + this.dataReady = true; - } + this.version = 0; - return true; + } - }, + set needsUpdate( value ) { - fromArray: function ( array, offset ) { + if ( value === true ) this.version ++; - if ( offset === undefined ) { offset = 0; } + } - for ( var i = 0; i < 16; i ++ ) { + toJSON( meta ) { - this.elements[ i ] = array[ i + offset ]; + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { + + return meta.images[ this.uuid ]; } - return this; + const output = { + uuid: this.uuid, + url: '' + }; - }, + const data = this.data; - toArray: function ( array, offset ) { + if ( data !== null ) { - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + let url; - var te = this.elements; + if ( Array.isArray( data ) ) { - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - array[ offset + 3 ] = te[ 3 ]; + // cube texture - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; + url = []; - array[ offset + 8 ] = te[ 8 ]; - array[ offset + 9 ] = te[ 9 ]; - array[ offset + 10 ] = te[ 10 ]; - array[ offset + 11 ] = te[ 11 ]; - - array[ offset + 12 ] = te[ 12 ]; - array[ offset + 13 ] = te[ 13 ]; - array[ offset + 14 ] = te[ 14 ]; - array[ offset + 15 ] = te[ 15 ]; - - return array; + for ( let i = 0, l = data.length; i < l; i ++ ) { - } + if ( data[ i ].isDataTexture ) { -} ); + url.push( serializeImage( data[ i ].image ) ); -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - */ + } else { -function Quaternion( x, y, z, w ) { + url.push( serializeImage( data[ i ] ) ); - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._w = ( w !== undefined ) ? w : 1; + } -} + } -Object.assign( Quaternion, { + } else { - slerp: function ( qa, qb, qm, t ) { + // texture - return qm.copy( qa ).slerp( qb, t ); + url = serializeImage( data ); - }, + } - slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + output.url = url; - // fuzz-free, array-based Quaternion SLERP operation + } - var x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ], + if ( ! isRootObject ) { - x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + meta.images[ this.uuid ] = output; - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + } - var s = 1 - t, + return output; - cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + } - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; +} - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { +function serializeImage( image ) { - var sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + // default images - } + return ImageUtils.getDataURL( image ); - var tDir = t * dir; + } else { - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + if ( image.data ) { - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + // images of DataTexture - var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + return { + data: Array.from( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + } else { - } + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; } - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - } -} ); +} -Object.defineProperties( Quaternion.prototype, { +let _textureId = 0; - x: { +class Texture extends EventDispatcher { - get: function () { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { - return this._x; + super(); - }, + this.isTexture = true; - set: function ( value ) { + Object.defineProperty( this, 'id', { value: _textureId ++ } ); - this._x = value; - this.onChangeCallback(); + this.uuid = generateUUID(); - } + this.name = ''; - }, + this.source = new Source( image ); + this.mipmaps = []; - y: { + this.mapping = mapping; + this.channel = 0; - get: function () { + this.wrapS = wrapS; + this.wrapT = wrapT; - return this._y; + this.magFilter = magFilter; + this.minFilter = minFilter; - }, + this.anisotropy = anisotropy; - set: function ( value ) { + this.format = format; + this.internalFormat = null; + this.type = type; - this._y = value; - this.onChangeCallback(); + 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; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - z: { + this.colorSpace = colorSpace; - get: function () { + this.userData = {}; - return this._z; + this.version = 0; + this.onUpdate = null; - }, + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) - set: function ( value ) { + } - this._z = value; - this.onChangeCallback(); + get image() { - } + return this.source.data; - }, + } - w: { + set image( value = null ) { - get: function () { + this.source.data = value; - return this._w; + } - }, + updateMatrix() { - set: function ( value ) { + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); - this._w = value; - this.onChangeCallback(); + } - } + clone() { + + return new this.constructor().copy( this ); } -} ); + copy( source ) { -Object.assign( Quaternion.prototype, { + this.name = source.name; - set: function ( x, y, z, w ) { + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); - this._x = x; - this._y = y; - this._z = z; - this._w = w; + this.mapping = source.mapping; + this.channel = source.channel; - this.onChangeCallback(); + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - return this; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - }, + this.anisotropy = source.anisotropy; - clone: function () { + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return new this.constructor( this._x, this._y, this._z, this._w ); + 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 ); - copy: function ( quaternion ) { + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - this.onChangeCallback(); + this.needsUpdate = true; return this; - }, - - setFromEuler: function ( euler, update ) { + } - if ( ! ( euler && euler.isEuler ) ) { + toJSON( meta ) { - throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - } + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - var x = euler._x, y = euler._y, z = euler._z, order = euler.order; + return meta.textures[ this.uuid ]; - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m + } - var cos = Math.cos; - var sin = Math.sin; + const output = { - var c1 = cos( x / 2 ); - var c2 = cos( y / 2 ); - var c3 = cos( z / 2 ); + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, - var s1 = sin( x / 2 ); - var s2 = sin( y / 2 ); - var s3 = sin( z / 2 ); + uuid: this.uuid, + name: this.name, - if ( order === 'XYZ' ) { + image: this.source.toJSON( meta ).uuid, - 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; + mapping: this.mapping, + channel: this.channel, - } else if ( order === 'YXZ' ) { + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - 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; + wrap: [ this.wrapS, this.wrapT ], - } else if ( order === 'ZXY' ) { + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, - 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; + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - } else if ( order === 'ZYX' ) { + flipY: this.flipY, - 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; + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - } else if ( order === '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; + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; - } else if ( order === 'XZY' ) { + if ( ! isRootObject ) { - 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; + meta.textures[ this.uuid ] = output; } - if ( update !== false ) { this.onChangeCallback(); } + return output; - return this; + } - }, + dispose() { - setFromAxisAngle: function ( axis, angle ) { + this.dispatchEvent( { type: 'dispose' } ); - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + } - // assumes axis is normalized + transformUv( uv ) { - var halfAngle = angle / 2, s = Math.sin( halfAngle ); + if ( this.mapping !== UVMapping ) return uv; - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + uv.applyMatrix3( this.matrix ); - this.onChangeCallback(); + if ( uv.x < 0 || uv.x > 1 ) { - return this; + switch ( this.wrapS ) { - }, + case RepeatWrapping: - setFromRotationMatrix: function ( m ) { + uv.x = uv.x - Math.floor( uv.x ); + break; - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + case ClampToEdgeWrapping: - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + uv.x = uv.x < 0 ? 0 : 1; + break; - var te = m.elements, + case MirroredRepeatWrapping: - 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( Math.floor( uv.x ) % 2 ) === 1 ) { - trace = m11 + m22 + m33, - s; + uv.x = Math.ceil( uv.x ) - uv.x; - if ( trace > 0 ) { + } else { - s = 0.5 / Math.sqrt( trace + 1.0 ); + uv.x = uv.x - Math.floor( uv.x ); - 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 ) { + break; - s = 2.0 * Math.sqrt( 1.0 + 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 ) { + if ( uv.y < 0 || uv.y > 1 ) { - s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + switch ( this.wrapT ) { - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + case RepeatWrapping: - } else { + uv.y = uv.y - Math.floor( uv.y ); + break; - s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + case ClampToEdgeWrapping: - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + uv.y = uv.y < 0 ? 0 : 1; + break; - } + case MirroredRepeatWrapping: - this.onChangeCallback(); + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - return this; + uv.y = Math.ceil( uv.y ) - uv.y; - }, + } else { - setFromUnitVectors: function () { + uv.y = uv.y - Math.floor( uv.y ); - // assumes direction vectors vFrom and vTo are normalized + } - var v1 = new Vector3(); - var r; + break; - var EPS = 0.000001; + } - return function setFromUnitVectors( vFrom, vTo ) { + } - if ( v1 === undefined ) { v1 = new Vector3(); } + if ( this.flipY ) { - r = vFrom.dot( vTo ) + 1; + uv.y = 1 - uv.y; - if ( r < EPS ) { + } - r = 0; + return uv; - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + } - v1.set( - vFrom.y, vFrom.x, 0 ); + set needsUpdate( value ) { - } else { + if ( value === true ) { - v1.set( 0, - vFrom.z, vFrom.y ); + this.version ++; + this.source.needsUpdate = true; - } + } - } else { + } - v1.crossVectors( vFrom, vTo ); + set needsPMREMUpdate( value ) { - } + if ( value === true ) { - this._x = v1.x; - this._y = v1.y; - this._z = v1.z; - this._w = r; + this.pmremVersion ++; - return this.normalize(); + } - }; + } - }(), +} - inverse: function () { +Texture.DEFAULT_IMAGE = null; +Texture.DEFAULT_MAPPING = UVMapping; +Texture.DEFAULT_ANISOTROPY = 1; - return this.conjugate().normalize(); +class Vector4 { - }, + constructor( x = 0, y = 0, z = 0, w = 1 ) { - conjugate: function () { + Vector4.prototype.isVector4 = true; - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; + this.x = x; + this.y = y; + this.z = z; + this.w = w; - this.onChangeCallback(); + } - return this; + get width() { - }, + return this.z; - dot: function ( v ) { + } - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + set width( value ) { - }, + this.z = value; - lengthSq: function () { + } - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + get height() { - }, + return this.w; - length: function () { + } - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); + set height( value ) { - }, + this.w = value; - normalize: function () { - - var 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: function ( q, p ) { - - if ( p !== undefined ) { - - console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); - return this.multiplyQuaternions( q, p ); - - } - - return this.multiplyQuaternions( this, q ); - - }, - - premultiply: function ( q ) { - - return this.multiplyQuaternions( q, this ); - - }, - - multiplyQuaternions: function ( a, b ) { - - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - - var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - var 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: function ( qb, t ) { - - if ( t === 0 ) { return this; } - if ( t === 1 ) { return this.copy( qb ); } - - var x = this._x, y = this._y, z = this._z, w = this._w; - - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - - var cosHalfTheta = w * qb._w + x * qb._x + y * 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.0 ) { - - this._w = w; - this._x = x; - this._y = y; - this._z = z; - - return this; - - } - - var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - - this._w = 0.5 * ( w + this._w ); - this._x = 0.5 * ( x + this._x ); - this._y = 0.5 * ( y + this._y ); - this._z = 0.5 * ( z + this._z ); - - return this; - - } - - var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); - - this.onChangeCallback(); - - return this; - - }, - - equals: function ( quaternion ) { - - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) { offset = 0; } - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this.onChangeCallback(); - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; - - return array; - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; - - }, - - onChangeCallback: function () {} - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ - -function Vector3( x, y, z ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - -} - -Object.assign( Vector3.prototype, { - - isVector3: true, + } - set: function ( x, y, z ) { + set( x, y, z, w ) { this.x = x; this.y = y; this.z = z; + this.w = w; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; this.z = scalar; + this.w = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setZ: function ( z ) { + setZ( z ) { this.z = z; return this; - }, + } + + setW( w ) { + + this.w = w; + + return this; + + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { 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: ' + index ); } return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { 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: ' + index ); } - }, + } - clone: function () { + clone() { - return new this.constructor( this.x, this.y, this.z ); + return new this.constructor( this.x, this.y, this.z, this.w ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; this.z += v.z; + this.w += v.w; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; this.z += s; + this.w += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; + this.w = a.w + b.w; return this; - }, + } - addScaledVector: function ( v, s ) { + 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: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; + this.w -= v.w; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; this.z -= s; + this.w -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; + this.w = a.w - b.w; return this; - }, - - multiply: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); - return this.multiplyVectors( v, w ); + } - } + multiply( v ) { this.x *= v.x; this.y *= v.y; this.z *= v.z; + this.w *= v.w; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; this.z *= scalar; + this.w *= scalar; return this; - }, + } - multiplyVectors: function ( a, b ) { + applyMatrix4( m ) { - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; return this; - }, + } - applyEuler: function () { + divideScalar( scalar ) { - var quaternion = new Quaternion(); + return this.multiplyScalar( 1 / scalar ); - return function applyEuler( euler ) { + } - if ( ! ( euler && euler.isEuler ) ) { + setAxisAngleFromQuaternion( q ) { - console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - } + // q is assumed to be normalized - return this.applyQuaternion( quaternion.setFromEuler( euler ) ); + this.w = 2 * Math.acos( q.w ); - }; + const s = Math.sqrt( 1 - q.w * q.w ); - }(), + if ( s < 0.0001 ) { - applyAxisAngle: function () { + this.x = 1; + this.y = 0; + this.z = 0; - var quaternion = new Quaternion(); + } else { - return function applyAxisAngle( axis, angle ) { + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; - return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) ); + } - }; + return this; - }(), + } - applyMatrix3: function ( m ) { + setAxisAngleFromRotationMatrix( m ) { - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - return this; + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - }, + te = m.elements, - applyMatrix4: function ( m ) { + 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 ]; - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { - var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - return this; + // this singularity is identity matrix so angle = 0 - }, + this.set( 1, 0, 0, 0 ); - applyQuaternion: function ( q ) { + return this; // zero angle, arbitrary axis - var x = this.x, y = this.y, z = this.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; + } - // calculate quat * vector + // otherwise this singularity is angle = 180 - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = - qx * x - qy * y - qz * z; + angle = Math.PI; - // calculate result * inverse quat + 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; - 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; + if ( ( xx > yy ) && ( xx > zz ) ) { - return this; + // m11 is the largest diagonal term - }, + if ( xx < epsilon ) { - project: function () { + x = 0; + y = 0.707106781; + z = 0.707106781; - var matrix = new Matrix4(); + } else { - return function project( camera ) { + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) ); - return this.applyMatrix4( matrix ); + } - }; + } else if ( yy > zz ) { - }(), + // m22 is the largest diagonal term - unproject: function () { + if ( yy < epsilon ) { - var matrix = new Matrix4(); + x = 0.707106781; + y = 0; + z = 0.707106781; - return function unproject( camera ) { + } else { - matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) ); - return this.applyMatrix4( matrix ); + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - }; + } - }(), + } else { - transformDirection: function ( m ) { + // m33 is the largest diagonal term so base result on this - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction + if ( zz < epsilon ) { - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + x = 0.707106781; + y = 0.707106781; + z = 0; - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; + } else { - return this.normalize(); + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - }, + } - divide: function ( v ) { + } - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; + this.set( x, y, z, angle ); + + return this; // return 180 deg rotation + + } + + // as we have reached here there are no singularities so we can handle normally + + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + + if ( Math.abs( s ) < 0.001 ) s = 1; + + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case + + 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; - }, + } - divideScalar: function ( scalar ) { + setFromMatrixPosition( m ) { - return this.multiplyScalar( 1 / scalar ); + const e = m.elements; - }, + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + this.w = e[ 15 ]; + + return this; + + } - min: function ( v ) { + 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: function ( v ) { + 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: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); return this; - }, - - clampScalar: function () { - - var min = new Vector3(); - var max = new Vector3(); - - return function clampScalar( minVal, maxVal ) { + } - min.set( minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + 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: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + 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: function () { + 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: function () { + 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: function () { + 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.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); + this.w = Math.trunc( this.w ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; this.z = - this.z; + this.w = - this.w; return this; - }, - - dot: function ( v ) { + } - return this.x * v.x + this.y * v.y + this.z * v.z; + dot( v ) { - }, + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - // TODO lengthSquared? + } - lengthSq: function () { + lengthSq() { - return this.x * this.x + this.y * this.y + this.z * this.z; + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - }, + } - length: function () { + length() { - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - }, + } - manhattanLength: function () { + manhattanLength() { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - }, + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + 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: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + 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; - cross: function ( v, w ) { + } - if ( w !== undefined ) { + equals( v ) { - console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); - return this.crossVectors( v, w ); + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - } + } - return this.crossVectors( this, v ); + fromArray( array, offset = 0 ) { - }, + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - crossVectors: function ( a, b ) { + return this; - var ax = a.x, ay = a.y, az = a.z; - var 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; + toArray( array = [], offset = 0 ) { - return this; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; - }, + return array; - projectOnVector: function ( vector ) { + } - var scalar = vector.dot( this ) / vector.lengthSq(); + fromBufferAttribute( attribute, index ) { - return this.copy( vector ).multiplyScalar( scalar ); + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); - }, + return this; - projectOnPlane: function () { + } - var v1 = new Vector3(); + random() { - return function projectOnPlane( planeNormal ) { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); - v1.copy( this ).projectOnVector( planeNormal ); + return this; - return this.sub( v1 ); + } - }; + *[ Symbol.iterator ]() { - }(), + yield this.x; + yield this.y; + yield this.z; + yield this.w; - reflect: function () { + } - // reflect incident vector off plane orthogonal to normal - // normal is assumed to have unit length +} - var v1 = new Vector3(); +/* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers +*/ +class RenderTarget extends EventDispatcher { - return function reflect( normal ) { + constructor( width = 1, height = 1, options = {} ) { - return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + super(); - }; + this.isRenderTarget = true; - }(), + this.width = width; + this.height = height; + this.depth = 1; - angleTo: function ( v ) { + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); + this.viewport = new Vector4( 0, 0, width, height ); - // clamp, to handle numerical problems + const image = { width: width, height: height, depth: 1 }; - return Math.acos( _Math.clamp( theta, - 1, 1 ) ); + options = Object.assign( { + generateMipmaps: false, + internalFormat: null, + minFilter: LinearFilter, + depthBuffer: true, + stencilBuffer: false, + resolveDepthBuffer: true, + resolveStencilBuffer: true, + depthTexture: null, + samples: 0, + count: 1 + }, options ); - }, + const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); - distanceTo: function ( v ) { + texture.flipY = false; + texture.generateMipmaps = options.generateMipmaps; + texture.internalFormat = options.internalFormat; - return Math.sqrt( this.distanceToSquared( v ) ); + this.textures = []; - }, + const count = options.count; + for ( let i = 0; i < count; i ++ ) { - distanceToSquared: function ( v ) { + this.textures[ i ] = texture.clone(); + this.textures[ i ].isRenderTargetTexture = true; - var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + } - return dx * dx + dy * dy + dz * dz; + this.depthBuffer = options.depthBuffer; + this.stencilBuffer = options.stencilBuffer; - }, + this.resolveDepthBuffer = options.resolveDepthBuffer; + this.resolveStencilBuffer = options.resolveStencilBuffer; - manhattanDistanceTo: function ( v ) { + this.depthTexture = options.depthTexture; - return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); + this.samples = options.samples; - }, + } - setFromSpherical: function ( s ) { + get texture() { - var sinPhiRadius = Math.sin( s.phi ) * s.radius; + return this.textures[ 0 ]; - this.x = sinPhiRadius * Math.sin( s.theta ); - this.y = Math.cos( s.phi ) * s.radius; - this.z = sinPhiRadius * Math.cos( s.theta ); + } - return this; + set texture( value ) { - }, + this.textures[ 0 ] = value; - setFromCylindrical: function ( c ) { + } - this.x = c.radius * Math.sin( c.theta ); - this.y = c.y; - this.z = c.radius * Math.cos( c.theta ); + setSize( width, height, depth = 1 ) { - return this; + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - }, + this.width = width; + this.height = height; + this.depth = depth; - setFromMatrixPosition: function ( m ) { + for ( let i = 0, il = this.textures.length; i < il; i ++ ) { - var e = m.elements; + this.textures[ i ].image.width = width; + this.textures[ i ].image.height = height; + this.textures[ i ].image.depth = depth; - this.x = e[ 12 ]; - this.y = e[ 13 ]; - this.z = e[ 14 ]; + } - return this; + this.dispose(); - }, + } - setFromMatrixScale: function ( m ) { + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - var sx = this.setFromMatrixColumn( m, 0 ).length(); - var sy = this.setFromMatrixColumn( m, 1 ).length(); - var sz = this.setFromMatrixColumn( m, 2 ).length(); + } - this.x = sx; - this.y = sy; - this.z = sz; + clone() { - return this; + return new this.constructor().copy( this ); - }, + } - setFromMatrixColumn: function ( m, index ) { + copy( source ) { - return this.fromArray( m.elements, index * 4 ); + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - }, + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - equals: function ( v ) { + this.viewport.copy( source.viewport ); - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); + this.textures.length = 0; - }, + for ( let i = 0, il = source.textures.length; i < il; i ++ ) { - fromArray: function ( array, offset ) { + this.textures[ i ] = source.textures[ i ].clone(); + this.textures[ i ].isRenderTargetTexture = true; - if ( offset === undefined ) { offset = 0; } + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; + // ensure image object is not shared, see #20328 - return this; + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); - }, + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - toArray: function ( array, offset ) { + this.resolveDepthBuffer = source.resolveDepthBuffer; + this.resolveStencilBuffer = source.resolveStencilBuffer; - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); + this.samples = source.samples; return this; } -} ); + dispose() { -/** - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - * @author tschw - */ + this.dispatchEvent( { type: 'dispose' } ); -function Matrix3() { + } - this.elements = [ +} - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 +class WebGLRenderTarget extends RenderTarget { - ]; + constructor( width = 1, height = 1, options = {} ) { - if ( arguments.length > 0 ) { + super( width, height, options ); - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); + this.isWebGLRenderTarget = true; } } -Object.assign( Matrix3.prototype, { +class DataArrayTexture extends Texture { - isMatrix3: true, + constructor( data = null, width = 1, height = 1, depth = 1 ) { - set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { + super( null ); - var te = this.elements; + this.isDataArrayTexture = true; - 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; + this.image = { data, width, height, depth }; - return this; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - }, + this.wrapR = ClampToEdgeWrapping; - identity: function () { + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - this.set( + this.layerUpdates = new Set(); - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 + } - ); + addLayerUpdate( layerIndex ) { - return this; + this.layerUpdates.add( layerIndex ); - }, + } - clone: function () { + clearLayerUpdates() { - return new this.constructor().fromArray( this.elements ); + this.layerUpdates.clear(); - }, + } - copy: function ( m ) { +} - var te = this.elements; - var me = m.elements; +class Data3DTexture extends Texture { - 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 ]; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - return this; + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 - }, + super( null ); - setFromMatrix4: function ( m ) { + this.isData3DTexture = true; - var me = m.elements; + this.image = { data, width, height, depth }; - this.set( + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - me[ 0 ], me[ 4 ], me[ 8 ], - me[ 1 ], me[ 5 ], me[ 9 ], - me[ 2 ], me[ 6 ], me[ 10 ] + this.wrapR = ClampToEdgeWrapping; - ); + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - return this; + } - }, +} - applyToBufferAttribute: function () { +class Quaternion { - var v1 = new Vector3(); + constructor( x = 0, y = 0, z = 0, w = 1 ) { - return function applyToBufferAttribute( attribute ) { + this.isQuaternion = true; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + this._x = x; + this._y = y; + this._z = z; + this._w = w; - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + } - v1.applyMatrix3( this ); + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + // fuzz-free, array-based Quaternion SLERP operation - } + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; - return attribute; + 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; - multiply: function ( m ) { + } - return this.multiplyMatrices( this, m ); + if ( t === 1 ) { - }, + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; - premultiply: function ( m ) { + } - return this.multiplyMatrices( m, this ); + 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; - multiplyMatrices: function ( a, b ) { + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - var ae = a.elements; - var be = b.elements; - var te = this.elements; + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; - var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; - var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; - var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; - var 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; + const tDir = t * dir; - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; - te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; - te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; - te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; - te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - return this; + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - }, + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - multiplyScalar: function ( s ) { + } - var 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; + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; - return this; + } - }, + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - determinant: function () { + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - var te = this.elements; + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; - var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], - d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], - g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; + 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 a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; + return dst; - }, + } - getInverse: function ( matrix, throwOnDegenerate ) { + get x() { - if ( matrix && matrix.isMatrix4 ) { + return this._x; - console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); + } - } + set x( value ) { - var me = matrix.elements, - te = this.elements, + this._x = value; + this._onChangeCallback(); - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], - n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ], - n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ], + } - t11 = n33 * n22 - n32 * n23, - t12 = n32 * n13 - n33 * n12, - t13 = n23 * n12 - n22 * n13, + get y() { - det = n11 * t11 + n21 * t12 + n31 * t13; + return this._y; - if ( det === 0 ) { + } - var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; + set y( value ) { - if ( throwOnDegenerate === true ) { + this._y = value; + this._onChangeCallback(); - throw new Error( msg ); + } - } else { + get z() { - console.warn( msg ); + return this._z; - } + } - return this.identity(); + set z( value ) { - } + this._z = value; + this._onChangeCallback(); - var detInv = 1 / det; + } - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; - te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; + get w() { - te[ 3 ] = t12 * detInv; - te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; - te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; + return this._w; - te[ 6 ] = t13 * detInv; - te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; - te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; + } - return this; + set w( value ) { - }, + this._w = value; + this._onChangeCallback(); - transpose: function () { + } - var tmp, m = this.elements; + set( x, y, z, w ) { - tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; - tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; - tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; + this._x = x; + this._y = y; + this._z = z; + this._w = w; + + this._onChangeCallback(); return this; - }, + } - getNormalMatrix: function ( matrix4 ) { + clone() { - return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); + return new this.constructor( this._x, this._y, this._z, this._w ); - }, + } - transposeIntoArray: function ( r ) { + copy( quaternion ) { - var m = this.elements; + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; - r[ 0 ] = m[ 0 ]; - r[ 1 ] = m[ 3 ]; - r[ 2 ] = m[ 6 ]; - r[ 3 ] = m[ 1 ]; - r[ 4 ] = m[ 4 ]; - r[ 5 ] = m[ 7 ]; - r[ 6 ] = m[ 2 ]; - r[ 7 ] = m[ 5 ]; - r[ 8 ] = m[ 8 ]; + this._onChangeCallback(); return this; - }, + } - setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { + setFromEuler( euler, update = true ) { - var c = Math.cos( rotation ); - var s = Math.sin( rotation ); + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - this.set( - sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, - - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, - 0, 0, 1 - ); + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - }, + const cos = Math.cos; + const sin = Math.sin; - scale: function ( sx, sy ) { + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - var te = this.elements; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; - te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; + switch ( order ) { - return this; + 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; - rotate: function ( theta ) { + 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; - var c = Math.cos( theta ); - var s = Math.sin( theta ); + 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; - var te = this.elements; + 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; - var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ]; - var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ]; + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); - te[ 0 ] = c * a11 + s * a21; - te[ 3 ] = c * a12 + s * a22; - te[ 6 ] = c * a13 + s * a23; + } - te[ 1 ] = - s * a11 + c * a21; - te[ 4 ] = - s * a12 + c * a22; - te[ 7 ] = - s * a13 + c * a23; + if ( update === true ) this._onChangeCallback(); return this; - }, + } - translate: function ( tx, ty ) { + setFromAxisAngle( axis, angle ) { - var te = this.elements; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - 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 ]; + // assumes axis is normalized - return this; + 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 ); - equals: function ( matrix ) { + this._onChangeCallback(); - var te = this.elements; - var me = matrix.elements; + return this; - for ( var i = 0; i < 9; i ++ ) { + } - if ( te[ i ] !== me[ i ] ) { return false; } + setFromRotationMatrix( m ) { - } + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - return true; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - }, + const te = m.elements, - fromArray: function ( array, offset ) { + 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 ( offset === undefined ) { offset = 0; } + trace = m11 + m22 + m33; - for ( var i = 0; i < 9; i ++ ) { + if ( trace > 0 ) { - this.elements[ i ] = array[ i + offset ]; + const s = 0.5 / Math.sqrt( trace + 1.0 ); - } + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; - return this; + } else if ( m11 > m22 && m11 > m33 ) { - }, + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - toArray: function ( array, offset ) { + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + } else if ( m22 > m33 ) { - var te = this.elements; + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - array[ offset + 3 ] = te[ 3 ]; - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; + } else { - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; - array[ offset + 8 ] = te[ 8 ]; + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - return array; + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; - } + } -} ); + this._onChangeCallback(); -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - */ + return this; -var textureId = 0; + } -function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + setFromUnitVectors( vFrom, vTo ) { - Object.defineProperty( this, 'id', { value: textureId ++ } ); + // assumes direction vectors vFrom and vTo are normalized - this.uuid = _Math.generateUUID(); + let r = vFrom.dot( vTo ) + 1; - this.name = ''; + if ( r < Number.EPSILON ) { - this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; - this.mipmaps = []; + // vFrom and vTo point in opposite directions - this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + r = 0; - this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + } else { - this.format = format !== undefined ? format : RGBAFormat; - this.type = type !== undefined ? type : UnsignedByteType; + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - 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(); + } else { - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding !== undefined ? encoding : LinearEncoding; + 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; - this.version = 0; - this.onUpdate = null; + } -} + return this.normalize(); -Texture.DEFAULT_IMAGE = undefined; -Texture.DEFAULT_MAPPING = UVMapping; + } -Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + angleTo( q ) { - constructor: Texture, + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); - isTexture: true, + } - clone: function () { + rotateTowards( q, step ) { - return new this.constructor().copy( this ); + const angle = this.angleTo( q ); - }, + if ( angle === 0 ) return this; - copy: function ( source ) { + const t = Math.min( 1, step / angle ); - this.name = source.name; + this.slerp( q, t ); - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); + return this; - this.mapping = source.mapping; + } - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + identity() { - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + return this.set( 0, 0, 0, 1 ); - this.anisotropy = source.anisotropy; + } - this.format = source.format; - this.type = source.type; + invert() { - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + // quaternion is assumed to have unit length - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + return this.conjugate(); - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + } + + conjugate() { + + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; + + this._onChangeCallback(); return this; - }, + } - toJSON: function ( meta ) { + dot( v ) { - var isRootObject = ( meta === undefined || typeof meta === 'string' ); + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { + } - return meta.textures[ this.uuid ]; + lengthSq() { - } + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - function getDataURL( image ) { + } - var canvas; + length() { - if ( image instanceof HTMLCanvasElement ) { + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); - canvas = image; + } - } else { + normalize() { - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; + let l = this.length(); - var context = canvas.getContext( '2d' ); + if ( l === 0 ) { - if ( image instanceof ImageData ) { + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - context.putImageData( image, 0, 0 ); + } else { - } else { + l = 1 / l; - context.drawImage( image, 0, 0, image.width, image.height ); + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - } + } - } + this._onChangeCallback(); - if ( canvas.width > 2048 || canvas.height > 2048 ) { + return this; - return canvas.toDataURL( 'image/jpeg', 0.6 ); + } - } else { + multiply( q ) { - return canvas.toDataURL( 'image/png' ); + return this.multiplyQuaternions( this, q ); - } + } - } + premultiply( q ) { - var output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + return this.multiplyQuaternions( q, this ); - uuid: this.uuid, - name: this.name, + } - mapping: this.mapping, + multiplyQuaternions( a, b ) { - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - wrap: [ this.wrapS, this.wrapT ], + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + 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; - flipY: this.flipY - }; + this._onChangeCallback(); - if ( this.image !== undefined ) { + return this; - // TODO: Move to THREE.Image + } - var image = this.image; + slerp( qb, t ) { - if ( image.uuid === undefined ) { + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - image.uuid = _Math.generateUUID(); // UGH + const x = this._x, y = this._y, z = this._z, w = this._w; - } + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: getDataURL( image ) - }; + if ( cosHalfTheta < 0 ) { - } + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; + + cosHalfTheta = - cosHalfTheta; + + } else { - output.image = image.uuid; + this.copy( qb ); } - if ( ! isRootObject ) { + if ( cosHalfTheta >= 1.0 ) { - meta.textures[ this.uuid ] = output; + this._w = w; + this._x = x; + this._y = y; + this._z = z; + + return this; } - return output; + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - }, + if ( sqrSinHalfTheta <= Number.EPSILON ) { - dispose: function () { + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - this.dispatchEvent( { type: 'dispose' } ); + this.normalize(); // normalize calls _onChangeCallback() - }, + return this; - transformUv: function ( uv ) { + } - if ( this.mapping !== UVMapping ) { return; } + 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; - uv.applyMatrix3( this.matrix ); + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - if ( uv.x < 0 || uv.x > 1 ) { + this._onChangeCallback(); - switch ( this.wrapS ) { + return this; - case RepeatWrapping: + } - uv.x = uv.x - Math.floor( uv.x ); - break; + slerpQuaternions( qa, qb, t ) { - case ClampToEdgeWrapping: + return this.copy( qa ).slerp( qb, t ); - uv.x = uv.x < 0 ? 0 : 1; - break; + } - case MirroredRepeatWrapping: + random() { - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + // sets this quaternion to a uniform random unit quaternnion - uv.x = Math.ceil( uv.x ) - uv.x; + // Ken Shoemake + // Uniform random rotations + // D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992. - } else { + const theta1 = 2 * Math.PI * Math.random(); + const theta2 = 2 * Math.PI * Math.random(); - uv.x = uv.x - Math.floor( uv.x ); + const x0 = Math.random(); + const r1 = Math.sqrt( 1 - x0 ); + const r2 = Math.sqrt( x0 ); - } - break; + return this.set( + r1 * Math.sin( theta1 ), + r1 * Math.cos( theta1 ), + r2 * Math.sin( theta2 ), + r2 * Math.cos( theta2 ), + ); - } + } - } + equals( quaternion ) { - if ( uv.y < 0 || uv.y > 1 ) { + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - switch ( this.wrapT ) { + } - case RepeatWrapping: + fromArray( array, offset = 0 ) { - uv.y = uv.y - Math.floor( uv.y ); - break; + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - case ClampToEdgeWrapping: + this._onChangeCallback(); - uv.y = uv.y < 0 ? 0 : 1; - break; + return this; - case MirroredRepeatWrapping: + } - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + toArray( array = [], offset = 0 ) { - uv.y = Math.ceil( uv.y ) - uv.y; + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; - } else { + return array; - uv.y = uv.y - Math.floor( uv.y ); + } - } - break; + fromBufferAttribute( attribute, index ) { - } + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); - } + this._onChangeCallback(); - if ( this.flipY ) { + return this; - uv.y = 1 - uv.y; + } - } + toJSON() { - } + return this.toArray(); -} ); + } -Object.defineProperty( Texture.prototype, "needsUpdate", { + _onChange( callback ) { - set: function ( value ) { + this._onChangeCallback = callback; - if ( value === true ) { this.version ++; } + return this; } -} ); + _onChangeCallback() {} -/** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ + *[ Symbol.iterator ]() { -function Vector4( x, y, z, w ) { + yield this._x; + yield this._y; + yield this._z; + yield this._w; - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; + } } -Object.assign( Vector4.prototype, { +class Vector3 { - isVector4: true, + constructor( x = 0, y = 0, z = 0 ) { - set: function ( x, y, z, w ) { + Vector3.prototype.isVector3 = true; + + this.x = x; + this.y = y; + this.z = z; + + } + + set( x, y, z ) { + + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) this.x = x; this.y = y; this.z = z; - this.w = w; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; this.z = scalar; - this.w = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setZ: function ( z ) { + setZ( z ) { this.z = z; return this; - }, - - setW: function ( w ) { - - this.w = w; - - return this; - - }, + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { 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: ' + index ); } return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { 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: ' + index ); } - }, + } - clone: function () { + clone() { - return new this.constructor( this.x, this.y, this.z, this.w ); + return new this.constructor( this.x, this.y, this.z ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; this.z += v.z; - this.w += v.w; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; this.z += s; - this.w += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; - this.w = a.w + b.w; return this; - }, + } - addScaledVector: function ( v, s ) { + 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: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; - this.w -= v.w; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; this.z -= s; - this.w -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; - this.w = a.w - b.w; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiply( v ) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; return this; - }, - - applyMatrix4: function ( m ) { + } - var x = this.x, y = this.y, z = this.z, w = this.w; - var e = m.elements; + multiplyScalar( scalar ) { - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; return this; - }, - - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - setAxisAngleFromQuaternion: function ( q ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - - // q is assumed to be normalized - - this.w = 2 * Math.acos( q.w ); - - var s = Math.sqrt( 1 - q.w * q.w ); - - if ( s < 0.0001 ) { - - 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; + multiplyVectors( a, b ) { - } + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; return this; - }, - - setAxisAngleFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + } - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + applyEuler( euler ) { - var angle, x, y, z, // variables for result - epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - te = m.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 ]; + applyAxisAngle( axis, angle ) { - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + } - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + applyMatrix3( m ) { - // this singularity is identity matrix so angle = 0 + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - this.set( 1, 0, 0, 0 ); + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - return this; // zero angle, arbitrary axis + return this; - } + } - // otherwise this singularity is angle = 180 + applyNormalMatrix( m ) { - angle = Math.PI; + return this.applyMatrix3( m ).normalize(); - var xx = ( m11 + 1 ) / 2; - var yy = ( m22 + 1 ) / 2; - var zz = ( m33 + 1 ) / 2; - var xy = ( m12 + m21 ) / 4; - var xz = ( m13 + m31 ) / 4; - var yz = ( m23 + m32 ) / 4; + } - if ( ( xx > yy ) && ( xx > zz ) ) { + applyMatrix4( m ) { - // m11 is the largest diagonal term + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - if ( xx < epsilon ) { + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - x = 0; - y = 0.707106781; - z = 0.707106781; + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - } else { + return this; - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + } - } + applyQuaternion( q ) { - } else if ( yy > zz ) { + // quaternion q is assumed to have unit length - // m22 is the largest diagonal term + const vx = this.x, vy = this.y, vz = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - if ( yy < epsilon ) { + // t = 2 * cross( q.xyz, v ); + const tx = 2 * ( qy * vz - qz * vy ); + const ty = 2 * ( qz * vx - qx * vz ); + const tz = 2 * ( qx * vy - qy * vx ); - x = 0.707106781; - y = 0; - z = 0.707106781; + // v + q.w * t + cross( q.xyz, t ); + this.x = vx + qw * tx + qy * tz - qz * ty; + this.y = vy + qw * ty + qz * tx - qx * tz; + this.z = vz + qw * tz + qx * ty - qy * tx; - } else { + return this; - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + } - } + project( camera ) { - } else { + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - // m33 is the largest diagonal term so base result on this + } - if ( zz < epsilon ) { + unproject( camera ) { - x = 0.707106781; - y = 0.707106781; - z = 0; + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); - } else { + } - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + transformDirection( m ) { - } + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - this.set( x, y, z, angle ); + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - return this; // return 180 deg rotation + return this.normalize(); - } + } - // as we have reached here there are no singularities so we can handle normally + divide( v ) { - var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; - if ( Math.abs( s ) < 0.001 ) { s = 1; } + return this; - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + } - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + divideScalar( scalar ) { - return this; + return this.multiplyScalar( 1 / scalar ); - }, + } - min: function ( v ) { + 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: function ( v ) { + 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: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); return this; - }, - - clampScalar: function () { - - var min, max; - - return function clampScalar( minVal, maxVal ) { - - if ( min === undefined ) { - - min = new Vector4(); - max = new Vector4(); - - } + } - min.set( minVal, minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + 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: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + 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: function () { + 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: function () { + 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: function () { + 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 ); + this.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; this.z = - this.z; - this.w = - this.w; return this; - }, + } - dot: function ( v ) { + dot( v ) { - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + return this.x * v.x + this.y * v.y + this.z * v.z; - }, + } - lengthSq: function () { + // TODO lengthSquared? - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + lengthSq() { - }, + return this.x * this.x + this.y * this.y + this.z * this.z; - length: function () { + } - return Math.sqrt( 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 ); - manhattanLength: function () { + } - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + manhattanLength() { - }, + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); + + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + 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: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + 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; - equals: function ( v ) { + } - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + cross( v ) { - }, + return this.crossVectors( this, v ); - fromArray: function ( array, offset ) { + } - if ( offset === undefined ) { offset = 0; } + crossVectors( a, b ) { - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + const ax = a.x, ay = a.y, az = a.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; - }, + } - toArray: function ( array, offset ) { + projectOnVector( v ) { - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + const denominator = v.lengthSq(); - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + if ( denominator === 0 ) return this.set( 0, 0, 0 ); - return array; + const scalar = v.dot( this ) / denominator; - }, + return this.copy( v ).multiplyScalar( scalar ); - fromBufferAttribute: function ( attribute, index, offset ) { + } - if ( offset !== undefined ) { + projectOnPlane( planeNormal ) { - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); + _vector$c.copy( this ).projectOnVector( planeNormal ); - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); - - return this; + return this.sub( _vector$c ); } -} ); - -/** - * @author szimek / https://github.com/szimek/ - * @author alteredq / http://alteredqualia.com/ - * @author Marius Kintel / https://github.com/kintel - */ - -/* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers -*/ -function WebGLRenderTarget( width, height, options ) { - - this.uuid = _Math.generateUUID(); + reflect( normal ) { - this.width = width; - this.height = height; + // reflect incident vector off plane orthogonal to normal + // normal is assumed to have unit length - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); - this.viewport = new Vector4( 0, 0, width, height ); + } - options = options || {}; + angleTo( v ) { - if ( options.minFilter === undefined ) { options.minFilter = LinearFilter; } + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); - this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( denominator === 0 ) return Math.PI / 2; - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + const theta = this.dot( v ) / denominator; -} + // clamp, to handle numerical problems -WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + return Math.acos( clamp( theta, - 1, 1 ) ); - constructor: WebGLRenderTarget, + } - isWebGLRenderTarget: true, + distanceTo( v ) { - setSize: function ( width, height ) { + return Math.sqrt( this.distanceToSquared( v ) ); - if ( this.width !== width || this.height !== height ) { + } - this.width = width; - this.height = height; + distanceToSquared( v ) { - this.dispose(); + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; - } + return dx * dx + dy * dy + dz * dz; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + } - }, + manhattanDistanceTo( v ) { - clone: function () { + return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); - return new this.constructor().copy( this ); + } - }, + setFromSpherical( s ) { - copy: function ( source ) { + return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); - this.width = source.width; - this.height = source.height; + } - this.viewport.copy( source.viewport ); + setFromSphericalCoords( radius, phi, theta ) { - this.texture = source.texture.clone(); + const sinPhiRadius = Math.sin( phi ) * radius; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + this.x = sinPhiRadius * Math.sin( theta ); + this.y = Math.cos( phi ) * radius; + this.z = sinPhiRadius * Math.cos( theta ); return this; - }, + } - dispose: function () { + setFromCylindrical( c ) { - this.dispatchEvent( { type: 'dispose' } ); + return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); } -} ); - -/** - * @author alteredq / http://alteredqualia.com - */ + setFromCylindricalCoords( radius, theta, y ) { -function WebGLRenderTargetCube( width, height, options ) { + this.x = radius * Math.sin( theta ); + this.y = y; + this.z = radius * Math.cos( theta ); - WebGLRenderTarget.call( this, width, height, options ); + return this; - this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 - this.activeMipMapLevel = 0; + } -} + setFromMatrixPosition( m ) { -WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); -WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; + const e = m.elements; -WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; -/** - * @author alteredq / http://alteredqualia.com/ - */ + return this; -function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + } - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + setFromMatrixScale( m ) { - this.image = { data: data, width: width, height: height }; + const sx = this.setFromMatrixColumn( m, 0 ).length(); + const sy = this.setFromMatrixColumn( m, 1 ).length(); + const sz = this.setFromMatrixColumn( m, 2 ).length(); - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + this.x = sx; + this.y = sy; + this.z = sz; - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; -} + } -DataTexture.prototype = Object.create( Texture.prototype ); -DataTexture.prototype.constructor = DataTexture; + setFromMatrixColumn( m, index ) { -DataTexture.prototype.isDataTexture = true; + return this.fromArray( m.elements, index * 4 ); -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + setFromMatrix3Column( m, index ) { - images = images !== undefined ? images : []; - mapping = mapping !== undefined ? mapping : CubeReflectionMapping; + return this.fromArray( m.elements, index * 3 ); - Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + } - this.flipY = false; + setFromEuler( e ) { -} + this.x = e._x; + this.y = e._y; + this.z = e._z; -CubeTexture.prototype = Object.create( Texture.prototype ); -CubeTexture.prototype.constructor = CubeTexture; + return this; -CubeTexture.prototype.isCubeTexture = true; + } -Object.defineProperty( CubeTexture.prototype, 'images', { + setFromColor( c ) { - get: function () { + this.x = c.r; + this.y = c.g; + this.z = c.b; - return this.image; + return this; - }, + } - set: function ( value ) { + equals( v ) { - this.image = value; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); } -} ); - -/** - * @author tschw - * - * Uniforms of a program. - * Those form a tree structure with a special top-level container for the root, - * which you get by calling 'new WebGLUniforms( gl, program, renderer )'. - * - * - * Properties of inner nodes including the top-level container: - * - * .seq - array of nested uniforms - * .map - nested uniforms by name - * - * - * Methods of all nodes except the top-level container: - * - * .setValue( gl, value, [renderer] ) - * - * uploads a uniform value(s) - * the 'renderer' parameter is needed for sampler uniforms - * - * - * Static methods of the top-level container (renderer factorizations): - * - * .upload( gl, seq, values, renderer ) - * - * sets uniforms in 'seq' to 'values[id].value' - * - * .seqWithValue( seq, values ) : filteredSeq - * - * filters 'seq' entries with corresponding entry in values - * - * - * Methods of the top-level container (renderer factorizations): - * - * .setValue( gl, name, value ) - * - * sets uniform with name 'name' to 'value' - * - * .set( gl, obj, prop ) - * - * sets uniform from object and property with same name than uniform - * - * .setOptional( gl, obj, prop ) - * - * like .set for an optional property of the object - * - */ + fromArray( array, offset = 0 ) { -var emptyTexture = new Texture(); -var emptyCubeTexture = new CubeTexture(); + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; -// --- Base for inner nodes (including the root) --- + return this; -function UniformContainer() { + } - this.seq = []; - this.map = {}; + toArray( array = [], offset = 0 ) { -} + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; -// --- Utilities --- + return array; -// Array Caches (provide typed arrays for temporary by size) + } -var arrayCacheF32 = []; -var arrayCacheI32 = []; + fromBufferAttribute( attribute, index ) { -// Float32Array caches used for uploading Matrix uniforms + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); -var mat4array = new Float32Array( 16 ); -var mat3array = new Float32Array( 9 ); + return this; -// Flattening for arrays of vectors and matrices + } -function flatten( array, nBlocks, blockSize ) { + random() { - var firstElem = array[ 0 ]; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); - if ( firstElem <= 0 || firstElem > 0 ) { return array; } - // unoptimized: ! isNaN( firstElem ) - // see http://jacksondunstan.com/articles/983 + return this; - var n = nBlocks * blockSize, - r = arrayCacheF32[ n ]; + } - if ( r === undefined ) { + randomDirection() { - r = new Float32Array( n ); - arrayCacheF32[ n ] = r; + // https://mathworld.wolfram.com/SpherePointPicking.html - } + const theta = Math.random() * Math.PI * 2; + const u = Math.random() * 2 - 1; + const c = Math.sqrt( 1 - u * u ); - if ( nBlocks !== 0 ) { + this.x = c * Math.cos( theta ); + this.y = u; + this.z = c * Math.sin( theta ); - firstElem.toArray( r, 0 ); + return this; - for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) { + } - offset += blockSize; - array[ i ].toArray( r, offset ); + *[ Symbol.iterator ]() { - } + yield this.x; + yield this.y; + yield this.z; } - return r; - } -// Texture unit allocation +const _vector$c = /*@__PURE__*/ new Vector3(); +const _quaternion$4 = /*@__PURE__*/ new Quaternion(); -function allocTexUnits( renderer, n ) { +class Box3 { - var r = arrayCacheI32[ n ]; + constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { - if ( r === undefined ) { + this.isBox3 = true; - r = new Int32Array( n ); - arrayCacheI32[ n ] = r; + this.min = min; + this.max = max; } - for ( var i = 0; i !== n; ++ i ) - { r[ i ] = renderer.allocTextureUnit(); } - - return r; + set( min, max ) { -} + this.min.copy( min ); + this.max.copy( max ); -// --- Setters --- + return this; -// Note: Defining these methods externally, because they come in a bunch -// and this way their names minify. + } -// Single scalar + setFromArray( array ) { -function setValue1f( gl, v ) { + this.makeEmpty(); - gl.uniform1f( this.addr, v ); + for ( let i = 0, il = array.length; i < il; i += 3 ) { -} + this.expandByPoint( _vector$b.fromArray( array, i ) ); -function setValue1i( gl, v ) { + } - gl.uniform1i( this.addr, v ); + return this; -} + } -// Single float vector (from flat array or THREE.VectorN) + setFromBufferAttribute( attribute ) { -function setValue2fv( gl, v ) { + this.makeEmpty(); - if ( v.x === undefined ) { + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - gl.uniform2fv( this.addr, v ); + this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); - } else { + } - gl.uniform2f( this.addr, v.x, v.y ); + return this; } -} + setFromPoints( points ) { -function setValue3fv( gl, v ) { + this.makeEmpty(); - if ( v.x !== undefined ) { + for ( let i = 0, il = points.length; i < il; i ++ ) { - gl.uniform3f( this.addr, v.x, v.y, v.z ); + this.expandByPoint( points[ i ] ); - } else if ( v.r !== undefined ) { + } - gl.uniform3f( this.addr, v.r, v.g, v.b ); + return this; - } else { + } - gl.uniform3fv( this.addr, v ); + setFromCenterAndSize( center, size ) { - } + const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); -} + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); -function setValue4fv( gl, v ) { + return this; - if ( v.x === undefined ) { + } - gl.uniform4fv( this.addr, v ); + setFromObject( object, precise = false ) { - } else { + this.makeEmpty(); - gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); + return this.expandByObject( object, precise ); } -} + clone() { -// Single matrix (from flat array or MatrixN) + return new this.constructor().copy( this ); -function setValue2fm( gl, v ) { + } - gl.uniformMatrix2fv( this.addr, false, v.elements || v ); + copy( box ) { -} + this.min.copy( box.min ); + this.max.copy( box.max ); -function setValue3fm( gl, v ) { + return this; - if ( v.elements === undefined ) { + } - gl.uniformMatrix3fv( this.addr, false, v ); + makeEmpty() { - } else { + this.min.x = this.min.y = this.min.z = + Infinity; + this.max.x = this.max.y = this.max.z = - Infinity; - mat3array.set( v.elements ); - gl.uniformMatrix3fv( this.addr, false, mat3array ); + return this; } -} + isEmpty() { -function setValue4fm( gl, v ) { + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - if ( v.elements === undefined ) { + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); - gl.uniformMatrix4fv( this.addr, false, v ); + } - } else { + getCenter( target ) { - mat4array.set( v.elements ); - gl.uniformMatrix4fv( this.addr, false, mat4array ); + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); } -} + getSize( target ) { -// Single texture (2D / Cube) + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); -function setValueT1( gl, v, renderer ) { + } - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTexture2D( v || emptyTexture, unit ); + expandByPoint( point ) { -} + this.min.min( point ); + this.max.max( point ); -function setValueT6( gl, v, renderer ) { + return this; - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTextureCube( v || emptyCubeTexture, unit ); + } -} + expandByVector( vector ) { -// Integer / Boolean vectors or arrays thereof (always flat arrays) + this.min.sub( vector ); + this.max.add( vector ); -function setValue2iv( gl, v ) { + return this; - gl.uniform2iv( this.addr, v ); + } -} + expandByScalar( scalar ) { -function setValue3iv( gl, v ) { + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); - gl.uniform3iv( this.addr, v ); + return this; -} + } -function setValue4iv( gl, v ) { + expandByObject( object, precise = false ) { - gl.uniform4iv( this.addr, v ); + // Computes the world-axis-aligned bounding box of an object (including its children), + // accounting for both the object's, and children's, world transforms -} + object.updateWorldMatrix( false, false ); -// Helper to pick the right setter for the singular case + const geometry = object.geometry; -function getSingularSetter( type ) { + if ( geometry !== undefined ) { - switch ( type ) { + const positionAttribute = geometry.getAttribute( 'position' ); - case 0x1406: return setValue1f; // FLOAT - case 0x8b50: return setValue2fv; // _VEC2 - case 0x8b51: return setValue3fv; // _VEC3 - case 0x8b52: return setValue4fv; // _VEC4 + // precise AABB computation based on vertex data requires at least a position attribute. + // instancing isn't supported so far and uses the normal (conservative) code path. - case 0x8b5a: return setValue2fm; // _MAT2 - case 0x8b5b: return setValue3fm; // _MAT3 - case 0x8b5c: return setValue4fm; // _MAT4 + if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { - case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES - case 0x8b60: return setValueT6; // SAMPLER_CUBE + for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { - case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 + if ( object.isMesh === true ) { - } + object.getVertexPosition( i, _vector$b ); -} + } else { -// Array of scalars + _vector$b.fromBufferAttribute( positionAttribute, i ); -function setValue1fv( gl, v ) { + } - gl.uniform1fv( this.addr, v ); + _vector$b.applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$b ); -} -function setValue1iv( gl, v ) { - - gl.uniform1iv( this.addr, v ); + } -} + } else { -// Array of vectors (flat or from THREE classes) + if ( object.boundingBox !== undefined ) { -function setValueV2a( gl, v ) { + // object-level bounding box - gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) ); + if ( object.boundingBox === null ) { -} + object.computeBoundingBox(); -function setValueV3a( gl, v ) { + } - gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) ); + _box$4.copy( object.boundingBox ); -} -function setValueV4a( gl, v ) { + } else { - gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) ); + // geometry-level bounding box -} + if ( geometry.boundingBox === null ) { -// Array of matrices (flat or from THREE clases) + geometry.computeBoundingBox(); -function setValueM2a( gl, v ) { + } - gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) ); + _box$4.copy( geometry.boundingBox ); -} + } -function setValueM3a( gl, v ) { + _box$4.applyMatrix4( object.matrixWorld ); - gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) ); + this.union( _box$4 ); -} + } -function setValueM4a( gl, v ) { + } - gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) ); + const children = object.children; -} + for ( let i = 0, l = children.length; i < l; i ++ ) { -// Array of textures (2D / Cube) + this.expandByObject( children[ i ], precise ); -function setValueT1a( gl, v, renderer ) { + } - var n = v.length, - units = allocTexUnits( renderer, n ); + return this; - gl.uniform1iv( this.addr, units ); + } - for ( var i = 0; i !== n; ++ i ) { + containsPoint( point ) { - renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); + 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; } -} + containsBox( box ) { -function setValueT6a( gl, v, renderer ) { + 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; - var n = v.length, - units = allocTexUnits( renderer, n ); + } - gl.uniform1iv( this.addr, units ); + getParameter( point, target ) { - for ( var i = 0; i !== n; ++ i ) { + // This can potentially have a divide by zero if the box + // has a size dimension of 0. - renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); + 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 ) + ); } -} - -// Helper to pick the right setter for a pure (bottom-level) array - -function getPureArraySetter( type ) { + intersectsBox( box ) { - switch ( type ) { + // using 6 splitting planes to rule out intersections. + 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; - case 0x1406: return setValue1fv; // FLOAT - case 0x8b50: return setValueV2a; // _VEC2 - case 0x8b51: return setValueV3a; // _VEC3 - case 0x8b52: return setValueV4a; // _VEC4 + } - case 0x8b5a: return setValueM2a; // _MAT2 - case 0x8b5b: return setValueM3a; // _MAT3 - case 0x8b5c: return setValueM4a; // _MAT4 + intersectsSphere( sphere ) { - case 0x8b5e: return setValueT1a; // SAMPLER_2D - case 0x8b60: return setValueT6a; // SAMPLER_CUBE + // Find the point on the AABB closest to the sphere center. + this.clampPoint( sphere.center, _vector$b ); - case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 + // If that point is inside the sphere, the AABB and sphere intersect. + return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); } -} + intersectsPlane( plane ) { -// --- Uniform Classes --- + // We compute the minimum and maximum dot product values. If those values + // are on the same side (back or front) of the plane, then there is no intersection. -function SingleUniform( id, activeInfo, addr ) { + let min, max; - this.id = id; - this.addr = addr; - this.setValue = getSingularSetter( activeInfo.type ); + if ( plane.normal.x > 0 ) { - // this.path = activeInfo.name; // DEBUG + min = plane.normal.x * this.min.x; + max = plane.normal.x * this.max.x; -} + } else { -function PureArrayUniform( id, activeInfo, addr ) { + min = plane.normal.x * this.max.x; + max = plane.normal.x * this.min.x; - this.id = id; - this.addr = addr; - this.size = activeInfo.size; - this.setValue = getPureArraySetter( activeInfo.type ); + } - // this.path = activeInfo.name; // DEBUG + if ( plane.normal.y > 0 ) { -} + min += plane.normal.y * this.min.y; + max += plane.normal.y * this.max.y; -function StructuredUniform( id ) { + } else { - this.id = id; + min += plane.normal.y * this.max.y; + max += plane.normal.y * this.min.y; - UniformContainer.call( this ); // mix-in + } -} + if ( plane.normal.z > 0 ) { -StructuredUniform.prototype.setValue = function ( gl, value ) { + min += plane.normal.z * this.min.z; + max += plane.normal.z * this.max.z; - // Note: Don't need an extra 'renderer' parameter, since samplers - // are not allowed in structured uniforms. + } else { - var seq = this.seq; + min += plane.normal.z * this.max.z; + max += plane.normal.z * this.min.z; - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + } - var u = seq[ i ]; - u.setValue( gl, value[ u.id ] ); + return ( min <= - plane.constant && max >= - plane.constant ); } -}; + intersectsTriangle( triangle ) { -// --- Top-level --- + if ( this.isEmpty() ) { -// Parser - builds up the property tree from the path strings + return false; -var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g; + } -// extracts -// - the identifier (member name or array index) -// - followed by an optional right bracket (found when array index) -// - followed by an optional left bracket or dot (type of subscript) -// -// Note: These portions can be read in a non-overlapping fashion and -// allow straightforward parsing of the hierarchy that WebGL encodes -// in the uniform names. + // compute box center and extents + this.getCenter( _center ); + _extents.subVectors( this.max, _center ); -function addUniform( container, uniformObject ) { + // translate triangle to aabb origin + _v0$3.subVectors( triangle.a, _center ); + _v1$7.subVectors( triangle.b, _center ); + _v2$4.subVectors( triangle.c, _center ); - container.seq.push( uniformObject ); - container.map[ uniformObject.id ] = uniformObject; + // compute edge vectors for triangle + _f0.subVectors( _v1$7, _v0$3 ); + _f1.subVectors( _v2$4, _v1$7 ); + _f2.subVectors( _v0$3, _v2$4 ); -} + // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb + // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation + // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) + 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$3, _v1$7, _v2$4, _extents ) ) { -function parseUniform( activeInfo, addr, container ) { + return false; - var path = activeInfo.name, - pathLength = path.length; + } - // reset RegExp object, because of the early exit of a previous run - RePathPart.lastIndex = 0; + // test 3 face normals from the aabb + axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; + if ( ! satForAxes( axes, _v0$3, _v1$7, _v2$4, _extents ) ) { - for ( ; ; ) { + return false; - var match = RePathPart.exec( path ), - matchEnd = RePathPart.lastIndex, + } - id = match[ 1 ], - idIsIndex = match[ 2 ] === ']', - subscript = match[ 3 ]; + // finally testing the face normal of the triangle + // use already existing triangle edge vectors here + _triangleNormal.crossVectors( _f0, _f1 ); + axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; - if ( idIsIndex ) { id = id | 0; } // convert to integer + return satForAxes( axes, _v0$3, _v1$7, _v2$4, _extents ); - if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { + } - // bare name or "pure" bottom-level array "[0]" suffix + clampPoint( point, target ) { - addUniform( container, subscript === undefined ? - new SingleUniform( id, activeInfo, addr ) : - new PureArrayUniform( id, activeInfo, addr ) ); + return target.copy( point ).clamp( this.min, this.max ); - break; + } - } else { + distanceToPoint( point ) { - // step into inner node / create it in case it doesn't exist + return this.clampPoint( point, _vector$b ).distanceTo( point ); - var map = container.map, next = map[ id ]; + } - if ( next === undefined ) { + getBoundingSphere( target ) { - next = new StructuredUniform( id ); - addUniform( container, next ); + if ( this.isEmpty() ) { - } + target.makeEmpty(); - container = next; + } else { + + this.getCenter( target.center ); + + target.radius = this.getSize( _vector$b ).length() * 0.5; } - } + return target; -} + } -// Root Container + intersect( box ) { -function WebGLUniforms( gl, program, renderer ) { + this.min.max( box.min ); + this.max.min( box.max ); - UniformContainer.call( this ); + // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. + if ( this.isEmpty() ) this.makeEmpty(); - this.renderer = renderer; + return this; - var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); + } - for ( var i = 0; i < n; ++ i ) { + union( box ) { - var info = gl.getActiveUniform( program, i ), - path = info.name, - addr = gl.getUniformLocation( program, path ); + this.min.min( box.min ); + this.max.max( box.max ); - parseUniform( info, addr, this ); + return this; } -} + applyMatrix4( matrix ) { -WebGLUniforms.prototype.setValue = function ( gl, name, value ) { + // transform of empty box is an empty box. + if ( this.isEmpty() ) return this; - var u = this.map[ name ]; + // NOTE: I am using a binary pattern to specify all 2^3 combinations below + _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 + _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 + _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 + _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 + _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 + _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 + _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 + _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 - if ( u !== undefined ) { u.setValue( gl, value, this.renderer ); } + this.setFromPoints( _points ); -}; + return this; -WebGLUniforms.prototype.setOptional = function ( gl, object, name ) { + } - var v = object[ name ]; + translate( offset ) { - if ( v !== undefined ) { this.setValue( gl, name, v ); } + this.min.add( offset ); + this.max.add( offset ); -}; + return this; + + } + + equals( box ) { + return box.min.equals( this.min ) && box.max.equals( this.max ); -// Static interface + } -WebGLUniforms.upload = function ( gl, seq, values, renderer ) { +} - for ( var i = 0, n = seq.length; i !== n; ++ i ) { +const _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 u = seq[ i ], - v = values[ u.id ]; +const _vector$b = /*@__PURE__*/ new Vector3(); - if ( v.needsUpdate !== false ) { +const _box$4 = /*@__PURE__*/ new Box3(); - // note: always updating when .needsUpdate is undefined - u.setValue( gl, v.value, renderer ); +// triangle centered vertices - } +const _v0$3 = /*@__PURE__*/ new Vector3(); +const _v1$7 = /*@__PURE__*/ new Vector3(); +const _v2$4 = /*@__PURE__*/ new Vector3(); - } +// triangle edge vectors -}; +const _f0 = /*@__PURE__*/ new Vector3(); +const _f1 = /*@__PURE__*/ new Vector3(); +const _f2 = /*@__PURE__*/ new Vector3(); + +const _center = /*@__PURE__*/ new Vector3(); +const _extents = /*@__PURE__*/ new Vector3(); +const _triangleNormal = /*@__PURE__*/ new Vector3(); +const _testAxis = /*@__PURE__*/ new Vector3(); + +function satForAxes( axes, v0, v1, v2, extents ) { -WebGLUniforms.seqWithValue = function ( seq, values ) { + for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { - var r = []; + _testAxis.fromArray( axes, i ); + // project the aabb onto the separating axis + const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); + // project all 3 vertices of the triangle onto the separating axis + const p0 = v0.dot( _testAxis ); + const p1 = v1.dot( _testAxis ); + const p2 = v2.dot( _testAxis ); + // actual test, basically see if either of the most extreme of the triangle points intersects r + if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + // points of the projected triangle are outside the projected half-length of the aabb + // the axis is separating and we can exit + return false; - var u = seq[ i ]; - if ( u.id in values ) { r.push( u ); } + } } - return r; + return true; -}; +} -/** - * @author mrdoob / http://mrdoob.com/ - */ +const _box$3 = /*@__PURE__*/ new Box3(); +const _v1$6 = /*@__PURE__*/ new Vector3(); +const _v2$3 = /*@__PURE__*/ new Vector3(); -var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; +class Sphere { -function Color( r, g, b ) { + constructor( center = new Vector3(), radius = - 1 ) { - if ( g === undefined && b === undefined ) { + this.isSphere = true; - // r is THREE.Color, hex or string - return this.set( r ); + this.center = center; + this.radius = radius; } - return this.setRGB( r, g, b ); + set( center, radius ) { -} + this.center.copy( center ); + this.radius = radius; + + return this; + + } -Object.assign( Color.prototype, { + setFromPoints( points, optionalCenter ) { - isColor: true, + const center = this.center; - r: 1, g: 1, b: 1, + if ( optionalCenter !== undefined ) { - set: function ( value ) { + center.copy( optionalCenter ); - if ( value && value.isColor ) { + } else { - this.copy( value ); + _box$3.setFromPoints( points ).getCenter( center ); - } else if ( typeof value === 'number' ) { + } - this.setHex( value ); + let maxRadiusSq = 0; - } else if ( typeof value === 'string' ) { + for ( let i = 0, il = points.length; i < il; i ++ ) { - this.setStyle( value ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); } + this.radius = Math.sqrt( maxRadiusSq ); + return this; - }, + } - setScalar: function ( scalar ) { + copy( sphere ) { - this.r = scalar; - this.g = scalar; - this.b = scalar; + this.center.copy( sphere.center ); + this.radius = sphere.radius; return this; - }, - - setHex: function ( hex ) { - - hex = Math.floor( hex ); + } - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + isEmpty() { - return this; + return ( this.radius < 0 ); - }, + } - setRGB: function ( r, g, b ) { + makeEmpty() { - this.r = r; - this.g = g; - this.b = b; + this.center.set( 0, 0, 0 ); + this.radius = - 1; return this; - }, + } - setHSL: function () { + containsPoint( point ) { - function hue2rgb( p, q, t ) { + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - 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; + } - } + distanceToPoint( point ) { - return function setHSL( h, s, l ) { + return ( point.distanceTo( this.center ) - this.radius ); - // h,s,l ranges are in 0.0 - 1.0 - h = _Math.euclideanModulo( h, 1 ); - s = _Math.clamp( s, 0, 1 ); - l = _Math.clamp( l, 0, 1 ); + } - if ( s === 0 ) { + intersectsSphere( sphere ) { - this.r = this.g = this.b = l; + const radiusSum = this.radius + sphere.radius; - } else { + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - var 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 ); + intersectsBox( box ) { - } + return box.intersectsSphere( this ); - return this; + } - }; + intersectsPlane( plane ) { - }(), + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - setStyle: function ( style ) { + } - function handleAlpha( string ) { + clampPoint( point, target ) { - if ( string === undefined ) { return; } + const deltaLengthSq = this.center.distanceToSquared( point ); - if ( parseFloat( string ) < 1 ) { + target.copy( point ); - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + if ( deltaLengthSq > ( this.radius * this.radius ) ) { - } + target.sub( this.center ).normalize(); + target.multiplyScalar( this.radius ).add( this.center ); } + return target; - var m; + } - if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) { + getBoundingBox( target ) { - // rgb / hsl + if ( this.isEmpty() ) { - var color; - var name = m[ 1 ]; - var components = m[ 2 ]; + // Empty sphere produces empty bounding box + target.makeEmpty(); + return target; - switch ( name ) { + } - case 'rgb': - case 'rgba': + target.set( this.center, this.center ); + target.expandByScalar( this.radius ); - if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + return target; - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; + } - handleAlpha( color[ 5 ] ); + applyMatrix4( matrix ) { - return this; + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); - } + return this; - if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + } - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; + translate( offset ) { - handleAlpha( color[ 5 ] ); + this.center.add( offset ); - return this; + return this; - } + } - break; + expandByPoint( point ) { - case 'hsl': - case 'hsla': + if ( this.isEmpty() ) { - if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + this.center.copy( point ); - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - var h = parseFloat( color[ 1 ] ) / 360; - var s = parseInt( color[ 2 ], 10 ) / 100; - var l = parseInt( color[ 3 ], 10 ) / 100; + this.radius = 0; - handleAlpha( color[ 5 ] ); + return this; - return this.setHSL( h, s, l ); + } - } + _v1$6.subVectors( point, this.center ); - break; + const lengthSq = _v1$6.lengthSq(); - } + if ( lengthSq > ( this.radius * this.radius ) ) { - } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) { + // calculate the minimal sphere - // hex color + const length = Math.sqrt( lengthSq ); - var hex = m[ 1 ]; - var size = hex.length; + const delta = ( length - this.radius ) * 0.5; - if ( size === 3 ) { + this.center.addScaledVector( _v1$6, delta / length ); - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; + this.radius += delta; - return this; + } - } else if ( size === 6 ) { + return this; - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + } - return this; + union( sphere ) { - } + if ( sphere.isEmpty() ) { + + return this; } - if ( style && style.length > 0 ) { + if ( this.isEmpty() ) { - // color keywords - var hex = ColorKeywords[ style ]; + this.copy( sphere ); - if ( hex !== undefined ) { + return this; - // red - this.setHex( hex ); + } - } else { + if ( this.center.equals( sphere.center ) === true ) { - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + this.radius = Math.max( this.radius, sphere.radius ); - } + } else { + + _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); + + this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); + + this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); } return this; - }, + } - clone: function () { + equals( sphere ) { - return new this.constructor( this.r, this.g, this.b ); + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - }, + } - copy: function ( color ) { + clone() { - this.r = color.r; - this.g = color.g; - this.b = color.b; + return new this.constructor().copy( this ); - return this; + } - }, +} - copyGammaToLinear: function ( color, gammaFactor ) { +const _vector$a = /*@__PURE__*/ new Vector3(); +const _segCenter = /*@__PURE__*/ new Vector3(); +const _segDir = /*@__PURE__*/ new Vector3(); +const _diff = /*@__PURE__*/ new Vector3(); - if ( gammaFactor === undefined ) { gammaFactor = 2.0; } +const _edge1 = /*@__PURE__*/ new Vector3(); +const _edge2 = /*@__PURE__*/ new Vector3(); +const _normal$1 = /*@__PURE__*/ new Vector3(); - this.r = Math.pow( color.r, gammaFactor ); - this.g = Math.pow( color.g, gammaFactor ); - this.b = Math.pow( color.b, gammaFactor ); +class Ray { - return this; + 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 ); - copyLinearToGamma: function ( color, gammaFactor ) { + return this; - if ( gammaFactor === undefined ) { gammaFactor = 2.0; } + } - var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; + copy( ray ) { - this.r = Math.pow( color.r, safeInverse ); - this.g = Math.pow( color.g, safeInverse ); - this.b = Math.pow( color.b, safeInverse ); + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); return this; - }, + } + + at( t, target ) { - convertGammaToLinear: function () { + return target.copy( this.origin ).addScaledVector( this.direction, t ); - var r = this.r, g = this.g, b = this.b; + } + + lookAt( v ) { - this.r = r * r; - this.g = g * g; - this.b = b * b; + this.direction.copy( v ).sub( this.origin ).normalize(); return this; - }, + } - convertLinearToGamma: function () { + recast( t ) { - this.r = Math.sqrt( this.r ); - this.g = Math.sqrt( this.g ); - this.b = Math.sqrt( this.b ); + this.origin.copy( this.at( t, _vector$a ) ); return this; - }, - - getHex: function () { + } - return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; + closestPointToPoint( point, target ) { - }, + target.subVectors( point, this.origin ); - getHexString: function () { + const directionDistance = target.dot( this.direction ); - return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); + if ( directionDistance < 0 ) { - }, + return target.copy( this.origin ); - getHSL: function ( optionalTarget ) { + } - // h,s,l ranges are in 0.0 - 1.0 + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - var hsl = optionalTarget || { h: 0, s: 0, l: 0 }; + } - var r = this.r, g = this.g, b = this.b; + distanceToPoint( point ) { - var max = Math.max( r, g, b ); - var min = Math.min( r, g, b ); + return Math.sqrt( this.distanceSqToPoint( point ) ); - var hue, saturation; - var lightness = ( min + max ) / 2.0; + } - if ( min === max ) { + distanceSqToPoint( point ) { - hue = 0; - saturation = 0; + const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); - } else { + // point behind the ray - var delta = max - min; + if ( directionDistance < 0 ) { - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + return this.origin.distanceToSquared( point ); - switch ( max ) { + } - 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; + _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - } + return _vector$a.distanceToSquared( point ); - hue /= 6; + } - } + distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - hsl.h = hue; - hsl.s = saturation; - hsl.l = lightness; + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h + // It returns the min distance between the ray and the segment + // defined by v0 and v1 + // It can also set two optional targets : + // - The closest point on the ray + // - The closest point on the segment - return hsl; + _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 c = _diff.lengthSq(); + const det = Math.abs( 1 - a01 * a01 ); + let s0, s1, sqrDist, extDet; - getStyle: function () { + if ( det > 0 ) { - return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; + // The ray and segment are not parallel. - }, + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; - offsetHSL: function ( h, s, l ) { + if ( s0 >= 0 ) { - var hsl = this.getHSL(); + if ( s1 >= - extDet ) { - hsl.h += h; hsl.s += s; hsl.l += l; + if ( s1 <= extDet ) { - this.setHSL( hsl.h, hsl.s, hsl.l ); + // region 0 + // Minimum at interior points of ray and segment. - return this; + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - }, + } else { - add: function ( color ) { + // region 1 - this.r += color.r; - this.g += color.g; - this.b += color.b; + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + } else { - addColors: function ( color1, color2 ) { + // region 5 - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + } else { - addScalar: function ( s ) { + if ( s1 <= - extDet ) { - this.r += s; - this.g += s; - this.b += s; + // region 4 - return this; + 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 ) + c; - }, + } else if ( s1 <= extDet ) { - sub: function ( color ) { + // region 3 - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; - return this; + } else { - }, + // region 2 - multiply: function ( color ) { + 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 ) + c; - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + } - return this; + } - }, + } else { - multiplyScalar: function ( s ) { + // Ray and segment are parallel. - this.r *= s; - this.g *= s; - this.b *= s; + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + if ( optionalPointOnRay ) { - lerp: function ( color, alpha ) { + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + } - return this; + if ( optionalPointOnSegment ) { - }, + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); - equals: function ( c ) { + } - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + return sqrDist; - }, + } - fromArray: function ( array, offset ) { + intersectSphere( sphere, target ) { - if ( offset === undefined ) { offset = 0; } + _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; - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + if ( d2 > radius2 ) return null; - return this; + const thc = Math.sqrt( radius2 - d2 ); - }, + // t0 = first intersect point - entrance on front of sphere + const t0 = tca - thc; - toArray: function ( array, offset ) { + // t1 = second intersect point - exit point on back of sphere + const t1 = tca + thc; - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + // test to see if t0 is behind the ray: + // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, + // in order to always return an intersect point that is in front of the ray. + if ( t0 < 0 ) return this.at( t1, target ); - return array; + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, target ); - }, + } - toJSON: function () { + intersectsSphere( sphere ) { - return this.getHex(); + return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); } -} ); + distanceToPlane( plane ) { -/** - * Uniforms library for shared webgl shaders - */ + const denominator = plane.normal.dot( this.direction ); -var UniformsLib = { + if ( denominator === 0 ) { - common: { + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, + return 0; - map: { value: null }, - uvTransform: { value: new Matrix3() }, + } - alphaMap: { value: null }, + // Null is preferable to undefined since undefined means.... it is undefined - }, + return null; - specularmap: { + } - specularMap: { value: null }, + const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - }, + // Return if the ray never intersects the plane - envmap: { + return t >= 0 ? t : null; - envMap: { value: null }, - flipEnvMap: { value: - 1 }, - reflectivity: { value: 1.0 }, - refractionRatio: { value: 0.98 } + } - }, + intersectPlane( plane, target ) { - aomap: { + const t = this.distanceToPlane( plane ); - aoMap: { value: null }, - aoMapIntensity: { value: 1 } + if ( t === null ) { - }, + return null; - lightmap: { + } - lightMap: { value: null }, - lightMapIntensity: { value: 1 } + return this.at( t, target ); - }, + } - emissivemap: { + intersectsPlane( plane ) { - emissiveMap: { value: null } + // check if the ray lies on the plane first - }, + const distToPoint = plane.distanceToPoint( this.origin ); - bumpmap: { + if ( distToPoint === 0 ) { - bumpMap: { value: null }, - bumpScale: { value: 1 } + return true; - }, + } - normalmap: { + const denominator = plane.normal.dot( this.direction ); - normalMap: { value: null }, - normalScale: { value: new Vector2( 1, 1 ) } + if ( denominator * distToPoint < 0 ) { - }, + return true; - displacementmap: { + } - displacementMap: { value: null }, - displacementScale: { value: 1 }, - displacementBias: { value: 0 } + // ray origin is behind the plane (and is pointing behind it) - }, + return false; - roughnessmap: { + } - roughnessMap: { value: null } + intersectBox( box, target ) { - }, + let tmin, tmax, tymin, tymax, tzmin, tzmax; - metalnessmap: { + const invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; - metalnessMap: { value: null } + const origin = this.origin; - }, + if ( invdirx >= 0 ) { - gradientmap: { + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; - gradientMap: { value: null } + } else { - }, + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; - fog: { + } - fogDensity: { value: 0.00025 }, - fogNear: { value: 1 }, - fogFar: { value: 2000 }, - fogColor: { value: new Color( 0xffffff ) } + if ( invdiry >= 0 ) { - }, + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; - lights: { + } else { - ambientLightColor: { value: [] }, + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; - directionalLights: { value: [], properties: { - direction: {}, - color: {}, + } - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; - directionalShadowMap: { value: [] }, - directionalShadowMatrix: { value: [] }, + if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; - spotLights: { value: [], properties: { - color: {}, - position: {}, - direction: {}, - distance: {}, - coneCos: {}, - penumbraCos: {}, - decay: {}, + if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, + if ( invdirz >= 0 ) { - spotShadowMap: { value: [] }, - spotShadowMatrix: { value: [] }, + tzmin = ( box.min.z - origin.z ) * invdirz; + tzmax = ( box.max.z - origin.z ) * invdirz; - pointLights: { value: [], properties: { - color: {}, - position: {}, - decay: {}, - distance: {}, + } else { - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {}, - shadowCameraNear: {}, - shadowCameraFar: {} - } }, + tzmin = ( box.max.z - origin.z ) * invdirz; + tzmax = ( box.min.z - origin.z ) * invdirz; - pointShadowMap: { value: [] }, - pointShadowMatrix: { value: [] }, + } - hemisphereLights: { value: [], properties: { - direction: {}, - skyColor: {}, - groundColor: {} - } }, + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; - // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src - rectAreaLights: { value: [], properties: { - color: {}, - position: {}, - width: {}, - height: {} - } } + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; - }, + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; - points: { + //return point closest to the ray (positive side) - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, - size: { value: 1.0 }, - scale: { value: 1.0 }, - map: { value: null }, - uvTransform: { value: new Matrix3() } + if ( tmax < 0 ) return null; + + return this.at( tmin >= 0 ? tmin : tmax, target ); } -}; + intersectsBox( box ) { -/** - * Uniform Utilities - */ + return this.intersectBox( box, _vector$a ) !== null; + + } -var UniformsUtils = { + intersectTriangle( a, b, c, backfaceCulling, target ) { - merge: function ( uniforms ) { + // Compute the offset origin, edges, and normal. - var merged = {}; + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - for ( var u = 0; u < uniforms.length; u ++ ) { + _edge1.subVectors( b, a ); + _edge2.subVectors( c, a ); + _normal$1.crossVectors( _edge1, _edge2 ); - var tmp = this.clone( uniforms[ u ] ); + // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, + // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by + // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) + // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) + // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) + let DdN = this.direction.dot( _normal$1 ); + let sign; - for ( var p in tmp ) { + if ( DdN > 0 ) { - merged[ p ] = tmp[ p ]; + if ( backfaceCulling ) return null; + sign = 1; - } + } else if ( DdN < 0 ) { + + sign = - 1; + DdN = - DdN; + + } else { + + return null; } - return merged; + _diff.subVectors( this.origin, a ); + const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); - }, + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { - clone: function ( uniforms_src ) { + return null; + + } - var uniforms_dst = {}; + const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); - for ( var u in uniforms_src ) { + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { - uniforms_dst[ u ] = {}; + return null; - for ( var p in uniforms_src[ u ] ) { + } - var parameter_src = uniforms_src[ u ][ p ]; + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { - if ( parameter_src && ( parameter_src.isColor || - parameter_src.isMatrix3 || parameter_src.isMatrix4 || - parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 || - parameter_src.isTexture ) ) { + return null; - uniforms_dst[ u ][ p ] = parameter_src.clone(); + } - } else if ( Array.isArray( parameter_src ) ) { + // Line intersects triangle, check if ray does. + const QdN = - sign * _diff.dot( _normal$1 ); - uniforms_dst[ u ][ p ] = parameter_src.slice(); + // t < 0, no intersection + if ( QdN < 0 ) { - } else { + return null; - uniforms_dst[ u ][ p ] = parameter_src; + } - } + // Ray intersects triangle. + 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 ); + + } + +} + +class Matrix4 { + + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + Matrix4.prototype.isMatrix4 = true; + + this.elements = [ + + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ]; + + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); } - return uniforms_dst; + } + + 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() { -var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n"; + this.set( -var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n"; + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 -var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n"; + ); -var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n"; + return this; -var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; + } -var begin_vertex = "\nvec3 transformed = vec3( position );\n"; + clone() { -var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n"; + return new Matrix4().fromArray( this.elements ); -var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; + } -var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n"; + copy( m ) { -var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n"; + const te = this.elements; + const me = m.elements; -var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n"; + 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 ]; -var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n"; + return this; -var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n"; + } -var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif"; + copyPosition( m ) { -var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n"; + const te = this.elements, me = m.elements; -var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif"; + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; -var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif"; + return this; -var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n"; + } -var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n"; + setFromMatrix3( m ) { -var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n"; + const me = m.elements; -var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n"; + this.set( -var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; + 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 -var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n"; + ); -var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n"; + return this; -var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n"; + } -var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n"; + extractBasis( xAxis, yAxis, zAxis ) { -var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n"; + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); -var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n"; + return this; -var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n"; + } -var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n"; + makeBasis( xAxis, yAxis, zAxis ) { -var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif"; + 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 + ); -var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n"; + return this; -var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n"; + } -var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n"; + extractRotation( m ) { -var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n"; + // this method does not support reflection matrices -var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n"; + const te = this.elements; + const me = m.elements; -var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; + const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); + const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); + const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); -var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n"; + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; + te[ 3 ] = 0; -var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; + te[ 7 ] = 0; -var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n"; + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; + te[ 11 ] = 0; -var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n"; + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; -var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n"; + return this; -var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n"; + } -var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; + makeRotationFromEuler( euler ) { -var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; + const te = this.elements; -var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n"; + const x = euler.x, y = euler.y, z = euler.z; + const a = Math.cos( x ), b = Math.sin( x ); + const c = Math.cos( y ), d = Math.sin( y ); + const e = Math.cos( z ), f = Math.sin( z ); -var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif"; + if ( euler.order === 'XYZ' ) { -var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n"; + const ae = a * e, af = a * f, be = b * e, bf = b * f; -var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; -var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n"; + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; -var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; -var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n"; + } else if ( euler.order === 'YXZ' ) { -var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n"; + const ce = c * e, cf = c * f, de = d * e, df = d * f; -var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; -var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n"; + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; -var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif"; + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; -var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n"; + } else if ( euler.order === 'ZXY' ) { -var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; + const ce = c * e, cf = c * f, de = d * e, df = d * f; -var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; -var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 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\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; -var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n"; + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; -var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n"; + } else if ( euler.order === 'ZYX' ) { -var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n"; + const ae = a * e, af = a * f, be = b * e, bf = b * f; -var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; -var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n"; + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; -var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; -var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n"; + } else if ( euler.order === 'YZX' ) { -var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n"; + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; -var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = bd - ac * f; + te[ 8 ] = bc * f + ad; -var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n"; + te[ 1 ] = f; + te[ 5 ] = a * e; + te[ 9 ] = - b * e; -var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; + te[ 2 ] = - d * e; + te[ 6 ] = ad * f + bc; + te[ 10 ] = ac - bd * f; -var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n"; + } else if ( euler.order === 'XZY' ) { -var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n"; + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; -var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = - f; + te[ 8 ] = d * e; -var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; + te[ 1 ] = ac * f + bd; + te[ 5 ] = a * e; + te[ 9 ] = ad * f - bc; -var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; + te[ 2 ] = bc * f - ad; + te[ 6 ] = b * e; + te[ 10 ] = bd * f + ac; -var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n"; + } -var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n"; + // bottom row + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; -var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif"; + // last column + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; -var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n"; + return this; -var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; + } -var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; + makeRotationFromQuaternion( q ) { -var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif"; + return this.compose( _zero, q, _one ); -var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif"; + } -var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n"; + lookAt( eye, target, up ) { -var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; + const te = this.elements; -var cube_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n"; + _z.subVectors( eye, target ); -var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n"; + if ( _z.lengthSq() === 0 ) { -var depth_vert = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + // eye and target are in the same position -var distanceRGBA_frag = "#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n"; + _z.z = 1; -var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n"; + } -var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; + _z.normalize(); + _x.crossVectors( up, _z ); -var equirect_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; + if ( _x.lengthSq() === 0 ) { -var linedashed_frag = "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\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + // up and z are parallel -var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n"; + if ( Math.abs( up.z ) === 1 ) { -var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _z.x += 0.0001; -var meshbasic_vert = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } else { -var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _z.z += 0.0001; -var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } -var meshphong_frag = "#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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _z.normalize(); + _x.crossVectors( up, _z ); -var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } -var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _x.normalize(); + _y.crossVectors( _z, _x ); -var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n"; + 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; -var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; + return this; -var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; + } -var points_frag = "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\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + multiply( m ) { -var points_vert = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + return this.multiplyMatrices( this, m ); -var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n"; + } -var shadow_vert = "#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + premultiply( m ) { -var ShaderChunk = { - alphamap_fragment: alphamap_fragment, - alphamap_pars_fragment: alphamap_pars_fragment, - alphatest_fragment: alphatest_fragment, - aomap_fragment: aomap_fragment, - aomap_pars_fragment: aomap_pars_fragment, - begin_vertex: begin_vertex, - beginnormal_vertex: beginnormal_vertex, - bsdfs: bsdfs, - bumpmap_pars_fragment: bumpmap_pars_fragment, - clipping_planes_fragment: clipping_planes_fragment, - clipping_planes_pars_fragment: clipping_planes_pars_fragment, - clipping_planes_pars_vertex: clipping_planes_pars_vertex, - clipping_planes_vertex: clipping_planes_vertex, - color_fragment: color_fragment, - color_pars_fragment: color_pars_fragment, - color_pars_vertex: color_pars_vertex, - color_vertex: color_vertex, - common: common, - cube_uv_reflection_fragment: cube_uv_reflection_fragment, - defaultnormal_vertex: defaultnormal_vertex, - displacementmap_pars_vertex: displacementmap_pars_vertex, - displacementmap_vertex: displacementmap_vertex, - emissivemap_fragment: emissivemap_fragment, - emissivemap_pars_fragment: emissivemap_pars_fragment, - encodings_fragment: encodings_fragment, - encodings_pars_fragment: encodings_pars_fragment, - envmap_fragment: envmap_fragment, - envmap_pars_fragment: envmap_pars_fragment, - envmap_pars_vertex: envmap_pars_vertex, - envmap_vertex: envmap_vertex, - fog_vertex: fog_vertex, - fog_pars_vertex: fog_pars_vertex, - fog_fragment: fog_fragment, - fog_pars_fragment: fog_pars_fragment, - gradientmap_pars_fragment: gradientmap_pars_fragment, - lightmap_fragment: lightmap_fragment, - lightmap_pars_fragment: lightmap_pars_fragment, - lights_lambert_vertex: lights_lambert_vertex, - lights_pars: lights_pars, - lights_phong_fragment: lights_phong_fragment, - lights_phong_pars_fragment: lights_phong_pars_fragment, - lights_physical_fragment: lights_physical_fragment, - lights_physical_pars_fragment: lights_physical_pars_fragment, - lights_template: lights_template, - logdepthbuf_fragment: logdepthbuf_fragment, - logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, - logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, - logdepthbuf_vertex: logdepthbuf_vertex, - map_fragment: map_fragment, - map_pars_fragment: map_pars_fragment, - map_particle_fragment: map_particle_fragment, - map_particle_pars_fragment: map_particle_pars_fragment, - metalnessmap_fragment: metalnessmap_fragment, - metalnessmap_pars_fragment: metalnessmap_pars_fragment, - morphnormal_vertex: morphnormal_vertex, - morphtarget_pars_vertex: morphtarget_pars_vertex, - morphtarget_vertex: morphtarget_vertex, - normal_fragment: normal_fragment, - normalmap_pars_fragment: normalmap_pars_fragment, - packing: packing, - premultiplied_alpha_fragment: premultiplied_alpha_fragment, - project_vertex: project_vertex, - dithering_fragment: dithering_fragment, - dithering_pars_fragment: dithering_pars_fragment, - roughnessmap_fragment: roughnessmap_fragment, - roughnessmap_pars_fragment: roughnessmap_pars_fragment, - shadowmap_pars_fragment: shadowmap_pars_fragment, - shadowmap_pars_vertex: shadowmap_pars_vertex, - shadowmap_vertex: shadowmap_vertex, - shadowmask_pars_fragment: shadowmask_pars_fragment, - skinbase_vertex: skinbase_vertex, - skinning_pars_vertex: skinning_pars_vertex, - skinning_vertex: skinning_vertex, - skinnormal_vertex: skinnormal_vertex, - specularmap_fragment: specularmap_fragment, - specularmap_pars_fragment: specularmap_pars_fragment, - tonemapping_fragment: tonemapping_fragment, - tonemapping_pars_fragment: tonemapping_pars_fragment, - uv_pars_fragment: uv_pars_fragment, - uv_pars_vertex: uv_pars_vertex, - uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, - worldpos_vertex: worldpos_vertex, - - cube_frag: cube_frag, - cube_vert: cube_vert, - depth_frag: depth_frag, - depth_vert: depth_vert, - distanceRGBA_frag: distanceRGBA_frag, - distanceRGBA_vert: distanceRGBA_vert, - equirect_frag: equirect_frag, - equirect_vert: equirect_vert, - linedashed_frag: linedashed_frag, - linedashed_vert: linedashed_vert, - meshbasic_frag: meshbasic_frag, - meshbasic_vert: meshbasic_vert, - meshlambert_frag: meshlambert_frag, - meshlambert_vert: meshlambert_vert, - meshphong_frag: meshphong_frag, - meshphong_vert: meshphong_vert, - meshphysical_frag: meshphysical_frag, - meshphysical_vert: meshphysical_vert, - normal_frag: normal_frag, - normal_vert: normal_vert, - points_frag: points_frag, - points_vert: points_vert, - shadow_frag: shadow_frag, - shadow_vert: shadow_vert -}; - -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -var ShaderLib = { - - basic: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.meshbasic_vert, - fragmentShader: ShaderChunk.meshbasic_frag - - }, - - lambert: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) } - } - ] ), - - vertexShader: ShaderChunk.meshlambert_vert, - fragmentShader: ShaderChunk.meshlambert_frag - - }, - - phong: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - UniformsLib.gradientmap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) }, - specular: { value: new Color( 0x111111 ) }, - shininess: { value: 30 } - } - ] ), - - vertexShader: ShaderChunk.meshphong_vert, - fragmentShader: ShaderChunk.meshphong_frag - - }, - - standard: { - - uniforms: UniformsUtils.merge( [ - 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: new Color( 0x000000 ) }, - roughness: { value: 0.5 }, - metalness: { value: 0.5 }, - envMapIntensity: { value: 1 } // temporary - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - - }, - - points: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.points, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.points_vert, - fragmentShader: ShaderChunk.points_frag - - }, - - dashed: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.fog, - { - scale: { value: 1 }, - dashSize: { value: 1 }, - totalSize: { value: 2 } - } - ] ), - - vertexShader: ShaderChunk.linedashed_vert, - fragmentShader: ShaderChunk.linedashed_frag - - }, - - depth: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap - ] ), - - vertexShader: ShaderChunk.depth_vert, - fragmentShader: ShaderChunk.depth_frag - - }, - - normal: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - { - opacity: { value: 1.0 } - } - ] ), - - vertexShader: ShaderChunk.normal_vert, - fragmentShader: ShaderChunk.normal_frag - - }, - - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ - - cube: { - - uniforms: { - tCube: { value: null }, - tFlip: { value: - 1 }, - opacity: { value: 1.0 } - }, - - vertexShader: ShaderChunk.cube_vert, - fragmentShader: ShaderChunk.cube_frag - - }, - - equirect: { - - uniforms: { - tEquirect: { value: null }, - }, - - vertexShader: ShaderChunk.equirect_vert, - fragmentShader: ShaderChunk.equirect_frag - - }, - - distanceRGBA: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap, - { - referencePosition: { value: new Vector3() }, - nearDistance: { value: 1 }, - farDistance: { value: 1000 } - } - ] ), - - vertexShader: ShaderChunk.distanceRGBA_vert, - fragmentShader: ShaderChunk.distanceRGBA_frag - - }, - - shadow: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.lights, - UniformsLib.fog, - { - color: { value: new Color( 0x00000 ) }, - opacity: { value: 1.0 } - } ] ), - - vertexShader: ShaderChunk.shadow_vert, - fragmentShader: ShaderChunk.shadow_frag - - } - -}; - -ShaderLib.physical = { - - uniforms: UniformsUtils.merge( [ - ShaderLib.standard.uniforms, - { - clearCoat: { value: 0 }, - clearCoatRoughness: { value: 0 } - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - -}; - -/** - * @author bhouston / http://clara.io - */ - -function Box2( min, max ) { - - this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity ); - -} - -Object.assign( Box2.prototype, { - - set: function ( min, max ) { - - this.min.copy( min ); - this.max.copy( max ); - - return this; - - }, - - setFromPoints: function ( points ) { - - this.makeEmpty(); - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - this.expandByPoint( points[ i ] ); - - } - - return this; - - }, - - setFromCenterAndSize: function () { - - var v1 = new Vector2(); - - return function setFromCenterAndSize( center, size ) { - - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); - - return this; - - }, - - makeEmpty: function () { - - this.min.x = this.min.y = + Infinity; - this.max.x = this.max.y = - Infinity; - - return this; - - }, - - isEmpty: function () { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); - - }, - - getSize: function ( optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.subVectors( this.max, this.min ); - - }, - - expandByPoint: function ( point ) { - - this.min.min( point ); - this.max.max( point ); - - return this; - - }, - - expandByVector: function ( vector ) { - - this.min.sub( vector ); - this.max.add( vector ); - - return this; - - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); - - return this; - - }, - - containsPoint: function ( 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: function ( 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: function ( point, optionalTarget ) { - - // This can potentially have a divide by zero if the box - // has a size dimension of 0. - - var result = optionalTarget || new Vector2(); - - return result.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ) - ); - - }, - - intersectsBox: function ( box ) { - - // using 4 splitting planes to rule out intersections - - 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: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return result.copy( point ).clamp( this.min, this.max ); - - }, - - distanceToPoint: function () { - - var v1 = new Vector2(); - - return function distanceToPoint( point ) { - - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); - - }; - - }(), - - intersect: function ( box ) { - - this.min.max( box.min ); - this.max.min( box.max ); - - return this; - - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); - - return this; - - }, - - translate: function ( offset ) { - - this.min.add( offset ); - this.max.add( offset ); - - return this; - - }, - - equals: function ( box ) { - - return box.min.equals( this.min ) && box.max.equals( this.max ); - - } - -} ); - -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - -function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) { - - var vertexBuffer, elementBuffer; - var shader, program, attributes, uniforms; - - var tempTexture, occlusionTexture; - - function init() { - - var vertices = new Float32Array( [ - - 1, - 1, 0, 0, - 1, - 1, 1, 0, - 1, 1, 1, 1, - - 1, 1, 0, 1 - ] ); - - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); - - // buffers - - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); - - // textures - - tempTexture = gl.createTexture(); - occlusionTexture = gl.createTexture(); - - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - - shader = { - - vertexShader: [ - - 'uniform lowp int renderType;', - - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', - 'uniform float rotation;', - - 'uniform sampler2D occlusionMap;', - - 'attribute vec2 position;', - 'attribute vec2 uv;', - - 'varying vec2 vUV;', - 'varying float vVisibility;', - - 'void main() {', - - ' vUV = uv;', - - ' vec2 pos = position;', - - ' if ( renderType == 2 ) {', - - ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', - - ' vVisibility = visibility.r / 9.0;', - ' vVisibility *= 1.0 - visibility.g / 9.0;', - ' vVisibility *= visibility.b / 9.0;', - ' vVisibility *= 1.0 - visibility.a / 9.0;', - - ' pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;', - ' pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;', - - ' }', - - ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', - - '}' - - ].join( '\n' ), - - fragmentShader: [ - - 'uniform lowp int renderType;', - - 'uniform sampler2D map;', - 'uniform float opacity;', - 'uniform vec3 color;', - - 'varying vec2 vUV;', - 'varying float vVisibility;', - - 'void main() {', - - // pink square - - ' if ( renderType == 0 ) {', - - ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );', - - // restore - - ' } else if ( renderType == 1 ) {', - - ' gl_FragColor = texture2D( map, vUV );', - - // flare - - ' } else {', - - ' vec4 texture = texture2D( map, vUV );', - ' texture.a *= opacity * vVisibility;', - ' gl_FragColor = texture;', - ' gl_FragColor.rgb *= color;', - - ' }', - - '}' - - ].join( '\n' ) - - }; - - program = createProgram( shader ); - - attributes = { - vertex: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; - - uniforms = { - renderType: gl.getUniformLocation( program, 'renderType' ), - map: gl.getUniformLocation( program, 'map' ), - occlusionMap: gl.getUniformLocation( program, 'occlusionMap' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - color: gl.getUniformLocation( program, 'color' ), - scale: gl.getUniformLocation( program, 'scale' ), - rotation: gl.getUniformLocation( program, 'rotation' ), - screenPosition: gl.getUniformLocation( program, 'screenPosition' ) - }; - - } - - /* - * Render lens flares - * Method: renders 16x16 0xff00ff-colored points scattered over the light source area, - * reads these back and calculates occlusion. - */ - - this.render = function ( flares, scene, camera, viewport ) { - - if ( flares.length === 0 ) { return; } - - var tempPosition = new Vector3(); - - var invAspect = viewport.w / viewport.z, - halfViewportWidth = viewport.z * 0.5, - halfViewportHeight = viewport.w * 0.5; - - var size = 16 / viewport.w, - scale = new Vector2( size * invAspect, size ); - - var screenPosition = new Vector3( 1, 1, 0 ), - screenPositionPixels = new Vector2( 1, 1 ); - - var validArea = new Box2(); - - validArea.min.set( viewport.x, viewport.y ); - validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); - - if ( program === undefined ) { - - init(); - - } - - state.useProgram( program ); - - state.initAttributes(); - state.enableAttribute( attributes.vertex ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); - - // loop through all lens flares to update their occlusion and positions - // setup gl and common used attribs/uniforms - - gl.uniform1i( uniforms.occlusionMap, 0 ); - gl.uniform1i( uniforms.map, 1 ); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - - state.disable( gl.CULL_FACE ); - state.buffers.depth.setMask( false ); - - for ( var i = 0, l = flares.length; i < l; i ++ ) { - - size = 16 / viewport.w; - scale.set( size * invAspect, size ); - - // calc object screen position - - var flare = flares[ i ]; - - tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] ); - - tempPosition.applyMatrix4( camera.matrixWorldInverse ); - tempPosition.applyMatrix4( camera.projectionMatrix ); - - // setup arrays for gl programs - - screenPosition.copy( tempPosition ); - - // horizontal and vertical coordinate of the lower left corner of the pixels to copy - - screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8; - screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8; - - // screen cull - - if ( validArea.containsPoint( screenPositionPixels ) === true ) { - - // save current RGB to temp texture - - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, null ); - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); - - - // render pink quad - - gl.uniform1i( uniforms.renderType, 0 ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - - state.disable( gl.BLEND ); - state.enable( gl.DEPTH_TEST ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - - // copy result to occlusionMap - - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); - - - // restore graphics - - gl.uniform1i( uniforms.renderType, 1 ); - state.disable( gl.DEPTH_TEST ); - - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - - // update object positions - - flare.positionScreen.copy( screenPosition ); - - if ( flare.customUpdateCallback ) { - - flare.customUpdateCallback( flare ); - - } else { - - flare.updateLensFlares(); - - } - - // render flares - - gl.uniform1i( uniforms.renderType, 2 ); - state.enable( gl.BLEND ); - - for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) { - - var sprite = flare.lensFlares[ j ]; - - if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) { - - screenPosition.x = sprite.x; - screenPosition.y = sprite.y; - screenPosition.z = sprite.z; - - size = sprite.size * sprite.scale / viewport.w; - - scale.x = size * invAspect; - scale.y = size; - - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform1f( uniforms.rotation, sprite.rotation ); - - gl.uniform1f( uniforms.opacity, sprite.opacity ); - gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); - - state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); - - textures.setTexture2D( sprite.texture, 1 ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - } - - } - - } - - } - - // restore gl - - state.enable( gl.CULL_FACE ); - state.enable( gl.DEPTH_TEST ); - state.buffers.depth.setMask( true ); - - state.reset(); - - }; - - function createProgram( shader ) { - - var program = gl.createProgram(); - - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - - var prefix = 'precision ' + capabilities.precision + ' float;\n'; - - gl.shaderSource( fragmentShader, prefix + shader.fragmentShader ); - gl.shaderSource( vertexShader, prefix + shader.vertexShader ); - - gl.compileShader( fragmentShader ); - gl.compileShader( vertexShader ); - - gl.attachShader( program, fragmentShader ); - gl.attachShader( program, vertexShader ); - - gl.linkProgram( program ); - - return program; - - } - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { - - Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - - this.needsUpdate = true; - -} - -CanvasTexture.prototype = Object.create( Texture.prototype ); -CanvasTexture.prototype.constructor = CanvasTexture; - -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - -function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { - - var vertexBuffer, elementBuffer; - var program, attributes, uniforms; - - var texture; - - // decompose matrixWorld - - var spritePosition = new Vector3(); - var spriteRotation = new Quaternion(); - var spriteScale = new Vector3(); - - function init() { - - var vertices = new Float32Array( [ - - 0.5, - 0.5, 0, 0, - 0.5, - 0.5, 1, 0, - 0.5, 0.5, 1, 1, - - 0.5, 0.5, 0, 1 - ] ); - - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); - - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); - - program = createProgram(); - - attributes = { - position: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; - - uniforms = { - uvOffset: gl.getUniformLocation( program, 'uvOffset' ), - uvScale: gl.getUniformLocation( program, 'uvScale' ), - - rotation: gl.getUniformLocation( program, 'rotation' ), - scale: gl.getUniformLocation( program, 'scale' ), - - color: gl.getUniformLocation( program, 'color' ), - map: gl.getUniformLocation( program, 'map' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - - modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ), - projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ), - - fogType: gl.getUniformLocation( program, 'fogType' ), - fogDensity: gl.getUniformLocation( program, 'fogDensity' ), - fogNear: gl.getUniformLocation( program, 'fogNear' ), - fogFar: gl.getUniformLocation( program, 'fogFar' ), - fogColor: gl.getUniformLocation( program, 'fogColor' ), - fogDepth: gl.getUniformLocation( program, 'fogDepth' ), - - alphaTest: gl.getUniformLocation( program, 'alphaTest' ) - }; - - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = 8; - canvas.height = 8; - - var context = canvas.getContext( '2d' ); - context.fillStyle = 'white'; - context.fillRect( 0, 0, 8, 8 ); - - texture = new CanvasTexture( canvas ); - - } - - this.render = function ( sprites, scene, camera ) { - - if ( sprites.length === 0 ) { return; } - - // setup gl - - if ( program === undefined ) { - - init(); - - } - - state.useProgram( program ); - - state.initAttributes(); - state.enableAttribute( attributes.position ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); - - state.disable( gl.CULL_FACE ); - state.enable( gl.BLEND ); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - - gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements ); - - state.activeTexture( gl.TEXTURE0 ); - gl.uniform1i( uniforms.map, 0 ); - - var oldFogType = 0; - var sceneFogType = 0; - var fog = scene.fog; - - if ( fog ) { - - gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b ); - - if ( fog.isFog ) { - - gl.uniform1f( uniforms.fogNear, fog.near ); - gl.uniform1f( uniforms.fogFar, fog.far ); - - gl.uniform1i( uniforms.fogType, 1 ); - oldFogType = 1; - sceneFogType = 1; - - } else if ( fog.isFogExp2 ) { - - gl.uniform1f( uniforms.fogDensity, fog.density ); - - gl.uniform1i( uniforms.fogType, 2 ); - oldFogType = 2; - sceneFogType = 2; - - } - - } else { - - gl.uniform1i( uniforms.fogType, 0 ); - oldFogType = 0; - sceneFogType = 0; - - } - - - // update positions and sort - - for ( var i = 0, l = sprites.length; i < l; i ++ ) { - - var sprite = sprites[ i ]; - - sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); - sprite.z = - sprite.modelViewMatrix.elements[ 14 ]; - - } - - sprites.sort( painterSortStable ); - - // render all sprites - - var scale = []; - - for ( var i = 0, l = sprites.length; i < l; i ++ ) { - - var sprite = sprites[ i ]; - var material = sprite.material; - - if ( material.visible === false ) { continue; } - - sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); - - gl.uniform1f( uniforms.alphaTest, material.alphaTest ); - gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); - - sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale ); - - scale[ 0 ] = spriteScale.x; - scale[ 1 ] = spriteScale.y; - - var fogType = 0; - - if ( scene.fog && material.fog ) { - - fogType = sceneFogType; - - } - - if ( oldFogType !== fogType ) { - - gl.uniform1i( uniforms.fogType, fogType ); - oldFogType = fogType; - - } - - if ( material.map !== null ) { - - gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y ); - gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y ); - - } else { - - gl.uniform2f( uniforms.uvOffset, 0, 0 ); - gl.uniform2f( uniforms.uvScale, 1, 1 ); - - } - - gl.uniform1f( uniforms.opacity, material.opacity ); - gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b ); - - gl.uniform1f( uniforms.rotation, material.rotation ); - gl.uniform2fv( uniforms.scale, scale ); - - state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); - state.buffers.depth.setTest( material.depthTest ); - state.buffers.depth.setMask( material.depthWrite ); - state.buffers.color.setMask( material.colorWrite ); - - textures.setTexture2D( material.map || texture, 0 ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); - - } - - // restore gl - - state.enable( gl.CULL_FACE ); - - state.reset(); - - }; - - function createProgram() { - - var program = gl.createProgram(); - - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - - gl.shaderSource( vertexShader, [ - - 'precision ' + capabilities.precision + ' float;', - - '#define SHADER_NAME ' + 'SpriteMaterial', - - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform float rotation;', - 'uniform vec2 scale;', - 'uniform vec2 uvOffset;', - 'uniform vec2 uvScale;', - - 'attribute vec2 position;', - 'attribute vec2 uv;', - - 'varying vec2 vUV;', - 'varying float fogDepth;', - - 'void main() {', - - ' vUV = uvOffset + uv * uvScale;', - - ' vec2 alignedPosition = position * scale;', - - ' vec2 rotatedPosition;', - ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', - ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', - - ' vec4 mvPosition;', - - ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', - ' mvPosition.xy += rotatedPosition;', - - ' gl_Position = projectionMatrix * mvPosition;', - - ' fogDepth = - mvPosition.z;', - - '}' - - ].join( '\n' ) ); - - gl.shaderSource( fragmentShader, [ - - 'precision ' + capabilities.precision + ' float;', - - '#define SHADER_NAME ' + 'SpriteMaterial', - - 'uniform vec3 color;', - 'uniform sampler2D map;', - 'uniform float opacity;', - - 'uniform int fogType;', - 'uniform vec3 fogColor;', - 'uniform float fogDensity;', - 'uniform float fogNear;', - 'uniform float fogFar;', - 'uniform float alphaTest;', - - 'varying vec2 vUV;', - 'varying float fogDepth;', - - 'void main() {', - - ' vec4 texture = texture2D( map, vUV );', - - ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', - - ' if ( gl_FragColor.a < alphaTest ) discard;', - - ' if ( fogType > 0 ) {', - - ' float fogFactor = 0.0;', - - ' if ( fogType == 1 ) {', - - ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );', - - ' } else {', - - ' const float LOG2 = 1.442695;', - ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', - ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', - - ' }', - - ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', - - ' }', - - '}' - - ].join( '\n' ) ); - - gl.compileShader( vertexShader ); - gl.compileShader( fragmentShader ); - - gl.attachShader( program, vertexShader ); - gl.attachShader( program, fragmentShader ); - - gl.linkProgram( program ); - - return program; - - } - - function painterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } else if ( a.z !== b.z ) { - - return b.z - a.z; - - } else { - - return b.id - a.id; - - } - - } - -} - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -var materialId = 0; - -function Material() { - - Object.defineProperty( this, 'id', { value: materialId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Material'; - - this.fog = true; - this.lights = true; - - this.blending = NormalBlending; - this.side = FrontSide; - this.flatShading = false; - this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors - - 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.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; - - this.colorWrite = true; - - this.precision = null; // override the renderer's default precision for this material - - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; - - this.dithering = false; - - this.alphaTest = 0; - this.premultipliedAlpha = false; - - this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer - - this.visible = true; - - this.userData = {}; - - this.needsUpdate = true; - -} - -Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: Material, - - isMaterial: true, - - onBeforeCompile: function () {}, - - setValues: function ( values ) { - - if ( values === undefined ) { return; } - - for ( var key in values ) { - - var newValue = values[ key ]; - - if ( newValue === undefined ) { - - console.warn( "THREE.Material: '" + key + "' parameter is undefined." ); - continue; - - } - - // for backward compatability if shading is set in the constructor - if ( key === 'shading' ) { - - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( newValue === FlatShading ) ? true : false; - continue; - - } - - var currentValue = this[ key ]; - - if ( currentValue === undefined ) { - - 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 if ( key === 'overdraw' ) { - - // ensure overdraw is backwards-compatible with legacy boolean type - this[ key ] = Number( newValue ); - - } else { - - this[ key ] = newValue; - - } - - } - - }, - - toJSON: function ( meta ) { - - var isRoot = ( meta === undefined || typeof meta === 'string' ); - - if ( isRoot ) { - - meta = { - textures: {}, - images: {} - }; - - } - - var data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; - - // standard Material serialization - 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 !== undefined ) { data.roughness = this.roughness; } - if ( this.metalness !== undefined ) { data.metalness = this.metalness; } - - if ( this.emissive && this.emissive.isColor ) { data.emissive = this.emissive.getHex(); } - if ( this.emissiveIntensity !== 1 ) { data.emissiveIntensity = this.emissiveIntensity; } - - if ( this.specular && this.specular.isColor ) { data.specular = this.specular.getHex(); } - if ( this.shininess !== undefined ) { data.shininess = this.shininess; } - if ( this.clearCoat !== undefined ) { data.clearCoat = this.clearCoat; } - if ( this.clearCoatRoughness !== undefined ) { data.clearCoatRoughness = this.clearCoatRoughness; } - - if ( this.map && this.map.isTexture ) { data.map = this.map.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; } - 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.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.envMap && this.envMap.isTexture ) { - - data.envMap = this.envMap.toJSON( meta ).uuid; - data.reflectivity = this.reflectivity; // Scale behind envMap - - } - - if ( this.gradientMap && this.gradientMap.isTexture ) { - - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; - - } - - if ( this.size !== undefined ) { data.size = this.size; } - if ( this.sizeAttenuation !== undefined ) { data.sizeAttenuation = this.sizeAttenuation; } - - if ( this.blending !== NormalBlending ) { data.blending = this.blending; } - if ( this.flatShading === true ) { data.flatShading = this.flatShading; } - if ( this.side !== FrontSide ) { data.side = this.side; } - if ( this.vertexColors !== NoColors ) { data.vertexColors = this.vertexColors; } - - 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; - - // rotation (SpriteMaterial) - if ( this.rotation !== 0 ) { data.rotation = this.rotation; } - - if ( this.linewidth !== 1 ) { data.linewidth = this.linewidth; } - if ( this.dashSize !== undefined ) { data.dashSize = this.dashSize; } - if ( this.gapSize !== undefined ) { data.gapSize = this.gapSize; } - if ( this.scale !== undefined ) { data.scale = this.scale; } - - if ( this.dithering === true ) { data.dithering = true; } - - if ( this.alphaTest > 0 ) { data.alphaTest = this.alphaTest; } - 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.morphTargets === true ) { data.morphTargets = true; } - if ( this.skinning === true ) { data.skinning = true; } - - if ( this.visible === false ) { data.visible = false; } - if ( JSON.stringify( this.userData ) !== '{}' ) { data.userData = this.userData; } - - // TODO: Copied from Object3D.toJSON - - function extractFromCache( cache ) { - - var values = []; - - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - - return values; - - } - - if ( isRoot ) { - - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - - if ( textures.length > 0 ) { data.textures = textures; } - if ( images.length > 0 ) { data.images = images; } - - } - - return data; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.name = source.name; - - this.fog = source.fog; - this.lights = source.lights; - - this.blending = source.blending; - this.side = source.side; - this.flatShading = source.flatShading; - 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.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.premultipliedAlpha = source.premultipliedAlpha; - - this.overdraw = source.overdraw; - - this.visible = source.visible; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); - - this.clipShadows = source.clipShadows; - this.clipIntersection = source.clipIntersection; - - var srcPlanes = source.clippingPlanes, - dstPlanes = null; - - if ( srcPlanes !== null ) { - - var n = srcPlanes.length; - dstPlanes = new Array( n ); - - for ( var i = 0; i !== n; ++ i ) - { dstPlanes[ i ] = srcPlanes[ i ].clone(); } - - } - - this.clippingPlanes = dstPlanes; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author bhouston / https://clara.io - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * - * opacity: , - * - * map: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * wireframe: , - * wireframeLinewidth: - * } - */ - -function MeshDepthMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshDepthMaterial'; - - this.depthPacking = BasicDepthPacking; - - this.skinning = false; - this.morphTargets = false; - - this.map = null; - - this.alphaMap = null; - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - -} - -MeshDepthMaterial.prototype = Object.create( Material.prototype ); -MeshDepthMaterial.prototype.constructor = MeshDepthMaterial; - -MeshDepthMaterial.prototype.isMeshDepthMaterial = true; - -MeshDepthMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.depthPacking = source.depthPacking; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - 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; - -}; - -/** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * - * referencePosition: , - * nearDistance: , - * farDistance: , - * - * skinning: , - * morphTargets: , - * - * map: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: - * - * } - */ - -function MeshDistanceMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshDistanceMaterial'; - - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - - this.skinning = false; - this.morphTargets = false; - - this.map = null; - - this.alphaMap = null; - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - -} - -MeshDistanceMaterial.prototype = Object.create( Material.prototype ); -MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; - -MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; - -MeshDistanceMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - this.map = source.map; - - this.alphaMap = source.alphaMap; - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - return this; - -}; - -/** - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - */ - -function Box3( min, max ) { - - this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity ); - -} - -Object.assign( Box3.prototype, { - - isBox3: true, - - set: function ( min, max ) { - - this.min.copy( min ); - this.max.copy( max ); - - return this; - - }, - - setFromArray: function ( array ) { - - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; - - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; - - for ( var i = 0, l = array.length; i < l; i += 3 ) { - - var x = array[ i ]; - var y = array[ i + 1 ]; - var z = array[ i + 2 ]; - - if ( x < minX ) { minX = x; } - if ( y < minY ) { minY = y; } - if ( z < minZ ) { minZ = z; } - - if ( x > maxX ) { maxX = x; } - if ( y > maxY ) { maxY = y; } - if ( z > maxZ ) { maxZ = z; } - - } - - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - - return this; - - }, - - setFromBufferAttribute: function ( attribute ) { - - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; - - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - var x = attribute.getX( i ); - var y = attribute.getY( i ); - var z = attribute.getZ( i ); - - if ( x < minX ) { minX = x; } - if ( y < minY ) { minY = y; } - if ( z < minZ ) { minZ = z; } - - if ( x > maxX ) { maxX = x; } - if ( y > maxY ) { maxY = y; } - if ( z > maxZ ) { maxZ = z; } - - } - - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - - return this; - - }, - - setFromPoints: function ( points ) { - - this.makeEmpty(); - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - this.expandByPoint( points[ i ] ); - - } - - return this; - - }, - - setFromCenterAndSize: function () { - - var v1 = new Vector3(); - - return function setFromCenterAndSize( center, size ) { - - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); - - return this; - - }; - - }(), - - setFromObject: function ( object ) { - - this.makeEmpty(); - - return this.expandByObject( object ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); - - return this; - - }, - - makeEmpty: function () { - - this.min.x = this.min.y = this.min.z = + Infinity; - this.max.x = this.max.y = this.max.z = - Infinity; - - return this; - - }, - - isEmpty: function () { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); - - }, - - getSize: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.subVectors( this.max, this.min ); - - }, - - expandByPoint: function ( point ) { - - this.min.min( point ); - this.max.max( point ); - - return this; - - }, - - expandByVector: function ( vector ) { - - this.min.sub( vector ); - this.max.add( vector ); - - return this; - - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); - - return this; - - }, - - expandByObject: function () { - - // Computes the world-axis-aligned bounding box of an object (including its children), - // accounting for both the object's, and children's, world transforms - - var scope, i, l; - - var v1 = new Vector3(); - - function traverse( node ) { - - var geometry = node.geometry; - - if ( geometry !== undefined ) { - - if ( geometry.isGeometry ) { - - var vertices = geometry.vertices; - - for ( i = 0, l = vertices.length; i < l; i ++ ) { - - v1.copy( vertices[ i ] ); - v1.applyMatrix4( node.matrixWorld ); - - scope.expandByPoint( v1 ); - - } - - } else if ( geometry.isBufferGeometry ) { - - var attribute = geometry.attributes.position; - - if ( attribute !== undefined ) { - - for ( i = 0, l = attribute.count; i < l; i ++ ) { - - v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); - - scope.expandByPoint( v1 ); - - } - - } - - } - - } - - } - - return function expandByObject( object ) { - - scope = this; - - object.updateMatrixWorld( true ); - - object.traverse( traverse ); - - return this; - - }; - - }(), - - containsPoint: function ( 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: function ( 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: function ( point, optionalTarget ) { - - // This can potentially have a divide by zero if the box - // has a size dimension of 0. - - var result = optionalTarget || new Vector3(); - - return result.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: function ( box ) { - - // using 6 splitting planes to rule out intersections. - 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: ( function () { - - var closestPoint = new Vector3(); - - return function intersectsSphere( sphere ) { - - // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, closestPoint ); - - // If that point is inside the sphere, the AABB and sphere intersect. - return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); - - }; - - } )(), - - intersectsPlane: function ( plane ) { - - // We compute the minimum and maximum dot product values. If those values - // are on the same side (back or front) of the plane, then there is no intersection. - - var min, max; - - if ( plane.normal.x > 0 ) { - - min = plane.normal.x * this.min.x; - max = plane.normal.x * this.max.x; - - } else { - - min = plane.normal.x * this.max.x; - max = plane.normal.x * this.min.x; - - } - - if ( plane.normal.y > 0 ) { - - min += plane.normal.y * this.min.y; - max += plane.normal.y * this.max.y; - - } else { - - min += plane.normal.y * this.max.y; - max += plane.normal.y * this.min.y; - - } - - if ( plane.normal.z > 0 ) { - - min += plane.normal.z * this.min.z; - max += plane.normal.z * this.max.z; - - } else { - - min += plane.normal.z * this.max.z; - max += plane.normal.z * this.min.z; - - } - - return ( min <= plane.constant && max >= plane.constant ); - - }, - - clampPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.copy( point ).clamp( this.min, this.max ); - - }, - - distanceToPoint: function () { - - var v1 = new Vector3(); - - return function distanceToPoint( point ) { - - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); - - }; - - }(), - - getBoundingSphere: function () { - - var v1 = new Vector3(); - - return function getBoundingSphere( optionalTarget ) { - - var result = optionalTarget || new Sphere(); - - this.getCenter( result.center ); - - result.radius = this.getSize( v1 ).length() * 0.5; - - return result; - - }; - - }(), - - intersect: function ( box ) { - - this.min.max( box.min ); - this.max.min( box.max ); - - // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. - if ( this.isEmpty() ) { this.makeEmpty(); } - - return this; - - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); - - return this; - - }, - - applyMatrix4: function () { - - var points = [ - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3() - ]; - - return function applyMatrix4( matrix ) { - - // transform of empty box is an empty box. - if ( this.isEmpty() ) { return this; } - - // NOTE: I am using a binary pattern to specify all 2^3 combinations below - points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 - points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 - points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 - points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 - points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 - points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 - points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 - points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 - - this.setFromPoints( points ); - - return this; - - }; - - }(), - - translate: function ( offset ) { - - this.min.add( offset ); - this.max.add( offset ); - - return this; - - }, - - equals: function ( box ) { - - return box.min.equals( this.min ) && box.max.equals( this.max ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ - -function Sphere( center, radius ) { - - this.center = ( center !== undefined ) ? center : new Vector3(); - this.radius = ( radius !== undefined ) ? radius : 0; - -} - -Object.assign( Sphere.prototype, { - - set: function ( center, radius ) { - - this.center.copy( center ); - this.radius = radius; - - return this; - - }, - - setFromPoints: function () { - - var box = new Box3(); - - return function setFromPoints( points, optionalCenter ) { - - var center = this.center; - - if ( optionalCenter !== undefined ) { - - center.copy( optionalCenter ); - - } else { - - box.setFromPoints( points ).getCenter( center ); - - } - - var maxRadiusSq = 0; - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); - - } - - this.radius = Math.sqrt( maxRadiusSq ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( sphere ) { - - this.center.copy( sphere.center ); - this.radius = sphere.radius; - - return this; - - }, - - empty: function () { - - return ( this.radius <= 0 ); - - }, - - containsPoint: function ( point ) { - - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - - }, - - distanceToPoint: function ( point ) { - - return ( point.distanceTo( this.center ) - this.radius ); - - }, - - intersectsSphere: function ( sphere ) { - - var radiusSum = this.radius + sphere.radius; - - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsSphere( this ); - - }, - - intersectsPlane: function ( plane ) { - - return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - - }, - - clampPoint: function ( point, optionalTarget ) { - - var deltaLengthSq = this.center.distanceToSquared( point ); - - var result = optionalTarget || new Vector3(); - - result.copy( point ); - - if ( deltaLengthSq > ( this.radius * this.radius ) ) { - - result.sub( this.center ).normalize(); - result.multiplyScalar( this.radius ).add( this.center ); - - } - - return result; - - }, - - getBoundingBox: function ( optionalTarget ) { - - var box = optionalTarget || new Box3(); - - box.set( this.center, this.center ); - box.expandByScalar( this.radius ); - - return box; - - }, - - applyMatrix4: function ( matrix ) { - - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); - - return this; - - }, - - translate: function ( offset ) { - - this.center.add( offset ); - - return this; - - }, - - equals: function ( sphere ) { - - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - */ - -function Plane( normal, constant ) { - - // normal is assumed to be normalized - - this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); - this.constant = ( constant !== undefined ) ? constant : 0; - -} - -Object.assign( Plane.prototype, { - - set: function ( normal, constant ) { - - this.normal.copy( normal ); - this.constant = constant; - - return this; - - }, - - setComponents: function ( x, y, z, w ) { - - this.normal.set( x, y, z ); - this.constant = w; - - return this; - - }, - - setFromNormalAndCoplanarPoint: function ( normal, point ) { - - this.normal.copy( normal ); - this.constant = - point.dot( this.normal ); - - return this; - - }, - - setFromCoplanarPoints: function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function setFromCoplanarPoints( a, b, c ) { - - var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize(); - - // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? - - this.setFromNormalAndCoplanarPoint( normal, a ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( plane ) { - - this.normal.copy( plane.normal ); - this.constant = plane.constant; - - return this; - - }, - - normalize: function () { - - // Note: will lead to a divide by zero if the plane is invalid. - - var inverseNormalLength = 1.0 / this.normal.length(); - this.normal.multiplyScalar( inverseNormalLength ); - this.constant *= inverseNormalLength; - - return this; - - }, - - negate: function () { - - this.constant *= - 1; - this.normal.negate(); - - return this; - - }, - - distanceToPoint: function ( point ) { - - return this.normal.dot( point ) + this.constant; - - }, - - distanceToSphere: function ( sphere ) { - - return this.distanceToPoint( sphere.center ) - sphere.radius; - - }, - - projectPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); - - }, - - intersectLine: function () { - - var v1 = new Vector3(); - - return function intersectLine( line, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - var direction = line.delta( v1 ); - - var denominator = this.normal.dot( direction ); - - if ( denominator === 0 ) { - - // line is coplanar, return origin - if ( this.distanceToPoint( line.start ) === 0 ) { - - return result.copy( line.start ); - - } - - // Unsure if this is the correct method to handle this case. - return undefined; - - } - - var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - - if ( t < 0 || t > 1 ) { - - return undefined; - - } - - return result.copy( direction ).multiplyScalar( t ).add( line.start ); - - }; - - }(), - - intersectsLine: function ( line ) { - - // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. - - var startSign = this.distanceToPoint( line.start ); - var endSign = this.distanceToPoint( line.end ); - - return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsPlane( this ); - - }, - - intersectsSphere: function ( sphere ) { - - return sphere.intersectsPlane( this ); - - }, - - coplanarPoint: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.normal ).multiplyScalar( - this.constant ); - - }, - - applyMatrix4: function () { - - var v1 = new Vector3(); - var m1 = new Matrix3(); - - return function applyMatrix4( matrix, optionalNormalMatrix ) { - - var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); - - var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); - - var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - - this.constant = - referencePoint.dot( normal ); - - return this; - - }; - - }(), - - translate: function ( offset ) { - - this.constant -= offset.dot( this.normal ); - - return this; - - }, - - equals: function ( plane ) { - - return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author bhouston / http://clara.io - */ - -function Frustum( p0, p1, p2, p3, p4, p5 ) { - - this.planes = [ - - ( p0 !== undefined ) ? p0 : new Plane(), - ( p1 !== undefined ) ? p1 : new Plane(), - ( p2 !== undefined ) ? p2 : new Plane(), - ( p3 !== undefined ) ? p3 : new Plane(), - ( p4 !== undefined ) ? p4 : new Plane(), - ( p5 !== undefined ) ? p5 : new Plane() - - ]; - -} - -Object.assign( Frustum.prototype, { - - set: function ( p0, p1, p2, p3, p4, p5 ) { - - var 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; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( frustum ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - planes[ i ].copy( frustum.planes[ i ] ); - - } - - return this; - - }, - - setFromMatrix: function ( m ) { - - var planes = this.planes; - var me = m.elements; - var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; - var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; - var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; - var 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: function () { - - var sphere = new Sphere(); - - return function intersectsObject( object ) { - - var geometry = object.geometry; - - if ( geometry.boundingSphere === null ) - { geometry.computeBoundingSphere(); } - - sphere.copy( geometry.boundingSphere ) - .applyMatrix4( object.matrixWorld ); - - return this.intersectsSphere( sphere ); - - }; - - }(), - - intersectsSprite: function () { - - var sphere = new Sphere(); - - return function intersectsSprite( sprite ) { - - sphere.center.set( 0, 0, 0 ); - sphere.radius = 0.7071067811865476; - sphere.applyMatrix4( sprite.matrixWorld ); - - return this.intersectsSphere( sphere ); - - }; - - }(), - - intersectsSphere: function ( sphere ) { - - var planes = this.planes; - var center = sphere.center; - var negRadius = - sphere.radius; - - for ( var i = 0; i < 6; i ++ ) { - - var distance = planes[ i ].distanceToPoint( center ); - - if ( distance < negRadius ) { - - return false; - - } - - } - - return true; - - }, - - intersectsBox: function () { - - var p1 = new Vector3(), - p2 = new Vector3(); - - return function intersectsBox( box ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - var plane = planes[ i ]; - - p1.x = plane.normal.x > 0 ? box.min.x : box.max.x; - p2.x = plane.normal.x > 0 ? box.max.x : box.min.x; - p1.y = plane.normal.y > 0 ? box.min.y : box.max.y; - p2.y = plane.normal.y > 0 ? box.max.y : box.min.y; - p1.z = plane.normal.z > 0 ? box.min.z : box.max.z; - p2.z = plane.normal.z > 0 ? box.max.z : box.min.z; - - var d1 = plane.distanceToPoint( p1 ); - var d2 = plane.distanceToPoint( p2 ); - - // if both outside plane, no intersection - - if ( d1 < 0 && d2 < 0 ) { - - return false; - - } - - } - - return true; - - }; - - }(), - - containsPoint: function ( point ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - if ( planes[ i ].distanceToPoint( point ) < 0 ) { - - return false; - - } - - } - - return true; - - } - -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { - - var _frustum = new Frustum(), - _projScreenMatrix = new Matrix4(), - - _shadowMapSize = new Vector2(), - _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), - - _lookTarget = new Vector3(), - _lightPositionWorld = new Vector3(), - - _MorphingFlag = 1, - _SkinningFlag = 2, - - _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1, - - _depthMaterials = new Array( _NumberOfMaterialVariants ), - _distanceMaterials = new Array( _NumberOfMaterialVariants ), - - _materialCache = {}; - - var cubeDirections = [ - new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), - new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) - ]; - - var cubeUps = [ - new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), - new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) - ]; - - var cube2DViewPorts = [ - new Vector4(), new Vector4(), new Vector4(), - new Vector4(), new Vector4(), new Vector4() - ]; - - // init - - for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { - - var useMorphing = ( i & _MorphingFlag ) !== 0; - var useSkinning = ( i & _SkinningFlag ) !== 0; - - var depthMaterial = new MeshDepthMaterial( { - - depthPacking: RGBADepthPacking, - - morphTargets: useMorphing, - skinning: useSkinning - - } ); - - _depthMaterials[ i ] = depthMaterial; - - // - - var distanceMaterial = new MeshDistanceMaterial( { - - morphTargets: useMorphing, - skinning: useSkinning - - } ); - - _distanceMaterials[ i ] = distanceMaterial; - - } - - // - - var scope = this; - - this.enabled = false; - - this.autoUpdate = true; - this.needsUpdate = false; - - this.type = PCFShadowMap; - - this.renderReverseSided = true; - this.renderSingleSided = true; - - this.render = function ( lights, scene, camera ) { - - if ( scope.enabled === false ) { return; } - if ( scope.autoUpdate === false && scope.needsUpdate === false ) { return; } - - if ( lights.length === 0 ) { return; } - - // TODO Clean up (needed in case of contextlost) - var _gl = _renderer.context; - var _state = _renderer.state; - - // Set GL state for depth map. - _state.disable( _gl.BLEND ); - _state.buffers.color.setClear( 1, 1, 1, 1 ); - _state.buffers.depth.setTest( true ); - _state.setScissorTest( false ); - - // render depth map - - var faceCount; - - for ( var i = 0, il = lights.length; i < il; i ++ ) { - - var light = lights[ i ]; - var shadow = light.shadow; - var isPointLight = light && light.isPointLight; - - if ( shadow === undefined ) { - - console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); - continue; - - } - - var shadowCamera = shadow.camera; - - _shadowMapSize.copy( shadow.mapSize ); - _shadowMapSize.min( _maxShadowMapSize ); - - if ( isPointLight ) { - - var vpWidth = _shadowMapSize.x; - var vpHeight = _shadowMapSize.y; - - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction - - // positive X - cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); - // negative X - cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); - // positive Z - cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); - // negative Z - cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); - // positive Y - cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); - // negative Y - cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - - _shadowMapSize.x *= 4.0; - _shadowMapSize.y *= 2.0; - - } - - if ( shadow.map === null ) { - - var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + ".shadowMap"; - - shadowCamera.updateProjectionMatrix(); - - } - - if ( shadow.isSpotLightShadow ) { - - shadow.update( light ); - - } - - var shadowMap = shadow.map; - var shadowMatrix = shadow.matrix; - - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld ); - - if ( isPointLight ) { - - faceCount = 6; - - // for point lights we set the shadow matrix to be a translation-only matrix - // equal to inverse of the light's position - - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - - } else { - - faceCount = 1; - - _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - - // compute shadow matrix - - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - - shadowMatrix.multiply( shadowCamera.projectionMatrix ); - shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - - } - - _renderer.setRenderTarget( shadowMap ); - _renderer.clear(); - - // render shadow map for each cube face (if omni-directional) or - // run a single pass if not - - for ( var face = 0; face < faceCount; face ++ ) { - - if ( isPointLight ) { - - _lookTarget.copy( shadowCamera.position ); - _lookTarget.add( cubeDirections[ face ] ); - shadowCamera.up.copy( cubeUps[ face ] ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - - var vpDimensions = cube2DViewPorts[ face ]; - _state.viewport( vpDimensions ); - - } - - // update camera matrices and frustum - - _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); - - // set object matrices & frustum culling - - renderObject( scene, camera, shadowCamera, isPointLight ); - - } - - } - - scope.needsUpdate = false; - - }; - - function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { - - var geometry = object.geometry; - - var result = null; - - var materialVariants = _depthMaterials; - var customMaterial = object.customDepthMaterial; - - if ( isPointLight ) { - - materialVariants = _distanceMaterials; - customMaterial = object.customDistanceMaterial; - - } - - if ( ! customMaterial ) { - - var useMorphing = false; - - if ( material.morphTargets ) { - - if ( geometry && geometry.isBufferGeometry ) { - - useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - - } else if ( geometry && geometry.isGeometry ) { - - useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - - } - - } - - if ( object.isSkinnedMesh && material.skinning === false ) { - - console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); - - } - - var useSkinning = object.isSkinnedMesh && material.skinning; - - var variantIndex = 0; - - if ( useMorphing ) { variantIndex |= _MorphingFlag; } - if ( useSkinning ) { variantIndex |= _SkinningFlag; } - - result = materialVariants[ variantIndex ]; - - } else { - - result = customMaterial; - - } - - if ( _renderer.localClippingEnabled && - material.clipShadows === true && - material.clippingPlanes.length !== 0 ) { - - // in this case we need a unique material instance reflecting the - // appropriate state - - var keyA = result.uuid, keyB = material.uuid; - - var materialsForVariant = _materialCache[ keyA ]; - - if ( materialsForVariant === undefined ) { - - materialsForVariant = {}; - _materialCache[ keyA ] = materialsForVariant; - - } - - var cachedMaterial = materialsForVariant[ keyB ]; - - if ( cachedMaterial === undefined ) { - - cachedMaterial = result.clone(); - materialsForVariant[ keyB ] = cachedMaterial; - - } - - result = cachedMaterial; - - } - - result.visible = material.visible; - result.wireframe = material.wireframe; - - var side = material.side; - - if ( scope.renderSingleSided && side == DoubleSide ) { - - side = FrontSide; - - } - - if ( scope.renderReverseSided ) { - - if ( side === FrontSide ) { side = BackSide; } - else if ( side === BackSide ) { side = FrontSide; } - - } - - result.side = side; - - result.clipShadows = material.clipShadows; - result.clippingPlanes = material.clippingPlanes; - result.clipIntersection = material.clipIntersection; - - result.wireframeLinewidth = material.wireframeLinewidth; - result.linewidth = material.linewidth; - - if ( isPointLight && result.isMeshDistanceMaterial ) { - - result.referencePosition.copy( lightPositionWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; - - } - - return result; - - } - - function renderObject( object, camera, shadowCamera, isPointLight ) { - - if ( object.visible === false ) { return; } - - var visible = object.layers.test( camera.layers ); - - if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - - if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - - object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - - var geometry = _objects.update( object ); - var material = object.material; - - if ( Array.isArray( material ) ) { - - var groups = geometry.groups; - - for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - - var group = groups[ k ]; - var groupMaterial = material[ group.materialIndex ]; - - if ( groupMaterial && groupMaterial.visible ) { - - var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - - } - - } - - } else if ( material.visible ) { - - var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - - } - - } - - } - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - renderObject( children[ i ], camera, shadowCamera, isPointLight ); - - } - - } - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLAttributes( gl ) { - - var buffers = {}; - - function createBuffer( attribute, bufferType ) { - - var array = attribute.array; - var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; - - var buffer = gl.createBuffer(); - - gl.bindBuffer( bufferType, buffer ); - gl.bufferData( bufferType, array, usage ); - - attribute.onUploadCallback(); - - var type = gl.FLOAT; - - if ( array instanceof Float32Array ) { - - type = gl.FLOAT; - - } else if ( array instanceof Float64Array ) { - - console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); - - } else if ( array instanceof Uint16Array ) { - - type = gl.UNSIGNED_SHORT; - - } else if ( array instanceof Int16Array ) { - - type = gl.SHORT; - - } else if ( array instanceof Uint32Array ) { - - type = gl.UNSIGNED_INT; - - } else if ( array instanceof Int32Array ) { - - type = gl.INT; - - } else if ( array instanceof Int8Array ) { - - type = gl.BYTE; - - } else if ( array instanceof Uint8Array ) { - - type = gl.UNSIGNED_BYTE; - - } - - return { - buffer: buffer, - type: type, - bytesPerElement: array.BYTES_PER_ELEMENT, - version: attribute.version - }; - - } - - function updateBuffer( buffer, attribute, bufferType ) { - - var array = attribute.array; - var updateRange = attribute.updateRange; - - gl.bindBuffer( bufferType, buffer ); - - if ( attribute.dynamic === false ) { - - gl.bufferData( bufferType, array, gl.STATIC_DRAW ); - - } else if ( updateRange.count === - 1 ) { - - // Not using update ranges - - gl.bufferSubData( bufferType, 0, array ); - - } else if ( updateRange.count === 0 ) { - - console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); - - } else { - - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); - - updateRange.count = - 1; // reset range - - } - - } - - // - - function get( attribute ) { - - if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; } - - return buffers[ attribute.uuid ]; - - } - - function remove( attribute ) { - - if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; } - - var data = buffers[ attribute.uuid ]; - - if ( data ) { - - gl.deleteBuffer( data.buffer ); - - delete buffers[ attribute.uuid ]; - - } - - } - - function update( attribute, bufferType ) { - - if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; } - - var data = buffers[ attribute.uuid ]; - - if ( data === undefined ) { - - buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); - - } else if ( data.version < attribute.version ) { - - updateBuffer( data.buffer, attribute, bufferType ); - - data.version = attribute.version; - - } - - } - - return { - - get: get, - remove: remove, - update: update - - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - */ - -function Euler( x, y, z, order ) { - - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._order = order || Euler.DefaultOrder; - -} - -Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]; - -Euler.DefaultOrder = 'XYZ'; - -Object.defineProperties( Euler.prototype, { - - x: { - - get: function () { - - return this._x; - - }, - - set: function ( value ) { - - this._x = value; - this.onChangeCallback(); - - } - - }, - - y: { - - get: function () { - - return this._y; - - }, - - set: function ( value ) { - - this._y = value; - this.onChangeCallback(); - - } - - }, - - z: { - - get: function () { - - return this._z; - - }, - - set: function ( value ) { - - this._z = value; - this.onChangeCallback(); - - } - - }, - - order: { - - get: function () { - - return this._order; - - }, - - set: function ( value ) { - - this._order = value; - this.onChangeCallback(); - - } - - } - -} ); - -Object.assign( Euler.prototype, { - - isEuler: true, - - set: function ( x, y, z, order ) { - - this._x = x; - this._y = y; - this._z = z; - this._order = order || this._order; - - this.onChangeCallback(); - - return this; - - }, - - clone: function () { - - return new this.constructor( this._x, this._y, this._z, this._order ); - - }, - - copy: function ( euler ) { - - this._x = euler._x; - this._y = euler._y; - this._z = euler._z; - this._order = euler._order; - - this.onChangeCallback(); - - return this; - - }, - - setFromRotationMatrix: function ( m, order, update ) { - - var clamp = _Math.clamp; - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - var te = m.elements; - var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; - var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; - var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - - order = order || this._order; - - if ( order === 'XYZ' ) { - - this._y = Math.asin( clamp( m13, - 1, 1 ) ); - - if ( Math.abs( m13 ) < 0.99999 ) { - - this._x = Math.atan2( - m23, m33 ); - this._z = Math.atan2( - m12, m11 ); - - } else { - - this._x = Math.atan2( m32, m22 ); - this._z = 0; - - } - - } else if ( order === 'YXZ' ) { - - this._x = Math.asin( - clamp( m23, - 1, 1 ) ); - - if ( Math.abs( m23 ) < 0.99999 ) { - - this._y = Math.atan2( m13, m33 ); - this._z = Math.atan2( m21, m22 ); - - } else { - - this._y = Math.atan2( - m31, m11 ); - this._z = 0; - - } - - } else if ( order === 'ZXY' ) { - - this._x = Math.asin( clamp( m32, - 1, 1 ) ); - - if ( Math.abs( m32 ) < 0.99999 ) { - - this._y = Math.atan2( - m31, m33 ); - this._z = Math.atan2( - m12, m22 ); - - } else { - - this._y = 0; - this._z = Math.atan2( m21, m11 ); - - } - - } else if ( order === 'ZYX' ) { - - this._y = Math.asin( - clamp( m31, - 1, 1 ) ); - - if ( Math.abs( m31 ) < 0.99999 ) { - - this._x = Math.atan2( m32, m33 ); - this._z = Math.atan2( m21, m11 ); - - } else { - - this._x = 0; - this._z = Math.atan2( - m12, m22 ); - - } - - } else if ( order === 'YZX' ) { - - this._z = Math.asin( clamp( m21, - 1, 1 ) ); - - if ( Math.abs( m21 ) < 0.99999 ) { - - this._x = Math.atan2( - m23, m22 ); - this._y = Math.atan2( - m31, m11 ); - - } else { - - this._x = 0; - this._y = Math.atan2( m13, m33 ); - - } - - } else if ( order === 'XZY' ) { - - this._z = Math.asin( - clamp( m12, - 1, 1 ) ); - - if ( Math.abs( m12 ) < 0.99999 ) { - - this._x = Math.atan2( m32, m22 ); - this._y = Math.atan2( m13, m11 ); - - } else { - - this._x = Math.atan2( - m23, m33 ); - this._y = 0; - - } - - } else { - - console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ); - - } - - this._order = order; - - if ( update !== false ) { this.onChangeCallback(); } - - return this; - - }, - - setFromQuaternion: function () { - - var matrix = new Matrix4(); - - return function setFromQuaternion( q, order, update ) { - - matrix.makeRotationFromQuaternion( q ); - - return this.setFromRotationMatrix( matrix, order, update ); - - }; - - }(), - - setFromVector3: function ( v, order ) { - - return this.set( v.x, v.y, v.z, order || this._order ); - - }, - - reorder: function () { - - // WARNING: this discards revolution information -bhouston - - var q = new Quaternion(); - - return function reorder( newOrder ) { - - q.setFromEuler( this ); - - return this.setFromQuaternion( q, newOrder ); - - }; - - }(), - - equals: function ( euler ) { - - return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); - - }, - - fromArray: function ( array ) { - - this._x = array[ 0 ]; - this._y = array[ 1 ]; - this._z = array[ 2 ]; - if ( array[ 3 ] !== undefined ) { this._order = array[ 3 ]; } - - this.onChangeCallback(); - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._order; - - return array; - - }, - - toVector3: function ( optionalResult ) { - - if ( optionalResult ) { - - return optionalResult.set( this._x, this._y, this._z ); - - } else { - - return new Vector3( this._x, this._y, this._z ); - - } - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; - - }, - - onChangeCallback: function () {} - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function Layers() { - - this.mask = 1 | 0; - -} - -Object.assign( Layers.prototype, { - - set: function ( channel ) { - - this.mask = 1 << channel | 0; - - }, - - enable: function ( channel ) { - - this.mask |= 1 << channel | 0; - - }, - - toggle: function ( channel ) { - - this.mask ^= 1 << channel | 0; - - }, - - disable: function ( channel ) { - - this.mask &= ~ ( 1 << channel | 0 ); - - }, - - test: function ( layers ) { - - return ( this.mask & layers.mask ) !== 0; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author elephantatwork / www.elephantatwork.ch - */ - -var object3DId = 0; - -function Object3D() { - - Object.defineProperty( this, 'id', { value: object3DId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Object3D'; - - this.parent = null; - this.children = []; - - this.up = Object3D.DefaultUp.clone(); - - var position = new Vector3(); - var rotation = new Euler(); - var quaternion = new Quaternion(); - var scale = new Vector3( 1, 1, 1 ); - - function onRotationChange() { - - quaternion.setFromEuler( rotation, false ); - - } - - function onQuaternionChange() { - - rotation.setFromQuaternion( quaternion, undefined, false ); - - } - - rotation.onChange( onRotationChange ); - quaternion.onChange( onQuaternionChange ); - - Object.defineProperties( this, { - position: { - enumerable: true, - value: position - }, - rotation: { - enumerable: true, - value: rotation - }, - quaternion: { - enumerable: true, - value: quaternion - }, - scale: { - 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.userData = {}; - -} - -Object3D.DefaultUp = new Vector3( 0, 1, 0 ); -Object3D.DefaultMatrixAutoUpdate = true; - -Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: Object3D, - - isObject3D: true, - - onBeforeRender: function () {}, - onAfterRender: function () {}, - - applyMatrix: function ( matrix ) { - - this.matrix.multiplyMatrices( matrix, this.matrix ); - - this.matrix.decompose( this.position, this.quaternion, this.scale ); - - }, - - applyQuaternion: function ( q ) { - - this.quaternion.premultiply( q ); - - return this; - - }, - - setRotationFromAxisAngle: function ( axis, angle ) { - - // assumes axis is normalized - - this.quaternion.setFromAxisAngle( axis, angle ); - - }, - - setRotationFromEuler: function ( euler ) { - - this.quaternion.setFromEuler( euler, true ); - - }, - - setRotationFromMatrix: function ( m ) { - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - this.quaternion.setFromRotationMatrix( m ); - - }, - - setRotationFromQuaternion: function ( q ) { - - // assumes q is normalized - - this.quaternion.copy( q ); - - }, - - rotateOnAxis: function () { - - // rotate object on axis in object space - // axis is assumed to be normalized - - var q1 = new Quaternion(); - - return function rotateOnAxis( axis, angle ) { - - q1.setFromAxisAngle( axis, angle ); - - this.quaternion.multiply( q1 ); - - return this; - - }; - - }(), - - rotateOnWorldAxis: function () { - - // rotate object on axis in world space - // axis is assumed to be normalized - // method assumes no rotated parent - - var q1 = new Quaternion(); - - return function rotateOnWorldAxis( axis, angle ) { - - q1.setFromAxisAngle( axis, angle ); - - this.quaternion.premultiply( q1 ); - - return this; - - }; - - }(), - - rotateX: function () { - - var v1 = new Vector3( 1, 0, 0 ); - - return function rotateX( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - rotateY: function () { - - var v1 = new Vector3( 0, 1, 0 ); - - return function rotateY( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - rotateZ: function () { - - var v1 = new Vector3( 0, 0, 1 ); - - return function rotateZ( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - translateOnAxis: function () { - - // translate object by distance along axis in object space - // axis is assumed to be normalized - - var v1 = new Vector3(); - - return function translateOnAxis( axis, distance ) { - - v1.copy( axis ).applyQuaternion( this.quaternion ); - - this.position.add( v1.multiplyScalar( distance ) ); - - return this; - - }; - - }(), - - translateX: function () { - - var v1 = new Vector3( 1, 0, 0 ); - - return function translateX( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - translateY: function () { - - var v1 = new Vector3( 0, 1, 0 ); - - return function translateY( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - translateZ: function () { - - var v1 = new Vector3( 0, 0, 1 ); - - return function translateZ( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - localToWorld: function ( vector ) { - - return vector.applyMatrix4( this.matrixWorld ); - - }, - - worldToLocal: function () { - - var m1 = new Matrix4(); - - return function worldToLocal( vector ) { - - return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) ); - - }; - - }(), - - lookAt: function () { - - // This method does not support objects with rotated and/or translated parent(s) - - var m1 = new Matrix4(); - var vector = new Vector3(); - - return function lookAt( x, y, z ) { - - if ( x.isVector3 ) { - - vector.copy( x ); - - } else { - - vector.set( x, y, z ); - - } - - if ( this.isCamera ) { - - m1.lookAt( this.position, vector, this.up ); - - } else { - - m1.lookAt( vector, this.position, this.up ); - - } - - this.quaternion.setFromRotationMatrix( m1 ); - - }; - - }(), - - add: function ( object ) { - var arguments$1 = arguments; - - - if ( arguments.length > 1 ) { - - for ( var i = 0; i < arguments.length; i ++ ) { - - this.add( arguments$1[ 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; - object.dispatchEvent( { type: 'added' } ); - - this.children.push( object ); - - } else { - - console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); - - } - - return this; - - }, - - remove: function ( object ) { - var arguments$1 = arguments; - - - if ( arguments.length > 1 ) { - - for ( var i = 0; i < arguments.length; i ++ ) { - - this.remove( arguments$1[ i ] ); - - } - - return this; - - } - - var index = this.children.indexOf( object ); - - if ( index !== - 1 ) { - - object.parent = null; - - object.dispatchEvent( { type: 'removed' } ); - - this.children.splice( index, 1 ); - - } - - return this; - - }, - - getObjectById: function ( id ) { - - return this.getObjectByProperty( 'id', id ); - - }, - - getObjectByName: function ( name ) { - - return this.getObjectByProperty( 'name', name ); - - }, - - getObjectByProperty: function ( name, value ) { - - if ( this[ name ] === value ) { return this; } - - for ( var i = 0, l = this.children.length; i < l; i ++ ) { - - var child = this.children[ i ]; - var object = child.getObjectByProperty( name, value ); - - if ( object !== undefined ) { - - return object; - - } - - } - - return undefined; - - }, - - getWorldPosition: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); - - return result.setFromMatrixPosition( this.matrixWorld ); - - }, - - getWorldQuaternion: function () { - - var position = new Vector3(); - var scale = new Vector3(); - - return function getWorldQuaternion( optionalTarget ) { - - var result = optionalTarget || new Quaternion(); - - this.updateMatrixWorld( true ); - - this.matrixWorld.decompose( position, result, scale ); - - return result; - - }; - - }(), - - getWorldRotation: function () { - - var quaternion = new Quaternion(); - - return function getWorldRotation( optionalTarget ) { - - var result = optionalTarget || new Euler(); - - this.getWorldQuaternion( quaternion ); - - return result.setFromQuaternion( quaternion, this.rotation.order, false ); - - }; - - }(), - - getWorldScale: function () { - - var position = new Vector3(); - var quaternion = new Quaternion(); - - return function getWorldScale( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); - - this.matrixWorld.decompose( position, quaternion, result ); - - return result; - - }; - - }(), - - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.getWorldQuaternion( quaternion ); - - return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); - - }; - - }(), - - raycast: function () {}, - - traverse: function ( callback ) { - - callback( this ); - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverse( callback ); - - } - - }, - - traverseVisible: function ( callback ) { - - if ( this.visible === false ) { return; } - - callback( this ); - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverseVisible( callback ); - - } - - }, - - traverseAncestors: function ( callback ) { - - var parent = this.parent; - - if ( parent !== null ) { - - callback( parent ); - - parent.traverseAncestors( callback ); - - } - - }, - - updateMatrix: function () { - - this.matrix.compose( this.position, this.quaternion, this.scale ); - - this.matrixWorldNeedsUpdate = true; - - }, - - updateMatrixWorld: function ( 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; - - } - - // update children - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].updateMatrixWorld( force ); - - } - - }, - - toJSON: function ( meta ) { - - // meta is a string when called from JSON.stringify - var isRootObject = ( meta === undefined || typeof meta === 'string' ); - - var output = {}; - - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { - - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {}, - shapes: {} - }; - - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; - - } - - // standard Object3D serialization - - var 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 ( JSON.stringify( this.userData ) !== '{}' ) { object.userData = this.userData; } - - object.matrix = this.matrix.toArray(); - - // - - function serialize( library, element ) { - - if ( library[ element.uuid ] === undefined ) { - - library[ element.uuid ] = element.toJSON( meta ); - - } - - return element.uuid; - - } - - if ( this.geometry !== undefined ) { - - object.geometry = serialize( meta.geometries, this.geometry ); - - var parameters = this.geometry.parameters; - - if ( parameters !== undefined && parameters.shapes !== undefined ) { - - var shapes = parameters.shapes; - - if ( Array.isArray( shapes ) ) { - - for ( var i = 0, l = shapes.length; i < l; i ++ ) { - - var shape = shapes[ i ]; - - serialize( meta.shapes, shape ); - - } - - } else { - - serialize( meta.shapes, shapes ); - - } - - } - - } - - if ( this.material !== undefined ) { - - if ( Array.isArray( this.material ) ) { - - var uuids = []; - - for ( var 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 ( var i = 0; i < this.children.length; i ++ ) { - - object.children.push( this.children[ i ].toJSON( meta ).object ); - - } - - } - - if ( isRootObject ) { - - var geometries = extractFromCache( meta.geometries ); - var materials = extractFromCache( meta.materials ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - var shapes = extractFromCache( meta.shapes ); - - 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; } - - } - - output.object = object; - - return output; - - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { - - var values = []; - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - return values; - - } - - }, - - clone: function ( recursive ) { - - return new this.constructor().copy( this, recursive ); - - }, - - copy: function ( source, recursive ) { - - if ( recursive === undefined ) { recursive = true; } - - this.name = source.name; - - this.up.copy( source.up ); - - this.position.copy( source.position ); - 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 ( var i = 0; i < source.children.length; i ++ ) { - - var child = source.children[ i ]; - this.add( child.clone() ); - - } - - } - - return this; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author WestLangley / http://github.com/WestLangley -*/ - -function Camera() { - - Object3D.call( this ); - - this.type = 'Camera'; - - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); - -} - -Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Camera, - - isCamera: true, - - copy: function ( source, recursive ) { - - Object3D.prototype.copy.call( this, source, recursive ); - - this.matrixWorldInverse.copy( source.matrixWorldInverse ); - this.projectionMatrix.copy( source.projectionMatrix ); - - return this; - - }, - - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.getWorldQuaternion( quaternion ); - - return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - - }; - - }(), - - updateMatrixWorld: function ( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - this.matrixWorldInverse.getInverse( this.matrixWorld ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - } - -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - * @author arose / http://github.com/arose - */ - -function OrthographicCamera( left, right, top, bottom, near, far ) { - - Camera.call( this ); - - this.type = 'OrthographicCamera'; - - this.zoom = 1; - this.view = null; - - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; - - this.near = ( near !== undefined ) ? near : 0.1; - this.far = ( far !== undefined ) ? far : 2000; - - this.updateProjectionMatrix(); - -} - -OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - - constructor: OrthographicCamera, - - isOrthographicCamera: true, - - copy: function ( source, recursive ) { - - Camera.prototype.copy.call( this, 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: function ( fullWidth, fullHeight, x, y, 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 = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; - - this.updateProjectionMatrix(); - - }, - - clearViewOffset: function () { - - if ( this.view !== null ) { - - this.view.enabled = false; - - } - - this.updateProjectionMatrix(); - - }, - - updateProjectionMatrix: function () { - - var dx = ( this.right - this.left ) / ( 2 * this.zoom ); - var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - var cx = ( this.right + this.left ) / 2; - var cy = ( this.top + this.bottom ) / 2; - - var left = cx - dx; - var right = cx + dx; - var top = cy + dy; - var bottom = cy - dy; - - if ( this.view !== null && this.view.enabled ) { - - var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); - var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); - var scaleW = ( this.right - this.left ) / this.view.width; - var scaleH = ( this.top - this.bottom ) / this.view.height; - - left += scaleW * ( this.view.offsetX / zoomW ); - right = left + scaleW * ( this.view.width / zoomW ); - top -= scaleH * ( this.view.offsetY / zoomH ); - bottom = top - scaleH * ( this.view.height / zoomH ); - - } - - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); - - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, 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; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -function Face3( a, b, c, normal, color, materialIndex ) { - - this.a = a; - this.b = b; - this.c = c; - - this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); - this.vertexNormals = Array.isArray( normal ) ? normal : []; - - this.color = ( color && color.isColor ) ? color : new Color(); - this.vertexColors = Array.isArray( color ) ? color : []; - - this.materialIndex = materialIndex !== undefined ? materialIndex : 0; - -} - -Object.assign( Face3.prototype, { - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.a = source.a; - this.b = source.b; - this.c = source.c; - - this.normal.copy( source.normal ); - this.color.copy( source.color ); - - this.materialIndex = source.materialIndex; - - for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { - - this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); - - } - - for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { - - this.vertexColors[ i ] = source.vertexColors[ i ].clone(); - - } - - return this; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author bhouston / http://clara.io - */ - -var geometryId = 0; // Geometry uses even numbers as Id - -function Geometry() { - - Object.defineProperty( this, 'id', { value: geometryId += 2 } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Geometry'; - - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - - this.morphTargets = []; - this.morphNormals = []; - - this.skinWeights = []; - this.skinIndices = []; - - this.lineDistances = []; - - this.boundingBox = null; - this.boundingSphere = null; - - // update flags - - this.elementsNeedUpdate = false; - this.verticesNeedUpdate = false; - this.uvsNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.lineDistancesNeedUpdate = false; - this.groupsNeedUpdate = false; - -} - -Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: Geometry, - - isGeometry: true, - - applyMatrix: function ( matrix ) { - - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { - - var vertex = this.vertices[ i ]; - vertex.applyMatrix4( matrix ); - - } - - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { - - var face = this.faces[ i ]; - face.normal.applyMatrix3( normalMatrix ).normalize(); - - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - - face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); - - } - - } - - if ( this.boundingBox !== null ) { - - this.computeBoundingBox(); - - } - - if ( this.boundingSphere !== null ) { - - this.computeBoundingSphere(); - - } - - this.verticesNeedUpdate = true; - this.normalsNeedUpdate = true; - - return this; - - }, - - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); - - return function rotateX( angle ) { - - m1.makeRotationX( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateY: function () { - - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateZ: function () { - - // rotate geometry around world z-axis - - var m1 = new Matrix4(); - - return function rotateZ( angle ) { - - m1.makeRotationZ( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - translate: function () { - - // translate geometry - - var m1 = new Matrix4(); - - return function translate( x, y, z ) { - - m1.makeTranslation( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - scale: function () { - - // scale geometry - - var m1 = new Matrix4(); - - return function scale( x, y, z ) { - - m1.makeScale( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - lookAt: function () { - - var obj = new Object3D(); - - return function lookAt( vector ) { - - obj.lookAt( vector ); - - obj.updateMatrix(); - - this.applyMatrix( obj.matrix ); - - }; - - }(), - - fromBufferGeometry: function ( geometry ) { - - var scope = this; - - var indices = geometry.index !== null ? geometry.index.array : undefined; - var attributes = geometry.attributes; - - var positions = attributes.position.array; - var normals = attributes.normal !== undefined ? attributes.normal.array : undefined; - var colors = attributes.color !== undefined ? attributes.color.array : undefined; - var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined; - var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined; - - if ( uvs2 !== undefined ) { this.faceVertexUvs[ 1 ] = []; } - - var tempNormals = []; - var tempUVs = []; - var tempUVs2 = []; - - for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { - - scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); - - if ( normals !== undefined ) { - - tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); - - } - - if ( colors !== undefined ) { - - scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); - - } - - if ( uvs !== undefined ) { - - tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); - - } - - if ( uvs2 !== undefined ) { - - tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); - - } - - } - - function addFace( a, b, c, materialIndex ) { - - var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; - var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; - - var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); - - scope.faces.push( face ); - - if ( uvs !== undefined ) { - - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); - - } - - if ( uvs2 !== undefined ) { - - scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); - - } - - } - - var groups = geometry.groups; - - if ( groups.length > 0 ) { - - for ( var i = 0; i < groups.length; i ++ ) { - - var group = groups[ i ]; - - var start = group.start; - var count = group.count; - - for ( var j = start, jl = start + count; j < jl; j += 3 ) { - - if ( indices !== undefined ) { - - addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); - - } else { - - addFace( j, j + 1, j + 2, group.materialIndex ); - - } - - } - - } - - } else { - - if ( indices !== undefined ) { - - for ( var i = 0; i < indices.length; i += 3 ) { - - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); - - } - - } else { - - for ( var i = 0; i < positions.length / 3; i += 3 ) { - - addFace( i, i + 1, i + 2 ); - - } - - } - - } - - this.computeFaceNormals(); - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - return this; - - }, - - center: function () { - - this.computeBoundingBox(); - - var offset = this.boundingBox.getCenter().negate(); - - this.translate( offset.x, offset.y, offset.z ); - - return offset; - - }, - - normalize: function () { - - this.computeBoundingSphere(); - - var center = this.boundingSphere.center; - var radius = this.boundingSphere.radius; - - var s = radius === 0 ? 1 : 1.0 / radius; - - var matrix = new Matrix4(); - matrix.set( - s, 0, 0, - s * center.x, - 0, s, 0, - s * center.y, - 0, 0, s, - s * center.z, - 0, 0, 0, 1 - ); - - this.applyMatrix( matrix ); - - return this; - - }, - - computeFaceNormals: function () { - - var cb = new Vector3(), ab = new Vector3(); - - for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { - - var face = this.faces[ f ]; - - var vA = this.vertices[ face.a ]; - var vB = this.vertices[ face.b ]; - var vC = this.vertices[ face.c ]; - - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); - - cb.normalize(); - - face.normal.copy( cb ); - - } - - }, - - computeVertexNormals: function ( areaWeighted ) { - - if ( areaWeighted === undefined ) { areaWeighted = true; } - - var v, vl, f, fl, face, vertices; - - vertices = new Array( this.vertices.length ); - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ] = new Vector3(); - - } - - if ( areaWeighted ) { - - // vertex normals weighted by triangle areas - // http://www.iquilezles.org/www/articles/normals/normals.htm - - var vA, vB, vC; - var cb = new Vector3(), ab = new Vector3(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; - - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); - - vertices[ face.a ].add( cb ); - vertices[ face.b ].add( cb ); - vertices[ face.c ].add( cb ); - - } - - } else { - - this.computeFaceNormals(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - vertices[ face.a ].add( face.normal ); - vertices[ face.b ].add( face.normal ); - vertices[ face.c ].add( face.normal ); - - } - - } - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ].normalize(); - - } - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - vertexNormals[ 0 ].copy( vertices[ face.a ] ); - vertexNormals[ 1 ].copy( vertices[ face.b ] ); - vertexNormals[ 2 ].copy( vertices[ face.c ] ); - - } else { - - vertexNormals[ 0 ] = vertices[ face.a ].clone(); - vertexNormals[ 1 ] = vertices[ face.b ].clone(); - vertexNormals[ 2 ] = vertices[ face.c ].clone(); - - } - - } - - if ( this.faces.length > 0 ) { - - this.normalsNeedUpdate = true; - - } - - }, - - computeFlatVertexNormals: function () { - - var f, fl, face; - - this.computeFaceNormals(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - vertexNormals[ 0 ].copy( face.normal ); - vertexNormals[ 1 ].copy( face.normal ); - vertexNormals[ 2 ].copy( face.normal ); - - } else { - - vertexNormals[ 0 ] = face.normal.clone(); - vertexNormals[ 1 ] = face.normal.clone(); - vertexNormals[ 2 ] = face.normal.clone(); - - } - - } - - if ( this.faces.length > 0 ) { - - this.normalsNeedUpdate = true; - - } - - }, - - computeMorphNormals: function () { - - var i, il, f, fl, face; - - // save original normals - // - create temp variables on first access - // otherwise just copy (for faster repeated calls) - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( ! face.__originalFaceNormal ) { - - face.__originalFaceNormal = face.normal.clone(); - - } else { - - face.__originalFaceNormal.copy( face.normal ); - - } - - if ( ! face.__originalVertexNormals ) { face.__originalVertexNormals = []; } - - for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { - - if ( ! face.__originalVertexNormals[ i ] ) { - - face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); - - } else { - - face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); - - } - - } - - } - - // use temp geometry to compute face and vertex normals for each morph - - var tmpGeo = new Geometry(); - tmpGeo.faces = this.faces; - - for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { - - // create on first access - - if ( ! this.morphNormals[ i ] ) { - - this.morphNormals[ i ] = {}; - this.morphNormals[ i ].faceNormals = []; - this.morphNormals[ i ].vertexNormals = []; - - var dstNormalsFace = this.morphNormals[ i ].faceNormals; - var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; - - var faceNormal, vertexNormals; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - faceNormal = new Vector3(); - vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; - - dstNormalsFace.push( faceNormal ); - dstNormalsVertex.push( vertexNormals ); - - } - - } - - var morphNormals = this.morphNormals[ i ]; - - // set vertices to morph target - - tmpGeo.vertices = this.morphTargets[ i ].vertices; - - // compute morph normals - - tmpGeo.computeFaceNormals(); - tmpGeo.computeVertexNormals(); - - // store morph normals - - var faceNormal, vertexNormals; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - faceNormal = morphNormals.faceNormals[ f ]; - vertexNormals = morphNormals.vertexNormals[ f ]; - - faceNormal.copy( face.normal ); - - vertexNormals.a.copy( face.vertexNormals[ 0 ] ); - vertexNormals.b.copy( face.vertexNormals[ 1 ] ); - vertexNormals.c.copy( face.vertexNormals[ 2 ] ); - - } - - } - - // restore original normals - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - face.normal = face.__originalFaceNormal; - face.vertexNormals = face.__originalVertexNormals; - - } - - }, - - computeLineDistances: function () { - - var d = 0; - var vertices = this.vertices; - - for ( var i = 0, il = vertices.length; i < il; i ++ ) { - - if ( i > 0 ) { - - d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); - - } - - this.lineDistances[ i ] = d; - - } - - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } - - this.boundingBox.setFromPoints( this.vertices ); - - }, - - computeBoundingSphere: function () { - - if ( this.boundingSphere === null ) { - - this.boundingSphere = new Sphere(); - - } - - this.boundingSphere.setFromPoints( this.vertices ); - - }, - - merge: function ( geometry, matrix, materialIndexOffset ) { - - if ( ! ( geometry && geometry.isGeometry ) ) { - - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); - return; - - } - - var normalMatrix, - vertexOffset = this.vertices.length, - vertices1 = this.vertices, - vertices2 = geometry.vertices, - faces1 = this.faces, - faces2 = geometry.faces, - uvs1 = this.faceVertexUvs[ 0 ], - uvs2 = geometry.faceVertexUvs[ 0 ], - colors1 = this.colors, - colors2 = geometry.colors; - - if ( materialIndexOffset === undefined ) { materialIndexOffset = 0; } - - if ( matrix !== undefined ) { - - normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - } - - // vertices - - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { - - var vertex = vertices2[ i ]; - - var vertexCopy = vertex.clone(); - - if ( matrix !== undefined ) { vertexCopy.applyMatrix4( matrix ); } - - vertices1.push( vertexCopy ); - - } - - // colors - - for ( var i = 0, il = colors2.length; i < il; i ++ ) { - - colors1.push( colors2[ i ].clone() ); - - } - - // faces - - for ( i = 0, il = faces2.length; i < il; i ++ ) { - - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; - - faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - faceCopy.normal.copy( face.normal ); - - if ( normalMatrix !== undefined ) { - - faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); - - } - - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { - - normal = faceVertexNormals[ j ].clone(); - - if ( normalMatrix !== undefined ) { - - normal.applyMatrix3( normalMatrix ).normalize(); - - } - - faceCopy.vertexNormals.push( normal ); - - } - - faceCopy.color.copy( face.color ); - - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { - - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); - - } - - faceCopy.materialIndex = face.materialIndex + materialIndexOffset; - - faces1.push( faceCopy ); - - } - - // uvs - - for ( i = 0, il = uvs2.length; i < il; i ++ ) { - - var uv = uvs2[ i ], uvCopy = []; - - if ( uv === undefined ) { - - continue; - - } - - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - - uvCopy.push( uv[ j ].clone() ); - - } - - uvs1.push( uvCopy ); - - } - - }, - - mergeMesh: function ( mesh ) { - - if ( ! ( mesh && mesh.isMesh ) ) { - - console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); - return; - - } - - mesh.matrixAutoUpdate && mesh.updateMatrix(); - - this.merge( mesh.geometry, mesh.matrix ); - - }, - - /* - * Checks for duplicate vertices with hashmap. - * Duplicated vertices are removed - * and faces' vertices are updated. - */ - - mergeVertices: function () { - - var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], changes = []; - - var v, key; - var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001 - var precision = Math.pow( 10, precisionPoints ); - var i, il, face; - var indices, j, jl; - - for ( i = 0, il = this.vertices.length; i < il; i ++ ) { - - v = this.vertices[ i ]; - key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); - - if ( verticesMap[ key ] === undefined ) { - - verticesMap[ key ] = i; - unique.push( this.vertices[ i ] ); - changes[ i ] = unique.length - 1; - - } else { - - //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); - changes[ i ] = changes[ verticesMap[ key ] ]; - - } - - } - - - // if faces are completely degenerate after merging vertices, we - // have to remove them from the geometry. - var faceIndicesToRemove = []; - - for ( i = 0, il = this.faces.length; i < il; i ++ ) { - - face = this.faces[ i ]; - - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; - - indices = [ face.a, face.b, face.c ]; - - // if any duplicate vertices are found in a Face3 - // we have to remove the face as nothing can be saved - for ( var n = 0; n < 3; n ++ ) { - - if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { - - faceIndicesToRemove.push( i ); - break; - - } - - } - - } - - for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - - var idx = faceIndicesToRemove[ i ]; - - this.faces.splice( idx, 1 ); - - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { - - this.faceVertexUvs[ j ].splice( idx, 1 ); - - } - - } - - // Use unique set of vertices - - var diff = this.vertices.length - unique.length; - this.vertices = unique; - return diff; - - }, - - setFromPoints: function ( points ) { - - this.vertices = []; - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); - - } - - return this; - - }, - - sortFacesByMaterialIndex: function () { - - var faces = this.faces; - var length = faces.length; - - // tag faces - - for ( var i = 0; i < length; i ++ ) { - - faces[ i ]._id = i; - - } - - // sort faces - - function materialIndexSort( a, b ) { - - return a.materialIndex - b.materialIndex; - - } - - faces.sort( materialIndexSort ); - - // sort uvs - - var uvs1 = this.faceVertexUvs[ 0 ]; - var uvs2 = this.faceVertexUvs[ 1 ]; - - var newUvs1, newUvs2; - - if ( uvs1 && uvs1.length === length ) { newUvs1 = []; } - if ( uvs2 && uvs2.length === length ) { newUvs2 = []; } - - for ( var i = 0; i < length; i ++ ) { - - var id = faces[ i ]._id; - - if ( newUvs1 ) { newUvs1.push( uvs1[ id ] ); } - if ( newUvs2 ) { newUvs2.push( uvs2[ id ] ); } - - } - - if ( newUvs1 ) { this.faceVertexUvs[ 0 ] = newUvs1; } - if ( newUvs2 ) { this.faceVertexUvs[ 1 ] = newUvs2; } - - }, - - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON' - } - }; - - // standard Geometry serialization - - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) { data.name = this.name; } - - if ( this.parameters !== undefined ) { - - var parameters = this.parameters; - - for ( var key in parameters ) { - - if ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; } - - } - - return data; - - } - - var vertices = []; - - for ( var i = 0; i < this.vertices.length; i ++ ) { - - var vertex = this.vertices[ i ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - var faces = []; - var normals = []; - var normalsHash = {}; - var colors = []; - var colorsHash = {}; - var uvs = []; - var uvsHash = {}; - - for ( var i = 0; i < this.faces.length; i ++ ) { - - var face = this.faces[ i ]; - - var hasMaterial = true; - var hasFaceUv = false; // deprecated - var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined; - var hasFaceNormal = face.normal.length() > 0; - var hasFaceVertexNormal = face.vertexNormals.length > 0; - var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1; - var hasFaceVertexColor = face.vertexColors.length > 0; - - var faceType = 0; - - faceType = setBit( faceType, 0, 0 ); // isQuad - faceType = setBit( faceType, 1, hasMaterial ); - faceType = setBit( faceType, 2, hasFaceUv ); - faceType = setBit( faceType, 3, hasFaceVertexUv ); - faceType = setBit( faceType, 4, hasFaceNormal ); - faceType = setBit( faceType, 5, hasFaceVertexNormal ); - faceType = setBit( faceType, 6, hasFaceColor ); - faceType = setBit( faceType, 7, hasFaceVertexColor ); - - faces.push( faceType ); - faces.push( face.a, face.b, face.c ); - faces.push( face.materialIndex ); - - if ( hasFaceVertexUv ) { - - var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; - - faces.push( - getUvIndex( faceVertexUvs[ 0 ] ), - getUvIndex( faceVertexUvs[ 1 ] ), - getUvIndex( faceVertexUvs[ 2 ] ) - ); - - } - - if ( hasFaceNormal ) { - - faces.push( getNormalIndex( face.normal ) ); - - } - - if ( hasFaceVertexNormal ) { - - var vertexNormals = face.vertexNormals; - - faces.push( - getNormalIndex( vertexNormals[ 0 ] ), - getNormalIndex( vertexNormals[ 1 ] ), - getNormalIndex( vertexNormals[ 2 ] ) - ); - - } - - if ( hasFaceColor ) { - - faces.push( getColorIndex( face.color ) ); - - } - - if ( hasFaceVertexColor ) { - - var vertexColors = face.vertexColors; - - faces.push( - getColorIndex( vertexColors[ 0 ] ), - getColorIndex( vertexColors[ 1 ] ), - getColorIndex( vertexColors[ 2 ] ) - ); - - } - - } - - function setBit( value, position, enabled ) { - - return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); - - } - - function getNormalIndex( normal ) { - - var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); - - if ( normalsHash[ hash ] !== undefined ) { - - return normalsHash[ hash ]; - - } - - normalsHash[ hash ] = normals.length / 3; - normals.push( normal.x, normal.y, normal.z ); - - return normalsHash[ hash ]; - - } - - function getColorIndex( color ) { - - var hash = color.r.toString() + color.g.toString() + color.b.toString(); - - if ( colorsHash[ hash ] !== undefined ) { - - return colorsHash[ hash ]; - - } - - colorsHash[ hash ] = colors.length; - colors.push( color.getHex() ); - - return colorsHash[ hash ]; - - } - - function getUvIndex( uv ) { - - var hash = uv.x.toString() + uv.y.toString(); - - if ( uvsHash[ hash ] !== undefined ) { - - return uvsHash[ hash ]; - - } - - uvsHash[ hash ] = uvs.length / 2; - uvs.push( uv.x, uv.y ); - - return uvsHash[ hash ]; - - } - - data.data = {}; - - data.data.vertices = vertices; - data.data.normals = normals; - if ( colors.length > 0 ) { data.data.colors = colors; } - if ( uvs.length > 0 ) { data.data.uvs = [ uvs ]; } // temporal backward compatibility - data.data.faces = faces; - - return data; - - }, - - clone: function () { - - /* - // Handle primitives - - var parameters = this.parameters; - - if ( parameters !== undefined ) { - - var values = []; - - for ( var key in parameters ) { - - values.push( parameters[ key ] ); - - } - - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; - - } - - return new this.constructor().copy( this ); - */ - - return new Geometry().copy( this ); - - }, - - copy: function ( source ) { - - var i, il, j, jl, k, kl; - - // reset - - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - this.morphTargets = []; - this.morphNormals = []; - this.skinWeights = []; - this.skinIndices = []; - this.lineDistances = []; - this.boundingBox = null; - this.boundingSphere = null; - - // name - - this.name = source.name; - - // vertices - - var vertices = source.vertices; - - for ( i = 0, il = vertices.length; i < il; i ++ ) { - - this.vertices.push( vertices[ i ].clone() ); - - } - - // colors - - var colors = source.colors; - - for ( i = 0, il = colors.length; i < il; i ++ ) { - - this.colors.push( colors[ i ].clone() ); - - } - - // faces - - var faces = source.faces; - - for ( i = 0, il = faces.length; i < il; i ++ ) { - - this.faces.push( faces[ i ].clone() ); - - } - - // face vertex uvs - - for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { - - var faceVertexUvs = source.faceVertexUvs[ i ]; - - if ( this.faceVertexUvs[ i ] === undefined ) { - - this.faceVertexUvs[ i ] = []; - - } - - for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { - - var uvs = faceVertexUvs[ j ], uvsCopy = []; - - for ( k = 0, kl = uvs.length; k < kl; k ++ ) { - - var uv = uvs[ k ]; - - uvsCopy.push( uv.clone() ); - - } - - this.faceVertexUvs[ i ].push( uvsCopy ); - - } - - } - - // morph targets - - var morphTargets = source.morphTargets; - - for ( i = 0, il = morphTargets.length; i < il; i ++ ) { - - var morphTarget = {}; - morphTarget.name = morphTargets[ i ].name; - - // vertices - - if ( morphTargets[ i ].vertices !== undefined ) { - - morphTarget.vertices = []; - - for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { - - morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); - - } - - } - - // normals - - if ( morphTargets[ i ].normals !== undefined ) { - - morphTarget.normals = []; - - for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { - - morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); - - } - - } - - this.morphTargets.push( morphTarget ); - - } - - // morph normals - - var morphNormals = source.morphNormals; - - for ( i = 0, il = morphNormals.length; i < il; i ++ ) { - - var morphNormal = {}; - - // vertex normals - - if ( morphNormals[ i ].vertexNormals !== undefined ) { - - morphNormal.vertexNormals = []; - - for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { - - var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; - var destVertexNormal = {}; - - destVertexNormal.a = srcVertexNormal.a.clone(); - destVertexNormal.b = srcVertexNormal.b.clone(); - destVertexNormal.c = srcVertexNormal.c.clone(); - - morphNormal.vertexNormals.push( destVertexNormal ); - - } - - } - - // face normals - - if ( morphNormals[ i ].faceNormals !== undefined ) { - - morphNormal.faceNormals = []; - - for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { - - morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); - - } - - } - - this.morphNormals.push( morphNormal ); - - } - - // skin weights - - var skinWeights = source.skinWeights; - - for ( i = 0, il = skinWeights.length; i < il; i ++ ) { - - this.skinWeights.push( skinWeights[ i ].clone() ); - - } - - // skin indices - - var skinIndices = source.skinIndices; - - for ( i = 0, il = skinIndices.length; i < il; i ++ ) { - - this.skinIndices.push( skinIndices[ i ].clone() ); - - } - - // line distances - - var lineDistances = source.lineDistances; - - for ( i = 0, il = lineDistances.length; i < il; i ++ ) { - - this.lineDistances.push( lineDistances[ i ] ); - - } - - // bounding box - - var boundingBox = source.boundingBox; - - if ( boundingBox !== null ) { - - this.boundingBox = boundingBox.clone(); - - } - - // bounding sphere - - var boundingSphere = source.boundingSphere; - - if ( boundingSphere !== null ) { - - this.boundingSphere = boundingSphere.clone(); - - } - - // update flags - - this.elementsNeedUpdate = source.elementsNeedUpdate; - this.verticesNeedUpdate = source.verticesNeedUpdate; - this.uvsNeedUpdate = source.uvsNeedUpdate; - this.normalsNeedUpdate = source.normalsNeedUpdate; - this.colorsNeedUpdate = source.colorsNeedUpdate; - this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate; - this.groupsNeedUpdate = source.groupsNeedUpdate; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function BufferAttribute( array, itemSize, normalized ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.uuid = _Math.generateUUID(); - this.name = ''; - - this.array = array; - this.itemSize = itemSize; - this.count = array !== undefined ? array.length / itemSize : 0; - this.normalized = normalized === true; - - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; - - this.onUploadCallback = function () {}; - - this.version = 0; - -} - -Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { - - set: function ( value ) { - - if ( value === true ) { this.version ++; } - - } - -} ); - -Object.assign( BufferAttribute.prototype, { - - isBufferAttribute: true, - - setArray: function ( array ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.count = array !== undefined ? array.length / this.itemSize : 0; - this.array = array; - - }, - - setDynamic: function ( value ) { - - this.dynamic = value; - - return this; - - }, - - copy: function ( source ) { - - this.array = new source.array.constructor( source.array ); - this.itemSize = source.itemSize; - this.count = source.count; - this.normalized = source.normalized; - - this.dynamic = source.dynamic; - - return this; - - }, - - copyAt: function ( index1, attribute, index2 ) { - - index1 *= this.itemSize; - index2 *= attribute.itemSize; - - for ( var i = 0, l = this.itemSize; i < l; i ++ ) { - - this.array[ index1 + i ] = attribute.array[ index2 + i ]; - - } - - return this; - - }, - - copyArray: function ( array ) { - - this.array.set( array ); - - return this; - - }, - - copyColorsArray: function ( colors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = colors.length; i < l; i ++ ) { - - var color = colors[ i ]; - - if ( color === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); - color = new Color(); - - } - - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; - - } - - return this; - - }, - - copyIndicesArray: function ( indices ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = indices.length; i < l; i ++ ) { - - var index = indices[ i ]; - - array[ offset ++ ] = index.a; - array[ offset ++ ] = index.b; - array[ offset ++ ] = index.c; - - } - - return this; - - }, - - copyVector2sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); - vector = new Vector2(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - - } - - return this; - - }, - - copyVector3sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); - vector = new Vector3(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - - } - - return this; - - }, - - copyVector4sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); - vector = new Vector4(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; - - } - - return this; - - }, - - set: function ( value, offset ) { - - if ( offset === undefined ) { offset = 0; } - - this.array.set( value, offset ); - - return this; - - }, - - getX: function ( index ) { - - return this.array[ index * this.itemSize ]; - - }, - - setX: function ( index, x ) { - - this.array[ index * this.itemSize ] = x; - - return this; - - }, - - getY: function ( index ) { - - return this.array[ index * this.itemSize + 1 ]; - - }, - - setY: function ( index, y ) { - - this.array[ index * this.itemSize + 1 ] = y; - - return this; - - }, - - getZ: function ( index ) { - - return this.array[ index * this.itemSize + 2 ]; - - }, - - setZ: function ( index, z ) { - - this.array[ index * this.itemSize + 2 ] = z; - - return this; - - }, - - getW: function ( index ) { - - return this.array[ index * this.itemSize + 3 ]; - - }, - - setW: function ( index, w ) { - - this.array[ index * this.itemSize + 3 ] = w; - - return this; - - }, - - setXY: function ( index, x, y ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - - return this; - - }, - - setXYZ: function ( index, x, y, z ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - - return this; - - }, - - setXYZW: function ( index, x, y, z, w ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - this.array[ index + 3 ] = w; - - return this; - - }, - - onUpload: function ( callback ) { - - this.onUploadCallback = callback; - - return this; - - }, - - clone: function () { - - return new this.constructor( this.array, this.itemSize ).copy( this ); - - } - -} ); - -// - -function Int8BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized ); - -} - -Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; - - -function Uint8BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized ); - -} - -Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; - - -function Uint8ClampedBufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized ); - -} - -Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; - - -function Int16BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized ); - -} - -Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; - - -function Uint16BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); - -} - -Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; - - -function Int32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized ); - -} - -Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; - - -function Uint32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized ); - -} - -Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; - - -function Float32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized ); - -} - -Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; - - -function Float64BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized ); - -} - -Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function DirectGeometry() { - - this.indices = []; - this.vertices = []; - this.normals = []; - this.colors = []; - this.uvs = []; - this.uvs2 = []; - - this.groups = []; - - this.morphTargets = {}; - - this.skinWeights = []; - this.skinIndices = []; - - // this.lineDistances = []; - - this.boundingBox = null; - this.boundingSphere = null; - - // update flags - - this.verticesNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.uvsNeedUpdate = false; - this.groupsNeedUpdate = false; - -} - -Object.assign( DirectGeometry.prototype, { - - computeGroups: function ( geometry ) { - - var group; - var groups = []; - var materialIndex = undefined; - - var faces = geometry.faces; - - for ( var i = 0; i < faces.length; i ++ ) { - - var face = faces[ i ]; - - // materials - - if ( face.materialIndex !== materialIndex ) { - - materialIndex = face.materialIndex; - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - group = { - start: i * 3, - materialIndex: materialIndex - }; - - } - - } - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - this.groups = groups; - - }, - - fromGeometry: function ( geometry ) { - - var faces = geometry.faces; - var vertices = geometry.vertices; - var faceVertexUvs = geometry.faceVertexUvs; - - var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; - - // morphs - - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; - - var morphTargetsPosition; - - if ( morphTargetsLength > 0 ) { - - morphTargetsPosition = []; - - for ( var i = 0; i < morphTargetsLength; i ++ ) { - - morphTargetsPosition[ i ] = []; - - } - - this.morphTargets.position = morphTargetsPosition; - - } - - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; - - var morphTargetsNormal; - - if ( morphNormalsLength > 0 ) { - - morphTargetsNormal = []; - - for ( var i = 0; i < morphNormalsLength; i ++ ) { - - morphTargetsNormal[ i ] = []; - - } - - this.morphTargets.normal = morphTargetsNormal; - - } - - // skins - - var skinIndices = geometry.skinIndices; - var skinWeights = geometry.skinWeights; - - var hasSkinIndices = skinIndices.length === vertices.length; - var hasSkinWeights = skinWeights.length === vertices.length; - - // - - for ( var i = 0; i < faces.length; i ++ ) { - - var face = faces[ i ]; - - this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); - - } else { - - var normal = face.normal; - - this.normals.push( normal, normal, normal ); - - } - - var vertexColors = face.vertexColors; - - if ( vertexColors.length === 3 ) { - - this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - - } else { - - var color = face.color; - - this.colors.push( color, color, color ); - - } - - if ( hasFaceVertexUv === true ) { - - var vertexUvs = faceVertexUvs[ 0 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); - - this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - if ( hasFaceVertexUv2 === true ) { - - var vertexUvs = faceVertexUvs[ 1 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); - - this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - // morphs - - for ( var j = 0; j < morphTargetsLength; j ++ ) { - - var morphTarget = morphTargets[ j ].vertices; - - morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); - - } - - for ( var j = 0; j < morphNormalsLength; j ++ ) { - - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; - - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); - - } - - // skins - - if ( hasSkinIndices ) { - - this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); - - } - - if ( hasSkinWeights ) { - - this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); - - } - - } - - this.computeGroups( geometry ); - - this.verticesNeedUpdate = geometry.verticesNeedUpdate; - this.normalsNeedUpdate = geometry.normalsNeedUpdate; - this.colorsNeedUpdate = geometry.colorsNeedUpdate; - this.uvsNeedUpdate = geometry.uvsNeedUpdate; - this.groupsNeedUpdate = geometry.groupsNeedUpdate; - - return this; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function arrayMax( array ) { - - if ( array.length === 0 ) { return - Infinity; } - - var max = array[ 0 ]; - - for ( var i = 1, l = array.length; i < l; ++ i ) { - - if ( array[ i ] > max ) { max = array[ i ]; } - - } - - return max; - -} - -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - -var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id - -function BufferGeometry() { - - Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'BufferGeometry'; - - this.index = null; - this.attributes = {}; - - this.morphAttributes = {}; - - this.groups = []; - - this.boundingBox = null; - this.boundingSphere = null; - - this.drawRange = { start: 0, count: Infinity }; - -} - -BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: BufferGeometry, - - isBufferGeometry: true, - - getIndex: function () { - - return this.index; - - }, - - setIndex: function ( index ) { - - if ( Array.isArray( index ) ) { - - this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - - } else { - - this.index = index; - - } - - }, - - addAttribute: function ( name, attribute ) { - - if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { - - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); - - this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); - - return; - - } - - if ( name === 'index' ) { - - console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); - this.setIndex( attribute ); - - return; - - } - - this.attributes[ name ] = attribute; - - return this; - - }, - - getAttribute: function ( name ) { - - return this.attributes[ name ]; - - }, - - removeAttribute: function ( name ) { - - delete this.attributes[ name ]; - - return this; - - }, - - addGroup: function ( start, count, materialIndex ) { - - this.groups.push( { - - start: start, - count: count, - materialIndex: materialIndex !== undefined ? materialIndex : 0 - - } ); - - }, - - clearGroups: function () { - - this.groups = []; - - }, - - setDrawRange: function ( start, count ) { - - this.drawRange.start = start; - this.drawRange.count = count; - - }, - - applyMatrix: function ( matrix ) { - - var position = this.attributes.position; - - if ( position !== undefined ) { - - matrix.applyToBufferAttribute( position ); - position.needsUpdate = true; - - } - - var normal = this.attributes.normal; - - if ( normal !== undefined ) { - - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - normalMatrix.applyToBufferAttribute( normal ); - normal.needsUpdate = true; - - } - - if ( this.boundingBox !== null ) { - - this.computeBoundingBox(); - - } - - if ( this.boundingSphere !== null ) { - - this.computeBoundingSphere(); - - } - - return this; - - }, - - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); - - return function rotateX( angle ) { - - m1.makeRotationX( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateY: function () { - - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateZ: function () { - - // rotate geometry around world z-axis - - var m1 = new Matrix4(); - - return function rotateZ( angle ) { - - m1.makeRotationZ( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - translate: function () { - - // translate geometry - - var m1 = new Matrix4(); - - return function translate( x, y, z ) { - - m1.makeTranslation( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - scale: function () { - - // scale geometry - - var m1 = new Matrix4(); - - return function scale( x, y, z ) { - - m1.makeScale( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - lookAt: function () { - - var obj = new Object3D(); - - return function lookAt( vector ) { - - obj.lookAt( vector ); - - obj.updateMatrix(); - - this.applyMatrix( obj.matrix ); - - }; - - }(), - - center: function () { - - this.computeBoundingBox(); - - var offset = this.boundingBox.getCenter().negate(); - - this.translate( offset.x, offset.y, offset.z ); - - return offset; - - }, - - setFromObject: function ( object ) { - - // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); - - var geometry = object.geometry; - - if ( object.isPoints || object.isLine ) { - - var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); - var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); - - this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); - this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); - - if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { - - var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); - - this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); - - } - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - } else if ( object.isMesh ) { - - if ( geometry && geometry.isGeometry ) { - - this.fromGeometry( geometry ); - - } - - } - - return this; - - }, - - setFromPoints: function ( points ) { - - var position = []; - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - position.push( point.x, point.y, point.z || 0 ); - - } - - this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - - return this; - - }, - - updateFromObject: function ( object ) { - - var geometry = object.geometry; - - if ( object.isMesh ) { - - var direct = geometry.__directGeometry; - - if ( geometry.elementsNeedUpdate === true ) { - - direct = undefined; - geometry.elementsNeedUpdate = false; - - } - - if ( direct === undefined ) { - - return this.fromGeometry( geometry ); - - } - - direct.verticesNeedUpdate = geometry.verticesNeedUpdate; - direct.normalsNeedUpdate = geometry.normalsNeedUpdate; - direct.colorsNeedUpdate = geometry.colorsNeedUpdate; - direct.uvsNeedUpdate = geometry.uvsNeedUpdate; - direct.groupsNeedUpdate = geometry.groupsNeedUpdate; - - geometry.verticesNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.groupsNeedUpdate = false; - - geometry = direct; - - } - - var attribute; - - if ( geometry.verticesNeedUpdate === true ) { - - attribute = this.attributes.position; - - if ( attribute !== undefined ) { - - attribute.copyVector3sArray( geometry.vertices ); - attribute.needsUpdate = true; - - } - - geometry.verticesNeedUpdate = false; - - } - - if ( geometry.normalsNeedUpdate === true ) { - - attribute = this.attributes.normal; - - if ( attribute !== undefined ) { - - attribute.copyVector3sArray( geometry.normals ); - attribute.needsUpdate = true; - - } - - geometry.normalsNeedUpdate = false; - - } - - if ( geometry.colorsNeedUpdate === true ) { - - attribute = this.attributes.color; - - if ( attribute !== undefined ) { - - attribute.copyColorsArray( geometry.colors ); - attribute.needsUpdate = true; - - } - - geometry.colorsNeedUpdate = false; - - } - - if ( geometry.uvsNeedUpdate ) { - - attribute = this.attributes.uv; - - if ( attribute !== undefined ) { - - attribute.copyVector2sArray( geometry.uvs ); - attribute.needsUpdate = true; - - } - - geometry.uvsNeedUpdate = false; - - } - - if ( geometry.lineDistancesNeedUpdate ) { - - attribute = this.attributes.lineDistance; - - if ( attribute !== undefined ) { - - attribute.copyArray( geometry.lineDistances ); - attribute.needsUpdate = true; - - } - - geometry.lineDistancesNeedUpdate = false; - - } - - if ( geometry.groupsNeedUpdate ) { - - geometry.computeGroups( object.geometry ); - this.groups = geometry.groups; - - geometry.groupsNeedUpdate = false; - - } - - return this; - - }, - - fromGeometry: function ( geometry ) { - - geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); - - return this.fromDirectGeometry( geometry.__directGeometry ); - - }, - - fromDirectGeometry: function ( geometry ) { - - var positions = new Float32Array( geometry.vertices.length * 3 ); - this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); - - if ( geometry.normals.length > 0 ) { - - var normals = new Float32Array( geometry.normals.length * 3 ); - this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); - - } - - if ( geometry.colors.length > 0 ) { - - var colors = new Float32Array( geometry.colors.length * 3 ); - this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); - - } - - if ( geometry.uvs.length > 0 ) { - - var uvs = new Float32Array( geometry.uvs.length * 2 ); - this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); - - } - - if ( geometry.uvs2.length > 0 ) { - - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); - - } - - if ( geometry.indices.length > 0 ) { - - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); - - } - - // groups - - this.groups = geometry.groups; - - // morphs - - for ( var name in geometry.morphTargets ) { - - var array = []; - var morphTargets = geometry.morphTargets[ name ]; - - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { - - var morphTarget = morphTargets[ i ]; - - var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); - - array.push( attribute.copyVector3sArray( morphTarget ) ); - - } - - this.morphAttributes[ name ] = array; - - } - - // skinning - - if ( geometry.skinIndices.length > 0 ) { - - var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); - - } - - if ( geometry.skinWeights.length > 0 ) { - - var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); - - } - - // - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - return this; - - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } - - var position = this.attributes.position; - - if ( position !== undefined ) { - - this.boundingBox.setFromBufferAttribute( position ); - - } 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: function () { - - var box = new Box3(); - var vector = new Vector3(); - - return function computeBoundingSphere() { - - if ( this.boundingSphere === null ) { - - this.boundingSphere = new Sphere(); - - } - - var position = this.attributes.position; - - if ( position ) { - - var center = this.boundingSphere.center; - - box.setFromBufferAttribute( position ); - box.getCenter( center ); - - // hoping to find a boundingSphere with a radius smaller than the - // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - - var maxRadiusSq = 0; - - for ( var i = 0, il = position.count; i < il; i ++ ) { - - vector.x = position.getX( i ); - vector.y = position.getY( i ); - vector.z = position.getZ( i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); - - } - - 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 ); - - } - - } - - }; - - }(), - - computeFaceNormals: function () { - - // backwards compatibility - - }, - - computeVertexNormals: function () { - - var index = this.index; - var attributes = this.attributes; - var groups = this.groups; - - if ( attributes.position ) { - - var positions = attributes.position.array; - - if ( attributes.normal === undefined ) { - - this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); - - } else { - - // reset existing normals to zero - - var array = attributes.normal.array; - - for ( var i = 0, il = array.length; i < il; i ++ ) { - - array[ i ] = 0; - - } - - } - - var normals = attributes.normal.array; - - var vA, vB, vC; - var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); - var cb = new Vector3(), ab = new Vector3(); - - // indexed elements - - if ( index ) { - - var indices = index.array; - - if ( groups.length === 0 ) { - - this.addGroup( 0, indices.length ); - - } - - for ( var j = 0, jl = groups.length; j < jl; ++ j ) { - - var group = groups[ j ]; - - var start = group.start; - var count = group.count; - - for ( var i = start, il = start + count; i < il; i += 3 ) { - - vA = indices[ i + 0 ] * 3; - vB = indices[ i + 1 ] * 3; - vC = indices[ i + 2 ] * 3; - - pA.fromArray( positions, vA ); - pB.fromArray( positions, vB ); - pC.fromArray( positions, vC ); - - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); - - normals[ vA ] += cb.x; - normals[ vA + 1 ] += cb.y; - normals[ vA + 2 ] += cb.z; - - normals[ vB ] += cb.x; - normals[ vB + 1 ] += cb.y; - normals[ vB + 2 ] += cb.z; - - normals[ vC ] += cb.x; - normals[ vC + 1 ] += cb.y; - normals[ vC + 2 ] += cb.z; - - } - - } - - } else { - - // non-indexed elements (unconnected triangle soup) - - for ( var i = 0, il = positions.length; i < il; i += 9 ) { - - pA.fromArray( positions, i ); - pB.fromArray( positions, i + 3 ); - pC.fromArray( positions, i + 6 ); - - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); - - normals[ i ] = cb.x; - normals[ i + 1 ] = cb.y; - normals[ i + 2 ] = cb.z; - - normals[ i + 3 ] = cb.x; - normals[ i + 4 ] = cb.y; - normals[ i + 5 ] = cb.z; - - normals[ i + 6 ] = cb.x; - normals[ i + 7 ] = cb.y; - normals[ i + 8 ] = cb.z; - - } - - } - - this.normalizeNormals(); - - attributes.normal.needsUpdate = true; - - } - - }, - - merge: function ( geometry, offset ) { - - if ( ! ( geometry && geometry.isBufferGeometry ) ) { - - console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); - return; - - } - - if ( offset === undefined ) { offset = 0; } - - var attributes = this.attributes; - - for ( var key in attributes ) { - - if ( geometry.attributes[ key ] === undefined ) { continue; } - - var attribute1 = attributes[ key ]; - var attributeArray1 = attribute1.array; - - var attribute2 = geometry.attributes[ key ]; - var attributeArray2 = attribute2.array; - - var attributeSize = attribute2.itemSize; - - for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { - - attributeArray1[ j ] = attributeArray2[ i ]; - - } - - } - - return this; - - }, - - normalizeNormals: function () { - - var vector = new Vector3(); - - return function normalizeNormals() { - - var normals = this.attributes.normal; - - for ( var i = 0, il = normals.count; i < il; i ++ ) { - - vector.x = normals.getX( i ); - vector.y = normals.getY( i ); - vector.z = normals.getZ( i ); - - vector.normalize(); - - normals.setXYZ( i, vector.x, vector.y, vector.z ); - - } - - }; - - }(), - - toNonIndexed: function () { - - if ( this.index === null ) { - - console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); - return this; - - } - - var geometry2 = new BufferGeometry(); - - var indices = this.index.array; - var attributes = this.attributes; - - for ( var name in attributes ) { - - var attribute = attributes[ name ]; - - var array = attribute.array; - var itemSize = attribute.itemSize; - - var array2 = new array.constructor( indices.length * itemSize ); - - var index = 0, index2 = 0; - - for ( var i = 0, l = indices.length; i < l; i ++ ) { - - index = indices[ i ] * itemSize; - - for ( var j = 0; j < itemSize; j ++ ) { - - array2[ index2 ++ ] = array[ index ++ ]; - - } - - } - - geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); - - } - - return geometry2; - - }, - - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'BufferGeometry', - generator: 'BufferGeometry.toJSON' - } - }; - - // standard BufferGeometry serialization - - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) { data.name = this.name; } - - if ( this.parameters !== undefined ) { - - var parameters = this.parameters; - - for ( var key in parameters ) { - - if ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; } - - } - - return data; - - } - - data.data = { attributes: {} }; - - var index = this.index; - - if ( index !== null ) { - - var array = Array.prototype.slice.call( index.array ); - - data.data.index = { - type: index.array.constructor.name, - array: array - }; - - } - - var attributes = this.attributes; - - for ( var key in attributes ) { - - var attribute = attributes[ key ]; - - var array = Array.prototype.slice.call( attribute.array ); - - data.data.attributes[ key ] = { - itemSize: attribute.itemSize, - type: attribute.array.constructor.name, - array: array, - normalized: attribute.normalized - }; - - } - - var groups = this.groups; - - if ( groups.length > 0 ) { - - data.data.groups = JSON.parse( JSON.stringify( groups ) ); - - } - - var boundingSphere = this.boundingSphere; - - if ( boundingSphere !== null ) { - - data.data.boundingSphere = { - center: boundingSphere.center.toArray(), - radius: boundingSphere.radius - }; - - } - - return data; - - }, - - clone: function () { - - /* - // Handle primitives - - var parameters = this.parameters; - - if ( parameters !== undefined ) { - - var values = []; - - for ( var key in parameters ) { - - values.push( parameters[ key ] ); - - } - - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; - - } - - return new this.constructor().copy( this ); - */ - - return new BufferGeometry().copy( this ); - - }, - - copy: function ( source ) { - - var name, i, l; - - // reset - - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; - - // name - - this.name = source.name; - - // index - - var index = source.index; - - if ( index !== null ) { - - this.setIndex( index.clone() ); - - } - - // attributes - - var attributes = source.attributes; - - for ( name in attributes ) { - - var attribute = attributes[ name ]; - this.addAttribute( name, attribute.clone() ); - - } - - // morph attributes - - var morphAttributes = source.morphAttributes; - - for ( name in morphAttributes ) { - - var array = []; - var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - - for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { - - array.push( morphAttribute[ i ].clone() ); - - } - - this.morphAttributes[ name ] = array; - - } - - // groups - - var groups = source.groups; - - for ( i = 0, l = groups.length; i < l; i ++ ) { - - var group = groups[ i ]; - this.addGroup( group.start, group.count, group.materialIndex ); - - } - - // bounding box - - var boundingBox = source.boundingBox; - - if ( boundingBox !== null ) { - - this.boundingBox = boundingBox.clone(); - - } - - // bounding sphere - - var boundingSphere = source.boundingSphere; - - if ( boundingSphere !== null ) { - - this.boundingSphere = boundingSphere.clone(); - - } - - // draw range - - this.drawRange.start = source.drawRange.start; - this.drawRange.count = source.drawRange.count; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - -// BoxGeometry - -function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - Geometry.call( this ); - - this.type = 'BoxGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; - - this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); - this.mergeVertices(); - -} - -BoxGeometry.prototype = Object.create( Geometry.prototype ); -BoxGeometry.prototype.constructor = BoxGeometry; - -// BoxBufferGeometry - -function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - BufferGeometry.call( this ); - - this.type = 'BoxBufferGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; - - var scope = this; - - width = width || 1; - height = height || 1; - depth = depth || 1; - - // segments - - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var numberOfVertices = 0; - var groupStart = 0; - - // build each side of the box geometry - - buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px - buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx - buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py - buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny - buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz - buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { - - var segmentWidth = width / gridX; - var segmentHeight = height / gridY; - - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; - - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; - - var vertexCounter = 0; - var groupCount = 0; - - var ix, iy; - - var vector = new Vector3(); - - // generate vertices, normals and uvs - - for ( iy = 0; iy < gridY1; iy ++ ) { - - var y = iy * segmentHeight - heightHalf; - - for ( ix = 0; ix < gridX1; ix ++ ) { - - var x = ix * segmentWidth - widthHalf; - - // set values to correct vector component - - vector[ u ] = x * udir; - vector[ v ] = y * vdir; - vector[ w ] = depthHalf; - - // now apply vector to vertex buffer - - vertices.push( vector.x, vector.y, vector.z ); - - // set values to correct vector component - - vector[ u ] = 0; - vector[ v ] = 0; - vector[ w ] = depth > 0 ? 1 : - 1; - - // now apply vector to normal buffer - - normals.push( vector.x, vector.y, vector.z ); - - // uvs - - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); - - // counters - - vertexCounter += 1; - - } - - } - - // indices - - // 1. you need three indices to draw a single face - // 2. a single segment consists of two faces - // 3. so we need to generate six (2*3) indices per segment - - for ( iy = 0; iy < gridY; iy ++ ) { - - for ( ix = 0; ix < gridX; ix ++ ) { - - var a = numberOfVertices + ix + gridX1 * iy; - var b = numberOfVertices + ix + gridX1 * ( iy + 1 ); - var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - // increase counter - - groupCount += 6; - - } - - } - - // add a group to the geometry. this will ensure multi material support - - scope.addGroup( groupStart, groupCount, materialIndex ); - - // calculate new start value for groups - - groupStart += groupCount; - - // update total number of vertices - - numberOfVertices += vertexCounter; - - } - -} - -BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; - -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - -// PlaneGeometry - -function PlaneGeometry( width, height, widthSegments, heightSegments ) { - - Geometry.call( this ); - - this.type = 'PlaneGeometry'; - - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; - - this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); - this.mergeVertices(); - -} - -PlaneGeometry.prototype = Object.create( Geometry.prototype ); -PlaneGeometry.prototype.constructor = PlaneGeometry; - -// PlaneBufferGeometry - -function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { - - BufferGeometry.call( this ); - - this.type = 'PlaneBufferGeometry'; - - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; - - width = width || 1; - height = height || 1; - - var width_half = width / 2; - var height_half = height / 2; - - var gridX = Math.floor( widthSegments ) || 1; - var gridY = Math.floor( heightSegments ) || 1; - - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; - - var segment_width = width / gridX; - var segment_height = height / gridY; - - var ix, iy; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // generate vertices, normals and uvs - - for ( iy = 0; iy < gridY1; iy ++ ) { - - var y = iy * segment_height - height_half; - - for ( ix = 0; ix < gridX1; ix ++ ) { - - var x = ix * segment_width - width_half; - - vertices.push( x, - y, 0 ); - - normals.push( 0, 0, 1 ); - - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); - - } - - } - - // indices - - for ( iy = 0; iy < gridY; iy ++ ) { - - for ( ix = 0; ix < gridX; ix ++ ) { - - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - -} - -PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * depthTest: , - * depthWrite: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: - * } - */ - -function MeshBasicMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshBasicMaterial'; - - this.color = new Color( 0xffffff ); // emissive - - this.map = null; - - this.lightMap = null; - this.lightMapIntensity = 1.0; - - this.aoMap = null; - this.aoMapIntensity = 1.0; - - 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.skinning = false; - this.morphTargets = false; - - this.lights = false; - - this.setValues( parameters ); - -} - -MeshBasicMaterial.prototype = Object.create( Material.prototype ); -MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; - -MeshBasicMaterial.prototype.isMeshBasicMaterial = true; - -MeshBasicMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, 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.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - return this; - -}; - -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * defines: { "label" : "value" }, - * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } }, - * - * fragmentShader: , - * vertexShader: , - * - * wireframe: , - * wireframeLinewidth: , - * - * lights: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ - -function ShaderMaterial( parameters ) { - - Material.call( this ); - - this.type = 'ShaderMaterial'; - - this.defines = {}; - this.uniforms = {}; - - this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'; - this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'; - - this.linewidth = 1; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; // set to use scene fog - this.lights = false; // set to use scene lights - this.clipping = false; // set to use user-defined clipping planes - - this.skinning = false; // set to use skinning attribute streams - this.morphTargets = false; // set to use morph targets - this.morphNormals = false; // set to use morph normals - - this.extensions = { - derivatives: false, // set to use derivatives - fragDepth: false, // set to use fragment depth values - drawBuffers: false, // set to use draw buffers - shaderTextureLOD: false // set to use shader texture LOD - }; - - // When rendered geometry doesn't include these attributes but the material does, - // use these default values in WebGL. This avoids errors when buffer data is missing. - this.defaultAttributeValues = { - 'color': [ 1, 1, 1 ], - 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] - }; - - this.index0AttributeName = undefined; - - if ( parameters !== undefined ) { - - if ( parameters.attributes !== undefined ) { - - console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); - - } - - this.setValues( parameters ); - - } - -} - -ShaderMaterial.prototype = Object.create( Material.prototype ); -ShaderMaterial.prototype.constructor = ShaderMaterial; - -ShaderMaterial.prototype.isShaderMaterial = true; - -ShaderMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.fragmentShader = source.fragmentShader; - this.vertexShader = source.vertexShader; - - this.uniforms = UniformsUtils.clone( source.uniforms ); - - this.defines = source.defines; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - - this.lights = source.lights; - this.clipping = source.clipping; - - this.skinning = source.skinning; - - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - this.extensions = source.extensions; - - return this; - -}; - -ShaderMaterial.prototype.toJSON = function ( meta ) { - - var data = Material.prototype.toJSON.call( this, meta ); - - data.uniforms = this.uniforms; - data.vertexShader = this.vertexShader; - data.fragmentShader = this.fragmentShader; - - return data; - -}; - -/** - * @author bhouston / http://clara.io - */ - -function Ray( origin, direction ) { - - this.origin = ( origin !== undefined ) ? origin : new Vector3(); - this.direction = ( direction !== undefined ) ? direction : new Vector3(); - -} - -Object.assign( Ray.prototype, { - - set: function ( origin, direction ) { - - this.origin.copy( origin ); - this.direction.copy( direction ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( ray ) { - - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); - - return this; - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - - }, - - lookAt: function ( v ) { - - this.direction.copy( v ).sub( this.origin ).normalize(); - - return this; - - }, - - recast: function () { - - var v1 = new Vector3(); - - return function recast( t ) { - - this.origin.copy( this.at( t, v1 ) ); - - return this; - - }; - - }(), - - closestPointToPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - result.subVectors( point, this.origin ); - var directionDistance = result.dot( this.direction ); - - if ( directionDistance < 0 ) { - - return result.copy( this.origin ); - - } - - return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - }, - - distanceToPoint: function ( point ) { - - return Math.sqrt( this.distanceSqToPoint( point ) ); - - }, - - distanceSqToPoint: function () { - - var v1 = new Vector3(); - - return function distanceSqToPoint( point ) { - - var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); - - // point behind the ray - - if ( directionDistance < 0 ) { - - return this.origin.distanceToSquared( point ); - - } - - v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - return v1.distanceToSquared( point ); - - }; - - }(), - - distanceSqToSegment: function () { - - var segCenter = new Vector3(); - var segDir = new Vector3(); - var diff = new Vector3(); - - return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h - // It returns the min distance between the ray and the segment - // defined by v0 and v1 - // It can also set two optional targets : - // - The closest point on the ray - // - The closest point on the segment - - segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - segDir.copy( v1 ).sub( v0 ).normalize(); - diff.copy( this.origin ).sub( segCenter ); - - var segExtent = v0.distanceTo( v1 ) * 0.5; - var a01 = - this.direction.dot( segDir ); - var b0 = diff.dot( this.direction ); - var b1 = - diff.dot( segDir ); - var c = diff.lengthSq(); - var det = Math.abs( 1 - a01 * a01 ); - var s0, s1, sqrDist, extDet; - - if ( det > 0 ) { - - // The ray and segment are not parallel. - - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; - - if ( s0 >= 0 ) { - - if ( s1 >= - extDet ) { - - if ( s1 <= extDet ) { - - // region 0 - // Minimum at interior points of ray and segment. - - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - - } else { - - // region 1 - - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } else { - - // region 5 - - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } else { - - if ( s1 <= - extDet ) { - - // region 4 - - 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 ) + c; - - } else if ( s1 <= extDet ) { - - // region 3 - - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; - - } else { - - // region 2 - - 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 ) + c; - - } - - } - - } else { - - // Ray and segment are parallel. - - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - if ( optionalPointOnRay ) { - - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); - - } - - if ( optionalPointOnSegment ) { - - optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); - - } - - return sqrDist; - - }; - - }(), - - intersectSphere: function () { - - var v1 = new Vector3(); - - return function intersectSphere( sphere, optionalTarget ) { - - v1.subVectors( sphere.center, this.origin ); - var tca = v1.dot( this.direction ); - var d2 = v1.dot( v1 ) - tca * tca; - var radius2 = sphere.radius * sphere.radius; - - if ( d2 > radius2 ) { return null; } - - var thc = Math.sqrt( radius2 - d2 ); - - // t0 = first intersect point - entrance on front of sphere - var t0 = tca - thc; - - // t1 = second intersect point - exit point on back of sphere - var t1 = tca + thc; - - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) { return null; } - - // test to see if t0 is behind the ray: - // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, - // in order to always return an intersect point that is in front of the ray. - if ( t0 < 0 ) { return this.at( t1, optionalTarget ); } - - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, optionalTarget ); - - }; - - }(), - - intersectsSphere: function ( sphere ) { - - return this.distanceToPoint( sphere.center ) <= sphere.radius; - - }, - - distanceToPlane: function ( plane ) { - - var denominator = plane.normal.dot( this.direction ); - - if ( denominator === 0 ) { - - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { - - return 0; - - } - - // Null is preferable to undefined since undefined means.... it is undefined - - return null; - - } - - var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - - // Return if the ray never intersects the plane - - return t >= 0 ? t : null; - - }, - - intersectPlane: function ( plane, optionalTarget ) { - - var t = this.distanceToPlane( plane ); - - if ( t === null ) { - - return null; - - } - - return this.at( t, optionalTarget ); - - }, - - intersectsPlane: function ( plane ) { - - // check if the ray lies on the plane first - - var distToPoint = plane.distanceToPoint( this.origin ); - - if ( distToPoint === 0 ) { - - return true; - - } - - var denominator = plane.normal.dot( this.direction ); - - if ( denominator * distToPoint < 0 ) { - - return true; - - } - - // ray origin is behind the plane (and is pointing behind it) - - return false; - - }, - - intersectBox: function ( box, optionalTarget ) { - - var tmin, tmax, tymin, tymax, tzmin, tzmax; - - var invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; - - var 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; } - - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN - - 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; } - - //return point closest to the ray (positive side) - - if ( tmax < 0 ) { return null; } - - return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); - - }, - - intersectsBox: ( function () { - - var v = new Vector3(); - - return function intersectsBox( box ) { - - return this.intersectBox( box, v ) !== null; - - }; - - } )(), - - intersectTriangle: function () { - - // Compute the offset origin, edges, and normal. - var diff = new Vector3(); - var edge1 = new Vector3(); - var edge2 = new Vector3(); - var normal = new Vector3(); - - return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { - - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - - edge1.subVectors( b, a ); - edge2.subVectors( c, a ); - normal.crossVectors( edge1, edge2 ); - - // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, - // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by - // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) - // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) - // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) - var DdN = this.direction.dot( normal ); - var 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, a ); - var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); - - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { - - return null; - - } - - var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); - - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { - - return null; - - } - - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { - - return null; - - } - - // Line intersects triangle, check if ray does. - var QdN = - sign * diff.dot( normal ); - - // t < 0, no intersection - if ( QdN < 0 ) { - - return null; - - } - - // Ray intersects triangle. - return this.at( QdN / DdN, optionalTarget ); - - }; - - }(), - - applyMatrix4: function ( matrix4 ) { - - this.origin.applyMatrix4( matrix4 ); - this.direction.transformDirection( matrix4 ); - - return this; - - }, - - equals: function ( ray ) { - - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - */ - -function Line3( start, end ) { - - this.start = ( start !== undefined ) ? start : new Vector3(); - this.end = ( end !== undefined ) ? end : new Vector3(); - -} - -Object.assign( Line3.prototype, { - - set: function ( start, end ) { - - this.start.copy( start ); - this.end.copy( end ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( line ) { - - this.start.copy( line.start ); - this.end.copy( line.end ); - - return this; - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); - - }, - - delta: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.subVectors( this.end, this.start ); - - }, - - distanceSq: function () { - - return this.start.distanceToSquared( this.end ); - - }, - - distance: function () { - - return this.start.distanceTo( this.end ); - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return this.delta( result ).multiplyScalar( t ).add( this.start ); - - }, - - closestPointToPointParameter: function () { - - var startP = new Vector3(); - var startEnd = new Vector3(); - - return function closestPointToPointParameter( point, clampToLine ) { - - startP.subVectors( point, this.start ); - startEnd.subVectors( this.end, this.start ); - - var startEnd2 = startEnd.dot( startEnd ); - var startEnd_startP = startEnd.dot( startP ); - - var t = startEnd_startP / startEnd2; - - if ( clampToLine ) { - - t = _Math.clamp( t, 0, 1 ); - - } - - return t; - - }; - - }(), - - closestPointToPoint: function ( point, clampToLine, optionalTarget ) { - - var t = this.closestPointToPointParameter( point, clampToLine ); - - var result = optionalTarget || new Vector3(); - - return this.delta( result ).multiplyScalar( t ).add( this.start ); - - }, - - applyMatrix4: function ( matrix ) { - - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); - - return this; - - }, - - equals: function ( line ) { - - return line.start.equals( this.start ) && line.end.equals( this.end ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ - -function Triangle( a, b, c ) { - - this.a = ( a !== undefined ) ? a : new Vector3(); - this.b = ( b !== undefined ) ? b : new Vector3(); - this.c = ( c !== undefined ) ? c : new Vector3(); - -} - -Object.assign( Triangle, { - - normal: function () { - - var v0 = new Vector3(); - - return function normal( a, b, c, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - result.subVectors( c, b ); - v0.subVectors( a, b ); - result.cross( v0 ); - - var resultLengthSq = result.lengthSq(); - if ( resultLengthSq > 0 ) { - - return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); - - } - - return result.set( 0, 0, 0 ); - - }; - - }(), - - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - barycoordFromPoint: function () { - - var v0 = new Vector3(); - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function barycoordFromPoint( point, a, b, c, optionalTarget ) { - - v0.subVectors( c, a ); - v1.subVectors( b, a ); - v2.subVectors( point, a ); - - var dot00 = v0.dot( v0 ); - var dot01 = v0.dot( v1 ); - var dot02 = v0.dot( v2 ); - var dot11 = v1.dot( v1 ); - var dot12 = v1.dot( v2 ); - - var denom = ( dot00 * dot11 - dot01 * dot01 ); - - var result = optionalTarget || new Vector3(); - - // collinear or singular triangle - if ( denom === 0 ) { - - // arbitrary location outside of triangle? - // not sure if this is the best idea, maybe should be returning undefined - return result.set( - 2, - 1, - 1 ); - - } - - var invDenom = 1 / denom; - var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - - // barycentric coordinates must always sum to 1 - return result.set( 1 - u - v, v, u ); - - }; - - }(), - - containsPoint: function () { - - var v1 = new Vector3(); - - return function containsPoint( point, a, b, c ) { - - var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); - - return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); - - }; - - }() - -} ); - -Object.assign( Triangle.prototype, { - - set: function ( a, b, c ) { - - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); - - return this; - - }, - - setFromPointsAndIndices: function ( points, i0, i1, i2 ) { - - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( triangle ) { - - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); - - return this; - - }, - - area: function () { - - var v0 = new Vector3(); - var v1 = new Vector3(); - - return function area() { - - v0.subVectors( this.c, this.b ); - v1.subVectors( this.a, this.b ); - - return v0.cross( v1 ).length() * 0.5; - - }; - - }(), - - midpoint: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - - }, - - normal: function ( optionalTarget ) { - - return Triangle.normal( this.a, this.b, this.c, optionalTarget ); - - }, - - plane: function ( optionalTarget ) { - - var result = optionalTarget || new Plane(); - - return result.setFromCoplanarPoints( this.a, this.b, this.c ); - - }, - - barycoordFromPoint: function ( point, optionalTarget ) { - - return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); - - }, - - containsPoint: function ( point ) { - - return Triangle.containsPoint( point, this.a, this.b, this.c ); - - }, - - closestPointToPoint: function () { - - var plane = new Plane(); - var edgeList = [ new Line3(), new Line3(), new Line3() ]; - var projectedPoint = new Vector3(); - var closestPoint = new Vector3(); - - return function closestPointToPoint( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - var minDistance = Infinity; - - // project the point onto the plane of the triangle - - plane.setFromCoplanarPoints( this.a, this.b, this.c ); - plane.projectPoint( point, projectedPoint ); - - // check if the projection lies within the triangle - - if ( this.containsPoint( projectedPoint ) === true ) { - - // if so, this is the closest point - - result.copy( projectedPoint ); - - } else { - - // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices - - edgeList[ 0 ].set( this.a, this.b ); - edgeList[ 1 ].set( this.b, this.c ); - edgeList[ 2 ].set( this.c, this.a ); - - for ( var i = 0; i < edgeList.length; i ++ ) { - - edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); - - var distance = projectedPoint.distanceToSquared( closestPoint ); - - if ( distance < minDistance ) { - - minDistance = distance; - - result.copy( closestPoint ); - - } - - } - - } - - return result; - - }; - - }(), - - equals: function ( triangle ) { - - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author jonobr1 / http://jonobr1.com/ - */ - -function Mesh( geometry, material ) { - - Object3D.call( this ); - - this.type = 'Mesh'; - - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); - - this.drawMode = TrianglesDrawMode; - - this.updateMorphTargets(); - -} - -Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Mesh, - - isMesh: true, - - setDrawMode: function ( value ) { - - this.drawMode = value; - - }, - - copy: function ( source ) { - - Object3D.prototype.copy.call( this, source ); - - this.drawMode = source.drawMode; - - if ( source.morphTargetInfluences !== undefined ) { - - this.morphTargetInfluences = source.morphTargetInfluences.slice(); - - } - - if ( source.morphTargetDictionary !== undefined ) { - - this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); - - } - - return this; - - }, - - updateMorphTargets: function () { - - var geometry = this.geometry; - var m, ml, name; - - if ( geometry.isBufferGeometry ) { - - var morphAttributes = geometry.morphAttributes; - var keys = Object.keys( morphAttributes ); - - if ( keys.length > 0 ) { - - var morphAttribute = morphAttributes[ keys[ 0 ] ]; - - if ( morphAttribute !== undefined ) { - - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - - name = morphAttribute[ m ].name || String( m ); - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; - - } - - } - - } - - } else { - - var morphTargets = geometry.morphTargets; - - if ( morphTargets !== undefined && morphTargets.length > 0 ) { - - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { - - name = morphTargets[ m ].name || String( m ); - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; - - } - - } - - } - - }, - - raycast: ( function () { - - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); - - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); - - var tempA = new Vector3(); - var tempB = new Vector3(); - var tempC = new Vector3(); - - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); - - var barycoord = new Vector3(); - - var intersectionPoint = new Vector3(); - var intersectionPointWorld = new Vector3(); - - function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { - - Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); - - uv1.multiplyScalar( barycoord.x ); - uv2.multiplyScalar( barycoord.y ); - uv3.multiplyScalar( barycoord.z ); - - uv1.add( uv2 ).add( uv3 ); - - return uv1.clone(); - - } - - function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { - - var 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 ); - - var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); - - if ( distance < raycaster.near || distance > raycaster.far ) { return null; } - - return { - distance: distance, - point: intersectionPointWorld.clone(), - object: object - }; - - } - - function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { - - vA.fromBufferAttribute( position, a ); - vB.fromBufferAttribute( position, b ); - vC.fromBufferAttribute( position, c ); - - var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); - - if ( intersection ) { - - if ( uv ) { - - uvA.fromBufferAttribute( uv, a ); - uvB.fromBufferAttribute( uv, b ); - uvC.fromBufferAttribute( uv, c ); - - intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); - - } - - intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); - intersection.faceIndex = a; - - } - - return intersection; - - } - - return function raycast( raycaster, intersects ) { - - var geometry = this.geometry; - var material = this.material; - var matrixWorld = this.matrixWorld; - - if ( material === undefined ) { return; } - - // Checking boundingSphere distance to ray - - if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); } - - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - - if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; } - - // - - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - - // Check boundingBox before continuing - - if ( geometry.boundingBox !== null ) { - - if ( ray.intersectsBox( geometry.boundingBox ) === false ) { return; } - - } - - var intersection; - - if ( geometry.isBufferGeometry ) { - - var a, b, c; - var index = geometry.index; - var position = geometry.attributes.position; - var uv = geometry.attributes.uv; - var i, l; - - if ( index !== null ) { - - // indexed buffer geometry - - for ( i = 0, l = index.count; i < l; i += 3 ) { - - a = index.getX( i ); - b = index.getX( i + 1 ); - c = index.getX( i + 2 ); - - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { - - intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics - intersects.push( intersection ); - - } - - } - - } else if ( position !== undefined ) { - - // non-indexed buffer geometry - - for ( i = 0, l = position.count; i < l; i += 3 ) { - - a = i; - b = i + 1; - c = i + 2; - - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { - - intersection.index = a; // triangle number in positions buffer semantics - intersects.push( intersection ); - - } - - } - - } - - } else if ( geometry.isGeometry ) { - - var fvA, fvB, fvC; - var isMultiMaterial = Array.isArray( material ); - - var vertices = geometry.vertices; - var faces = geometry.faces; - var uvs; - - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - if ( faceVertexUvs.length > 0 ) { uvs = faceVertexUvs; } - - for ( var f = 0, fl = faces.length; f < fl; f ++ ) { - - var face = faces[ f ]; - var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; - - if ( faceMaterial === undefined ) { continue; } - - fvA = vertices[ face.a ]; - fvB = vertices[ face.b ]; - fvC = vertices[ face.c ]; - - if ( faceMaterial.morphTargets === true ) { - - var morphTargets = geometry.morphTargets; - var morphInfluences = this.morphTargetInfluences; - - vA.set( 0, 0, 0 ); - vB.set( 0, 0, 0 ); - vC.set( 0, 0, 0 ); - - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { - - var influence = morphInfluences[ t ]; - - if ( influence === 0 ) { continue; } - - var targets = morphTargets[ t ].vertices; - - vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); - vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); - vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); - - } - - vA.add( fvA ); - vB.add( fvB ); - vC.add( fvC ); - - fvA = vA; - fvB = vB; - fvC = vC; - - } - - intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); - - if ( intersection ) { - - if ( uvs && uvs[ f ] ) { - - var uvs_f = uvs[ f ]; - uvA.copy( uvs_f[ 0 ] ); - uvB.copy( uvs_f[ 1 ] ); - uvC.copy( uvs_f[ 2 ] ); - - intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); - - } - - intersection.face = face; - intersection.faceIndex = f; - intersects.push( intersection ); - - } - - } - - } - - }; - - }() ), - - clone: function () { - - return new this.constructor( this.geometry, this.material ).copy( this ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) { - - var clearColor = new Color( 0x000000 ); - var clearAlpha = 0; - - var planeCamera, planeMesh; - var boxMesh; - - function render( renderList, scene, camera, forceClear ) { - - var background = scene.background; - - 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 ) { - - if ( boxMesh === undefined ) { - - boxMesh = new Mesh( - new BoxBufferGeometry( 1, 1, 1 ), - new ShaderMaterial( { - uniforms: ShaderLib.cube.uniforms, - vertexShader: ShaderLib.cube.vertexShader, - fragmentShader: ShaderLib.cube.fragmentShader, - side: BackSide, - depthTest: true, - depthWrite: false, - fog: false - } ) - ); - - boxMesh.geometry.removeAttribute( 'normal' ); - boxMesh.geometry.removeAttribute( 'uv' ); - - boxMesh.onBeforeRender = function ( renderer, scene, camera ) { - - this.matrixWorld.copyPosition( camera.matrixWorld ); - - }; - - geometries.update( boxMesh.geometry ); - - } - - boxMesh.material.uniforms.tCube.value = background; - - renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); - - } else if ( background && background.isTexture ) { - - if ( planeCamera === undefined ) { - - planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - planeMesh = new Mesh( - new PlaneBufferGeometry( 2, 2 ), - new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) - ); - - geometries.update( planeMesh.geometry ); - - } - - planeMesh.material.map = background; - - // TODO Push this to renderList - - renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); - - } - - } - - function setClear( color, alpha ) { - - state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); - - } - - return { - - getClearColor: function () { - - return clearColor; - - }, - setClearColor: function ( color, alpha ) { - - clearColor.set( color ); - clearAlpha = alpha !== undefined ? alpha : 1; - setClear( clearColor, clearAlpha ); - - }, - getClearAlpha: function () { - - return clearAlpha; - - }, - setClearAlpha: function ( alpha ) { - - clearAlpha = alpha; - setClear( clearColor, clearAlpha ); - - }, - render: render - - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function painterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } else if ( a.program && b.program && a.program !== b.program ) { - - return a.program.id - b.program.id; - - } else if ( a.material.id !== b.material.id ) { - - return a.material.id - b.material.id; - - } else if ( a.z !== b.z ) { - - return a.z - b.z; - - } else { - - return a.id - b.id; - - } - -} - -function reversePainterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } if ( a.z !== b.z ) { - - return b.z - a.z; - - } else { - - return a.id - b.id; - - } - -} - -function WebGLRenderList() { - - var renderItems = []; - var renderItemsIndex = 0; - - var opaque = []; - var transparent = []; - - function init() { - - renderItemsIndex = 0; - - opaque.length = 0; - transparent.length = 0; - - } - - function push( object, geometry, material, z, group ) { - - var renderItem = renderItems[ renderItemsIndex ]; - - if ( renderItem === undefined ) { - - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - program: material.program, - renderOrder: object.renderOrder, - z: z, - group: group - }; - - renderItems[ renderItemsIndex ] = renderItem; - - } else { - - renderItem.id = object.id; - renderItem.object = object; - renderItem.geometry = geometry; - renderItem.material = material; - renderItem.program = material.program; - renderItem.renderOrder = object.renderOrder; - renderItem.z = z; - renderItem.group = group; - - } - - ( material.transparent === true ? transparent : opaque ).push( renderItem ); - - renderItemsIndex ++; - - } - - function sort() { - - if ( opaque.length > 1 ) { opaque.sort( painterSortStable ); } - if ( transparent.length > 1 ) { transparent.sort( reversePainterSortStable ); } - - } - - return { - opaque: opaque, - transparent: transparent, - - init: init, - push: push, - - sort: sort - }; - -} - -function WebGLRenderLists() { - - var lists = {}; - - function get( scene, camera ) { - - var hash = scene.id + ',' + camera.id; - var list = lists[ hash ]; - - if ( list === undefined ) { - - // console.log( 'THREE.WebGLRenderLists:', hash ); - - list = new WebGLRenderList(); - lists[ hash ] = list; - - } - - return list; - - } - - function dispose() { - - lists = {}; - - } - - return { - get: get, - dispose: dispose - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function absNumericalSort( a, b ) { - - return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); - -} - -function WebGLMorphtargets( gl ) { - - var influencesList = {}; - var morphInfluences = new Float32Array( 8 ); - - function update( object, geometry, material, program ) { - - var objectInfluences = object.morphTargetInfluences; - - var length = objectInfluences.length; - - var influences = influencesList[ geometry.id ]; - - if ( influences === undefined ) { - - // initialise list - - influences = []; - - for ( var i = 0; i < length; i ++ ) { - - influences[ i ] = [ i, 0 ]; - - } - - influencesList[ geometry.id ] = influences; - - } - - var morphTargets = material.morphTargets && geometry.morphAttributes.position; - var morphNormals = material.morphNormals && geometry.morphAttributes.normal; - - // Remove current morphAttributes - - for ( var i = 0; i < length; i ++ ) { - - var influence = influences[ i ]; - - if ( influence[ 1 ] !== 0 ) { - - if ( morphTargets ) { geometry.removeAttribute( 'morphTarget' + i ); } - if ( morphNormals ) { geometry.removeAttribute( 'morphNormal' + i ); } - - } - - } - - // Collect influences - - for ( var i = 0; i < length; i ++ ) { - - var influence = influences[ i ]; - - influence[ 0 ] = i; - influence[ 1 ] = objectInfluences[ i ]; - - } - - influences.sort( absNumericalSort ); - - // Add morphAttributes - - for ( var i = 0; i < 8; i ++ ) { - - var influence = influences[ i ]; - - if ( influence ) { - - var index = influence[ 0 ]; - var value = influence[ 1 ]; - - if ( value ) { - - if ( morphTargets ) { geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); } - if ( morphNormals ) { geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); } - - morphInfluences[ i ] = value; - continue; - - } - - } - - morphInfluences[ i ] = 0; - - } - - program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); - - } - - return { - - update: update - - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { - - var mode; - - function setMode( value ) { - - mode = value; - - } - - var type, bytesPerElement; - - function setIndex( value ) { - - type = value.type; - bytesPerElement = value.bytesPerElement; - - } - - function render( start, count ) { - - gl.drawElements( mode, count, type, start * bytesPerElement ); - - infoRender.calls ++; - infoRender.vertices += count; - - if ( mode === gl.TRIANGLES ) { infoRender.faces += count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += count; } - - } - - function renderInstances( geometry, start, count ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); - - if ( extension === null ) { - - console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; - - } - - extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); - - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; - - if ( mode === gl.TRIANGLES ) { infoRender.faces += geometry.maxInstancedCount * count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += geometry.maxInstancedCount * count; } + return this.multiplyMatrices( m, this ); } - // + multiplyMatrices( a, b ) { - this.setMode = setMode; - this.setIndex = setIndex; - this.render = render; - this.renderInstances = renderInstances; + const ae = a.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 ]; -/** - * @author mrdoob / http://mrdoob.com/ - */ + 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 ]; -function WebGLBufferRenderer( gl, extensions, infoRender ) { + 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; - var mode; + 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; - function setMode( value ) { + 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; - mode = value; + return this; } - function render( start, count ) { + multiplyScalar( s ) { - gl.drawArrays( mode, start, count ); + const te = this.elements; - infoRender.calls ++; - infoRender.vertices += count; + 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; - if ( mode === gl.TRIANGLES ) { infoRender.faces += count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += count; } + return this; } - function renderInstances( geometry, start, count ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + determinant() { - if ( extension === null ) { - - console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + 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 ]; - var position = geometry.attributes.position; + //TODO: make this more efficient + //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) - if ( position.isInterleavedBufferAttribute ) { + 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 + ) - count = position.data.count; + ); - extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount ); + } - } else { + transpose() { - extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount ); + 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; - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; + 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; - if ( mode === gl.TRIANGLES ) { infoRender.faces += geometry.maxInstancedCount * count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += geometry.maxInstancedCount * count; } + return this; } - // - - this.setMode = setMode; - this.render = render; - this.renderInstances = renderInstances; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLGeometries( gl, attributes, infoMemory ) { + setPosition( x, y, z ) { - var geometries = {}; - var wireframeAttributes = {}; + const te = this.elements; - function onGeometryDispose( event ) { + if ( x.isVector3 ) { - var geometry = event.target; - var buffergeometry = geometries[ geometry.id ]; + te[ 12 ] = x.x; + te[ 13 ] = x.y; + te[ 14 ] = x.z; - if ( buffergeometry.index !== null ) { + } else { - attributes.remove( buffergeometry.index ); + te[ 12 ] = x; + te[ 13 ] = y; + te[ 14 ] = z; } - for ( var name in buffergeometry.attributes ) { - - attributes.remove( buffergeometry.attributes[ name ] ); - - } + return this; - geometry.removeEventListener( 'dispose', onGeometryDispose ); + } - delete geometries[ geometry.id ]; + invert() { - // TODO Remove duplicate code + // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + const te = this.elements, - var attribute = wireframeAttributes[ geometry.id ]; + 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 ], - if ( attribute ) { + 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; - attributes.remove( attribute ); - delete wireframeAttributes[ geometry.id ]; + 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 ); - attribute = wireframeAttributes[ buffergeometry.id ]; + const detInv = 1 / det; - if ( attribute ) { + 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; - attributes.remove( attribute ); - delete wireframeAttributes[ buffergeometry.id ]; + 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; - infoMemory.geometries --; + return this; } - function get( object, geometry ) { - - var buffergeometry = geometries[ geometry.id ]; - - if ( buffergeometry ) { return buffergeometry; } - - geometry.addEventListener( 'dispose', onGeometryDispose ); - - if ( geometry.isBufferGeometry ) { - - buffergeometry = geometry; - - } else if ( geometry.isGeometry ) { - - if ( geometry._bufferGeometry === undefined ) { + scale( v ) { - geometry._bufferGeometry = new BufferGeometry().setFromObject( object ); + const te = this.elements; + const x = v.x, y = v.y, z = v.z; - } - - buffergeometry = geometry._bufferGeometry; - - } - - geometries[ geometry.id ] = buffergeometry; - - infoMemory.geometries ++; + te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; + te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; + te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; + te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; - return buffergeometry; + return this; } - function update( geometry ) { - - var index = geometry.index; - var geometryAttributes = geometry.attributes; + getMaxScaleOnAxis() { - if ( index !== null ) { + const te = this.elements; - attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); + 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 ) ); - for ( var name in geometryAttributes ) { + } - attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); + makeTranslation( x, y, z ) { - } + if ( x.isVector3 ) { - // morph targets + this.set( - var morphAttributes = geometry.morphAttributes; + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 - for ( var name in morphAttributes ) { + ); - var array = morphAttributes[ name ]; + } else { - for ( var i = 0, l = array.length; i < l; i ++ ) { + this.set( - attributes.update( array[ i ], gl.ARRAY_BUFFER ); + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 - } + ); } - } - - function getWireframeAttribute( geometry ) { - - var attribute = wireframeAttributes[ geometry.id ]; - - if ( attribute ) { return attribute; } - - var indices = []; - - var geometryIndex = geometry.index; - var geometryAttributes = geometry.attributes; - - // console.time( 'wireframe' ); - - if ( geometryIndex !== null ) { - - var array = geometryIndex.array; - - for ( var i = 0, l = array.length; i < l; i += 3 ) { - - var a = array[ i + 0 ]; - var b = array[ i + 1 ]; - var c = array[ i + 2 ]; + return this; - indices.push( a, b, b, c, c, a ); + } - } + makeRotationX( theta ) { - } else { + const c = Math.cos( theta ), s = Math.sin( theta ); - var array = geometryAttributes.position.array; + this.set( - for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { + 1, 0, 0, 0, + 0, c, - s, 0, + 0, s, c, 0, + 0, 0, 0, 1 - var a = i + 0; - var b = i + 1; - var c = i + 2; + ); - indices.push( a, b, b, c, c, a ); + return this; - } + } - } + makeRotationY( theta ) { - // console.timeEnd( 'wireframe' ); + const c = Math.cos( theta ), s = Math.sin( theta ); - attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + this.set( - attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER ); + c, 0, s, 0, + 0, 1, 0, 0, + - s, 0, c, 0, + 0, 0, 0, 1 - wireframeAttributes[ geometry.id ] = attribute; + ); - return attribute; + return this; } - return { - - get: get, - update: update, - - getWireframeAttribute: getWireframeAttribute - - }; - -} + makeRotationZ( theta ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + const c = Math.cos( theta ), s = Math.sin( theta ); -function UniformsCache() { + this.set( - var lights = {}; + c, - s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - return { + ); - get: function ( light ) { + return this; - if ( lights[ light.id ] !== undefined ) { + } - return lights[ light.id ]; + makeRotationAxis( axis, angle ) { - } + // Based on http://www.gamedev.net/reference/articles/article1199.asp - var uniforms; + const c = Math.cos( angle ); + const s = Math.sin( angle ); + const t = 1 - c; + const x = axis.x, y = axis.y, z = axis.z; + const tx = t * x, ty = t * y; - switch ( light.type ) { + this.set( - case 'DirectionalLight': - uniforms = { - direction: new Vector3(), - color: new Color(), + tx * x + c, tx * y - s * z, tx * z + s * y, 0, + tx * y + s * z, ty * y + c, ty * z - s * x, 0, + tx * z - s * y, ty * z + s * x, t * z * z + c, 0, + 0, 0, 0, 1 - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; + ); - case 'SpotLight': - uniforms = { - position: new Vector3(), - direction: new Vector3(), - color: new Color(), - distance: 0, - coneCos: 0, - penumbraCos: 0, - decay: 0, + return this; - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; + } - case 'PointLight': - uniforms = { - position: new Vector3(), - color: new Color(), - distance: 0, - decay: 0, + makeScale( x, y, z ) { - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2(), - shadowCameraNear: 1, - shadowCameraFar: 1000 - }; - break; + this.set( - case 'HemisphereLight': - uniforms = { - direction: new Vector3(), - skyColor: new Color(), - groundColor: new Color() - }; - break; + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 - case 'RectAreaLight': - uniforms = { - color: new Color(), - position: new Vector3(), - halfWidth: new Vector3(), - halfHeight: new Vector3() - // TODO (abelnation): set RectAreaLight shadow uniforms - }; - break; + ); - } + return this; - lights[ light.id ] = uniforms; + } - return uniforms; + 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 -} + ); -function WebGLLights() { + return this; - var cache = new UniformsCache(); + } - var state = { + compose( position, quaternion, scale ) { - hash: '', + const te = this.elements; - ambient: [ 0, 0, 0 ], - directional: [], - directionalShadowMap: [], - directionalShadowMatrix: [], - spot: [], - spotShadowMap: [], - spotShadowMatrix: [], - rectArea: [], - point: [], - pointShadowMap: [], - pointShadowMatrix: [], - hemi: [] + const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; + const x2 = x + x, y2 = y + y, z2 = z + z; + const xx = x * x2, xy = x * y2, xz = x * z2; + const yy = y * y2, yz = y * z2, zz = z * z2; + const wx = w * x2, wy = w * y2, wz = w * z2; - }; + const sx = scale.x, sy = scale.y, sz = scale.z; - var vector3 = new Vector3(); - var matrix4 = new Matrix4(); - var matrix42 = new Matrix4(); + te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; + te[ 1 ] = ( xy + wz ) * sx; + te[ 2 ] = ( xz - wy ) * sx; + te[ 3 ] = 0; - function setup( lights, shadows, camera ) { + te[ 4 ] = ( xy - wz ) * sy; + te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; + te[ 6 ] = ( yz + wx ) * sy; + te[ 7 ] = 0; - var r = 0, g = 0, b = 0; + te[ 8 ] = ( xz + wy ) * sz; + te[ 9 ] = ( yz - wx ) * sz; + te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; + te[ 11 ] = 0; - var directionalLength = 0; - var pointLength = 0; - var spotLength = 0; - var rectAreaLength = 0; - var hemiLength = 0; + te[ 12 ] = position.x; + te[ 13 ] = position.y; + te[ 14 ] = position.z; + te[ 15 ] = 1; - var viewMatrix = camera.matrixWorldInverse; + return this; - for ( var i = 0, l = lights.length; i < l; i ++ ) { + } - var light = lights[ i ]; + decompose( position, quaternion, scale ) { - var color = light.color; - var intensity = light.intensity; - var distance = light.distance; + const te = this.elements; - var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; + 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(); - if ( light.isAmbientLight ) { + // if determine is negative, we need to invert one scale + const det = this.determinant(); + if ( det < 0 ) sx = - sx; - r += color.r * intensity; - g += color.g * intensity; - b += color.b * intensity; + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; - } else if ( light.isDirectionalLight ) { + // scale the rotation part + _m1$4.copy( this ); - var uniforms = cache.get( light ); + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); + _m1$4.elements[ 0 ] *= invSX; + _m1$4.elements[ 1 ] *= invSX; + _m1$4.elements[ 2 ] *= invSX; - uniforms.shadow = light.castShadow; + _m1$4.elements[ 4 ] *= invSY; + _m1$4.elements[ 5 ] *= invSY; + _m1$4.elements[ 6 ] *= invSY; - if ( light.castShadow ) { + _m1$4.elements[ 8 ] *= invSZ; + _m1$4.elements[ 9 ] *= invSZ; + _m1$4.elements[ 10 ] *= invSZ; - var shadow = light.shadow; + quaternion.setFromRotationMatrix( _m1$4 ); - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; + scale.x = sx; + scale.y = sy; + scale.z = sz; - } + return this; - state.directionalShadowMap[ directionalLength ] = shadowMap; - state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - state.directional[ directionalLength ] = uniforms; + } - directionalLength ++; + makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { - } else if ( light.isSpotLight ) { + const te = this.elements; + const x = 2 * near / ( right - left ); + const y = 2 * near / ( top - bottom ); - var uniforms = cache.get( light ); + const a = ( right + left ) / ( right - left ); + const b = ( top + bottom ) / ( top - bottom ); - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + let c, d; - uniforms.color.copy( color ).multiplyScalar( intensity ); - uniforms.distance = distance; + if ( coordinateSystem === WebGLCoordinateSystem ) { - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); + c = - ( far + near ) / ( far - near ); + d = ( - 2 * far * near ) / ( far - near ); - uniforms.coneCos = Math.cos( light.angle ); - uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - uniforms.shadow = light.castShadow; + c = - far / ( far - near ); + d = ( - far * near ) / ( far - near ); - if ( light.castShadow ) { + } else { - var shadow = light.shadow; + throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; + } - } + te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; + te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; - state.spotShadowMap[ spotLength ] = shadowMap; - state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; - state.spot[ spotLength ] = uniforms; + return this; - spotLength ++; + } - } else if ( light.isRectAreaLight ) { + makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { - var uniforms = cache.get( light ); + const te = this.elements; + const w = 1.0 / ( right - left ); + const h = 1.0 / ( top - bottom ); + const p = 1.0 / ( far - near ); - // (a) intensity controls irradiance of entire light - uniforms.color - .copy( color ) - .multiplyScalar( intensity / ( light.width * light.height ) ); + const x = ( right + left ) * w; + const y = ( top + bottom ) * h; - // (b) intensity controls the radiance per light area - // uniforms.color.copy( color ).multiplyScalar( intensity ); + let z, zInv; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + if ( coordinateSystem === WebGLCoordinateSystem ) { - // extract local rotation of light to derive width/height half vectors - matrix42.identity(); - matrix4.copy( light.matrixWorld ); - matrix4.premultiply( viewMatrix ); - matrix42.extractRotation( matrix4 ); + z = ( far + near ) * p; + zInv = - 2 * p; - uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); - uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - uniforms.halfWidth.applyMatrix4( matrix42 ); - uniforms.halfHeight.applyMatrix4( matrix42 ); + z = near * p; + zInv = - 1 * p; - // TODO (abelnation): RectAreaLight distance? - // uniforms.distance = distance; + } else { - state.rectArea[ rectAreaLength ] = uniforms; + throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); - rectAreaLength ++; + } - } else if ( light.isPointLight ) { + te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; + te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; - var uniforms = cache.get( light ); + return this; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + } - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.distance = light.distance; - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + equals( matrix ) { - uniforms.shadow = light.castShadow; + const te = this.elements; + const me = matrix.elements; - if ( light.castShadow ) { + for ( let i = 0; i < 16; i ++ ) { - var shadow = light.shadow; + if ( te[ i ] !== me[ i ] ) return false; - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - uniforms.shadowCameraNear = shadow.camera.near; - uniforms.shadowCameraFar = shadow.camera.far; + } - } + return true; - state.pointShadowMap[ pointLength ] = shadowMap; - state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - state.point[ pointLength ] = uniforms; + } - pointLength ++; + fromArray( array, offset = 0 ) { - } else if ( light.isHemisphereLight ) { + for ( let i = 0; i < 16; i ++ ) { - var uniforms = cache.get( light ); + this.elements[ i ] = array[ i + offset ]; - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - uniforms.direction.transformDirection( viewMatrix ); - uniforms.direction.normalize(); + } - uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); - uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); + return this; - state.hemi[ hemiLength ] = uniforms; + } - hemiLength ++; + toArray( array = [], offset = 0 ) { - } + const te = this.elements; - } + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + array[ offset + 3 ] = te[ 3 ]; - state.ambient[ 0 ] = r; - state.ambient[ 1 ] = g; - state.ambient[ 2 ] = b; + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; - state.directional.length = directionalLength; - state.spot.length = spotLength; - state.rectArea.length = rectAreaLength; - state.point.length = pointLength; - state.hemi.length = hemiLength; + array[ offset + 8 ] = te[ 8 ]; + array[ offset + 9 ] = te[ 9 ]; + array[ offset + 10 ] = te[ 10 ]; + array[ offset + 11 ] = te[ 11 ]; + + array[ offset + 12 ] = te[ 12 ]; + array[ offset + 13 ] = te[ 13 ]; + array[ offset + 14 ] = te[ 14 ]; + array[ offset + 15 ] = te[ 15 ]; - // TODO (sam-g-steel) why aren't we using join - state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; + return array; } - return { - setup: setup, - state: state - }; - } -/** - * @author mrdoob / http://mrdoob.com/ - */ +const _v1$5 = /*@__PURE__*/ new Vector3(); +const _m1$4 = /*@__PURE__*/ new Matrix4(); +const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); +const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); +const _x = /*@__PURE__*/ new Vector3(); +const _y = /*@__PURE__*/ new Vector3(); +const _z = /*@__PURE__*/ new Vector3(); -function WebGLObjects( geometries, infoRender ) { +const _matrix$2 = /*@__PURE__*/ new Matrix4(); +const _quaternion$3 = /*@__PURE__*/ new Quaternion(); - var updateList = {}; +class Euler { - function update( object ) { + constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { - var frame = infoRender.frame; + this.isEuler = true; - var geometry = object.geometry; - var buffergeometry = geometries.get( object, geometry ); + this._x = x; + this._y = y; + this._z = z; + this._order = order; - // Update once per frame + } - if ( updateList[ buffergeometry.id ] !== frame ) { + get x() { - if ( geometry.isGeometry ) { + return this._x; - buffergeometry.updateFromObject( object ); + } - } + set x( value ) { - geometries.update( buffergeometry ); + this._x = value; + this._onChangeCallback(); - updateList[ buffergeometry.id ] = frame; + } - } + get y() { - return buffergeometry; + return this._y; } - function clear() { + set y( value ) { - updateList = {}; + this._y = value; + this._onChangeCallback(); } - return { - - update: update, - clear: clear + get z() { - }; + return this._z; -} + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + set z( value ) { -function addLineNumbers( string ) { + this._z = value; + this._onChangeCallback(); - var lines = string.split( '\n' ); + } - for ( var i = 0; i < lines.length; i ++ ) { + get order() { - lines[ i ] = ( i + 1 ) + ': ' + lines[ i ]; + return this._order; } - return lines.join( '\n' ); + set order( value ) { -} + this._order = value; + this._onChangeCallback(); -function WebGLShader( gl, type, string ) { + } - var shader = gl.createShader( type ); + set( x, y, z, order = this._order ) { - gl.shaderSource( shader, string ); - gl.compileShader( shader ); + this._x = x; + this._y = y; + this._z = z; + this._order = order; - if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { + this._onChangeCallback(); - console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); + return this; } - if ( gl.getShaderInfoLog( shader ) !== '' ) { + clone() { - console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) ); + return new this.constructor( this._x, this._y, this._z, this._order ); } - // --enable-privileged-webgl-extension - // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - - return shader; + copy( euler ) { -} + this._x = euler._x; + this._y = euler._y; + this._z = euler._z; + this._order = euler._order; -/** - * @author mrdoob / http://mrdoob.com/ - */ + this._onChangeCallback(); -var programIdCount = 0; - -function getEncodingComponents( encoding ) { - - switch ( encoding ) { - - case LinearEncoding: - return [ 'Linear', '( value )' ]; - case sRGBEncoding: - return [ 'sRGB', '( value )' ]; - case RGBEEncoding: - return [ 'RGBE', '( value )' ]; - case RGBM7Encoding: - return [ 'RGBM', '( value, 7.0 )' ]; - case RGBM16Encoding: - return [ 'RGBM', '( value, 16.0 )' ]; - case RGBDEncoding: - return [ 'RGBD', '( value, 256.0 )' ]; - case GammaEncoding: - return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; - default: - throw new Error( 'unsupported encoding: ' + encoding ); + return this; } -} + setFromRotationMatrix( m, order = this._order, update = true ) { + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) -function getTexelDecodingFunction( functionName, encoding ) { + const te = m.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 ]; - var components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }'; + switch ( order ) { -} + case 'XYZ': -function getTexelEncodingFunction( functionName, encoding ) { + this._y = Math.asin( clamp( m13, - 1, 1 ) ); - var components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; + if ( Math.abs( m13 ) < 0.9999999 ) { -} + this._x = Math.atan2( - m23, m33 ); + this._z = Math.atan2( - m12, m11 ); -function getToneMappingFunction( functionName, toneMapping ) { + } else { - var toneMappingName; + this._x = Math.atan2( m32, m22 ); + this._z = 0; - switch ( toneMapping ) { + } - case LinearToneMapping: - toneMappingName = 'Linear'; - break; + break; - case ReinhardToneMapping: - toneMappingName = 'Reinhard'; - break; + case 'YXZ': - case Uncharted2ToneMapping: - toneMappingName = 'Uncharted2'; - break; + this._x = Math.asin( - clamp( m23, - 1, 1 ) ); - case CineonToneMapping: - toneMappingName = 'OptimizedCineon'; - break; + if ( Math.abs( m23 ) < 0.9999999 ) { - default: - throw new Error( 'unsupported toneMapping: ' + toneMapping ); + this._y = Math.atan2( m13, m33 ); + this._z = Math.atan2( m21, m22 ); - } + } else { - return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; + this._y = Math.atan2( - m31, m11 ); + this._z = 0; -} + } -function generateExtensions( extensions, parameters, rendererExtensions ) { + break; - extensions = extensions || {}; + case 'ZXY': - var chunks = [ - ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', - ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '', - ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '', - ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '' - ]; + this._x = Math.asin( clamp( m32, - 1, 1 ) ); - return chunks.filter( filterEmptyLine ).join( '\n' ); + if ( Math.abs( m32 ) < 0.9999999 ) { -} + this._y = Math.atan2( - m31, m33 ); + this._z = Math.atan2( - m12, m22 ); -function generateDefines( defines ) { + } else { - var chunks = []; + this._y = 0; + this._z = Math.atan2( m21, m11 ); + + } - for ( var name in defines ) { + break; - var value = defines[ name ]; + case 'ZYX': - if ( value === false ) { continue; } + this._y = Math.asin( - clamp( m31, - 1, 1 ) ); - chunks.push( '#define ' + name + ' ' + value ); + if ( Math.abs( m31 ) < 0.9999999 ) { - } + this._x = Math.atan2( m32, m33 ); + this._z = Math.atan2( m21, m11 ); - return chunks.join( '\n' ); + } else { -} + this._x = 0; + this._z = Math.atan2( - m12, m22 ); -function fetchAttributeLocations( gl, program ) { + } - var attributes = {}; + break; - var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); + case 'YZX': - for ( var i = 0; i < n; i ++ ) { + this._z = Math.asin( clamp( m21, - 1, 1 ) ); - var info = gl.getActiveAttrib( program, i ); - var name = info.name; + if ( Math.abs( m21 ) < 0.9999999 ) { - // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); + this._x = Math.atan2( - m23, m22 ); + this._y = Math.atan2( - m31, m11 ); - attributes[ name ] = gl.getAttribLocation( program, name ); + } else { - } + this._x = 0; + this._y = Math.atan2( m13, m33 ); - return attributes; + } -} + break; -function filterEmptyLine( string ) { + case 'XZY': - return string !== ''; + this._z = Math.asin( - clamp( m12, - 1, 1 ) ); -} + if ( Math.abs( m12 ) < 0.9999999 ) { -function replaceLightNums( string, parameters ) { + this._x = Math.atan2( m32, m22 ); + this._y = Math.atan2( m13, m11 ); - 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 ); + } else { -} + this._x = Math.atan2( - m23, m33 ); + this._y = 0; -function parseIncludes( string ) { + } - var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm; + break; - function replace( match, include ) { + default: - var replace = ShaderChunk[ include ]; + console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); - if ( replace === undefined ) { + } - throw new Error( 'Can not resolve #include <' + include + '>' ); + this._order = order; - } + if ( update === true ) this._onChangeCallback(); - return parseIncludes( replace ); + return this; } - return string.replace( pattern, replace ); + setFromQuaternion( q, order, update ) { -} + _matrix$2.makeRotationFromQuaternion( q ); -function unrollLoops( string ) { + return this.setFromRotationMatrix( _matrix$2, order, update ); - var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; + } - function replace( match, start, end, snippet ) { + setFromVector3( v, order = this._order ) { - var unroll = ''; + return this.set( v.x, v.y, v.z, order ); - for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) { + } - unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' ); + reorder( newOrder ) { - } + // WARNING: this discards revolution information -bhouston - return unroll; + _quaternion$3.setFromEuler( this ); + + return this.setFromQuaternion( _quaternion$3, newOrder ); } - return string.replace( pattern, replace ); + equals( euler ) { -} + return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); -function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { + } - var gl = renderer.context; + fromArray( array ) { - var defines = material.defines; + this._x = array[ 0 ]; + this._y = array[ 1 ]; + this._z = array[ 2 ]; + if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; - var vertexShader = shader.vertexShader; - var fragmentShader = shader.fragmentShader; + this._onChangeCallback(); - var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; + return this; - if ( parameters.shadowMapType === PCFShadowMap ) { + } - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; + toArray( array = [], offset = 0 ) { - } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._order; - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; + return array; } - var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; - var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + _onChange( callback ) { - if ( parameters.envMap ) { + this._onChangeCallback = callback; - switch ( material.envMap.mapping ) { + return this; - case CubeReflectionMapping: - case CubeRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - break; + } - case CubeUVReflectionMapping: - case CubeUVRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; - break; + _onChangeCallback() {} - case EquirectangularReflectionMapping: - case EquirectangularRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; - break; + *[ Symbol.iterator ]() { - case SphericalReflectionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; - break; + yield this._x; + yield this._y; + yield this._z; + yield this._order; - } + } - switch ( material.envMap.mapping ) { +} - case CubeRefractionMapping: - case EquirectangularRefractionMapping: - envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; - break; +Euler.DEFAULT_ORDER = 'XYZ'; - } +class Layers { - switch ( material.combine ) { + constructor() { - case MultiplyOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; - break; + this.mask = 1 | 0; - case MixOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; - break; + } - case AddOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; - break; + set( channel ) { - } + this.mask = ( 1 << channel | 0 ) >>> 0; } - var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; + enable( channel ) { - // console.log( 'building new program ' ); - - // - - var customExtensions = generateExtensions( material.extensions, parameters, extensions ); + this.mask |= 1 << channel | 0; - var customDefines = generateDefines( defines ); + } - // + enableAll() { - var program = gl.createProgram(); + this.mask = 0xffffffff | 0; - var prefixVertex, prefixFragment; + } - if ( material.isRawShaderMaterial ) { + toggle( channel ) { - prefixVertex = [ + this.mask ^= 1 << channel | 0; - customDefines + } - ].filter( filterEmptyLine ).join( '\n' ); + disable( channel ) { - if ( prefixVertex.length > 0 ) { + this.mask &= ~ ( 1 << channel | 0 ); - prefixVertex += '\n'; + } - } + disableAll() { - prefixFragment = [ + this.mask = 0; - customExtensions, - customDefines + } - ].filter( filterEmptyLine ).join( '\n' ); + test( layers ) { - if ( prefixFragment.length > 0 ) { + return ( this.mask & layers.mask ) !== 0; - prefixFragment += '\n'; + } - } + isEnabled( channel ) { - } else { + return ( this.mask & ( 1 << channel | 0 ) ) !== 0; - prefixVertex = [ + } - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', +} - '#define SHADER_NAME ' + shader.name, +let _object3DId = 0; - customDefines, +const _v1$4 = /*@__PURE__*/ new Vector3(); +const _q1 = /*@__PURE__*/ new Quaternion(); +const _m1$3 = /*@__PURE__*/ new Matrix4(); +const _target = /*@__PURE__*/ new Vector3(); - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', +const _position$3 = /*@__PURE__*/ new Vector3(); +const _scale$2 = /*@__PURE__*/ new Vector3(); +const _quaternion$2 = /*@__PURE__*/ new Quaternion(); - '#define GAMMA_FACTOR ' + gammaFactorDefine, +const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); +const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); +const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); - '#define MAX_BONES ' + parameters.maxBones, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', +const _addedEvent = { type: 'added' }; +const _removedEvent = { type: 'removed' }; - 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.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', +const _childaddedEvent = { type: 'childadded', child: null }; +const _childremovedEvent = { type: 'childremoved', child: null }; - parameters.flatShading ? '#define FLAT_SHADED' : '', +class Object3D extends EventDispatcher { - parameters.skinning ? '#define USE_SKINNING' : '', - parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', + constructor() { - parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', - parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', + super(); - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, + this.isObject3D = true; - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + Object.defineProperty( this, 'id', { value: _object3DId ++ } ); - parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + this.uuid = generateUUID(); - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + this.name = ''; + this.type = 'Object3D'; - 'uniform mat4 modelMatrix;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform mat4 viewMatrix;', - 'uniform mat3 normalMatrix;', - 'uniform vec3 cameraPosition;', + this.parent = null; + this.children = []; - 'attribute vec3 position;', - 'attribute vec3 normal;', - 'attribute vec2 uv;', + this.up = Object3D.DEFAULT_UP.clone(); - '#ifdef USE_COLOR', + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3( 1, 1, 1 ); - ' attribute vec3 color;', + function onRotationChange() { - '#endif', + quaternion.setFromEuler( rotation, false ); - '#ifdef USE_MORPHTARGETS', + } - ' attribute vec3 morphTarget0;', - ' attribute vec3 morphTarget1;', - ' attribute vec3 morphTarget2;', - ' attribute vec3 morphTarget3;', + function onQuaternionChange() { - ' #ifdef USE_MORPHNORMALS', + rotation.setFromQuaternion( quaternion, undefined, false ); - ' attribute vec3 morphNormal0;', - ' attribute vec3 morphNormal1;', - ' attribute vec3 morphNormal2;', - ' attribute vec3 morphNormal3;', + } - ' #else', + rotation._onChange( onRotationChange ); + quaternion._onChange( onQuaternionChange ); - ' attribute vec3 morphTarget4;', - ' attribute vec3 morphTarget5;', - ' attribute vec3 morphTarget6;', - ' attribute vec3 morphTarget7;', + 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() + } + } ); - ' #endif', + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); - '#endif', + this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; - '#ifdef USE_SKINNING', + this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer + this.matrixWorldNeedsUpdate = false; - ' attribute vec4 skinIndex;', - ' attribute vec4 skinWeight;', + this.layers = new Layers(); + this.visible = true; - '#endif', + this.castShadow = false; + this.receiveShadow = false; - '\n' + this.frustumCulled = true; + this.renderOrder = 0; - ].filter( filterEmptyLine ).join( '\n' ); + this.animations = []; - prefixFragment = [ + this.userData = {}; - customExtensions, + } - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', + onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} - '#define SHADER_NAME ' + shader.name, + onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} - customDefines, + onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} - parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', + onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} - '#define GAMMA_FACTOR ' + gammaFactorDefine, + applyMatrix4( matrix ) { - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', + if ( this.matrixAutoUpdate ) this.updateMatrix(); - parameters.map ? '#define USE_MAP' : '', - parameters.envMap ? '#define USE_ENVMAP' : '', - parameters.envMap ? '#define ' + envMapTypeDefine : '', - parameters.envMap ? '#define ' + envMapModeDefine : '', - parameters.envMap ? '#define ' + envMapBlendingDefine : '', - 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.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', + this.matrix.premultiply( matrix ); - parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', + this.matrix.decompose( this.position, this.quaternion, this.scale ); - parameters.flatShading ? '#define FLAT_SHADED' : '', + } - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', + applyQuaternion( q ) { - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, - '#define UNION_CLIPPING_PLANES ' + ( parameters.numClippingPlanes - parameters.numClipIntersection ), + this.quaternion.premultiply( q ); - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + return this; - parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', + } - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + setRotationFromAxisAngle( axis, angle ) { - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + // assumes axis is normalized - parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', + this.quaternion.setFromAxisAngle( axis, angle ); - 'uniform mat4 viewMatrix;', - 'uniform vec3 cameraPosition;', + } - ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', - ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below - ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', + setRotationFromEuler( euler ) { - parameters.dithering ? '#define DITHERING' : '', + this.quaternion.setFromEuler( euler, true ); - ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below - parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', - parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', - parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', - parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '', + } - parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '', + setRotationFromMatrix( m ) { - '\n' + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - ].filter( filterEmptyLine ).join( '\n' ); + this.quaternion.setFromRotationMatrix( m ); } - vertexShader = parseIncludes( vertexShader ); - vertexShader = replaceLightNums( vertexShader, parameters ); - - fragmentShader = parseIncludes( fragmentShader ); - fragmentShader = replaceLightNums( fragmentShader, parameters ); + setRotationFromQuaternion( q ) { - if ( ! material.isShaderMaterial ) { + // assumes q is normalized - vertexShader = unrollLoops( vertexShader ); - fragmentShader = unrollLoops( fragmentShader ); + this.quaternion.copy( q ); } - var vertexGlsl = prefixVertex + vertexShader; - var fragmentGlsl = prefixFragment + fragmentShader; + rotateOnAxis( axis, angle ) { - // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); - - var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); - var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); + // rotate object on axis in object space + // axis is assumed to be normalized - gl.attachShader( program, glVertexShader ); - gl.attachShader( program, glFragmentShader ); + _q1.setFromAxisAngle( axis, angle ); - // Force a particular attribute to index 0. + this.quaternion.multiply( _q1 ); - if ( material.index0AttributeName !== undefined ) { + return this; - gl.bindAttribLocation( program, 0, material.index0AttributeName ); + } - } else if ( parameters.morphTargets === true ) { + rotateOnWorldAxis( axis, angle ) { - // programs with morphTargets displace position out of attribute 0 - gl.bindAttribLocation( program, 0, 'position' ); + // rotate object on axis in world space + // axis is assumed to be normalized + // method assumes no rotated parent - } + _q1.setFromAxisAngle( axis, angle ); - gl.linkProgram( program ); + this.quaternion.premultiply( _q1 ); - var programLog = gl.getProgramInfoLog( program ); - var vertexLog = gl.getShaderInfoLog( glVertexShader ); - var fragmentLog = gl.getShaderInfoLog( glFragmentShader ); + return this; - var runnable = true; - var haveDiagnostics = true; + } - // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) ); - // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) ); + rotateX( angle ) { - if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { + return this.rotateOnAxis( _xAxis, angle ); - runnable = false; + } - console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog ); + rotateY( angle ) { - } else if ( programLog !== '' ) { + return this.rotateOnAxis( _yAxis, angle ); - console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); + } - } else if ( vertexLog === '' || fragmentLog === '' ) { + rotateZ( angle ) { - haveDiagnostics = false; + return this.rotateOnAxis( _zAxis, angle ); } - if ( haveDiagnostics ) { + translateOnAxis( axis, distance ) { - this.diagnostics = { + // translate object by distance along axis in object space + // axis is assumed to be normalized - runnable: runnable, - material: material, + _v1$4.copy( axis ).applyQuaternion( this.quaternion ); - programLog: programLog, + this.position.add( _v1$4.multiplyScalar( distance ) ); - vertexShader: { + return this; - log: vertexLog, - prefix: prefixVertex + } - }, + translateX( distance ) { - fragmentShader: { + return this.translateOnAxis( _xAxis, distance ); - log: fragmentLog, - prefix: prefixFragment + } - } + translateY( distance ) { - }; + return this.translateOnAxis( _yAxis, distance ); } - // clean up + translateZ( distance ) { - gl.deleteShader( glVertexShader ); - gl.deleteShader( glFragmentShader ); + return this.translateOnAxis( _zAxis, distance ); - // set up caching for uniform locations + } - var cachedUniforms; + localToWorld( vector ) { - this.getUniforms = function () { + this.updateWorldMatrix( true, false ); + + return vector.applyMatrix4( this.matrixWorld ); + + } - if ( cachedUniforms === undefined ) { + worldToLocal( vector ) { - cachedUniforms = new WebGLUniforms( gl, program, renderer ); + this.updateWorldMatrix( true, false ); - } + return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() ); - return cachedUniforms; + } - }; + lookAt( x, y, z ) { - // set up caching for attribute locations + // This method does not support objects having non-uniformly-scaled parent(s) - var cachedAttributes; + if ( x.isVector3 ) { - this.getAttributes = function () { + _target.copy( x ); - if ( cachedAttributes === undefined ) { + } else { - cachedAttributes = fetchAttributeLocations( gl, program ); + _target.set( x, y, z ); } - return cachedAttributes; + const parent = this.parent; - }; + this.updateWorldMatrix( true, false ); - // free resource + _position$3.setFromMatrixPosition( this.matrixWorld ); - this.destroy = function () { + if ( this.isCamera || this.isLight ) { - gl.deleteProgram( program ); - this.program = undefined; + _m1$3.lookAt( _position$3, _target, this.up ); - }; + } else { - // DEPRECATED + _m1$3.lookAt( _target, _position$3, this.up ); - Object.defineProperties( this, { + } - uniforms: { - get: function () { + this.quaternion.setFromRotationMatrix( _m1$3 ); - console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' ); - return this.getUniforms(); + if ( parent ) { - } - }, + _m1$3.extractRotation( parent.matrixWorld ); + _q1.setFromRotationMatrix( _m1$3 ); + this.quaternion.premultiply( _q1.invert() ); - attributes: { - get: function () { + } - console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' ); - return this.getAttributes(); + } - } - } + add( object ) { - } ); + if ( arguments.length > 1 ) { + for ( let i = 0; i < arguments.length; i ++ ) { - // + this.add( arguments[ i ] ); - this.id = programIdCount ++; - this.code = code; - this.usedTimes = 1; - this.program = program; - this.vertexShader = glVertexShader; - this.fragmentShader = glFragmentShader; + } - return this; + return this; -} + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + if ( object === this ) { -function WebGLPrograms( renderer, extensions, capabilities ) { + console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); + return this; - var programs = []; + } - var shaderIDs = { - MeshDepthMaterial: 'depth', - MeshDistanceMaterial: 'distanceRGBA', - MeshNormalMaterial: 'normal', - MeshBasicMaterial: 'basic', - MeshLambertMaterial: 'lambert', - MeshPhongMaterial: 'phong', - MeshToonMaterial: 'phong', - MeshStandardMaterial: 'physical', - MeshPhysicalMaterial: 'physical', - LineBasicMaterial: 'basic', - LineDashedMaterial: 'dashed', - PointsMaterial: 'points', - ShadowMaterial: 'shadow' - }; + if ( object && object.isObject3D ) { - var parameterNames = [ - "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", - "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", - "roughnessMap", "metalnessMap", "gradientMap", - "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", - "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", - "maxBones", "useVertexTexture", "morphTargets", "morphNormals", - "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", - "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", - "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', - "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering" - ]; + object.removeFromParent(); + object.parent = this; + this.children.push( object ); + object.dispatchEvent( _addedEvent ); - function allocateBones( object ) { + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; - var skeleton = object.skeleton; - var bones = skeleton.bones; + } else { - if ( capabilities.floatVertexTextures ) { + console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); - return 1024; + } - } else { + return this; - // default for when object is not specified - // ( for example when prebuilding shader to be used with multiple objects ) - // - // - leave some extra space for other uniforms - // - limit here is ANGLE's 254 max uniform vectors - // (up to 54 should be safe) + } - var nVertexUniforms = capabilities.maxVertexUniforms; - var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 ); + remove( object ) { - var maxBones = Math.min( nVertexMatrices, bones.length ); + if ( arguments.length > 1 ) { - if ( maxBones < bones.length ) { + for ( let i = 0; i < arguments.length; i ++ ) { - console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' ); - return 0; + this.remove( arguments[ i ] ); } - return maxBones; + return this; } - } + const index = this.children.indexOf( object ); - function getTextureEncodingFromMap( map, gammaOverrideLinear ) { + if ( index !== - 1 ) { - var encoding; + object.parent = null; + this.children.splice( index, 1 ); - if ( ! map ) { + object.dispatchEvent( _removedEvent ); - encoding = LinearEncoding; + _childremovedEvent.child = object; + this.dispatchEvent( _childremovedEvent ); + _childremovedEvent.child = null; - } else if ( map.isTexture ) { + } - encoding = map.encoding; + return this; - } else if ( map.isWebGLRenderTarget ) { + } - console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." ); - encoding = map.texture.encoding; + removeFromParent() { - } + const parent = this.parent; - // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point. - if ( encoding === LinearEncoding && gammaOverrideLinear ) { + if ( parent !== null ) { - encoding = GammaEncoding; + parent.remove( this ); } - return encoding; + return this; } - this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { + clear() { - var shaderID = shaderIDs[ material.type ]; + return this.remove( ... this.children ); - // heuristics to create shader parameters according to lights in the scene - // (not to blow over maxLights budget) + } - var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; - var precision = capabilities.precision; + attach( object ) { - if ( material.precision !== null ) { + // adds object as a child of this, while maintaining the object's world transform - precision = capabilities.getMaxPrecision( material.precision ); + // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) - if ( precision !== material.precision ) { + this.updateWorldMatrix( true, false ); - console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); + _m1$3.copy( this.matrixWorld ).invert(); - } + if ( object.parent !== null ) { + + object.parent.updateWorldMatrix( true, false ); + + _m1$3.multiply( object.parent.matrixWorld ); } - var currentRenderTarget = renderer.getRenderTarget(); + object.applyMatrix4( _m1$3 ); - var parameters = { + object.removeFromParent(); + object.parent = this; + this.children.push( object ); - shaderID: shaderID, + object.updateWorldMatrix( false, true ); - precision: precision, - supportsVertexTextures: capabilities.vertexTextures, - outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ), - map: !! material.map, - mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ), - envMap: !! material.envMap, - envMapMode: material.envMap && material.envMap.mapping, - envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ), - envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ), - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ), - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - alphaMap: !! material.alphaMap, - - gradientMap: !! material.gradientMap, + object.dispatchEvent( _addedEvent ); - combine: material.combine, + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; - vertexColors: material.vertexColors, + return this; - fog: !! fog, - useFog: material.fog, - fogExp: ( fog && fog.isFogExp2 ), + } - flatShading: material.flatShading, + getObjectById( id ) { - sizeAttenuation: material.sizeAttenuation, - logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, + return this.getObjectByProperty( 'id', id ); - skinning: material.skinning && maxBones > 0, - maxBones: maxBones, - useVertexTexture: capabilities.floatVertexTextures, + } - morphTargets: material.morphTargets, - morphNormals: material.morphNormals, - maxMorphTargets: renderer.maxMorphTargets, - maxMorphNormals: renderer.maxMorphNormals, + getObjectByName( name ) { - numDirLights: lights.directional.length, - numPointLights: lights.point.length, - numSpotLights: lights.spot.length, - numRectAreaLights: lights.rectArea.length, - numHemiLights: lights.hemi.length, + return this.getObjectByProperty( 'name', name ); - numClippingPlanes: nClipPlanes, - numClipIntersection: nClipIntersection, + } - dithering: material.dithering, + getObjectByProperty( name, value ) { - shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, - shadowMapType: renderer.shadowMap.type, + if ( this[ name ] === value ) return this; - toneMapping: renderer.toneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + for ( let i = 0, l = this.children.length; i < l; i ++ ) { - premultipliedAlpha: material.premultipliedAlpha, + const child = this.children[ i ]; + const object = child.getObjectByProperty( name, value ); - alphaTest: material.alphaTest, - doubleSided: material.side === DoubleSide, - flipSided: material.side === BackSide, + if ( object !== undefined ) { - depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false + return object; - }; + } - return parameters; + } - }; + return undefined; - this.getProgramCode = function ( material, parameters ) { + } - var array = []; + getObjectsByProperty( name, value, result = [] ) { - if ( parameters.shaderID ) { + if ( this[ name ] === value ) result.push( this ); - array.push( parameters.shaderID ); + const children = this.children; - } else { + for ( let i = 0, l = children.length; i < l; i ++ ) { - array.push( material.fragmentShader ); - array.push( material.vertexShader ); + children[ i ].getObjectsByProperty( name, value, result ); } - if ( material.defines !== undefined ) { + return result; - for ( var name in material.defines ) { + } - array.push( name ); - array.push( material.defines[ name ] ); + getWorldPosition( target ) { - } + this.updateWorldMatrix( true, false ); - } + return target.setFromMatrixPosition( this.matrixWorld ); - for ( var i = 0; i < parameterNames.length; i ++ ) { + } - array.push( parameters[ parameterNames[ i ] ] ); + getWorldQuaternion( target ) { - } + this.updateWorldMatrix( true, false ); - array.push( material.onBeforeCompile.toString() ); + this.matrixWorld.decompose( _position$3, target, _scale$2 ); - array.push( renderer.gammaOutput ); + return target; - return array.join(); + } - }; + getWorldScale( target ) { - this.acquireProgram = function ( material, shader, parameters, code ) { + this.updateWorldMatrix( true, false ); - var program; + this.matrixWorld.decompose( _position$3, _quaternion$2, target ); - // Check if code has been already compiled - for ( var p = 0, pl = programs.length; p < pl; p ++ ) { + return target; - var programInfo = programs[ p ]; + } - if ( programInfo.code === code ) { + getWorldDirection( target ) { - program = programInfo; - ++ program.usedTimes; + this.updateWorldMatrix( true, false ); - break; + const e = this.matrixWorld.elements; - } + return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); - } + } - if ( program === undefined ) { + raycast( /* raycaster, intersects */ ) {} - program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); - programs.push( program ); + traverse( callback ) { + + callback( this ); + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverse( callback ); } - return program; + } - }; + traverseVisible( callback ) { - this.releaseProgram = function ( program ) { + if ( this.visible === false ) return; - if ( -- program.usedTimes === 0 ) { + callback( this ); - // Remove from unordered set - var i = programs.indexOf( program ); - programs[ i ] = programs[ programs.length - 1 ]; - programs.pop(); + const children = this.children; - // Free WebGL resources - program.destroy(); + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverseVisible( callback ); } - }; + } - // Exposed for resource monitoring & error feedback via renderer.info: - this.programs = programs; + traverseAncestors( callback ) { -} + const parent = this.parent; -/** - * @author mrdoob / http://mrdoob.com/ - */ + if ( parent !== null ) { -function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) { + callback( parent ); - var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof window.WebGL2RenderingContext ); - var _videoTextures = {}; + parent.traverseAncestors( callback ); - // + } - function clampToMaxSize( image, maxSize ) { + } - if ( image.width > maxSize || image.height > maxSize ) { + updateMatrix() { - // Warning: Scaling through the canvas will only work with images that use - // premultiplied alpha. + this.matrix.compose( this.position, this.quaternion, this.scale ); - var scale = maxSize / Math.max( image.width, image.height ); + this.matrixWorldNeedsUpdate = true; - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = Math.floor( image.width * scale ); - canvas.height = Math.floor( image.height * scale ); + } - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height ); + updateMatrixWorld( force ) { - console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); + if ( this.matrixAutoUpdate ) this.updateMatrix(); - return canvas; + if ( this.matrixWorldNeedsUpdate || force ) { - } + if ( this.matrixWorldAutoUpdate === true ) { - return image; + if ( this.parent === null ) { - } + this.matrixWorld.copy( this.matrix ); - function isPowerOfTwo( image ) { + } else { - return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height ); + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - } + } + + } + + this.matrixWorldNeedsUpdate = false; - function makePowerOfTwo( image ) { + force = true; - if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) { + } - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = _Math.floorPowerOfTwo( image.width ); - canvas.height = _Math.floorPowerOfTwo( image.height ); + // make sure descendants are updated if required - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, canvas.width, canvas.height ); + const children = this.children; - console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - return canvas; + const child = children[ i ]; - } + child.updateMatrixWorld( force ); - return image; + } } - function textureNeedsPowerOfTwo( texture ) { + updateWorldMatrix( updateParents, updateChildren ) { - return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || - ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); + const parent = this.parent; - } + if ( updateParents === true && parent !== null ) { - function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { + parent.updateWorldMatrix( true, false ); - return texture.generateMipmaps && isPowerOfTwo && - texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + } - } + if ( this.matrixAutoUpdate ) this.updateMatrix(); - // Fallback filters for non-power-of-2 textures + if ( this.matrixWorldAutoUpdate === true ) { - function filterFallback( f ) { + if ( this.parent === null ) { - if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) { + this.matrixWorld.copy( this.matrix ); - return _gl.NEAREST; + } else { - } + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - return _gl.LINEAR; + } - } + } - // + // make sure descendants are updated - function onTextureDispose( event ) { + if ( updateChildren === true ) { - var texture = event.target; + const children = this.children; - texture.removeEventListener( 'dispose', onTextureDispose ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - deallocateTexture( texture ); + const child = children[ i ]; - if ( texture.isVideoTexture ) { + child.updateWorldMatrix( false, true ); - delete _videoTextures[ texture.id ]; + } } - infoMemory.textures --; - } - function onRenderTargetDispose( event ) { + toJSON( meta ) { - var renderTarget = event.target; + // meta is a string when called from JSON.stringify + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); + const output = {}; - deallocateRenderTarget( renderTarget ); + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { - infoMemory.textures --; + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {}, + nodes: {} + }; - } + output.metadata = { + version: 4.6, + type: 'Object', + generator: 'Object3D.toJSON' + }; - // + } - function deallocateTexture( texture ) { + // standard Object3D serialization - var textureProperties = properties.get( texture ); + const object = {}; - if ( texture.image && textureProperties.__image__webglTextureCube ) { + object.uuid = this.uuid; + object.type = this.type; - // cube texture + 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 ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; - _gl.deleteTexture( textureProperties.__image__webglTextureCube ); + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); - } else { + if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; - // 2D texture + // object specific properties - if ( textureProperties.__webglInit === undefined ) { return; } + if ( this.isInstancedMesh ) { - _gl.deleteTexture( textureProperties.__webglTexture ); + object.type = 'InstancedMesh'; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); } - // remove all webgl properties - properties.remove( texture ); + if ( this.isBatchedMesh ) { - } + object.type = 'BatchedMesh'; + object.perObjectFrustumCulled = this.perObjectFrustumCulled; + object.sortObjects = this.sortObjects; - function deallocateRenderTarget( renderTarget ) { + object.drawRanges = this._drawRanges; + object.reservedRanges = this._reservedRanges; - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); + object.visibility = this._visibility; + object.active = this._active; + object.bounds = this._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + boxMin: bound.box.min.toArray(), + boxMax: bound.box.max.toArray(), - if ( ! renderTarget ) { return; } + sphereInitialized: bound.sphereInitialized, + sphereRadius: bound.sphere.radius, + sphereCenter: bound.sphere.center.toArray() + } ) ); - if ( textureProperties.__webglTexture !== undefined ) { + object.maxInstanceCount = this._maxInstanceCount; + object.maxVertexCount = this._maxVertexCount; + object.maxIndexCount = this._maxIndexCount; - _gl.deleteTexture( textureProperties.__webglTexture ); + object.geometryInitialized = this._geometryInitialized; + object.geometryCount = this._geometryCount; - } + object.matricesTexture = this._matricesTexture.toJSON( meta ); - if ( renderTarget.depthTexture ) { + if ( this._colorsTexture !== null ) object.colorsTexture = this._colorsTexture.toJSON( meta ); - renderTarget.depthTexture.dispose(); + if ( this.boundingSphere !== null ) { - } + object.boundingSphere = { + center: object.boundingSphere.center.toArray(), + radius: object.boundingSphere.radius + }; - if ( renderTarget.isWebGLRenderTargetCube ) { + } - for ( var i = 0; i < 6; i ++ ) { + if ( this.boundingBox !== null ) { - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - if ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); } + object.boundingBox = { + min: object.boundingBox.min.toArray(), + max: object.boundingBox.max.toArray() + }; } - } else { + } - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - if ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); } + // - } + function serialize( library, element ) { - properties.remove( renderTarget.texture ); - properties.remove( renderTarget ); + if ( library[ element.uuid ] === undefined ) { - } + library[ element.uuid ] = element.toJSON( meta ); - // + } + return element.uuid; + } - function setTexture2D( texture, slot ) { + if ( this.isScene ) { - var textureProperties = properties.get( texture ); + if ( this.background ) { - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + if ( this.background.isColor ) { - var image = texture.image; + object.background = this.background.toJSON(); - if ( image === undefined ) { + } else if ( this.background.isTexture ) { - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture ); + object.background = this.background.toJSON( meta ).uuid; - } else if ( image.complete === false ) { + } - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture ); + } - } else { + if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { - uploadTexture( textureProperties, texture, slot ); - return; + object.environment = this.environment.toJSON( meta ).uuid; } - } + } else if ( this.isMesh || this.isLine || this.isPoints ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); + object.geometry = serialize( meta.geometries, this.geometry ); - } + const parameters = this.geometry.parameters; - function setTextureCube( texture, slot ) { + if ( parameters !== undefined && parameters.shapes !== undefined ) { - var textureProperties = properties.get( texture ); + const shapes = parameters.shapes; - if ( texture.image.length === 6 ) { + if ( Array.isArray( shapes ) ) { + + for ( let i = 0, l = shapes.length; i < l; i ++ ) { - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + const shape = shapes[ i ]; - if ( ! textureProperties.__image__webglTextureCube ) { + serialize( meta.shapes, shape ); - texture.addEventListener( 'dispose', onTextureDispose ); + } - textureProperties.__image__webglTextureCube = _gl.createTexture(); + } else { - infoMemory.textures ++; + serialize( meta.shapes, shapes ); } - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); + } - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + } - var isCompressed = ( texture && texture.isCompressedTexture ); - var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); + if ( this.isSkinnedMesh ) { - var cubeImage = []; + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); - for ( var i = 0; i < 6; i ++ ) { + if ( this.skeleton !== undefined ) { - if ( ! isCompressed && ! isDataTexture ) { + serialize( meta.skeletons, this.skeleton ); - cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize ); + object.skeleton = this.skeleton.uuid; - } else { + } - cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; + } - } + if ( this.material !== undefined ) { - } + if ( Array.isArray( this.material ) ) { - var image = cubeImage[ 0 ], - isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); + const uuids = []; - setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); + for ( let i = 0, l = this.material.length; i < l; i ++ ) { - for ( var i = 0; i < 6; i ++ ) { + uuids.push( serialize( meta.materials, this.material[ i ] ) ); - if ( ! isCompressed ) { + } - if ( isDataTexture ) { + object.material = uuids; - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); + } else { - } else { + object.material = serialize( meta.materials, this.material ); - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] ); + } - } + } - } else { + // - var mipmap, mipmaps = cubeImage[ i ].mipmaps; + if ( this.children.length > 0 ) { - for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) { + object.children = []; - mipmap = mipmaps[ j ]; + for ( let i = 0; i < this.children.length; i ++ ) { - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { + object.children.push( this.children[ i ].toJSON( meta ).object ); - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { + } - state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + } - } else { + // - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); + if ( this.animations.length > 0 ) { - } + object.animations = []; - } else { + for ( let i = 0; i < this.animations.length; i ++ ) { - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + const animation = this.animations[ i ]; - } + object.animations.push( serialize( meta.animations, animation ) ); - } + } - } + } - } + if ( isRootObject ) { - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { + 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 ); - _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); + 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; - } + } - textureProperties.__version = texture.version; + output.object = object; - if ( texture.onUpdate ) { texture.onUpdate( texture ); } + return output; - } else { + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { + + const values = []; + for ( const key in cache ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); + const data = cache[ key ]; + delete data.metadata; + values.push( data ); } + return values; + } } - function setTextureCubeDynamic( texture, slot ) { + clone( recursive ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture ); + return new this.constructor().copy( this, recursive ); } - function setTextureParameters( textureType, texture, isPowerOfTwoImage ) { - - var extension; - - if ( isPowerOfTwoImage ) { - - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); + copy( source, recursive = true ) { - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( 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 ); + this.name = source.name; - if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { + this.up.copy( source.up ); - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture ); + 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 ); - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); + this.matrixAutoUpdate = source.matrixAutoUpdate; - if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { + this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture ); + 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; - extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + this.animations = source.animations.slice(); - if ( extension ) { + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) { return; } - if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) { return; } + if ( recursive === true ) { - if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { + for ( let i = 0; i < source.children.length; i ++ ) { - _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); - properties.get( texture ).__currentAnisotropy = texture.anisotropy; + const child = source.children[ i ]; + this.add( child.clone() ); } } - } - - function uploadTexture( textureProperties, texture, slot ) { - - if ( textureProperties.__webglInit === undefined ) { + return this; - textureProperties.__webglInit = true; + } - texture.addEventListener( 'dispose', onTextureDispose ); +} - textureProperties.__webglTexture = _gl.createTexture(); +Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); +Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; +Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; - if ( texture.isVideoTexture ) { +const _v0$2 = /*@__PURE__*/ new Vector3(); +const _v1$3 = /*@__PURE__*/ new Vector3(); +const _v2$2 = /*@__PURE__*/ new Vector3(); +const _v3$2 = /*@__PURE__*/ new Vector3(); - _videoTextures[ texture.id ] = texture; +const _vab = /*@__PURE__*/ new Vector3(); +const _vac = /*@__PURE__*/ new Vector3(); +const _vbc = /*@__PURE__*/ new Vector3(); +const _vap = /*@__PURE__*/ new Vector3(); +const _vbp = /*@__PURE__*/ new Vector3(); +const _vcp = /*@__PURE__*/ new Vector3(); - } +class Triangle { - infoMemory.textures ++; + constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { - } + this.a = a; + this.b = b; + this.c = c; - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); + } - _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 ); + static getNormal( a, b, c, target ) { - var image = clampToMaxSize( texture.image, capabilities.maxTextureSize ); + target.subVectors( c, b ); + _v0$2.subVectors( a, b ); + target.cross( _v0$2 ); - if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) { + const targetLengthSq = target.lengthSq(); + if ( targetLengthSq > 0 ) { - image = makePowerOfTwo( image ); + return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); } - var isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); + return target.set( 0, 0, 0 ); - setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); + } - var mipmap, mipmaps = texture.mipmaps; + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + static getBarycoord( point, a, b, c, target ) { - if ( texture.isDepthTexture ) { + _v0$2.subVectors( c, a ); + _v1$3.subVectors( b, a ); + _v2$2.subVectors( point, a ); - // populate depth texture with dummy data + const dot00 = _v0$2.dot( _v0$2 ); + const dot01 = _v0$2.dot( _v1$3 ); + const dot02 = _v0$2.dot( _v2$2 ); + const dot11 = _v1$3.dot( _v1$3 ); + const dot12 = _v1$3.dot( _v2$2 ); - var internalFormat = _gl.DEPTH_COMPONENT; + const denom = ( dot00 * dot11 - dot01 * dot01 ); - if ( texture.type === FloatType ) { + // collinear or singular triangle + if ( denom === 0 ) { - if ( ! _isWebGL2 ) { throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); } - internalFormat = _gl.DEPTH_COMPONENT32F; + target.set( 0, 0, 0 ); + return null; - } else if ( _isWebGL2 ) { + } - // WebGL 2.0 requires signed internalformat for glTexImage2D - internalFormat = _gl.DEPTH_COMPONENT16; + const invDenom = 1 / denom; + const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - } + // barycentric coordinates must always sum to 1 + return target.set( 1 - u - v, v, u ); - if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) { + } - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { + static containsPoint( point, a, b, c ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); + // if the triangle is degenerate then we can't contain a point + if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) { - texture.type = UnsignedShortType; - glType = utils.convert( texture.type ); + return false; - } + } - } + return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 ); - // Depth stencil textures need the DEPTH_STENCIL internal format - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.format === DepthStencilFormat ) { + } - internalFormat = _gl.DEPTH_STENCIL; + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedInt248Type ) { + if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); + target.x = 0; + target.y = 0; + if ( 'z' in target ) target.z = 0; + if ( 'w' in target ) target.w = 0; + return null; - texture.type = UnsignedInt248Type; - glType = utils.convert( texture.type ); + } - } + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$2.x ); + target.addScaledVector( v2, _v3$2.y ); + target.addScaledVector( v3, _v3$2.z ); - } + return target; - state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null ); + } - } else if ( texture.isDataTexture ) { + static isFrontFacing( a, b, c, direction ) { - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels + _v0$2.subVectors( c, b ); + _v1$3.subVectors( a, b ); - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { + // strictly front facing + return ( _v0$2.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + } - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + set( a, b, c ) { - } + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); - texture.generateMipmaps = false; + return this; - } else { + } - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data ); + setFromPointsAndIndices( points, i0, i1, i2 ) { - } + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); - } else if ( texture.isCompressedTexture ) { + return this; - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + } - mipmap = mipmaps[ i ]; + setFromAttributeAndIndices( attribute, i0, i1, i2 ) { - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { + this.a.fromBufferAttribute( attribute, i0 ); + this.b.fromBufferAttribute( attribute, i1 ); + this.c.fromBufferAttribute( attribute, i2 ); - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { + return this; - state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + } - } else { + clone() { - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); + return new this.constructor().copy( this ); - } + } - } else { + copy( triangle ) { - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); - } + return this; - } + } - } else { + getArea() { - // regular Texture (image, video, canvas) + _v0$2.subVectors( this.c, this.b ); + _v1$3.subVectors( this.a, this.b ); - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels + return _v0$2.cross( _v1$3 ).length() * 0.5; - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { + } - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + getMidpoint( target ) { - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap ); + return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - } + } - texture.generateMipmaps = false; + getNormal( target ) { - } else { + return Triangle.getNormal( this.a, this.b, this.c, target ); - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image ); + } - } + getPlane( target ) { - } + return target.setFromCoplanarPoints( this.a, this.b, this.c ); - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { _gl.generateMipmap( _gl.TEXTURE_2D ); } + } - textureProperties.__version = texture.version; + getBarycoord( point, target ) { - if ( texture.onUpdate ) { texture.onUpdate( texture ); } + return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); } - // Render targets - - // Setup storage for target texture and bind it to correct framebuffer - function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { + getInterpolation( point, v1, v2, v3, target ) { - var glFormat = utils.convert( renderTarget.texture.format ); - var glType = utils.convert( renderTarget.texture.type ); - state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); } - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer - function setupRenderBufferStorage( renderbuffer, renderTarget ) { - - _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); - - if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { + containsPoint( point ) { - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); + return Triangle.containsPoint( point, this.a, this.b, this.c ); - } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { + } - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); + isFrontFacing( direction ) { - } else { + return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); - // FIXME: We don't support !depth !stencil - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height ); + } - } + intersectsBox( box ) { - _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); + return box.intersectsTriangle( this ); } - // Setup resources for a Depth Texture for a FBO (needs an extension) - function setupDepthTexture( framebuffer, renderTarget ) { + closestPointToPoint( p, target ) { - var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - if ( isCube ) { throw new Error( 'Depth Texture with cube render targets is not supported' ); } + const a = this.a, b = this.b, c = this.c; + let v, w; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + // algorithm thanks to Real-Time Collision Detection by Christer Ericson, + // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., + // under the accompanying license; see chapter 5.1.5 for detailed explanation. + // basically, we're distinguishing which of the voronoi regions of the triangle + // the point lies in with the minimum amount of redundant computation. - if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { + _vab.subVectors( b, a ); + _vac.subVectors( c, a ); + _vap.subVectors( p, a ); + const d1 = _vab.dot( _vap ); + const d2 = _vac.dot( _vap ); + if ( d1 <= 0 && d2 <= 0 ) { - throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); + // vertex region of A; barycentric coords (1, 0, 0) + return target.copy( a ); } - // upload an empty depth texture with framebuffer size - if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || - renderTarget.depthTexture.image.width !== renderTarget.width || - renderTarget.depthTexture.image.height !== renderTarget.height ) { + _vbp.subVectors( p, b ); + const d3 = _vab.dot( _vbp ); + const d4 = _vac.dot( _vbp ); + if ( d3 >= 0 && d4 <= d3 ) { - renderTarget.depthTexture.image.width = renderTarget.width; - renderTarget.depthTexture.image.height = renderTarget.height; - renderTarget.depthTexture.needsUpdate = true; + // vertex region of B; barycentric coords (0, 1, 0) + return target.copy( b ); } - setTexture2D( renderTarget.depthTexture, 0 ); + const vc = d1 * d4 - d3 * d2; + if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { - var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + v = d1 / ( d1 - d3 ); + // edge region of AB; barycentric coords (1-v, v, 0) + return target.copy( a ).addScaledVector( _vab, v ); - if ( renderTarget.depthTexture.format === DepthFormat ) { + } - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + _vcp.subVectors( p, c ); + const d5 = _vab.dot( _vcp ); + const d6 = _vac.dot( _vcp ); + if ( d6 >= 0 && d5 <= d6 ) { - } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { + // vertex region of C; barycentric coords (0, 0, 1) + return target.copy( c ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + } - } else { + const vb = d5 * d2 - d1 * d6; + if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { - throw new Error( 'Unknown depthTexture format' ); + w = d2 / ( d2 - d6 ); + // edge region of AC; barycentric coords (1-w, 0, w) + return target.copy( a ).addScaledVector( _vac, w ); } - } + const va = d3 * d6 - d5 * d4; + if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { - // Setup GL resources for a non-texture depth buffer - function setupDepthRenderbuffer( renderTarget ) { + _vbc.subVectors( c, b ); + w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + // edge region of BC; barycentric coords (0, 1-w, w) + return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC - var renderTargetProperties = properties.get( renderTarget ); + } - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); + // face region + const denom = 1 / ( va + vb + vc ); + // u = va * denom + v = vb * denom; + w = vc * denom; - if ( renderTarget.depthTexture ) { + return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); - if ( isCube ) { throw new Error( 'target.depthTexture not supported in Cube render targets' ); } + } - setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); + equals( triangle ) { - } else { + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - if ( isCube ) { + } - renderTargetProperties.__webglDepthbuffer = []; +} + +const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - for ( var i = 0; i < 6; i ++ ) { +const _hslA = { h: 0, s: 0, l: 0 }; +const _hslB = { h: 0, s: 0, l: 0 }; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); - renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget ); +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; - } else { +} - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget ); +class Color { - } + constructor( r, g, b ) { - } + this.isColor = true; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); + this.r = 1; + this.g = 1; + this.b = 1; - } + return this.set( r, g, b ); - // Set up GL resources for the render target - function setupRenderTarget( renderTarget ) { + } - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); + set( r, g, b ) { - renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); + if ( g === undefined && b === undefined ) { - textureProperties.__webglTexture = _gl.createTexture(); + // r is THREE.Color, hex or string - infoMemory.textures ++; + const value = r; - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); + if ( value && value.isColor ) { - // Setup framebuffer + this.copy( value ); - if ( isCube ) { + } else if ( typeof value === 'number' ) { - renderTargetProperties.__webglFramebuffer = []; + this.setHex( value ); - for ( var i = 0; i < 6; i ++ ) { + } else if ( typeof value === 'string' ) { - renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); + this.setStyle( value ); } } else { - renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); + this.setRGB( r, g, b ); } - // Setup color buffer + return this; - if ( isCube ) { + } - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo ); + setScalar( scalar ) { + + this.r = scalar; + this.g = scalar; + this.b = scalar; - for ( var i = 0; i < 6; i ++ ) { + return this; - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i ); + } - } + setHex( hex, colorSpace = SRGBColorSpace ) { - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) { _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); } - state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); + hex = Math.floor( hex ); - } else { + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) { _gl.generateMipmap( _gl.TEXTURE_2D ); } - state.bindTexture( _gl.TEXTURE_2D, null ); + return this; - } + } - // Setup depth and stencil buffers + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - if ( renderTarget.depthBuffer ) { + this.r = r; + this.g = g; + this.b = b; - setupDepthRenderbuffer( renderTarget ); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - } + return this; } - function updateRenderTargetMipmap( renderTarget ) { - - var texture = renderTarget.texture; - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { - if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); - var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; - var webglTexture = properties.get( texture ).__webglTexture; + if ( s === 0 ) { - state.bindTexture( target, webglTexture ); - _gl.generateMipmap( target ); - state.bindTexture( target, null ); + 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; - function updateVideoTextures() { + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); - for ( var id in _videoTextures ) { + } - _videoTextures[ id ].update(); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - } + return this; } - this.setTexture2D = setTexture2D; - this.setTextureCube = setTextureCube; - this.setTextureCubeDynamic = setTextureCubeDynamic; - this.setupRenderTarget = setupRenderTarget; - this.updateRenderTargetMipmap = updateRenderTargetMipmap; - this.updateVideoTextures = updateVideoTextures; + setStyle( style, colorSpace = SRGBColorSpace ) { -} + function handleAlpha( string ) { -/** - * @author fordacious / fordacious.github.io - */ + if ( string === undefined ) return; -function WebGLProperties() { + if ( parseFloat( string ) < 1 ) { - var properties = {}; + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); - function get( object ) { + } - var uuid = object.uuid; - var map = properties[ uuid ]; + } - if ( map === undefined ) { - map = {}; - properties[ uuid ] = map; + let m; - } + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { - return map; + // rgb / hsl - } + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - function remove( object ) { + switch ( name ) { - delete properties[ object.uuid ]; + case 'rgb': + case 'rgba': - } + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - function clear() { + // rgb(255,0,0) rgba(255,0,0,0.5) - properties = {}; + handleAlpha( color[ 4 ] ); - } + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); - return { - get: get, - remove: remove, - clear: clear - }; + } -} + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) -function WebGLState( gl, extensions, utils ) { + handleAlpha( color[ 4 ] ); - function ColorBuffer() { + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); - var locked = false; + } - var color = new Vector4(); - var currentColorMask = null; - var currentColorClear = new Vector4( 0, 0, 0, 0 ); + break; - return { + case 'hsl': + case 'hsla': - setMask: function ( colorMask ) { + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - if ( currentColorMask !== colorMask && ! locked ) { + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - gl.colorMask( colorMask, colorMask, colorMask, colorMask ); - currentColorMask = colorMask; + handleAlpha( color[ 4 ] ); - } + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); - }, + } - setLocked: function ( lock ) { + break; - locked = lock; + default: - }, + console.warn( 'THREE.Color: Unknown color model ' + style ); - setClear: function ( r, g, b, a, premultipliedAlpha ) { + } - if ( premultipliedAlpha === true ) { + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - r *= a; g *= a; b *= a; + // hex color - } + const hex = m[ 1 ]; + const size = hex.length; - color.set( r, g, b, a ); + if ( size === 3 ) { - if ( currentColorClear.equals( color ) === false ) { + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); - gl.clearColor( r, g, b, a ); - currentColorClear.copy( color ); + } else if ( size === 6 ) { - } + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); - }, + } else { - reset: function () { + console.warn( 'THREE.Color: Invalid hex color ' + style ); - locked = false; + } - currentColorMask = null; - currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state + } else if ( style && style.length > 0 ) { - } + return this.setColorName( style, colorSpace ); - }; + } - } + return this; - function DepthBuffer() { + } - var locked = false; + setColorName( style, colorSpace = SRGBColorSpace ) { - var currentDepthMask = null; - var currentDepthFunc = null; - var currentDepthClear = null; + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - return { + if ( hex !== undefined ) { - setTest: function ( depthTest ) { + // red + this.setHex( hex, colorSpace ); - if ( depthTest ) { + } else { - enable( gl.DEPTH_TEST ); + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - } else { + } - disable( gl.DEPTH_TEST ); + return this; - } + } - }, + clone() { - setMask: function ( depthMask ) { + return new this.constructor( this.r, this.g, this.b ); - if ( currentDepthMask !== depthMask && ! locked ) { + } - gl.depthMask( depthMask ); - currentDepthMask = depthMask; + copy( color ) { - } + this.r = color.r; + this.g = color.g; + this.b = color.b; - }, + return this; - setFunc: function ( depthFunc ) { + } - if ( currentDepthFunc !== depthFunc ) { + copySRGBToLinear( color ) { - if ( depthFunc ) { + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - switch ( depthFunc ) { + return this; - case NeverDepth: + } - gl.depthFunc( gl.NEVER ); - break; + copyLinearToSRGB( color ) { - case AlwaysDepth: + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - gl.depthFunc( gl.ALWAYS ); - break; + return this; - case LessDepth: + } - gl.depthFunc( gl.LESS ); - break; + convertSRGBToLinear() { - case LessEqualDepth: + this.copySRGBToLinear( this ); - gl.depthFunc( gl.LEQUAL ); - break; + return this; - case EqualDepth: + } - gl.depthFunc( gl.EQUAL ); - break; + convertLinearToSRGB() { - case GreaterEqualDepth: + this.copyLinearToSRGB( this ); - gl.depthFunc( gl.GEQUAL ); - break; + return this; - case GreaterDepth: + } - gl.depthFunc( gl.GREATER ); - break; + getHex( colorSpace = SRGBColorSpace ) { - case NotEqualDepth: + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - gl.depthFunc( gl.NOTEQUAL ); - break; + return Math.round( clamp( _color$1.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color$1.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color$1.b * 255, 0, 255 ) ); - default: + } - gl.depthFunc( gl.LEQUAL ); + getHexString( colorSpace = SRGBColorSpace ) { - } + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); - } else { + } - gl.depthFunc( gl.LEQUAL ); + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { - } + // h,s,l ranges are in 0.0 - 1.0 - currentDepthFunc = depthFunc; + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - } + const r = _color$1.r, g = _color$1.g, b = _color$1.b; - }, + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - setLocked: function ( lock ) { + let hue, saturation; + const lightness = ( min + max ) / 2.0; - locked = lock; + if ( min === max ) { - }, + hue = 0; + saturation = 0; - setClear: function ( depth ) { + } else { - if ( currentDepthClear !== depth ) { + const delta = max - min; - gl.clearDepth( depth ); - currentDepthClear = depth; + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - } + switch ( max ) { - }, + 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; - reset: function () { + } - locked = false; + hue /= 6; - currentDepthMask = null; - currentDepthFunc = null; - currentDepthClear = null; + } - } + target.h = hue; + target.s = saturation; + target.l = lightness; - }; + return target; } - function StencilBuffer() { - - var locked = false; + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - var currentStencilMask = null; - var currentStencilFunc = null; - var currentStencilRef = null; - var currentStencilFuncMask = null; - var currentStencilFail = null; - var currentStencilZFail = null; - var currentStencilZPass = null; - var currentStencilClear = null; + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - return { + target.r = _color$1.r; + target.g = _color$1.g; + target.b = _color$1.b; - setTest: function ( stencilTest ) { + return target; - if ( stencilTest ) { + } - enable( gl.STENCIL_TEST ); + getStyle( colorSpace = SRGBColorSpace ) { - } else { + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - disable( gl.STENCIL_TEST ); + const r = _color$1.r, g = _color$1.g, b = _color$1.b; - } + if ( colorSpace !== SRGBColorSpace ) { - }, + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; - setMask: function ( stencilMask ) { + } - if ( currentStencilMask !== stencilMask && ! locked ) { + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; - gl.stencilMask( stencilMask ); - currentStencilMask = stencilMask; + } - } + offsetHSL( h, s, l ) { - }, + this.getHSL( _hslA ); - setFunc: function ( stencilFunc, stencilRef, stencilMask ) { + return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); - if ( currentStencilFunc !== stencilFunc || - currentStencilRef !== stencilRef || - currentStencilFuncMask !== stencilMask ) { + } - gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); + add( color ) { - currentStencilFunc = stencilFunc; - currentStencilRef = stencilRef; - currentStencilFuncMask = stencilMask; + this.r += color.r; + this.g += color.g; + this.b += color.b; - } + return this; - }, + } - setOp: function ( stencilFail, stencilZFail, stencilZPass ) { + addColors( color1, color2 ) { - if ( currentStencilFail !== stencilFail || - currentStencilZFail !== stencilZFail || - currentStencilZPass !== stencilZPass ) { + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); + return this; - currentStencilFail = stencilFail; - currentStencilZFail = stencilZFail; - currentStencilZPass = stencilZPass; + } - } + addScalar( s ) { - }, + this.r += s; + this.g += s; + this.b += s; - setLocked: function ( lock ) { + return this; - locked = lock; + } - }, + sub( color ) { - setClear: function ( stencil ) { + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - if ( currentStencilClear !== stencil ) { + return this; - gl.clearStencil( stencil ); - currentStencilClear = stencil; + } - } + multiply( color ) { - }, + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - reset: function () { + return this; - locked = false; + } - currentStencilMask = null; - currentStencilFunc = null; - currentStencilRef = null; - currentStencilFuncMask = null; - currentStencilFail = null; - currentStencilZFail = null; - currentStencilZPass = null; - currentStencilClear = null; + multiplyScalar( s ) { - } + this.r *= s; + this.g *= s; + this.b *= s; - }; + return this; } - // + lerp( color, alpha ) { - var colorBuffer = new ColorBuffer(); - var depthBuffer = new DepthBuffer(); - var stencilBuffer = new StencilBuffer(); + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; - var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var newAttributes = new Uint8Array( maxVertexAttributes ); - var enabledAttributes = new Uint8Array( maxVertexAttributes ); - var attributeDivisors = new Uint8Array( maxVertexAttributes ); + return this; - var capabilities = {}; + } - var compressedTextureFormats = null; + lerpColors( color1, color2, alpha ) { - var currentProgram = null; + 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; - var currentBlending = null; - var currentBlendEquation = null; - var currentBlendSrc = null; - var currentBlendDst = null; - var currentBlendEquationAlpha = null; - var currentBlendSrcAlpha = null; - var currentBlendDstAlpha = null; - var currentPremultipledAlpha = false; + return this; - var currentFlipSided = null; - var currentCullFace = null; + } - var currentLineWidth = null; + lerpHSL( color, alpha ) { - var currentPolygonOffsetFactor = null; - var currentPolygonOffsetUnits = null; + this.getHSL( _hslA ); + color.getHSL( _hslB ); - var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); - var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] ); - var lineWidthAvailable = parseFloat( version ) >= 1.0; + this.setHSL( h, s, l ); - var currentTextureSlot = null; - var currentBoundTextures = {}; + return this; - var currentScissor = new Vector4(); - var currentViewport = new Vector4(); + } - function createTexture( type, target, count ) { + setFromVector3( v ) { - var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. - var texture = gl.createTexture(); + this.r = v.x; + this.g = v.y; + this.b = v.z; - gl.bindTexture( type, texture ); - gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); + return this; - for ( var i = 0; i < count; i ++ ) { + } - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + applyMatrix3( m ) { - } + const r = this.r, g = this.g, b = this.b; + const e = m.elements; - return texture; + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; - } + return this; - var 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 ); + } - // init + equals( c ) { - colorBuffer.setClear( 0, 0, 0, 1 ); - depthBuffer.setClear( 1 ); - stencilBuffer.setClear( 0 ); + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - enable( gl.DEPTH_TEST ); - depthBuffer.setFunc( LessEqualDepth ); + } - setFlipSided( false ); - setCullFace( CullFaceBack ); - enable( gl.CULL_FACE ); + fromArray( array, offset = 0 ) { - enable( gl.BLEND ); - setBlending( NormalBlending ); + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; - // + return this; - function initAttributes() { + } - for ( var i = 0, l = newAttributes.length; i < l; i ++ ) { + toArray( array = [], offset = 0 ) { - newAttributes[ i ] = 0; + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; - } + return array; } - function enableAttribute( attribute ) { + fromBufferAttribute( attribute, index ) { - newAttributes[ attribute ] = 1; + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); - if ( enabledAttributes[ attribute ] === 0 ) { + return this; - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; + } - } + toJSON() { - if ( attributeDivisors[ attribute ] !== 0 ) { + return this.getHex(); - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + } - extension.vertexAttribDivisorANGLE( attribute, 0 ); - attributeDivisors[ attribute ] = 0; + *[ Symbol.iterator ]() { - } + yield this.r; + yield this.g; + yield this.b; } - function enableAttributeAndDivisor( attribute, meshPerAttribute ) { - - newAttributes[ attribute ] = 1; +} - if ( enabledAttributes[ attribute ] === 0 ) { +const _color$1 = /*@__PURE__*/ new Color(); - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; +Color.NAMES = _colorKeywords; - } +let _materialId = 0; - if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { +class Material extends EventDispatcher { - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + constructor() { - extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute ); - attributeDivisors[ attribute ] = meshPerAttribute; + super(); - } + this.isMaterial = true; - } + Object.defineProperty( this, 'id', { value: _materialId ++ } ); - function disableUnusedAttributes() { + this.uuid = generateUUID(); - for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) { + this.name = ''; + this.type = 'Material'; - if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; + this.opacity = 1; + this.transparent = false; + this.alphaHash = false; - } + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + this.blendColor = new Color( 0, 0, 0 ); + this.blendAlpha = 0; - } + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; - } + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; - function enable( id ) { + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; - if ( capabilities[ id ] !== true ) { + this.shadowSide = null; - gl.enable( id ); - capabilities[ id ] = true; + this.colorWrite = true; - } + this.precision = null; // override the renderer's default precision for this material - } + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; - function disable( id ) { + this.dithering = false; - if ( capabilities[ id ] !== false ) { + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; - gl.disable( id ); - capabilities[ id ] = false; + this.visible = true; - } + this.toneMapped = true; - } + this.userData = {}; - function getCompressedTextureFormats() { + this.version = 0; - if ( compressedTextureFormats === null ) { + this._alphaTest = 0; - compressedTextureFormats = []; + } - if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) || - extensions.get( 'WEBGL_compressed_texture_s3tc' ) || - extensions.get( 'WEBGL_compressed_texture_etc1' ) ) { + get alphaTest() { - var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS ); + return this._alphaTest; - for ( var i = 0; i < formats.length; i ++ ) { + } - compressedTextureFormats.push( formats[ i ] ); + set alphaTest( value ) { - } + if ( this._alphaTest > 0 !== value > 0 ) { - } + this.version ++; } - return compressedTextureFormats; + this._alphaTest = value; } - function useProgram( program ) { + onBeforeCompile( /* shaderobject, renderer */ ) {} - if ( currentProgram !== program ) { + customProgramCacheKey() { - gl.useProgram( program ); + return this.onBeforeCompile.toString(); - currentProgram = program; + } - return true; + setValues( values ) { - } + if ( values === undefined ) return; - return false; + for ( const key in values ) { - } + const newValue = values[ key ]; - function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { + if ( newValue === undefined ) { - if ( blending !== NoBlending ) { + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; - enable( gl.BLEND ); + } - } else { + const currentValue = this[ key ]; - disable( gl.BLEND ); + if ( currentValue === undefined ) { - } + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; - if ( blending !== CustomBlending ) { + } - if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { + if ( currentValue && currentValue.isColor ) { - switch ( blending ) { + currentValue.set( newValue ); - case AdditiveBlending: + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { - if ( premultipliedAlpha ) { + currentValue.copy( newValue ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); + } else { - } else { + this[ key ] = newValue; - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + } - } - break; + } + + } - case SubtractiveBlending: + toJSON( meta ) { - if ( premultipliedAlpha ) { + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); + if ( isRootObject ) { - } else { + meta = { + textures: {}, + images: {} + }; - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); + } - } - break; + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; - case MultiplyBlending: + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; - if ( premultipliedAlpha ) { + if ( this.name !== '' ) data.name = this.name; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); - } else { + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; - } - break; + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; - default: + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { - if ( premultipliedAlpha ) { + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + } - } else { + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + 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(); - currentBlendEquation = null; - currentBlendSrc = null; - currentBlendDst = null; - currentBlendEquationAlpha = null; - currentBlendSrcAlpha = null; - currentBlendDstAlpha = null; + } - } else { + if ( this.dispersion !== undefined ) data.dispersion = this.dispersion; - blendEquationAlpha = blendEquationAlpha || blendEquation; - blendSrcAlpha = blendSrcAlpha || blendSrc; - blendDstAlpha = blendDstAlpha || blendDst; + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; - if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { - gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; - currentBlendEquation = blendEquation; - currentBlendEquationAlpha = blendEquationAlpha; + } - } + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { - if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; - gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); + } - currentBlendSrc = blendSrc; - currentBlendDst = blendDst; - currentBlendSrcAlpha = blendSrcAlpha; - currentBlendDstAlpha = blendDstAlpha; + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; - } + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; } - currentBlending = blending; - currentPremultipledAlpha = premultipliedAlpha; + 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 ) { - function setMaterial( material, frontFaceCW ) { + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; - material.side === DoubleSide - ? disable( gl.CULL_FACE ) - : enable( gl.CULL_FACE ); + } - var flipSided = ( material.side === BackSide ); - if ( frontFaceCW ) { flipSided = ! flipSided; } + if ( this.aoMap && this.aoMap.isTexture ) { - setFlipSided( flipSided ); + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; - material.transparent === true - ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ) - : setBlending( NoBlending ); + } - depthBuffer.setFunc( material.depthFunc ); - depthBuffer.setTest( material.depthTest ); - depthBuffer.setMask( material.depthWrite ); - colorBuffer.setMask( material.colorWrite ); + if ( this.bumpMap && this.bumpMap.isTexture ) { - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; - } + } - // + if ( this.normalMap && this.normalMap.isTexture ) { - function setFlipSided( flipSided ) { + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); - if ( currentFlipSided !== flipSided ) { + } - if ( flipSided ) { + if ( this.displacementMap && this.displacementMap.isTexture ) { - gl.frontFace( gl.CW ); + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; - } else { + } - gl.frontFace( gl.CCW ); + 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; - currentFlipSided = flipSided; + if ( this.envMap && this.envMap.isTexture ) { - } + data.envMap = this.envMap.toJSON( meta ).uuid; - } + if ( this.combine !== undefined ) data.combine = this.combine; - function setCullFace( cullFace ) { + } - if ( cullFace !== CullFaceNone ) { + if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray(); + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; - enable( gl.CULL_FACE ); + if ( this.gradientMap && this.gradientMap.isTexture ) { - if ( cullFace !== currentCullFace ) { + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; - if ( cullFace === CullFaceBack ) { + } - gl.cullFace( gl.BACK ); + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors === true ) data.vertexColors = true; + + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = true; + + if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; + if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; + if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; + if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; + if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; + if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; + if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); + if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; + + if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; + if ( this.depthTest === false ) data.depthTest = this.depthTest; + if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; + if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; + + if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; + if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; + if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; + if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask; + if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; + if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; + if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; + if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; - } else if ( cullFace === CullFaceFront ) { + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; - gl.cullFace( gl.FRONT ); + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; - } else { + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; - gl.cullFace( gl.FRONT_AND_BACK ); + if ( this.dithering === true ) data.dithering = true; - } + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaHash === true ) data.alphaHash = true; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; + if ( this.forceSinglePass === true ) data.forceSinglePass = true; - } + if ( this.wireframe === true ) data.wireframe = true; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; - } else { + if ( this.flatShading === true ) data.flatShading = true; - disable( gl.CULL_FACE ); + if ( this.visible === false ) data.visible = false; - } + if ( this.toneMapped === false ) data.toneMapped = false; - currentCullFace = cullFace; + if ( this.fog === false ) data.fog = false; - } + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; - function setLineWidth( width ) { + // TODO: Copied from Object3D.toJSON - if ( width !== currentLineWidth ) { + function extractFromCache( cache ) { - if ( lineWidthAvailable ) { gl.lineWidth( width ); } + const values = []; - currentLineWidth = width; + for ( const key in cache ) { - } + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - } + } - function setPolygonOffset( polygonOffset, factor, units ) { + return values; - if ( polygonOffset ) { + } - enable( gl.POLYGON_OFFSET_FILL ); + if ( isRootObject ) { - if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); - gl.polygonOffset( factor, units ); + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; - currentPolygonOffsetFactor = factor; - currentPolygonOffsetUnits = units; + } - } + return data; - } else { + } - disable( gl.POLYGON_OFFSET_FILL ); + clone() { - } + return new this.constructor().copy( this ); } - function setScissorTest( scissorTest ) { + copy( source ) { - if ( scissorTest ) { + this.name = source.name; - enable( gl.SCISSOR_TEST ); + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; - } else { + this.opacity = source.opacity; + this.transparent = source.transparent; - disable( gl.SCISSOR_TEST ); + 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.blendColor.copy( source.blendColor ); + this.blendAlpha = source.blendAlpha; - } + 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; - // texture + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; - function activeTexture( webglSlot ) { + if ( srcPlanes !== null ) { + + const n = srcPlanes.length; + dstPlanes = new Array( n ); - if ( webglSlot === undefined ) { webglSlot = gl.TEXTURE0 + maxTextures - 1; } + for ( let i = 0; i !== n; ++ i ) { - if ( currentTextureSlot !== webglSlot ) { + dstPlanes[ i ] = srcPlanes[ i ].clone(); - gl.activeTexture( webglSlot ); - currentTextureSlot = webglSlot; + } } - } + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; - function bindTexture( webglType, webglTexture ) { + this.shadowSide = source.shadowSide; - if ( currentTextureSlot === null ) { + this.colorWrite = source.colorWrite; - activeTexture(); + this.precision = source.precision; - } + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; - var boundTexture = currentBoundTextures[ currentTextureSlot ]; + this.dithering = source.dithering; - if ( boundTexture === undefined ) { + this.alphaTest = source.alphaTest; + this.alphaHash = source.alphaHash; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; - boundTexture = { type: undefined, texture: undefined }; - currentBoundTextures[ currentTextureSlot ] = boundTexture; + this.visible = source.visible; - } + this.toneMapped = source.toneMapped; - if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); + return this; - boundTexture.type = webglType; - boundTexture.texture = webglTexture; + } - } + dispose() { - } + this.dispatchEvent( { type: 'dispose' } ); - function compressedTexImage2D() { + } - try { + set needsUpdate( value ) { - gl.compressedTexImage2D.apply( gl, arguments ); + if ( value === true ) this.version ++; - } catch ( error ) { + } - console.error( 'THREE.WebGLState:', error ); + onBuild( /* shaderobject, renderer */ ) { - } + console.warn( 'Material: onBuild() has been removed.' ); // @deprecated, r166 } - function texImage2D() { + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) { - try { + console.warn( 'Material: onBeforeRender() has been removed.' ); // @deprecated, r166 - gl.texImage2D.apply( gl, arguments ); + } - } catch ( error ) { - console.error( 'THREE.WebGLState:', error ); +} - } +class MeshBasicMaterial extends Material { - } + constructor( parameters ) { - // + super(); - function scissor( scissor ) { + this.isMeshBasicMaterial = true; - if ( currentScissor.equals( scissor ) === false ) { + this.type = 'MeshBasicMaterial'; - gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); - currentScissor.copy( scissor ); + this.color = new Color( 0xffffff ); // emissive - } + this.map = null; - } + this.lightMap = null; + this.lightMapIntensity = 1.0; - function viewport( viewport ) { + this.aoMap = null; + this.aoMapIntensity = 1.0; - if ( currentViewport.equals( viewport ) === false ) { + this.specularMap = null; - gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); - currentViewport.copy( viewport ); + this.alphaMap = null; - } + this.envMap = null; + this.envMapRotation = new Euler(); + 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; - function reset() { + this.setValues( parameters ); - for ( var i = 0; i < enabledAttributes.length; i ++ ) { + } - if ( enabledAttributes[ i ] === 1 ) { + copy( source ) { - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; + super.copy( source ); - } + this.color.copy( source.color ); - } + this.map = source.map; - capabilities = {}; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - compressedTextureFormats = null; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - currentTextureSlot = null; - currentBoundTextures = {}; + this.specularMap = source.specularMap; - currentProgram = null; + this.alphaMap = source.alphaMap; - currentBlending = null; + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; - currentFlipSided = null; - currentCullFace = null; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - colorBuffer.reset(); - depthBuffer.reset(); - stencilBuffer.reset(); + this.fog = source.fog; + + return this; } - return { +} - buffers: { - color: colorBuffer, - depth: depthBuffer, - stencil: stencilBuffer - }, +const _vector$9 = /*@__PURE__*/ new Vector3(); +const _vector2$1 = /*@__PURE__*/ new Vector2(); - initAttributes: initAttributes, - enableAttribute: enableAttribute, - enableAttributeAndDivisor: enableAttributeAndDivisor, - disableUnusedAttributes: disableUnusedAttributes, - enable: enable, - disable: disable, - getCompressedTextureFormats: getCompressedTextureFormats, +class BufferAttribute { - useProgram: useProgram, + constructor( array, itemSize, normalized = false ) { - setBlending: setBlending, - setMaterial: setMaterial, + if ( Array.isArray( array ) ) { - setFlipSided: setFlipSided, - setCullFace: setCullFace, + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - setLineWidth: setLineWidth, - setPolygonOffset: setPolygonOffset, + } - setScissorTest: setScissorTest, + this.isBufferAttribute = true; - activeTexture: activeTexture, - bindTexture: bindTexture, - compressedTexImage2D: compressedTexImage2D, - texImage2D: texImage2D, + this.name = ''; - scissor: scissor, - viewport: viewport, + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized; - reset: reset + this.usage = StaticDrawUsage; + this._updateRange = { offset: 0, count: - 1 }; + this.updateRanges = []; + this.gpuType = FloatType; - }; + this.version = 0; -} + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + onUploadCallback() {} -function WebGLCapabilities( gl, extensions, parameters ) { + set needsUpdate( value ) { - var maxAnisotropy; + if ( value === true ) this.version ++; - function getMaxAnisotropy() { + } - if ( maxAnisotropy !== undefined ) { return maxAnisotropy; } + get updateRange() { - var extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 + return this._updateRange; - if ( extension !== null ) { + } - maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); + setUsage( value ) { - } else { + this.usage = value; - maxAnisotropy = 0; + return this; - } + } - return maxAnisotropy; + addUpdateRange( start, count ) { + + this.updateRanges.push( { start, count } ); } - function getMaxPrecision( precision ) { + clearUpdateRanges() { - if ( precision === 'highp' ) { + this.updateRanges.length = 0; - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { + } - return 'highp'; + 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; - precision = 'mediump'; + this.usage = source.usage; + this.gpuType = source.gpuType; - } + return this; - if ( precision === 'mediump' ) { + } - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { + copyAt( index1, attribute, index2 ) { - return 'mediump'; + 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 'lowp'; + return this; } - var precision = parameters.precision !== undefined ? parameters.precision : 'highp'; - var maxPrecision = getMaxPrecision( precision ); + copyArray( array ) { - if ( maxPrecision !== precision ) { + this.array.set( array ); - console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); - precision = maxPrecision; + return this; } - var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; + applyMatrix3( m ) { - var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); - var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); - var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); - var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); + if ( this.itemSize === 2 ) { - var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); - var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); - var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); + for ( let i = 0, l = this.count; i < l; i ++ ) { - var vertexTextures = maxVertexTextures > 0; - var floatFragmentTextures = !! extensions.get( 'OES_texture_float' ); - var floatVertexTextures = vertexTextures && floatFragmentTextures; + _vector2$1.fromBufferAttribute( this, i ); + _vector2$1.applyMatrix3( m ); - return { + this.setXY( i, _vector2$1.x, _vector2$1.y ); - getMaxAnisotropy: getMaxAnisotropy, - getMaxPrecision: getMaxPrecision, + } - precision: precision, - logarithmicDepthBuffer: logarithmicDepthBuffer, + } else if ( this.itemSize === 3 ) { - maxTextures: maxTextures, - maxVertexTextures: maxVertexTextures, - maxTextureSize: maxTextureSize, - maxCubemapSize: maxCubemapSize, + for ( let i = 0, l = this.count; i < l; i ++ ) { - maxAttributes: maxAttributes, - maxVertexUniforms: maxVertexUniforms, - maxVaryings: maxVaryings, - maxFragmentUniforms: maxFragmentUniforms, + _vector$9.fromBufferAttribute( this, i ); + _vector$9.applyMatrix3( m ); - vertexTextures: vertexTextures, - floatFragmentTextures: floatFragmentTextures, - floatVertexTextures: floatVertexTextures + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - }; + } -} + } -/** - * @author mrdoob / http://mrdoob.com/ - * @author greggman / http://games.greggman.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author tschw - */ + return this; -function PerspectiveCamera( fov, aspect, near, far ) { + } - Camera.call( this ); + applyMatrix4( m ) { - this.type = 'PerspectiveCamera'; + for ( let i = 0, l = this.count; i < l; i ++ ) { - this.fov = fov !== undefined ? fov : 50; - this.zoom = 1; + _vector$9.fromBufferAttribute( this, i ); - this.near = near !== undefined ? near : 0.1; - this.far = far !== undefined ? far : 2000; - this.focus = 10; + _vector$9.applyMatrix4( m ); - this.aspect = aspect !== undefined ? aspect : 1; - this.view = null; + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + } - this.updateProjectionMatrix(); + return this; -} + } -PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + applyNormalMatrix( m ) { - constructor: PerspectiveCamera, + for ( let i = 0, l = this.count; i < l; i ++ ) { - isPerspectiveCamera: true, + _vector$9.fromBufferAttribute( this, i ); - copy: function ( source, recursive ) { + _vector$9.applyNormalMatrix( m ); - Camera.prototype.copy.call( this, source, recursive ); + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.fov = source.fov; - this.zoom = source.zoom; + } - this.near = source.near; - this.far = source.far; - this.focus = source.focus; + return this; - this.aspect = source.aspect; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + } - this.filmGauge = source.filmGauge; - this.filmOffset = source.filmOffset; + transformDirection( m ) { - return this; + for ( let i = 0, l = this.count; i < l; i ++ ) { - }, + _vector$9.fromBufferAttribute( this, i ); - /** - * Sets the FOV by focal length in respect to the current .filmGauge. - * - * The default film gauge is 35, so that the focal length can be specified for - * a 35mm (full frame) camera. - * - * Values for focal length and film gauge must have the same unit. - */ - setFocalLength: function ( focalLength ) { + _vector$9.transformDirection( m ); - // see http://www.bobatkins.com/photography/technical/field_of_view.html - var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); - this.updateProjectionMatrix(); + } - }, + return this; - /** - * Calculates the focal length from the current .fov and .filmGauge. - */ - getFocalLength: function () { + } - var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); + set( value, offset = 0 ) { - return 0.5 * this.getFilmHeight() / vExtentSlope; + // Matching BufferAttribute constructor, do not normalize the array. + this.array.set( value, offset ); - }, + return this; - getEffectiveFOV: function () { + } - return _Math.RAD2DEG * 2 * Math.atan( - Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); + getComponent( index, component ) { - }, + let value = this.array[ index * this.itemSize + component ]; - getFilmWidth: function () { + if ( this.normalized ) value = denormalize( value, this.array ); - // film not completely covered in portrait format (aspect < 1) - return this.filmGauge * Math.min( this.aspect, 1 ); + return value; - }, + } - getFilmHeight: function () { + setComponent( index, component, value ) { - // film not completely covered in landscape format (aspect > 1) - return this.filmGauge / Math.max( this.aspect, 1 ); + if ( this.normalized ) value = normalize( value, this.array ); - }, + this.array[ index * this.itemSize + component ] = value; - /** - * Sets an offset in a larger frustum. This is useful for multi-window or - * multi-monitor/multi-machine setups. - * - * For example, if you have 3x2 monitors and each monitor is 1920x1080 and - * the monitors are in grid like this - * - * +---+---+---+ - * | A | B | C | - * +---+---+---+ - * | D | E | F | - * +---+---+---+ - * - * then for each monitor you would call it like this - * - * var w = 1920; - * var h = 1080; - * var fullWidth = w * 3; - * var fullHeight = h * 2; - * - * --A-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); - * - * Note there is no reason monitors have to be the same size or in a grid. - */ - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { + return this; - this.aspect = fullWidth / fullHeight; + } - if ( this.view === null ) { + getX( index ) { - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; + let x = this.array[ index * this.itemSize ]; - } + if ( this.normalized ) x = denormalize( x, this.array ); - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; + return x; - this.updateProjectionMatrix(); + } - }, + setX( index, x ) { - clearViewOffset: function () { + if ( this.normalized ) x = normalize( x, this.array ); - if ( this.view !== null ) { + this.array[ index * this.itemSize ] = x; - this.view.enabled = false; + return this; - } + } - this.updateProjectionMatrix(); + getY( index ) { - }, + let y = this.array[ index * this.itemSize + 1 ]; - updateProjectionMatrix: function () { + if ( this.normalized ) y = denormalize( y, this.array ); - var near = this.near, - top = near * Math.tan( - _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom, - height = 2 * top, - width = this.aspect * height, - left = - 0.5 * width, - view = this.view; + return y; - if ( this.view !== null && this.view.enabled ) { + } - var fullWidth = view.fullWidth, - fullHeight = view.fullHeight; + setY( index, y ) { - left += view.offsetX * width / fullWidth; - top -= view.offsetY * height / fullHeight; - width *= view.width / fullWidth; - height *= view.height / fullHeight; + if ( this.normalized ) y = normalize( y, this.array ); - } + this.array[ index * this.itemSize + 1 ] = y; - var skew = this.filmOffset; - if ( skew !== 0 ) { left += near * skew / this.getFilmWidth(); } + return this; - this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + } - }, + getZ( index ) { - toJSON: function ( meta ) { + let z = this.array[ index * this.itemSize + 2 ]; - var data = Object3D.prototype.toJSON.call( this, meta ); + if ( this.normalized ) z = denormalize( z, this.array ); - data.object.fov = this.fov; - data.object.zoom = this.zoom; + return z; - data.object.near = this.near; - data.object.far = this.far; - data.object.focus = this.focus; + } - data.object.aspect = this.aspect; + setZ( index, z ) { - if ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); } + if ( this.normalized ) z = normalize( z, this.array ); - data.object.filmGauge = this.filmGauge; - data.object.filmOffset = this.filmOffset; + this.array[ index * this.itemSize + 2 ] = z; - return data; + return this; } -} ); + getW( index ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + let w = this.array[ index * this.itemSize + 3 ]; -function ArrayCamera( array ) { + if ( this.normalized ) w = denormalize( w, this.array ); - PerspectiveCamera.call( this ); + return w; - this.cameras = array || []; + } -} + setW( index, w ) { -ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + if ( this.normalized ) w = normalize( w, this.array ); - constructor: ArrayCamera, + this.array[ index * this.itemSize + 3 ] = w; - isArrayCamera: true + return this; -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + setXY( index, x, y ) { -function WebVRManager( renderer ) { + index *= this.itemSize; - var scope = this; + if ( this.normalized ) { - var device = null; - var frameData = null; + x = normalize( x, this.array ); + y = normalize( y, this.array ); - var poseTarget = null; + } - if ( typeof window !== 'undefined' && 'VRFrameData' in window ) { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; - frameData = new window.VRFrameData(); + return this; } - var matrixWorldInverse = new Matrix4(); + setXYZ( index, x, y, z ) { - var cameraL = new PerspectiveCamera(); - cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); - cameraL.layers.enable( 1 ); - - var cameraR = new PerspectiveCamera(); - cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); - cameraR.layers.enable( 2 ); + index *= this.itemSize; - var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + if ( this.normalized ) { - // + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); - var currentSize, currentPixelRatio; + } - function onVRDisplayPresentChange() { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; - if ( device !== null && device.isPresenting ) { + return this; - var eyeParameters = device.getEyeParameters( 'left' ); - var renderWidth = eyeParameters.renderWidth; - var renderHeight = eyeParameters.renderHeight; + } - currentPixelRatio = renderer.getPixelRatio(); - currentSize = renderer.getSize(); + setXYZW( index, x, y, z, w ) { - renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); + index *= this.itemSize; - } else if ( scope.enabled ) { + if ( this.normalized ) { - renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); } + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + this.array[ index + 3 ] = w; + + return this; + } - if ( typeof window !== 'undefined' ) { + onUpload( callback ) { + + this.onUploadCallback = callback; - window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); + return this; } - // + clone() { - this.enabled = false; + return new this.constructor( this.array, this.itemSize ).copy( this ); - this.getDevice = function () { + } - return device; + toJSON() { - }; + const data = { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: Array.from( this.array ), + normalized: this.normalized + }; - this.setDevice = function ( value ) { + if ( this.name !== '' ) data.name = this.name; + if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; - if ( value !== undefined ) { device = value; } + return data; - }; + } - this.setPoseTarget = function ( object ) { +} - if ( object !== undefined ) { poseTarget = object; } +class Uint16BufferAttribute extends BufferAttribute { - }; + constructor( array, itemSize, normalized ) { - this.getCamera = function ( camera ) { + super( new Uint16Array( array ), itemSize, normalized ); - if ( device === null ) { return camera; } + } - device.depthNear = camera.near; - device.depthFar = camera.far; +} - device.getFrameData( frameData ); +class Uint32BufferAttribute extends BufferAttribute { - // + constructor( array, itemSize, normalized ) { - var pose = frameData.pose; - var poseObject = poseTarget !== null ? poseTarget : camera; + super( new Uint32Array( array ), itemSize, normalized ); - if ( pose.position !== null ) { + } - poseObject.position.fromArray( pose.position ); +} - } else { - poseObject.position.set( 0, 0, 0 ); +class Float32BufferAttribute extends BufferAttribute { - } + constructor( array, itemSize, normalized ) { - if ( pose.orientation !== null ) { + super( new Float32Array( array ), itemSize, normalized ); - poseObject.quaternion.fromArray( pose.orientation ); + } - } +} - poseObject.updateMatrixWorld(); +let _id$2 = 0; - if ( device.isPresenting === false ) { return camera; } +const _m1$2 = /*@__PURE__*/ new Matrix4(); +const _obj = /*@__PURE__*/ new Object3D(); +const _offset = /*@__PURE__*/ new Vector3(); +const _box$2 = /*@__PURE__*/ new Box3(); +const _boxMorphTargets = /*@__PURE__*/ new Box3(); +const _vector$8 = /*@__PURE__*/ new Vector3(); - // +class BufferGeometry extends EventDispatcher { - cameraL.near = camera.near; - cameraR.near = camera.near; + constructor() { - cameraL.far = camera.far; - cameraR.far = camera.far; + super(); - cameraVR.matrixWorld.copy( camera.matrixWorld ); - cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); + this.isBufferGeometry = true; - cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); - cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); + Object.defineProperty( this, 'id', { value: _id$2 ++ } ); - var parent = poseObject.parent; + this.uuid = generateUUID(); - if ( parent !== null ) { + this.name = ''; + this.type = 'BufferGeometry'; - matrixWorldInverse.getInverse( parent.matrixWorld ); + this.index = null; + this.attributes = {}; - cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); - cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); + this.morphAttributes = {}; + this.morphTargetsRelative = false; - } + this.groups = []; - // envMap and Mirror needs camera.matrixWorld + this.boundingBox = null; + this.boundingSphere = null; - cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); - cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); + this.drawRange = { start: 0, count: Infinity }; - cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); - cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); + this.userData = {}; - // HACK @mrdoob - // https://github.com/w3c/webvr/issues/203 + } - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + getIndex() { - // + return this.index; - var layers = device.getLayers(); + } - if ( layers.length ) { + setIndex( index ) { - var layer = layers[ 0 ]; + if ( Array.isArray( index ) ) { - if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { + this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - cameraL.bounds.fromArray( layer.leftBounds ); + } else { - } + this.index = index; - if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { + } - cameraR.bounds.fromArray( layer.rightBounds ); + return this; - } + } - } + getAttribute( name ) { - return cameraVR; + return this.attributes[ name ]; - }; + } - this.submitFrame = function () { + setAttribute( name, attribute ) { - if ( device && device.isPresenting ) { device.submitFrame(); } + this.attributes[ name ] = attribute; - }; + return this; - this.dispose = function () { + } - if ( typeof window !== 'undefined' ) { + deleteAttribute( name ) { - window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); + delete this.attributes[ name ]; - } + return this; - }; + } -} + hasAttribute( name ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + return this.attributes[ name ] !== undefined; -function WebGLExtensions( gl ) { + } - var extensions = {}; + addGroup( start, count, materialIndex = 0 ) { - return { + this.groups.push( { - get: function ( name ) { + start: start, + count: count, + materialIndex: materialIndex - if ( extensions[ name ] !== undefined ) { + } ); - return extensions[ name ]; + } - } + clearGroups() { - var extension; + this.groups = []; - 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; + setDrawRange( start, count ) { - 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; + this.drawRange.start = start; + this.drawRange.count = count; - 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; + applyMatrix4( matrix ) { - case 'WEBGL_compressed_texture_etc1': - extension = gl.getExtension( 'WEBGL_compressed_texture_etc1' ); - break; + const position = this.attributes.position; - default: - extension = gl.getExtension( name ); + if ( position !== undefined ) { - } + position.applyMatrix4( matrix ); - if ( extension === null ) { + position.needsUpdate = true; - console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); + } - } + const normal = this.attributes.normal; - extensions[ name ] = extension; + if ( normal !== undefined ) { - return extension; + const normalMatrix = new Matrix3().getNormalMatrix( matrix ); - } + normal.applyNormalMatrix( normalMatrix ); - }; + normal.needsUpdate = true; -} + } -/** - * @author tschw - */ + const tangent = this.attributes.tangent; -function WebGLClipping() { + if ( tangent !== undefined ) { - var scope = this, + tangent.transformDirection( matrix ); - globalState = null, - numGlobalPlanes = 0, - localClippingEnabled = false, - renderingShadows = false, + tangent.needsUpdate = true; - plane = new Plane(), - viewNormalMatrix = new Matrix3(), + } - uniform = { value: null, needsUpdate: false }; + if ( this.boundingBox !== null ) { - this.uniform = uniform; - this.numPlanes = 0; - this.numIntersection = 0; + this.computeBoundingBox(); - this.init = function ( planes, enableLocalClipping, camera ) { + } - var enabled = - planes.length !== 0 || - enableLocalClipping || - // enable state of previous frame - the clipping code has to - // run another frame in order to reset the state: - numGlobalPlanes !== 0 || - localClippingEnabled; + if ( this.boundingSphere !== null ) { - localClippingEnabled = enableLocalClipping; + this.computeBoundingSphere(); - globalState = projectPlanes( planes, camera, 0 ); - numGlobalPlanes = planes.length; + } - return enabled; + return this; - }; + } - this.beginShadows = function () { + applyQuaternion( q ) { - renderingShadows = true; - projectPlanes( null ); + _m1$2.makeRotationFromQuaternion( q ); - }; + this.applyMatrix4( _m1$2 ); - this.endShadows = function () { + return this; - renderingShadows = false; - resetGlobalState(); + } - }; + rotateX( angle ) { - this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) { + // rotate geometry around world x-axis - if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { + _m1$2.makeRotationX( angle ); - // there's no local clipping + this.applyMatrix4( _m1$2 ); - if ( renderingShadows ) { + return this; - // there's no global clipping + } - projectPlanes( null ); + rotateY( angle ) { - } else { + // rotate geometry around world y-axis - resetGlobalState(); + _m1$2.makeRotationY( angle ); - } + this.applyMatrix4( _m1$2 ); - } else { + return this; - var nGlobal = renderingShadows ? 0 : numGlobalPlanes, - lGlobal = nGlobal * 4, + } - dstArray = cache.clippingState || null; + rotateZ( angle ) { - uniform.value = dstArray; // ensure unique state + // rotate geometry around world z-axis - dstArray = projectPlanes( planes, camera, lGlobal, fromCache ); + _m1$2.makeRotationZ( angle ); - for ( var i = 0; i !== lGlobal; ++ i ) { + this.applyMatrix4( _m1$2 ); - dstArray[ i ] = globalState[ i ]; + return this; - } + } - cache.clippingState = dstArray; - this.numIntersection = clipIntersection ? this.numPlanes : 0; - this.numPlanes += nGlobal; + translate( x, y, z ) { - } + // translate geometry + _m1$2.makeTranslation( x, y, z ); - }; + this.applyMatrix4( _m1$2 ); - function resetGlobalState() { + return this; - if ( uniform.value !== globalState ) { + } - uniform.value = globalState; - uniform.needsUpdate = numGlobalPlanes > 0; + scale( x, y, z ) { - } + // scale geometry - scope.numPlanes = numGlobalPlanes; - scope.numIntersection = 0; + _m1$2.makeScale( x, y, z ); + + this.applyMatrix4( _m1$2 ); + + return this; } - function projectPlanes( planes, camera, dstOffset, skipTransform ) { + lookAt( vector ) { - var nPlanes = planes !== null ? planes.length : 0, - dstArray = null; + _obj.lookAt( vector ); - if ( nPlanes !== 0 ) { + _obj.updateMatrix(); - dstArray = uniform.value; + this.applyMatrix4( _obj.matrix ); - if ( skipTransform !== true || dstArray === null ) { + return this; - var flatSize = dstOffset + nPlanes * 4, - viewMatrix = camera.matrixWorldInverse; + } - viewNormalMatrix.getNormalMatrix( viewMatrix ); + center() { - if ( dstArray === null || dstArray.length < flatSize ) { + this.computeBoundingBox(); - dstArray = new Float32Array( flatSize ); + this.boundingBox.getCenter( _offset ).negate(); - } + this.translate( _offset.x, _offset.y, _offset.z ); - for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { + return this; - plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); + } - plane.normal.toArray( dstArray, i4 ); - dstArray[ i4 + 3 ] = plane.constant; + setFromPoints( points ) { - } + const position = []; - } + for ( let i = 0, l = points.length; i < l; i ++ ) { - uniform.value = dstArray; - uniform.needsUpdate = true; + const point = points[ i ]; + position.push( point.x, point.y, point.z || 0 ); } - scope.numPlanes = nPlanes; + this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - return dstArray; + return this; } -} + computeBoundingBox() { -/** - * @author thespite / http://www.twitter.com/thespite - */ + if ( this.boundingBox === null ) { -function WebGLUtils( gl, extensions ) { + this.boundingBox = new Box3(); + + } - function convert( p ) { + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; - var extension; + if ( position && position.isGLBufferAttribute ) { - if ( p === RepeatWrapping ) { return gl.REPEAT; } - if ( p === ClampToEdgeWrapping ) { return gl.CLAMP_TO_EDGE; } - if ( p === MirroredRepeatWrapping ) { return gl.MIRRORED_REPEAT; } + console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); - if ( p === NearestFilter ) { return gl.NEAREST; } - if ( p === NearestMipMapNearestFilter ) { return gl.NEAREST_MIPMAP_NEAREST; } - if ( p === NearestMipMapLinearFilter ) { return gl.NEAREST_MIPMAP_LINEAR; } + this.boundingBox.set( + new Vector3( - Infinity, - Infinity, - Infinity ), + new Vector3( + Infinity, + Infinity, + Infinity ) + ); - if ( p === LinearFilter ) { return gl.LINEAR; } - if ( p === LinearMipMapNearestFilter ) { return gl.LINEAR_MIPMAP_NEAREST; } - if ( p === LinearMipMapLinearFilter ) { return gl.LINEAR_MIPMAP_LINEAR; } + return; - if ( p === UnsignedByteType ) { return gl.UNSIGNED_BYTE; } - if ( p === UnsignedShort4444Type ) { return gl.UNSIGNED_SHORT_4_4_4_4; } - if ( p === UnsignedShort5551Type ) { return gl.UNSIGNED_SHORT_5_5_5_1; } - if ( p === UnsignedShort565Type ) { return gl.UNSIGNED_SHORT_5_6_5; } + } - if ( p === ByteType ) { return gl.BYTE; } - if ( p === ShortType ) { return gl.SHORT; } - if ( p === UnsignedShortType ) { return gl.UNSIGNED_SHORT; } - if ( p === IntType ) { return gl.INT; } - if ( p === UnsignedIntType ) { return gl.UNSIGNED_INT; } - if ( p === FloatType ) { return gl.FLOAT; } + if ( position !== undefined ) { - if ( p === HalfFloatType ) { + this.boundingBox.setFromBufferAttribute( position ); - extension = extensions.get( 'OES_texture_half_float' ); + // process morph attributes if present - if ( extension !== null ) { return extension.HALF_FLOAT_OES; } + if ( morphAttributesPosition ) { - } + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { - if ( p === AlphaFormat ) { return gl.ALPHA; } - if ( p === RGBFormat ) { return gl.RGB; } - if ( p === RGBAFormat ) { return gl.RGBA; } - if ( p === LuminanceFormat ) { return gl.LUMINANCE; } - if ( p === LuminanceAlphaFormat ) { return gl.LUMINANCE_ALPHA; } - if ( p === DepthFormat ) { return gl.DEPTH_COMPONENT; } - if ( p === DepthStencilFormat ) { return gl.DEPTH_STENCIL; } + const morphAttribute = morphAttributesPosition[ i ]; + _box$2.setFromBufferAttribute( morphAttribute ); - if ( p === AddEquation ) { return gl.FUNC_ADD; } - if ( p === SubtractEquation ) { return gl.FUNC_SUBTRACT; } - if ( p === ReverseSubtractEquation ) { return gl.FUNC_REVERSE_SUBTRACT; } + if ( this.morphTargetsRelative ) { - if ( p === ZeroFactor ) { return gl.ZERO; } - if ( p === OneFactor ) { return gl.ONE; } - if ( p === SrcColorFactor ) { return gl.SRC_COLOR; } - if ( p === OneMinusSrcColorFactor ) { return gl.ONE_MINUS_SRC_COLOR; } - if ( p === SrcAlphaFactor ) { return gl.SRC_ALPHA; } - if ( p === OneMinusSrcAlphaFactor ) { return gl.ONE_MINUS_SRC_ALPHA; } - if ( p === DstAlphaFactor ) { return gl.DST_ALPHA; } - if ( p === OneMinusDstAlphaFactor ) { return gl.ONE_MINUS_DST_ALPHA; } + _vector$8.addVectors( this.boundingBox.min, _box$2.min ); + this.boundingBox.expandByPoint( _vector$8 ); - if ( p === DstColorFactor ) { return gl.DST_COLOR; } - if ( p === OneMinusDstColorFactor ) { return gl.ONE_MINUS_DST_COLOR; } - if ( p === SrcAlphaSaturateFactor ) { return gl.SRC_ALPHA_SATURATE; } + _vector$8.addVectors( this.boundingBox.max, _box$2.max ); + this.boundingBox.expandByPoint( _vector$8 ); - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + } else { - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + this.boundingBox.expandByPoint( _box$2.min ); + this.boundingBox.expandByPoint( _box$2.max ); - 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; } + } } - } - - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + } else { - extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + this.boundingBox.makeEmpty(); - 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; } + 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 ); } - if ( p === RGB_ETC1_Format ) { + } + + computeBoundingSphere() { - extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); + if ( this.boundingSphere === null ) { - if ( extension !== null ) { return extension.COMPRESSED_RGB_ETC1_WEBGL; } + this.boundingSphere = new Sphere(); } - if ( p === MinEquation || p === MaxEquation ) { + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; - extension = extensions.get( 'EXT_blend_minmax' ); + if ( position && position.isGLBufferAttribute ) { - if ( extension !== null ) { + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); - if ( p === MinEquation ) { return extension.MIN_EXT; } - if ( p === MaxEquation ) { return extension.MAX_EXT; } + this.boundingSphere.set( new Vector3(), Infinity ); - } + return; } - if ( p === UnsignedInt248Type ) { + if ( position ) { - extension = extensions.get( 'WEBGL_depth_texture' ); + // first, find the center of the bounding sphere - if ( extension !== null ) { return extension.UNSIGNED_INT_24_8_WEBGL; } + const center = this.boundingSphere.center; - } + _box$2.setFromBufferAttribute( position ); - return 0; + // process morph attributes if present - } + if ( morphAttributesPosition ) { - return { convert: convert }; + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { -} + const morphAttribute = morphAttributesPosition[ i ]; + _boxMorphTargets.setFromBufferAttribute( morphAttribute ); -/** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - * @author tschw - */ + if ( this.morphTargetsRelative ) { + + _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); + _box$2.expandByPoint( _vector$8 ); + + _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); + _box$2.expandByPoint( _vector$8 ); + + } else { + + _box$2.expandByPoint( _boxMorphTargets.min ); + _box$2.expandByPoint( _boxMorphTargets.max ); -function WebGLRenderer( parameters ) { + } + + } - console.log( 'THREE.WebGLRenderer', REVISION ); + } - parameters = parameters || {}; + _box$2.getCenter( center ); - var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ), - _context = parameters.context !== undefined ? parameters.context : null, + // second, try to find a boundingSphere with a radius smaller than the + // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - _alpha = parameters.alpha !== undefined ? parameters.alpha : false, - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default'; + let maxRadiusSq = 0; - var lightsArray = []; - var shadowsArray = []; + for ( let i = 0, il = position.count; i < il; i ++ ) { - var currentRenderList = null; + _vector$8.fromBufferAttribute( position, i ); - var spritesArray = []; - var flaresArray = []; + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); - // public properties + } - this.domElement = _canvas; - this.context = null; + // process morph attributes if present - // clearing + if ( morphAttributesPosition ) { - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { - // scene graph + const morphAttribute = morphAttributesPosition[ i ]; + const morphTargetsRelative = this.morphTargetsRelative; - this.sortObjects = true; + for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { - // user-defined clipping + _vector$8.fromBufferAttribute( morphAttribute, j ); - this.clippingPlanes = []; - this.localClippingEnabled = false; + if ( morphTargetsRelative ) { - // physically based shading + _offset.fromBufferAttribute( position, j ); + _vector$8.add( _offset ); - this.gammaFactor = 2.0; // for backwards compatibility - this.gammaInput = false; - this.gammaOutput = false; + } - // physical lights + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); - this.physicallyCorrectLights = false; + } - // tone mapping + } - this.toneMapping = LinearToneMapping; - this.toneMappingExposure = 1.0; - this.toneMappingWhitePoint = 1.0; + } - // morphs + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - this.maxMorphTargets = 8; - this.maxMorphNormals = 4; + if ( isNaN( this.boundingSphere.radius ) ) { - // internal properties + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); - var _this = this, + } - _isContextLost = false, + } - // internal state cache + } - _currentRenderTarget = null, - _currentFramebuffer = null, - _currentMaterialId = - 1, - _currentGeometryProgram = '', + computeTangents() { - _currentCamera = null, - _currentArrayCamera = null, + const index = this.index; + const attributes = this.attributes; - _currentViewport = new Vector4(), - _currentScissor = new Vector4(), - _currentScissorTest = null, + // based on http://www.terathon.com/code/tangent.html + // (per vertex tangents) - // + if ( index === null || + attributes.position === undefined || + attributes.normal === undefined || + attributes.uv === undefined ) { - _usedTextureUnits = 0, + console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); + return; - // + } - _width = _canvas.width, - _height = _canvas.height, + const positionAttribute = attributes.position; + const normalAttribute = attributes.normal; + const uvAttribute = attributes.uv; - _pixelRatio = 1, + if ( this.hasAttribute( 'tangent' ) === false ) { - _viewport = new Vector4( 0, 0, _width, _height ), - _scissor = new Vector4( 0, 0, _width, _height ), - _scissorTest = false, + this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) ); - // frustum + } - _frustum = new Frustum(), + const tangentAttribute = this.getAttribute( 'tangent' ); - // clipping + const tan1 = [], tan2 = []; - _clipping = new WebGLClipping(), - _clippingEnabled = false, - _localClippingEnabled = false, + for ( let i = 0; i < positionAttribute.count; i ++ ) { - // camera matrices cache + tan1[ i ] = new Vector3(); + tan2[ i ] = new Vector3(); - _projScreenMatrix = new Matrix4(), + } - _vector3 = new Vector3(), + const vA = new Vector3(), + vB = new Vector3(), + vC = new Vector3(), - // info + uvA = new Vector2(), + uvB = new Vector2(), + uvC = new Vector2(), - _infoMemory = { - geometries: 0, - textures: 0 - }, + sdir = new Vector3(), + tdir = new Vector3(); - _infoRender = { + function handleTriangle( a, b, c ) { - frame: 0, - calls: 0, - vertices: 0, - faces: 0, - points: 0 + vA.fromBufferAttribute( positionAttribute, a ); + vB.fromBufferAttribute( positionAttribute, b ); + vC.fromBufferAttribute( positionAttribute, c ); - }; + uvA.fromBufferAttribute( uvAttribute, a ); + uvB.fromBufferAttribute( uvAttribute, b ); + uvC.fromBufferAttribute( uvAttribute, c ); - this.info = { + vB.sub( vA ); + vC.sub( vA ); - render: _infoRender, - memory: _infoMemory, - programs: null + uvB.sub( uvA ); + uvC.sub( uvA ); - }; + const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); - function getTargetPixelRatio() { + // silently ignore degenerate uv triangles having coincident or colinear vertices - return _currentRenderTarget === null ? _pixelRatio : 1; + 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 ); - // initialize + tan1[ a ].add( sdir ); + tan1[ b ].add( sdir ); + tan1[ c ].add( sdir ); - var _gl; + tan2[ a ].add( tdir ); + tan2[ b ].add( tdir ); + tan2[ c ].add( tdir ); - try { + } - var contextAttributes = { - alpha: _alpha, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference - }; + let groups = this.groups; - // event listeners must be registered before WebGL context is created, see #12753 + if ( groups.length === 0 ) { - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + groups = [ { + start: 0, + count: index.count + } ]; - _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes ); + } - if ( _gl === null ) { + for ( let i = 0, il = groups.length; i < il; ++ i ) { - if ( _canvas.getContext( 'webgl' ) !== null ) { + const group = groups[ i ]; - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + const start = group.start; + const count = group.count; - } else { + for ( let j = start, jl = start + count; j < jl; j += 3 ) { - throw new Error( 'Error creating WebGL context.' ); + handleTriangle( + index.getX( j + 0 ), + index.getX( j + 1 ), + index.getX( j + 2 ) + ); } } - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + const tmp = new Vector3(), tmp2 = new Vector3(); + const n = new Vector3(), n2 = new Vector3(); - if ( _gl.getShaderPrecisionFormat === undefined ) { + function handleVertex( v ) { - _gl.getShaderPrecisionFormat = function () { + n.fromBufferAttribute( normalAttribute, v ); + n2.copy( n ); - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + const t = tan1[ v ]; - }; + // Gram-Schmidt orthogonalize - } + tmp.copy( t ); + tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); - } catch ( error ) { + // Calculate handedness - console.error( 'THREE.WebGLRenderer: ' + error.message ); + tmp2.crossVectors( n2, t ); + const test = tmp2.dot( tan2[ v ] ); + const w = ( test < 0.0 ) ? - 1.0 : 1.0; - } + tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w ); - var extensions, capabilities, state; - var properties, textures, attributes, geometries, objects, lights; - var programCache, renderLists; + } - var background, morphtargets, bufferRenderer, indexedBufferRenderer; - var flareRenderer, spriteRenderer; + for ( let i = 0, il = groups.length; i < il; ++ i ) { - var utils; + const group = groups[ i ]; - function initGLContext() { + const start = group.start; + const count = group.count; - extensions = new WebGLExtensions( _gl ); - extensions.get( 'WEBGL_depth_texture' ); - extensions.get( 'OES_texture_float' ); - extensions.get( 'OES_texture_float_linear' ); - extensions.get( 'OES_texture_half_float' ); - extensions.get( 'OES_texture_half_float_linear' ); - extensions.get( 'OES_standard_derivatives' ); - extensions.get( 'OES_element_index_uint' ); - extensions.get( 'ANGLE_instanced_arrays' ); + for ( let j = start, jl = start + count; j < jl; j += 3 ) { - utils = new WebGLUtils( _gl, extensions ); + handleVertex( index.getX( j + 0 ) ); + handleVertex( index.getX( j + 1 ) ); + handleVertex( index.getX( j + 2 ) ); - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + } - state = new WebGLState( _gl, extensions, utils ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); + } - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory ); - attributes = new WebGLAttributes( _gl ); - geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); - objects = new WebGLObjects( geometries, _infoRender ); - morphtargets = new WebGLMorphtargets( _gl ); - programCache = new WebGLPrograms( _this, extensions, capabilities ); - lights = new WebGLLights(); - renderLists = new WebGLRenderLists(); + } - background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha ); + computeVertexNormals() { - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); + const index = this.index; + const positionAttribute = this.getAttribute( 'position' ); - flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities ); - spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); + if ( positionAttribute !== undefined ) { - _this.info.programs = programCache.programs; + let normalAttribute = this.getAttribute( 'normal' ); - _this.context = _gl; - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.state = state; + if ( normalAttribute === undefined ) { - } + normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); + this.setAttribute( 'normal', normalAttribute ); - initGLContext(); + } else { - // vr + // reset existing normals to zero - var vr = new WebVRManager( _this ); + for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { - this.vr = vr; + normalAttribute.setXYZ( i, 0, 0, 0 ); - // shadow map + } - var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); + } - this.shadowMap = shadowMap; + 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(); - // API + // indexed elements - this.getContext = function () { + if ( index ) { - return _gl; + for ( let i = 0, il = index.count; i < il; i += 3 ) { - }; + const vA = index.getX( i + 0 ); + const vB = index.getX( i + 1 ); + const vC = index.getX( i + 2 ); - this.getContextAttributes = function () { + pA.fromBufferAttribute( positionAttribute, vA ); + pB.fromBufferAttribute( positionAttribute, vB ); + pC.fromBufferAttribute( positionAttribute, vC ); - return _gl.getContextAttributes(); + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - }; + nA.fromBufferAttribute( normalAttribute, vA ); + nB.fromBufferAttribute( normalAttribute, vB ); + nC.fromBufferAttribute( normalAttribute, vC ); - this.forceContextLoss = function () { + nA.add( cb ); + nB.add( cb ); + nC.add( cb ); - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) { extension.loseContext(); } + 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 ); - }; + } - this.forceContextRestore = function () { + } else { - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) { extension.restoreContext(); } + // non-indexed elements (unconnected triangle soup) - }; + for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { - this.getPixelRatio = function () { + pA.fromBufferAttribute( positionAttribute, i + 0 ); + pB.fromBufferAttribute( positionAttribute, i + 1 ); + pC.fromBufferAttribute( positionAttribute, i + 2 ); - return _pixelRatio; + 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.setPixelRatio = function ( value ) { + } - if ( value === undefined ) { return; } + } - _pixelRatio = value; + this.normalizeNormals(); - this.setSize( _width, _height, false ); + normalAttribute.needsUpdate = true; - }; + } - this.getSize = function () { + } - return { - width: _width, - height: _height - }; + normalizeNormals() { - }; + const normals = this.attributes.normal; - this.setSize = function ( width, height, updateStyle ) { + for ( let i = 0, il = normals.count; i < il; i ++ ) { - var device = vr.getDevice(); + _vector$8.fromBufferAttribute( normals, i ); - if ( device && device.isPresenting ) { + _vector$8.normalize(); - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } - _width = width; - _height = height; + } - _canvas.width = width * _pixelRatio; - _canvas.height = height * _pixelRatio; + toNonIndexed() { - if ( updateStyle !== false ) { + function convertBufferAttribute( attribute, indices ) { - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + const array = attribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; - } + const array2 = new array.constructor( indices.length * itemSize ); - this.setViewport( 0, 0, width, height ); + let index = 0, index2 = 0; - }; + for ( let i = 0, l = indices.length; i < l; i ++ ) { - this.getDrawingBufferSize = function () { + if ( attribute.isInterleavedBufferAttribute ) { - return { - width: _width * _pixelRatio, - height: _height * _pixelRatio - }; + index = indices[ i ] * attribute.data.stride + attribute.offset; - }; + } else { - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + index = indices[ i ] * itemSize; - _width = width; - _height = height; + } - _pixelRatio = pixelRatio; + for ( let j = 0; j < itemSize; j ++ ) { - _canvas.width = width * pixelRatio; - _canvas.height = height * pixelRatio; + array2[ index2 ++ ] = array[ index ++ ]; - this.setViewport( 0, 0, width, height ); + } - }; + } - this.setViewport = function ( x, y, width, height ) { + return new BufferAttribute( array2, itemSize, normalized ); - _viewport.set( x, _height - y - height, width, height ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); + } - }; + // - this.setScissor = function ( x, y, width, height ) { + if ( this.index === null ) { - _scissor.set( x, _height - y - height, width, height ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); + console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); + return this; - }; + } - this.setScissorTest = function ( boolean ) { + const geometry2 = new BufferGeometry(); - state.setScissorTest( _scissorTest = boolean ); + const indices = this.index.array; + const attributes = this.attributes; - }; + // attributes - // Clearing + for ( const name in attributes ) { - this.getClearColor = function () { + const attribute = attributes[ name ]; - return background.getClearColor(); + const newAttribute = convertBufferAttribute( attribute, indices ); - }; + geometry2.setAttribute( name, newAttribute ); - this.setClearColor = function () { + } - background.setClearColor.apply( background, arguments ); + // morph attributes - }; + const morphAttributes = this.morphAttributes; - this.getClearAlpha = function () { + for ( const name in morphAttributes ) { - return background.getClearAlpha(); + const morphArray = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - }; + for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { - this.setClearAlpha = function () { + const attribute = morphAttribute[ i ]; - background.setClearAlpha.apply( background, arguments ); + const newAttribute = convertBufferAttribute( attribute, indices ); - }; + morphArray.push( newAttribute ); - this.clear = function ( color, depth, stencil ) { + } - var bits = 0; + geometry2.morphAttributes[ name ] = morphArray; - if ( color === undefined || color ) { bits |= _gl.COLOR_BUFFER_BIT; } - if ( depth === undefined || depth ) { bits |= _gl.DEPTH_BUFFER_BIT; } - if ( stencil === undefined || stencil ) { bits |= _gl.STENCIL_BUFFER_BIT; } + } - _gl.clear( bits ); + geometry2.morphTargetsRelative = this.morphTargetsRelative; - }; + // groups - this.clearColor = function () { + const groups = this.groups; - this.clear( true, false, false ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - }; + const group = groups[ i ]; + geometry2.addGroup( group.start, group.count, group.materialIndex ); - this.clearDepth = function () { + } - this.clear( false, true, false ); + return geometry2; - }; + } - this.clearStencil = function () { + toJSON() { - this.clear( false, false, true ); + const data = { + metadata: { + version: 4.6, + type: 'BufferGeometry', + generator: 'BufferGeometry.toJSON' + } + }; - }; + // standard BufferGeometry serialization + + 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; - this.clearTarget = function ( renderTarget, color, depth, stencil ) { + if ( this.parameters !== undefined ) { - this.setRenderTarget( renderTarget ); - this.clear( color, depth, stencil ); + const parameters = this.parameters; - }; + for ( const key in parameters ) { - // + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + + } + + return data; + + } + + // for simplicity the code assumes attributes are not shared across geometries, see #15811 + + data.data = { attributes: {} }; - this.dispose = function () { + const index = this.index; - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + if ( index !== null ) { - renderLists.dispose(); + data.data.index = { + type: index.array.constructor.name, + array: Array.prototype.slice.call( index.array ) + }; - vr.dispose(); + } - }; + const attributes = this.attributes; - // Events + for ( const key in attributes ) { - function onContextLost( event ) { + const attribute = attributes[ key ]; - event.preventDefault(); + data.data.attributes[ key ] = attribute.toJSON( data.data ); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + } - _isContextLost = true; + const morphAttributes = {}; + let hasMorphAttributes = false; - } + for ( const key in this.morphAttributes ) { - function onContextRestore( /* event */ ) { + const attributeArray = this.morphAttributes[ key ]; - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + const array = []; - _isContextLost = false; + for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { - initGLContext(); + const attribute = attributeArray[ i ]; - } + array.push( attribute.toJSON( data.data ) ); - function onMaterialDispose( event ) { + } - var material = event.target; + if ( array.length > 0 ) { - material.removeEventListener( 'dispose', onMaterialDispose ); + morphAttributes[ key ] = array; - deallocateMaterial( material ); + hasMorphAttributes = true; - } + } - // Buffer deallocation + } - function deallocateMaterial( material ) { + if ( hasMorphAttributes ) { - releaseMaterialProgramReference( material ); + data.data.morphAttributes = morphAttributes; + data.data.morphTargetsRelative = this.morphTargetsRelative; - properties.remove( material ); + } - } + const groups = this.groups; + if ( groups.length > 0 ) { - function releaseMaterialProgramReference( material ) { + data.data.groups = JSON.parse( JSON.stringify( groups ) ); - var programInfo = properties.get( material ).program; + } - material.program = undefined; + const boundingSphere = this.boundingSphere; - if ( programInfo !== undefined ) { + if ( boundingSphere !== null ) { - programCache.releaseProgram( programInfo ); + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; } + return data; + } - // Buffer rendering + clone() { - function renderObjectImmediate( object, program, material ) { + return new this.constructor().copy( this ); - object.render( function ( object ) { + } - _this.renderBufferImmediate( object, program, material ); + copy( source ) { - } ); + // reset - } + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; - this.renderBufferImmediate = function ( object, program, material ) { + // used for storing cloned, shared data - state.initAttributes(); + const data = {}; - var buffers = properties.get( object ); + // name - if ( object.hasPositions && ! buffers.position ) { buffers.position = _gl.createBuffer(); } - if ( object.hasNormals && ! buffers.normal ) { buffers.normal = _gl.createBuffer(); } - if ( object.hasUvs && ! buffers.uv ) { buffers.uv = _gl.createBuffer(); } - if ( object.hasColors && ! buffers.color ) { buffers.color = _gl.createBuffer(); } + this.name = source.name; - var programAttributes = program.getAttributes(); + // index - if ( object.hasPositions ) { + const index = source.index; - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); + if ( index !== null ) { - state.enableAttribute( programAttributes.position ); - _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 ); + this.setIndex( index.clone( data ) ); } - if ( object.hasNormals ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal ); + // attributes - if ( ! material.isMeshPhongMaterial && - ! material.isMeshStandardMaterial && - ! material.isMeshNormalMaterial && - material.flatShading === true ) { + const attributes = source.attributes; - for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { + for ( const name in attributes ) { - var array = object.normalArray; + const attribute = attributes[ name ]; + this.setAttribute( name, attribute.clone( data ) ); - var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3; - var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3; - var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3; + } - array[ i + 0 ] = nx; - array[ i + 1 ] = ny; - array[ i + 2 ] = nz; + // morph attributes - array[ i + 3 ] = nx; - array[ i + 4 ] = ny; - array[ i + 5 ] = nz; + const morphAttributes = source.morphAttributes; - array[ i + 6 ] = nx; - array[ i + 7 ] = ny; - array[ i + 8 ] = nz; + for ( const name in morphAttributes ) { - } + const array = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - } + for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { - _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); + array.push( morphAttribute[ i ].clone( data ) ); - state.enableAttribute( programAttributes.normal ); + } - _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 ); + this.morphAttributes[ name ] = array; } - if ( object.hasUvs && material.map ) { + this.morphTargetsRelative = source.morphTargetsRelative; + + // groups - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW ); + const groups = source.groups; - state.enableAttribute( programAttributes.uv ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); + const group = groups[ i ]; + this.addGroup( group.start, group.count, group.materialIndex ); } - if ( object.hasColors && material.vertexColors !== NoColors ) { + // bounding box - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW ); + const boundingBox = source.boundingBox; - state.enableAttribute( programAttributes.color ); + if ( boundingBox !== null ) { - _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 ); + this.boundingBox = boundingBox.clone(); } - state.disableUnusedAttributes(); - - _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); - - object.count = 0; + // bounding sphere - }; + const boundingSphere = source.boundingSphere; - this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { + if ( boundingSphere !== null ) { - var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + this.boundingSphere = boundingSphere.clone(); - state.setMaterial( material, frontFaceCW ); + } - var program = setProgram( camera, fog, material, object ); - var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true ); + // draw range - var updateBuffers = false; + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; - if ( geometryProgram !== _currentGeometryProgram ) { + // user data - _currentGeometryProgram = geometryProgram; - updateBuffers = true; + this.userData = source.userData; - } + return this; - if ( object.morphTargetInfluences ) { + } - morphtargets.update( object, geometry, material, program ); + dispose() { - updateBuffers = true; + this.dispatchEvent( { type: 'dispose' } ); - } + } - // +} - var index = geometry.index; - var position = geometry.attributes.position; - var rangeFactor = 1; +const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); +const _ray$3 = /*@__PURE__*/ new Ray(); +const _sphere$6 = /*@__PURE__*/ new Sphere(); +const _sphereHitAt = /*@__PURE__*/ new Vector3(); - if ( material.wireframe === true ) { +const _vA$1 = /*@__PURE__*/ new Vector3(); +const _vB$1 = /*@__PURE__*/ new Vector3(); +const _vC$1 = /*@__PURE__*/ new Vector3(); - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; +const _tempA = /*@__PURE__*/ new Vector3(); +const _morphA = /*@__PURE__*/ new Vector3(); - } +const _uvA$1 = /*@__PURE__*/ new Vector2(); +const _uvB$1 = /*@__PURE__*/ new Vector2(); +const _uvC$1 = /*@__PURE__*/ new Vector2(); - var attribute; - var renderer = bufferRenderer; +const _normalA = /*@__PURE__*/ new Vector3(); +const _normalB = /*@__PURE__*/ new Vector3(); +const _normalC = /*@__PURE__*/ new Vector3(); - if ( index !== null ) { +const _intersectionPoint = /*@__PURE__*/ new Vector3(); +const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); - attribute = attributes.get( index ); +class Mesh extends Object3D { - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { - } + super(); - if ( updateBuffers ) { + this.isMesh = true; - setupVertexAttributes( material, program, geometry ); + this.type = 'Mesh'; - if ( index !== null ) { + this.geometry = geometry; + this.material = material; - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); + this.updateMorphTargets(); - } + } - } + copy( source, recursive ) { - // + super.copy( source, recursive ); - var dataCount = 0; + if ( source.morphTargetInfluences !== undefined ) { - if ( index !== null ) { + this.morphTargetInfluences = source.morphTargetInfluences.slice(); - dataCount = index.count; + } - } else if ( position !== undefined ) { + if ( source.morphTargetDictionary !== undefined ) { - dataCount = position.count; + this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); } - var rangeStart = geometry.drawRange.start * rangeFactor; - var rangeCount = geometry.drawRange.count * rangeFactor; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - var groupStart = group !== null ? group.start * rangeFactor : 0; - var groupCount = group !== null ? group.count * rangeFactor : Infinity; - - var drawStart = Math.max( rangeStart, groupStart ); - var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1; + return this; - var drawCount = Math.max( 0, drawEnd - drawStart + 1 ); + } - if ( drawCount === 0 ) { return; } + updateMorphTargets() { - // + const geometry = this.geometry; - if ( object.isMesh ) { + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - if ( material.wireframe === true ) { + if ( keys.length > 0 ) { - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - } else { + if ( morphAttribute !== undefined ) { - switch ( object.drawMode ) { + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - case TrianglesDrawMode: - renderer.setMode( _gl.TRIANGLES ); - break; + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - case TriangleStripDrawMode: - renderer.setMode( _gl.TRIANGLE_STRIP ); - break; + const name = morphAttribute[ m ].name || String( m ); - case TriangleFanDrawMode: - renderer.setMode( _gl.TRIANGLE_FAN ); - break; + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; } } + } - } else if ( object.isLine ) { - - var lineWidth = material.linewidth; + } - if ( lineWidth === undefined ) { lineWidth = 1; } // Not using Line*Material + getVertexPosition( index, target ) { - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + const geometry = this.geometry; + const position = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; - if ( object.isLineSegments ) { + target.fromBufferAttribute( position, index ); - renderer.setMode( _gl.LINES ); + const morphInfluences = this.morphTargetInfluences; - } else if ( object.isLineLoop ) { + if ( morphPosition && morphInfluences ) { - renderer.setMode( _gl.LINE_LOOP ); + _morphA.set( 0, 0, 0 ); - } else { + for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { - renderer.setMode( _gl.LINE_STRIP ); + const influence = morphInfluences[ i ]; + const morphAttribute = morphPosition[ i ]; - } + if ( influence === 0 ) continue; - } else if ( object.isPoints ) { + _tempA.fromBufferAttribute( morphAttribute, index ); - renderer.setMode( _gl.POINTS ); + if ( morphTargetsRelative ) { - } + _morphA.addScaledVector( _tempA, influence ); - if ( geometry && geometry.isInstancedBufferGeometry ) { + } else { - if ( geometry.maxInstancedCount > 0 ) { + _morphA.addScaledVector( _tempA.sub( target ), influence ); - renderer.renderInstances( geometry, drawStart, drawCount ); + } } - } else { - - renderer.render( drawStart, drawCount ); + target.add( _morphA ); } - }; - - function setupVertexAttributes( material, program, geometry, startIndex ) { - - if ( geometry && geometry.isInstancedBufferGeometry ) { + return target; - if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { - - console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + } - } + raycast( raycaster, intersects ) { - } + const geometry = this.geometry; + const material = this.material; + const matrixWorld = this.matrixWorld; - if ( startIndex === undefined ) { startIndex = 0; } + if ( material === undefined ) return; - state.initAttributes(); + // test with bounding sphere in world space - var geometryAttributes = geometry.attributes; + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - var programAttributes = program.getAttributes(); + _sphere$6.copy( geometry.boundingSphere ); + _sphere$6.applyMatrix4( matrixWorld ); - var materialDefaultAttributeValues = material.defaultAttributeValues; + // check distance from ray origin to bounding sphere - for ( var name in programAttributes ) { + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); - var programAttribute = programAttributes[ name ]; + if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { - if ( programAttribute >= 0 ) { + if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; - var geometryAttribute = geometryAttributes[ name ]; + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; - if ( geometryAttribute !== undefined ) { + } - var normalized = geometryAttribute.normalized; - var size = geometryAttribute.itemSize; + // convert ray to local space of mesh - var attribute = attributes.get( geometryAttribute ); + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); - // TODO Attribute may not be available on context restore + // test with bounding box in local space - if ( attribute === undefined ) { continue; } + if ( geometry.boundingBox !== null ) { - var buffer = attribute.buffer; - var type = attribute.type; - var bytesPerElement = attribute.bytesPerElement; + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; - if ( geometryAttribute.isInterleavedBufferAttribute ) { + } - var data = geometryAttribute.data; - var stride = data.stride; - var offset = geometryAttribute.offset; + // test for intersections with geometry - if ( data && data.isInstancedInterleavedBuffer ) { + this._computeIntersections( raycaster, intersects, _ray$3 ); - state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute ); + } - if ( geometry.maxInstancedCount === undefined ) { + _computeIntersections( raycaster, intersects, rayLocalSpace ) { - geometry.maxInstancedCount = data.meshPerAttribute * data.count; + let intersection; - } + const geometry = this.geometry; + const material = this.material; - } else { + const index = geometry.index; + const position = geometry.attributes.position; + const uv = geometry.attributes.uv; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; + const groups = geometry.groups; + const drawRange = geometry.drawRange; - state.enableAttribute( programAttribute ); + if ( index !== null ) { - } + // indexed buffer geometry - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, ( startIndex * stride + offset ) * bytesPerElement ); + if ( Array.isArray( material ) ) { - } else { + for ( let i = 0, il = groups.length; i < il; i ++ ) { - if ( geometryAttribute.isInstancedBufferAttribute ) { + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute ); + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); - if ( geometry.maxInstancedCount === undefined ) { + for ( let j = start, jl = end; j < jl; j += 3 ) { - geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; + const a = index.getX( j ); + const b = index.getX( j + 1 ); + const c = index.getX( j + 2 ); - } + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - } else { + if ( intersection ) { - state.enableAttribute( programAttribute ); + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); } - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * bytesPerElement ); - } - } else if ( materialDefaultAttributeValues !== undefined ) { - - var value = materialDefaultAttributeValues[ name ]; + } - if ( value !== undefined ) { + } else { - switch ( value.length ) { + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - case 2: - _gl.vertexAttrib2fv( programAttribute, value ); - break; + for ( let i = start, il = end; i < il; i += 3 ) { - case 3: - _gl.vertexAttrib3fv( programAttribute, value ); - break; + const a = index.getX( i ); + const b = index.getX( i + 1 ); + const c = index.getX( i + 2 ); - case 4: - _gl.vertexAttrib4fv( programAttribute, value ); - break; + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - default: - _gl.vertexAttrib1fv( programAttribute, value ); + if ( intersection ) { - } + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics + intersects.push( intersection ); } @@ -22168,29717 +11366,30820 @@ function WebGLRenderer( parameters ) { } - } - - state.disableUnusedAttributes(); + } else if ( position !== undefined ) { - } + // non-indexed buffer geometry - // Compile + if ( Array.isArray( material ) ) { - this.compile = function ( scene, camera ) { + for ( let i = 0, il = groups.length; i < il; i ++ ) { - lightsArray.length = 0; - shadowsArray.length = 0; + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - scene.traverse( function ( object ) { + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); - if ( object.isLight ) { + for ( let j = start, jl = end; j < jl; j += 3 ) { - lightsArray.push( object ); + const a = j; + const b = j + 1; + const c = j + 2; - if ( object.castShadow ) { + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - shadowsArray.push( object ); + if ( intersection ) { - } + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); - } + } - } ); + } - lights.setup( lightsArray, shadowsArray, camera ); + } - scene.traverse( function ( object ) { + } else { - if ( object.material ) { + const start = Math.max( 0, drawRange.start ); + const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); - if ( Array.isArray( object.material ) ) { + for ( let i = start, il = end; i < il; i += 3 ) { - for ( var i = 0; i < object.material.length; i ++ ) { + const a = i; + const b = i + 1; + const c = i + 2; - initMaterial( object.material[ i ], scene.fog, object ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - } + if ( intersection ) { - } else { + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics + intersects.push( intersection ); - initMaterial( object.material, scene.fog, object ); + } } } - } ); - - }; - - // Animation Loop - - var isAnimating = false; - var onAnimationFrame = null; - - function start() { + } - if ( isAnimating ) { return; } + } - var device = vr.getDevice(); +} - if ( device && device.isPresenting ) { +function checkIntersection$1( object, material, raycaster, ray, pA, pB, pC, point ) { - device.requestAnimationFrame( loop ); + let intersect; - } else { + if ( material.side === BackSide ) { - window.requestAnimationFrame( loop ); + intersect = ray.intersectTriangle( pC, pB, pA, true, point ); - } + } else { - isAnimating = true; + intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); } - function loop( time ) { + if ( intersect === null ) return null; - if ( onAnimationFrame !== null ) { onAnimationFrame( time ); } + _intersectionPointWorld.copy( point ); + _intersectionPointWorld.applyMatrix4( object.matrixWorld ); - var device = vr.getDevice(); + const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); - if ( device && device.isPresenting ) { + if ( distance < raycaster.near || distance > raycaster.far ) return null; - device.requestAnimationFrame( loop ); + return { + distance: distance, + point: _intersectionPointWorld.clone(), + object: object + }; - } else { +} - window.requestAnimationFrame( loop ); +function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { - } + object.getVertexPosition( a, _vA$1 ); + object.getVertexPosition( b, _vB$1 ); + object.getVertexPosition( c, _vC$1 ); - } + const intersection = checkIntersection$1( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); - this.animate = function ( callback ) { + if ( intersection ) { - onAnimationFrame = callback; - start(); + if ( uv ) { - }; + _uvA$1.fromBufferAttribute( uv, a ); + _uvB$1.fromBufferAttribute( uv, b ); + _uvC$1.fromBufferAttribute( uv, c ); - // Rendering + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); - this.render = function ( scene, camera, renderTarget, forceClear ) { + } - if ( ! ( camera && camera.isCamera ) ) { + if ( uv1 ) { - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + _uvA$1.fromBufferAttribute( uv1, a ); + _uvB$1.fromBufferAttribute( uv1, b ); + _uvC$1.fromBufferAttribute( uv1, c ); - } + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); - if ( _isContextLost ) { return; } + } - // reset caching for this frame + if ( normal ) { - _currentGeometryProgram = ''; - _currentMaterialId = - 1; - _currentCamera = null; + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); - // update scene graph + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); - if ( scene.autoUpdate === true ) { scene.updateMatrixWorld(); } + if ( intersection.normal.dot( ray.direction ) > 0 ) { - // update camera matrices and frustum + intersection.normal.multiplyScalar( - 1 ); - if ( camera.parent === null ) { camera.updateMatrixWorld(); } + } - if ( vr.enabled ) { + } - camera = vr.getCamera( camera ); + const face = { + a: a, + b: b, + c: c, + normal: new Vector3(), + materialIndex: 0 + }; - } + Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); + intersection.face = face; - lightsArray.length = 0; - shadowsArray.length = 0; + } - spritesArray.length = 0; - flaresArray.length = 0; + return intersection; - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); +} - currentRenderList = renderLists.get( scene, camera ); - currentRenderList.init(); +class BoxGeometry extends BufferGeometry { - projectObject( scene, camera, _this.sortObjects ); + constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { - if ( _this.sortObjects === true ) { + super(); - currentRenderList.sort(); + this.type = 'BoxGeometry'; - } + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - // + const scope = this; - textures.updateVideoTextures(); + // segments - // + widthSegments = Math.floor( widthSegments ); + heightSegments = Math.floor( heightSegments ); + depthSegments = Math.floor( depthSegments ); - if ( _clippingEnabled ) { _clipping.beginShadows(); } + // buffers - shadowMap.render( shadowsArray, scene, camera ); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - lights.setup( lightsArray, shadowsArray, camera ); + // helper variables - if ( _clippingEnabled ) { _clipping.endShadows(); } + let numberOfVertices = 0; + let groupStart = 0; - // + // build each side of the box geometry - _infoRender.frame ++; - _infoRender.calls = 0; - _infoRender.vertices = 0; - _infoRender.faces = 0; - _infoRender.points = 0; + buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px + buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx + buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py + buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny + buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz + buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz - if ( renderTarget === undefined ) { + // build geometry - renderTarget = null; + 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, width, height, depth, gridX, gridY, materialIndex ) { - this.setRenderTarget( renderTarget ); + const segmentWidth = width / gridX; + const segmentHeight = height / gridY; - // + const widthHalf = width / 2; + const heightHalf = height / 2; + const depthHalf = depth / 2; - background.render( currentRenderList, scene, camera, forceClear ); + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; - // render scene + let vertexCounter = 0; + let groupCount = 0; - var opaqueObjects = currentRenderList.opaque; - var transparentObjects = currentRenderList.transparent; + const vector = new Vector3(); - if ( scene.overrideMaterial ) { + // generate vertices, normals and uvs - var overrideMaterial = scene.overrideMaterial; + for ( let iy = 0; iy < gridY1; iy ++ ) { - if ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera, overrideMaterial ); } - if ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera, overrideMaterial ); } + const y = iy * segmentHeight - heightHalf; - } else { + for ( let ix = 0; ix < gridX1; ix ++ ) { - // opaque pass (front-to-back order) + const x = ix * segmentWidth - widthHalf; - if ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera ); } + // set values to correct vector component - // transparent pass (back-to-front order) + vector[ u ] = x * udir; + vector[ v ] = y * vdir; + vector[ w ] = depthHalf; - if ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera ); } + // now apply vector to vertex buffer - } + vertices.push( vector.x, vector.y, vector.z ); - // custom renderers + // set values to correct vector component - spriteRenderer.render( spritesArray, scene, camera ); - flareRenderer.render( flaresArray, scene, camera, _currentViewport ); + vector[ u ] = 0; + vector[ v ] = 0; + vector[ w ] = depth > 0 ? 1 : - 1; - // Generate mipmap if we're using any kind of mipmap filtering + // now apply vector to normal buffer - if ( renderTarget ) { + normals.push( vector.x, vector.y, vector.z ); - textures.updateRenderTargetMipmap( renderTarget ); + // uvs - } + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - // Ensure depth buffer writing is enabled so it can be cleared on next render + // counters - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + vertexCounter += 1; - state.setPolygonOffset( false ); + } - if ( vr.enabled ) { + } - vr.submitFrame(); + // indices - } + // 1. you need three indices to draw a single face + // 2. a single segment consists of two faces + // 3. so we need to generate six (2*3) indices per segment - // _gl.finish(); + for ( let iy = 0; iy < gridY; iy ++ ) { - }; + for ( let ix = 0; ix < gridX; ix ++ ) { - /* - // TODO Duplicated code (Frustum) + const a = numberOfVertices + ix + gridX1 * iy; + const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); + const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; - var _sphere = new Sphere(); + // faces - function isObjectViewable( object ) { + indices.push( a, b, d ); + indices.push( b, c, d ); - var geometry = object.geometry; + // increase counter - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); + groupCount += 6; - _sphere.copy( geometry.boundingSphere ). - applyMatrix4( object.matrixWorld ); + } - return isSphereViewable( _sphere ); + } - } + // add a group to the geometry. this will ensure multi material support - function isSpriteViewable( sprite ) { + scope.addGroup( groupStart, groupCount, materialIndex ); - _sphere.center.set( 0, 0, 0 ); - _sphere.radius = 0.7071067811865476; - _sphere.applyMatrix4( sprite.matrixWorld ); + // calculate new start value for groups - return isSphereViewable( _sphere ); + groupStart += groupCount; - } + // update total number of vertices - function isSphereViewable( sphere ) { + numberOfVertices += vertexCounter; - if ( ! _frustum.intersectsSphere( sphere ) ) return false; + } - var numPlanes = _clipping.numPlanes; + } - if ( numPlanes === 0 ) return true; + copy( source ) { - var planes = _this.clippingPlanes, + super.copy( source ); - center = sphere.center, - negRad = - sphere.radius, - i = 0; + this.parameters = Object.assign( {}, source.parameters ); - do { + return this; - // out when deeper than radius in the negative halfspace - if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; + } - } while ( ++ i !== numPlanes ); + static fromJSON( data ) { - return true; + return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); } - */ - function projectObject( object, camera, sortObjects ) { +} - if ( object.visible === false ) { return; } +/** + * Uniform Utilities + */ - var visible = object.layers.test( camera.layers ); +function cloneUniforms( src ) { - if ( visible ) { + const dst = {}; - if ( object.isLight ) { + for ( const u in src ) { - lightsArray.push( object ); + dst[ u ] = {}; - if ( object.castShadow ) { + for ( const p in src[ u ] ) { - shadowsArray.push( object ); + const property = src[ u ][ p ]; - } + if ( property && ( property.isColor || + property.isMatrix3 || property.isMatrix4 || + property.isVector2 || property.isVector3 || property.isVector4 || + property.isTexture || property.isQuaternion ) ) { - } else if ( object.isSprite ) { + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + } else { - spritesArray.push( object ); + dst[ u ][ p ] = property.clone(); } - } else if ( object.isLensFlare ) { - - flaresArray.push( object ); + } else if ( Array.isArray( property ) ) { - } else if ( object.isImmediateRenderObject ) { + dst[ u ][ p ] = property.slice(); - if ( sortObjects ) { + } else { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + dst[ u ][ p ] = property; - } + } - currentRenderList.push( object, null, object.material, _vector3.z, null ); + } - } else if ( object.isMesh || object.isLine || object.isPoints ) { + } - if ( object.isSkinnedMesh ) { + return dst; - object.skeleton.update(); +} - } +function mergeUniforms( uniforms ) { - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + const merged = {}; - if ( sortObjects ) { + for ( let u = 0; u < uniforms.length; u ++ ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + const tmp = cloneUniforms( uniforms[ u ] ); - } + for ( const p in tmp ) { - var geometry = objects.update( object ); - var material = object.material; + merged[ p ] = tmp[ p ]; - if ( Array.isArray( material ) ) { + } - var groups = geometry.groups; + } - for ( var i = 0, l = groups.length; i < l; i ++ ) { + return merged; - var group = groups[ i ]; - var groupMaterial = material[ group.materialIndex ]; +} - if ( groupMaterial && groupMaterial.visible ) { +function cloneUniformsGroups( src ) { - currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group ); + const dst = []; - } + for ( let u = 0; u < src.length; u ++ ) { - } + dst.push( src[ u ].clone() ); - } else if ( material.visible ) { + } - currentRenderList.push( object, geometry, material, _vector3.z, null ); + return dst; - } +} - } +function getUnlitUniformColorSpace( renderer ) { - } + const currentRenderTarget = renderer.getRenderTarget(); - } + if ( currentRenderTarget === null ) { - var children = object.children; + // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 + return renderer.outputColorSpace; - for ( var i = 0, l = children.length; i < l; i ++ ) { + } - projectObject( children[ i ], camera, sortObjects ); + // https://github.com/mrdoob/three.js/issues/27868 + if ( currentRenderTarget.isXRRenderTarget === true ) { - } + return currentRenderTarget.texture.colorSpace; } - function renderObjects( renderList, scene, camera, overrideMaterial ) { + return ColorManagement.workingColorSpace; - for ( var i = 0, l = renderList.length; i < l; i ++ ) { +} - var renderItem = renderList[ i ]; +// Legacy - var object = renderItem.object; - var geometry = renderItem.geometry; - var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; - var group = renderItem.group; +const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; - if ( camera.isArrayCamera ) { +var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; - _currentArrayCamera = camera; +var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; - var cameras = camera.cameras; +class ShaderMaterial extends Material { - for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { + constructor( parameters ) { - var camera2 = cameras[ j ]; + super(); - if ( object.layers.test( camera2.layers ) ) { + this.isShaderMaterial = true; - var bounds = camera2.bounds; + this.type = 'ShaderMaterial'; - var x = bounds.x * _width; - var y = bounds.y * _height; - var width = bounds.z * _width; - var height = bounds.w * _height; + this.defines = {}; + this.uniforms = {}; + this.uniformsGroups = []; - state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; - renderObject( object, scene, camera2, geometry, material, group ); + this.linewidth = 1; - } + this.wireframe = false; + this.wireframeLinewidth = 1; - } + this.fog = false; // set to use scene fog + this.lights = false; // set to use scene lights + this.clipping = false; // set to use user-defined clipping planes - } else { + this.forceSinglePass = true; - _currentArrayCamera = null; + this.extensions = { + clipCullDistance: false, // set to use vertex shader clipping + multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID + }; - renderObject( object, scene, camera, geometry, material, group ); + // When rendered geometry doesn't include these attributes but the material does, + // use these default values in WebGL. This avoids errors when buffer data is missing. + this.defaultAttributeValues = { + 'color': [ 1, 1, 1 ], + 'uv': [ 0, 0 ], + 'uv1': [ 0, 0 ] + }; - } + this.index0AttributeName = undefined; + this.uniformsNeedUpdate = false; - } + this.glslVersion = null; - } + if ( parameters !== undefined ) { - function renderObject( object, scene, camera, geometry, material, group ) { + this.setValues( parameters ); - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + } - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + } - if ( object.isImmediateRenderObject ) { + copy( source ) { - var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + super.copy( source ); - state.setMaterial( material, frontFaceCW ); + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; - var program = setProgram( camera, scene.fog, material, object ); + this.uniforms = cloneUniforms( source.uniforms ); + this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); - _currentGeometryProgram = ''; + this.defines = Object.assign( {}, source.defines ); - renderObjectImmediate( object, program, material ); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; - } else { + this.fog = source.fog; + this.lights = source.lights; + this.clipping = source.clipping; - _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group ); + this.extensions = Object.assign( {}, source.extensions ); - } + this.glslVersion = source.glslVersion; - object.onAfterRender( _this, scene, camera, geometry, material, group ); + return this; } - function initMaterial( material, fog, object ) { + toJSON( meta ) { - var materialProperties = properties.get( material ); + const data = super.toJSON( meta ); - var parameters = programCache.getParameters( - material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); + data.glslVersion = this.glslVersion; + data.uniforms = {}; - var code = programCache.getProgramCode( material, parameters ); + for ( const name in this.uniforms ) { - var program = materialProperties.program; - var programChange = true; + const uniform = this.uniforms[ name ]; + const value = uniform.value; - if ( program === undefined ) { + if ( value && value.isTexture ) { - // new material - material.addEventListener( 'dispose', onMaterialDispose ); + data.uniforms[ name ] = { + type: 't', + value: value.toJSON( meta ).uuid + }; - } else if ( program.code !== code ) { + } else if ( value && value.isColor ) { - // changed glsl or parameters - releaseMaterialProgramReference( material ); + data.uniforms[ name ] = { + type: 'c', + value: value.getHex() + }; - } else if ( parameters.shaderID !== undefined ) { + } else if ( value && value.isVector2 ) { - // same glsl and uniform list - return; + data.uniforms[ name ] = { + type: 'v2', + value: value.toArray() + }; - } else { + } else if ( value && value.isVector3 ) { - // only rebuild uniform list - programChange = false; + data.uniforms[ name ] = { + type: 'v3', + value: value.toArray() + }; - } + } else if ( value && value.isVector4 ) { - if ( programChange ) { + data.uniforms[ name ] = { + type: 'v4', + value: value.toArray() + }; + + } else if ( value && value.isMatrix3 ) { - if ( parameters.shaderID ) { + data.uniforms[ name ] = { + type: 'm3', + value: value.toArray() + }; - var shader = ShaderLib[ parameters.shaderID ]; + } else if ( value && value.isMatrix4 ) { - materialProperties.shader = { - name: material.type, - uniforms: UniformsUtils.clone( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + data.uniforms[ name ] = { + type: 'm4', + value: value.toArray() }; } else { - materialProperties.shader = { - name: material.type, - uniforms: material.uniforms, - vertexShader: material.vertexShader, - fragmentShader: material.fragmentShader + data.uniforms[ name ] = { + value: value }; - } + // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far - material.onBeforeCompile( materialProperties.shader ); + } - program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); + } - materialProperties.program = program; - material.program = program; + if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; - } + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; - var programAttributes = program.getAttributes(); + data.lights = this.lights; + data.clipping = this.clipping; - if ( material.morphTargets ) { + const extensions = {}; - material.numSupportedMorphTargets = 0; + for ( const key in this.extensions ) { - for ( var i = 0; i < _this.maxMorphTargets; i ++ ) { + if ( this.extensions[ key ] === true ) extensions[ key ] = true; - if ( programAttributes[ 'morphTarget' + i ] >= 0 ) { + } - material.numSupportedMorphTargets ++; + if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; - } + return data; - } + } - } +} - if ( material.morphNormals ) { +class Camera extends Object3D { - material.numSupportedMorphNormals = 0; + constructor() { - for ( var i = 0; i < _this.maxMorphNormals; i ++ ) { + super(); - if ( programAttributes[ 'morphNormal' + i ] >= 0 ) { + this.isCamera = true; - material.numSupportedMorphNormals ++; + this.type = 'Camera'; - } + this.matrixWorldInverse = new Matrix4(); - } + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); - } + this.coordinateSystem = WebGLCoordinateSystem; - var uniforms = materialProperties.shader.uniforms; + } - if ( ! material.isShaderMaterial && - ! material.isRawShaderMaterial || - material.clipping === true ) { + copy( source, recursive ) { - materialProperties.numClippingPlanes = _clipping.numPlanes; - materialProperties.numIntersection = _clipping.numIntersection; - uniforms.clippingPlanes = _clipping.uniform; + super.copy( source, recursive ); - } + this.matrixWorldInverse.copy( source.matrixWorldInverse ); - materialProperties.fog = fog; + this.projectionMatrix.copy( source.projectionMatrix ); + this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); - // store the light setup it was created for + this.coordinateSystem = source.coordinateSystem; - materialProperties.lightsHash = lights.state.hash; + return this; - if ( material.lights ) { + } - // wire up the material to this renderer's lighting state + getWorldDirection( target ) { - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.directionalLights.value = lights.state.directional; - uniforms.spotLights.value = lights.state.spot; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.pointLights.value = lights.state.point; - uniforms.hemisphereLights.value = lights.state.hemi; + return super.getWorldDirection( target ).negate(); - 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; - // TODO (abelnation): add area lights shadow info to uniforms + } - } + updateMatrixWorld( force ) { - var progUniforms = materialProperties.program.getUniforms(), - uniformsList = - WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + super.updateMatrixWorld( force ); - materialProperties.uniformsList = uniformsList; + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); } - function setProgram( camera, fog, material, object ) { + updateWorldMatrix( updateParents, updateChildren ) { + + super.updateWorldMatrix( updateParents, updateChildren ); - _usedTextureUnits = 0; + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); - var materialProperties = properties.get( material ); + } - if ( _clippingEnabled ) { + clone() { - if ( _localClippingEnabled || camera !== _currentCamera ) { + return new this.constructor().copy( this ); - var useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + } - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - _clipping.setState( - material.clippingPlanes, material.clipIntersection, material.clipShadows, - camera, materialProperties, useCache ); +} - } +const _v3$1 = /*@__PURE__*/ new Vector3(); +const _minTarget = /*@__PURE__*/ new Vector2(); +const _maxTarget = /*@__PURE__*/ new Vector2(); - } - if ( material.needsUpdate === false ) { +class PerspectiveCamera extends Camera { - if ( materialProperties.program === undefined ) { + constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { - material.needsUpdate = true; + super(); - } else if ( material.fog && materialProperties.fog !== fog ) { + this.isPerspectiveCamera = true; - material.needsUpdate = true; + this.type = 'PerspectiveCamera'; - } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { + this.fov = fov; + this.zoom = 1; - material.needsUpdate = true; + this.near = near; + this.far = far; + this.focus = 10; - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== _clipping.numPlanes || - materialProperties.numIntersection !== _clipping.numIntersection ) ) { + this.aspect = aspect; + this.view = null; - material.needsUpdate = true; + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - } + this.updateProjectionMatrix(); - } + } - if ( material.needsUpdate ) { + copy( source, recursive ) { - initMaterial( material, fog, object ); - material.needsUpdate = false; + super.copy( source, recursive ); - } + this.fov = source.fov; + this.zoom = source.zoom; - var refreshProgram = false; - var refreshMaterial = false; - var refreshLights = false; + this.near = source.near; + this.far = source.far; + this.focus = source.focus; - var program = materialProperties.program, - p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.shader.uniforms; + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - if ( state.useProgram( program.program ) ) { + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + return this; - } + } - if ( material.id !== _currentMaterialId ) { + /** + * Sets the FOV by focal length in respect to the current .filmGauge. + * + * The default film gauge is 35, so that the focal length can be specified for + * a 35mm (full frame) camera. + * + * Values for focal length and film gauge must have the same unit. + */ + setFocalLength( focalLength ) { - _currentMaterialId = material.id; + /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ + const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - refreshMaterial = true; + this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.updateProjectionMatrix(); - } + } - if ( refreshProgram || camera !== _currentCamera ) { + /** + * Calculates the focal length from the current .fov and .filmGauge. + */ + getFocalLength() { - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); - if ( capabilities.logarithmicDepthBuffer ) { + return 0.5 * this.getFilmHeight() / vExtentSlope; - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } - } + getEffectiveFOV() { - // Avoid unneeded uniform updates per ArrayCamera's sub-camera + return RAD2DEG * 2 * Math.atan( + Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); - if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { + } - _currentCamera = ( _currentArrayCamera || camera ); + getFilmWidth() { - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + // film not completely covered in portrait format (aspect < 1) + return this.filmGauge * Math.min( this.aspect, 1 ); - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + } - } + getFilmHeight() { - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + // film not completely covered in landscape format (aspect > 1) + return this.filmGauge / Math.max( this.aspect, 1 ); - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + } - var uCamPos = p_uniforms.map.cameraPosition; + /** + * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction. + * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle. + */ + getViewBounds( distance, minTarget, maxTarget ) { - if ( uCamPos !== undefined ) { + _v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); - } + _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); - } + maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); - if ( material.isMeshPhongMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.skinning ) { + } - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + /** + * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction. + * Copies the result into the target Vector2, where x is width and y is height. + */ + getViewSize( distance, target ) { - } + this.getViewBounds( distance, _minTarget, _maxTarget ); - } + return target.subVectors( _maxTarget, _minTarget ); - // skinning uniforms must be set even if material didn't change - // auto-setting of texture unit for bone texture must go before other textures - // not sure why, but otherwise weird things happen + } - if ( material.skinning ) { + /** + * Sets an offset in a larger frustum. This is useful for multi-window or + * multi-monitor/multi-machine setups. + * + * For example, if you have 3x2 monitors and each monitor is 1920x1080 and + * the monitors are in grid like this + * + * +---+---+---+ + * | A | B | C | + * +---+---+---+ + * | D | E | F | + * +---+---+---+ + * + * then for each monitor you would call it like this + * + * const w = 1920; + * const h = 1080; + * const fullWidth = w * 3; + * const fullHeight = h * 2; + * + * --A-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); + * --B-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); + * --C-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); + * --D-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); + * --E-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); + * --F-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); + * + * Note there is no reason monitors have to be the same size or in a grid. + */ + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + this.aspect = fullWidth / fullHeight; - var skeleton = object.skeleton; + if ( this.view === null ) { - if ( skeleton ) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - var bones = skeleton.bones; + } - if ( capabilities.floatVertexTextures ) { + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - if ( skeleton.boneTexture === undefined ) { + this.updateProjectionMatrix(); - // layout (1 matrix = 4 pixels) - // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) - // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) - // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) - // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) - // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) + } + clearViewOffset() { - var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix - size = _Math.ceilPowerOfTwo( size ); - size = Math.max( size, 4 ); + if ( this.view !== null ) { - var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel - boneMatrices.set( skeleton.boneMatrices ); // copy current values + this.view.enabled = false; - var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + } - skeleton.boneMatrices = boneMatrices; - skeleton.boneTexture = boneTexture; - skeleton.boneTextureSize = size; + this.updateProjectionMatrix(); - } + } - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + updateProjectionMatrix() { - } else { + 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; - p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' ); + 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; } - if ( refreshMaterial ) { + const skew = this.filmOffset; + if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); + this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); - if ( material.lights ) { + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - // the current material requires lighting info + } - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + toJSON( meta ) { - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); + const data = super.toJSON( meta ); - } + data.object.fov = this.fov; + data.object.zoom = this.zoom; - // refresh uniforms common to several materials + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; - if ( fog && material.fog ) { + data.object.aspect = this.aspect; - refreshUniformsFog( m_uniforms, fog ); + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - } + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; - if ( material.isMeshBasicMaterial ) { + return data; - refreshUniformsCommon( m_uniforms, material ); + } - } else if ( material.isMeshLambertMaterial ) { +} - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsLambert( m_uniforms, material ); +const fov = - 90; // negative fov is not an error +const aspect = 1; - } else if ( material.isMeshPhongMaterial ) { +class CubeCamera extends Object3D { - refreshUniformsCommon( m_uniforms, material ); + constructor( near, far, renderTarget ) { - if ( material.isMeshToonMaterial ) { + super(); - refreshUniformsToon( m_uniforms, material ); + this.type = 'CubeCamera'; - } else { + this.renderTarget = renderTarget; + this.coordinateSystem = null; + this.activeMipmapLevel = 0; - refreshUniformsPhong( m_uniforms, material ); + const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); + cameraPX.layers = this.layers; + this.add( cameraPX ); - } + const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); + cameraNX.layers = this.layers; + this.add( cameraNX ); - } else if ( material.isMeshStandardMaterial ) { + const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); + cameraPY.layers = this.layers; + this.add( cameraPY ); - refreshUniformsCommon( m_uniforms, material ); + const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); + cameraNY.layers = this.layers; + this.add( cameraNY ); - if ( material.isMeshPhysicalMaterial ) { + const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraPZ.layers = this.layers; + this.add( cameraPZ ); - refreshUniformsPhysical( m_uniforms, material ); + const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraNZ.layers = this.layers; + this.add( cameraNZ ); - } else { + } - refreshUniformsStandard( m_uniforms, material ); + updateCoordinateSystem() { - } + const coordinateSystem = this.coordinateSystem; - } else if ( material.isMeshDepthMaterial ) { + const cameras = this.children.concat(); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDepth( m_uniforms, material ); + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; - } else if ( material.isMeshDistanceMaterial ) { + for ( const camera of cameras ) this.remove( camera ); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDistance( m_uniforms, material ); + if ( coordinateSystem === WebGLCoordinateSystem ) { - } else if ( material.isMeshNormalMaterial ) { + cameraPX.up.set( 0, 1, 0 ); + cameraPX.lookAt( 1, 0, 0 ); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsNormal( m_uniforms, material ); + cameraNX.up.set( 0, 1, 0 ); + cameraNX.lookAt( - 1, 0, 0 ); - } else if ( material.isLineBasicMaterial ) { + cameraPY.up.set( 0, 0, - 1 ); + cameraPY.lookAt( 0, 1, 0 ); - refreshUniformsLine( m_uniforms, material ); + cameraNY.up.set( 0, 0, 1 ); + cameraNY.lookAt( 0, - 1, 0 ); - if ( material.isLineDashedMaterial ) { + cameraPZ.up.set( 0, 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); - refreshUniformsDash( m_uniforms, material ); + cameraNZ.up.set( 0, 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); - } + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - } else if ( material.isPointsMaterial ) { + cameraPX.up.set( 0, - 1, 0 ); + cameraPX.lookAt( - 1, 0, 0 ); - refreshUniformsPoints( m_uniforms, material ); + cameraNX.up.set( 0, - 1, 0 ); + cameraNX.lookAt( 1, 0, 0 ); - } else if ( material.isShadowMaterial ) { + cameraPY.up.set( 0, 0, 1 ); + cameraPY.lookAt( 0, 1, 0 ); - m_uniforms.color.value = material.color; - m_uniforms.opacity.value = material.opacity; + cameraNY.up.set( 0, 0, - 1 ); + cameraNY.lookAt( 0, - 1, 0 ); - } + cameraPZ.up.set( 0, - 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); - // RectAreaLight Texture - // TODO (mrdoob): Find a nicer implementation + cameraNZ.up.set( 0, - 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); - if ( m_uniforms.ltcMat !== undefined ) { m_uniforms.ltcMat.value = UniformsLib.LTC_MAT_TEXTURE; } - if ( m_uniforms.ltcMag !== undefined ) { m_uniforms.ltcMag.value = UniformsLib.LTC_MAG_TEXTURE; } + } else { - WebGLUniforms.upload( - _gl, materialProperties.uniformsList, m_uniforms, _this ); + throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); } + for ( const camera of cameras ) { - // common matrices + this.add( camera ); - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + camera.updateMatrixWorld(); - return program; + } } - // Uniforms (refresh uniforms objects) + update( renderer, scene ) { - function refreshUniformsCommon( uniforms, material ) { + if ( this.parent === null ) this.updateMatrixWorld(); - uniforms.opacity.value = material.opacity; + const { renderTarget, activeMipmapLevel } = this; - if ( material.color ) { + if ( this.coordinateSystem !== renderer.coordinateSystem ) { + + this.coordinateSystem = renderer.coordinateSystem; - uniforms.diffuse.value = material.color; + this.updateCoordinateSystem(); } - if ( material.emissive ) { + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; - uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); + const currentRenderTarget = renderer.getRenderTarget(); + const currentActiveCubeFace = renderer.getActiveCubeFace(); + const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); - } + const currentXrEnabled = renderer.xr.enabled; - if ( material.map ) { + renderer.xr.enabled = false; - uniforms.map.value = material.map; + const generateMipmaps = renderTarget.texture.generateMipmaps; - } + renderTarget.texture.generateMipmaps = false; - if ( material.alphaMap ) { + renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); + renderer.render( scene, cameraPX ); - uniforms.alphaMap.value = material.alphaMap; + renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); + renderer.render( scene, cameraNX ); - } + renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); + renderer.render( scene, cameraPY ); - if ( material.specularMap ) { + renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); + renderer.render( scene, cameraNY ); - uniforms.specularMap.value = material.specularMap; + renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); + renderer.render( scene, cameraPZ ); - } + // mipmaps are generated during the last call of render() + // at this point, all sides of the cube render target are defined - if ( material.envMap ) { + renderTarget.texture.generateMipmaps = generateMipmaps; - uniforms.envMap.value = material.envMap; + renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); + renderer.render( scene, cameraNZ ); - // don't flip CubeTexture envMaps, flip everything else: - // WebGLRenderTargetCube will be flipped for backwards compatibility - // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture - // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future - uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; + renderer.xr.enabled = currentXrEnabled; - } + renderTarget.texture.needsPMREMUpdate = true; - if ( material.lightMap ) { + } - uniforms.lightMap.value = material.lightMap; - uniforms.lightMapIntensity.value = material.lightMapIntensity; +} - } +class CubeTexture extends Texture { - if ( material.aoMap ) { + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { - uniforms.aoMap.value = material.aoMap; - uniforms.aoMapIntensity.value = material.aoMapIntensity; + images = images !== undefined ? images : []; + mapping = mapping !== undefined ? mapping : CubeReflectionMapping; + + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + this.isCubeTexture = true; + + this.flipY = false; + + } + + get images() { + + return this.image; + + } + + set images( value ) { + + this.image = value; - } + } - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. normal map - // 4. bump map - // 5. alpha map - // 6. emissive map +} - var uvScaleMap; +class WebGLCubeRenderTarget extends WebGLRenderTarget { - if ( material.map ) { + constructor( size = 1, options = {} ) { - uvScaleMap = material.map; + super( size, size, options ); - } else if ( material.specularMap ) { + this.isWebGLCubeRenderTarget = true; - uvScaleMap = material.specularMap; + const image = { width: size, height: size, depth: 1 }; + const images = [ image, image, image, image, image, image ]; - } else if ( material.displacementMap ) { + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); - uvScaleMap = material.displacementMap; + // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) + // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, + // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. - } else if ( material.normalMap ) { + // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped + // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture + // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). - uvScaleMap = material.normalMap; + this.texture.isRenderTargetTexture = true; - } else if ( material.bumpMap ) { + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - uvScaleMap = material.bumpMap; + } - } else if ( material.roughnessMap ) { + fromEquirectangularTexture( renderer, texture ) { - uvScaleMap = material.roughnessMap; + this.texture.type = texture.type; + this.texture.colorSpace = texture.colorSpace; - } else if ( material.metalnessMap ) { + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; - uvScaleMap = material.metalnessMap; + const shader = { - } else if ( material.alphaMap ) { + uniforms: { + tEquirect: { value: null }, + }, - uvScaleMap = material.alphaMap; + vertexShader: /* glsl */` - } else if ( material.emissiveMap ) { + varying vec3 vWorldDirection; - uvScaleMap = material.emissiveMap; + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { - } + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); - if ( uvScaleMap !== undefined ) { + } - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { + void main() { - uvScaleMap = uvScaleMap.texture; + vWorldDirection = transformDirection( position, modelMatrix ); - } + #include + #include - if ( uvScaleMap.matrixAutoUpdate === true ) { + } + `, - var offset = uvScaleMap.offset; - var repeat = uvScaleMap.repeat; - var rotation = uvScaleMap.rotation; - var center = uvScaleMap.center; + fragmentShader: /* glsl */` - uvScaleMap.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); + uniform sampler2D tEquirect; - } + varying vec3 vWorldDirection; - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); + #include - } + void main() { - } + vec3 direction = normalize( vWorldDirection ); - function refreshUniformsLine( uniforms, material ) { + vec2 sampleUV = equirectUv( direction ); - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; + gl_FragColor = texture2D( tEquirect, sampleUV ); - } + } + ` + }; - function refreshUniformsDash( uniforms, material ) { + const geometry = new BoxGeometry( 5, 5, 5 ); - uniforms.dashSize.value = material.dashSize; - uniforms.totalSize.value = material.dashSize + material.gapSize; - uniforms.scale.value = material.scale; + const material = new ShaderMaterial( { - } + name: 'CubemapFromEquirect', - function refreshUniformsPoints( uniforms, material ) { + uniforms: cloneUniforms( shader.uniforms ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide, + blending: NoBlending - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - uniforms.size.value = material.size * _pixelRatio; - uniforms.scale.value = _height * 0.5; + } ); - uniforms.map.value = material.map; + material.uniforms.tEquirect.value = texture; - if ( material.map !== null ) { + const mesh = new Mesh( geometry, material ); - if ( material.map.matrixAutoUpdate === true ) { + const currentMinFilter = texture.minFilter; - var offset = material.map.offset; - var repeat = material.map.repeat; - var rotation = material.map.rotation; - var center = material.map.center; + // Avoid blurred poles + if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; - material.map.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); + const camera = new CubeCamera( 1, 10, this ); + camera.update( renderer, mesh ); - } + texture.minFilter = currentMinFilter; - uniforms.uvTransform.value.copy( material.map.matrix ); + mesh.geometry.dispose(); + mesh.material.dispose(); - } + return this; } - function refreshUniformsFog( uniforms, fog ) { + clear( renderer, color, depth, stencil ) { - uniforms.fogColor.value = fog.color; + const currentRenderTarget = renderer.getRenderTarget(); - if ( fog.isFog ) { - - uniforms.fogNear.value = fog.near; - uniforms.fogFar.value = fog.far; + for ( let i = 0; i < 6; i ++ ) { - } else if ( fog.isFogExp2 ) { + renderer.setRenderTarget( this, i ); - uniforms.fogDensity.value = fog.density; + renderer.clear( color, depth, stencil ); } + renderer.setRenderTarget( currentRenderTarget ); + } - function refreshUniformsLambert( uniforms, material ) { +} - if ( material.emissiveMap ) { +const _vector1 = /*@__PURE__*/ new Vector3(); +const _vector2 = /*@__PURE__*/ new Vector3(); +const _normalMatrix = /*@__PURE__*/ new Matrix3(); - uniforms.emissiveMap.value = material.emissiveMap; +class Plane { - } + constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { - } + this.isPlane = true; - function refreshUniformsPhong( uniforms, material ) { + // normal is assumed to be normalized - uniforms.specular.value = material.specular; - uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) + this.normal = normal; + this.constant = constant; - if ( material.emissiveMap ) { + } - uniforms.emissiveMap.value = material.emissiveMap; + set( normal, constant ) { - } + this.normal.copy( normal ); + this.constant = constant; - if ( material.bumpMap ) { + return this; - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + } - } + setComponents( x, y, z, w ) { - if ( material.normalMap ) { + this.normal.set( x, y, z ); + this.constant = w; - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + return this; - } + } - if ( material.displacementMap ) { + setFromNormalAndCoplanarPoint( normal, point ) { - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + this.normal.copy( normal ); + this.constant = - point.dot( this.normal ); - } + return this; } - function refreshUniformsToon( uniforms, material ) { + setFromCoplanarPoints( a, b, c ) { - refreshUniformsPhong( uniforms, material ); + const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); - if ( material.gradientMap ) { + // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? - uniforms.gradientMap.value = material.gradientMap; + this.setFromNormalAndCoplanarPoint( normal, a ); - } + return this; } - 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 ) { + copy( plane ) { - uniforms.metalnessMap.value = material.metalnessMap; + this.normal.copy( plane.normal ); + this.constant = plane.constant; - } + return this; - if ( material.emissiveMap ) { + } - uniforms.emissiveMap.value = material.emissiveMap; + normalize() { - } + // Note: will lead to a divide by zero if the plane is invalid. - if ( material.bumpMap ) { + const inverseNormalLength = 1.0 / this.normal.length(); + this.normal.multiplyScalar( inverseNormalLength ); + this.constant *= inverseNormalLength; - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + return this; - } + } - if ( material.normalMap ) { + negate() { - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + this.constant *= - 1; + this.normal.negate(); - } + return this; - if ( material.displacementMap ) { + } - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + distanceToPoint( point ) { - } + return this.normal.dot( point ) + this.constant; - if ( material.envMap ) { + } - //uniforms.envMap.value = material.envMap; // part of uniforms common - uniforms.envMapIntensity.value = material.envMapIntensity; + distanceToSphere( sphere ) { - } + return this.distanceToPoint( sphere.center ) - sphere.radius; } - function refreshUniformsPhysical( uniforms, material ) { - - uniforms.clearCoat.value = material.clearCoat; - uniforms.clearCoatRoughness.value = material.clearCoatRoughness; + projectPoint( point, target ) { - refreshUniformsStandard( uniforms, material ); + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); } - function refreshUniformsDepth( uniforms, material ) { + intersectLine( line, target ) { - if ( material.displacementMap ) { + const direction = line.delta( _vector1 ); - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + const denominator = this.normal.dot( direction ); - } + if ( denominator === 0 ) { - } + // line is coplanar, return origin + if ( this.distanceToPoint( line.start ) === 0 ) { - function refreshUniformsDistance( uniforms, material ) { + return target.copy( line.start ); - if ( material.displacementMap ) { + } - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + // Unsure if this is the correct method to handle this case. + return null; } - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; - - } - - function refreshUniformsNormal( uniforms, material ) { + const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - if ( material.bumpMap ) { + if ( t < 0 || t > 1 ) { - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + return null; } - if ( material.normalMap ) { + return target.copy( line.start ).addScaledVector( direction, t ); - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + } - } + intersectsLine( line ) { - if ( material.displacementMap ) { + // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + const startSign = this.distanceToPoint( line.start ); + const endSign = this.distanceToPoint( line.end ); - } + return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); } - // If uniforms are marked as clean, they don't need to be loaded to the GPU. - - function markUniformsLightsNeedsUpdate( uniforms, value ) { - - uniforms.ambientLightColor.needsUpdate = value; + intersectsBox( box ) { - uniforms.directionalLights.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + return box.intersectsPlane( this ); } - // GL state setting + intersectsSphere( sphere ) { - this.setFaceCulling = function ( cullFace, frontFaceDirection ) { + return sphere.intersectsPlane( this ); - state.setCullFace( cullFace ); - state.setFlipSided( frontFaceDirection === FrontFaceDirectionCW ); + } - }; + coplanarPoint( target ) { - // Textures + return target.copy( this.normal ).multiplyScalar( - this.constant ); - function allocTextureUnit() { + } - var textureUnit = _usedTextureUnits; + applyMatrix4( matrix, optionalNormalMatrix ) { - if ( textureUnit >= capabilities.maxTextures ) { + const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); - console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); + const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); - } + const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - _usedTextureUnits += 1; + this.constant = - referencePoint.dot( normal ); - return textureUnit; + return this; } - this.allocTextureUnit = allocTextureUnit; + translate( offset ) { - // this.setTexture2D = setTexture2D; - this.setTexture2D = ( function () { + this.constant -= offset.dot( this.normal ); - var warned = false; + return this; - // backwards compatibility: peel texture.texture - return function setTexture2D( texture, slot ) { + } - if ( texture && texture.isWebGLRenderTarget ) { + equals( plane ) { - if ( ! warned ) { + return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); - console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." ); - warned = true; + } - } + clone() { - texture = texture.texture; + return new this.constructor().copy( this ); - } + } - textures.setTexture2D( texture, slot ); +} - }; +const _sphere$5 = /*@__PURE__*/ new Sphere(); +const _vector$7 = /*@__PURE__*/ new Vector3(); - }() ); +class Frustum { - this.setTexture = ( function () { + constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { - var warned = false; + this.planes = [ p0, p1, p2, p3, p4, p5 ]; - return function setTexture( texture, slot ) { + } - if ( ! warned ) { + set( p0, p1, p2, p3, p4, p5 ) { - console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." ); - warned = true; + 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 ); - textures.setTexture2D( texture, slot ); + return this; - }; + } - }() ); + copy( frustum ) { - this.setTextureCube = ( function () { + const planes = this.planes; - var warned = false; + for ( let i = 0; i < 6; i ++ ) { - return function setTextureCube( texture, slot ) { + planes[ i ].copy( frustum.planes[ i ] ); - // backwards compatibility: peel texture.texture - if ( texture && texture.isWebGLRenderTargetCube ) { + } - if ( ! warned ) { + return this; - console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." ); - warned = true; + } - } + setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { - texture = texture.texture; + const planes = this.planes; + const me = m.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(); - // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture - // TODO: unify these code paths - if ( ( texture && texture.isCubeTexture ) || - ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) { + if ( coordinateSystem === WebGLCoordinateSystem ) { - // CompressedTexture can have Array in image :/ + planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); - // this function alone should take care of cube textures - textures.setTextureCube( texture, slot ); + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - } else { + planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); + + } else { - // assumed: texture property of THREE.WebGLRenderTargetCube + throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); - textures.setTextureCubeDynamic( texture, slot ); + } - } + return this; - }; + } - }() ); + intersectsObject( object ) { - this.getRenderTarget = function () { + if ( object.boundingSphere !== undefined ) { - return _currentRenderTarget; + if ( object.boundingSphere === null ) object.computeBoundingSphere(); - }; + _sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); - this.setRenderTarget = function ( renderTarget ) { + } else { - _currentRenderTarget = renderTarget; + const geometry = object.geometry; - if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) { + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - textures.setupRenderTarget( renderTarget ); + _sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); } - var framebuffer = null; - var isCube = false; + return this.intersectsSphere( _sphere$5 ); - if ( renderTarget ) { - - var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; + } - if ( renderTarget.isWebGLRenderTargetCube ) { + intersectsSprite( sprite ) { - framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; - isCube = true; + _sphere$5.center.set( 0, 0, 0 ); + _sphere$5.radius = 0.7071067811865476; + _sphere$5.applyMatrix4( sprite.matrixWorld ); - } else { + return this.intersectsSphere( _sphere$5 ); - framebuffer = __webglFramebuffer; + } - } + intersectsSphere( sphere ) { - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + const planes = this.planes; + const center = sphere.center; + const negRadius = - sphere.radius; - } else { + for ( let i = 0; i < 6; i ++ ) { - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); - _currentScissorTest = _scissorTest; + const distance = planes[ i ].distanceToPoint( center ); - } + if ( distance < negRadius ) { - if ( _currentFramebuffer !== framebuffer ) { + return false; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _currentFramebuffer = framebuffer; + } } - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); - - if ( isCube ) { + return true; - var textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel ); + } - } + intersectsBox( box ) { - }; + const planes = this.planes; - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { + for ( let i = 0; i < 6; i ++ ) { - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + const plane = planes[ i ]; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + // corner at max distance - } + _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; - var framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( plane.distanceToPoint( _vector$7 ) < 0 ) { - if ( framebuffer ) { + return false; - var restore = false; + } - if ( framebuffer !== _currentFramebuffer ) { + } - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + return true; - restore = true; + } - } + containsPoint( point ) { - try { + const planes = this.planes; - var texture = renderTarget.texture; - var textureFormat = texture.format; - var textureType = texture.type; + for ( let i = 0; i < 6; i ++ ) { - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + if ( planes[ i ].distanceToPoint( point ) < 0 ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + return false; - } + } - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { + } - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + return true; - } + } - if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) { + clone() { - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + return new this.constructor().copy( this ); - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + } - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); +} - } +function WebGLAnimation() { - } else { + let context = null; + let isAnimating = false; + let animationLoop = null; + let requestId = null; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' ); + function onAnimationFrame( time, frame ) { - } + animationLoop( time, frame ); - } finally { + requestId = context.requestAnimationFrame( onAnimationFrame ); - if ( restore ) { + } - _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer ); + return { - } + start: function () { - } + if ( isAnimating === true ) return; + if ( animationLoop === null ) return; - } + requestId = context.requestAnimationFrame( onAnimationFrame ); - }; + isAnimating = true; -} + }, -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + stop: function () { -function FogExp2( color, density ) { + context.cancelAnimationFrame( requestId ); - this.name = ''; + isAnimating = false; - this.color = new Color( color ); - this.density = ( density !== undefined ) ? density : 0.00025; + }, -} + setAnimationLoop: function ( callback ) { -FogExp2.prototype.isFogExp2 = true; + animationLoop = callback; -FogExp2.prototype.clone = function () { + }, - return new FogExp2( this.color.getHex(), this.density ); + setContext: function ( value ) { -}; + context = value; -FogExp2.prototype.toJSON = function ( /* meta */ ) { + } - return { - type: 'FogExp2', - color: this.color.getHex(), - density: this.density }; -}; +} -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ +function WebGLAttributes( gl ) { -function Fog( color, near, far ) { + const buffers = new WeakMap(); - this.name = ''; + function createBuffer( attribute, bufferType ) { - this.color = new Color( color ); + const array = attribute.array; + const usage = attribute.usage; + const size = array.byteLength; - this.near = ( near !== undefined ) ? near : 1; - this.far = ( far !== undefined ) ? far : 1000; + const buffer = gl.createBuffer(); -} + gl.bindBuffer( bufferType, buffer ); + gl.bufferData( bufferType, array, usage ); -Fog.prototype.isFog = true; + attribute.onUploadCallback(); -Fog.prototype.clone = function () { + let type; - return new Fog( this.color.getHex(), this.near, this.far ); + if ( array instanceof Float32Array ) { -}; + type = gl.FLOAT; -Fog.prototype.toJSON = function ( /* meta */ ) { + } else if ( array instanceof Uint16Array ) { - return { - type: 'Fog', - color: this.color.getHex(), - near: this.near, - far: this.far - }; + if ( attribute.isFloat16BufferAttribute ) { -}; + type = gl.HALF_FLOAT; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } else { -function Scene() { + type = gl.UNSIGNED_SHORT; - Object3D.call( this ); + } - this.type = 'Scene'; + } else if ( array instanceof Int16Array ) { - this.background = null; - this.fog = null; - this.overrideMaterial = null; + type = gl.SHORT; - this.autoUpdate = true; // checked by the renderer + } else if ( array instanceof Uint32Array ) { -} + type = gl.UNSIGNED_INT; -Scene.prototype = Object.assign( Object.create( Object3D.prototype ), { + } else if ( array instanceof Int32Array ) { - constructor: Scene, + type = gl.INT; - copy: function ( source, recursive ) { + } else if ( array instanceof Int8Array ) { - Object3D.prototype.copy.call( this, source, recursive ); + type = gl.BYTE; - if ( source.background !== null ) { this.background = source.background.clone(); } - if ( source.fog !== null ) { this.fog = source.fog.clone(); } - if ( source.overrideMaterial !== null ) { this.overrideMaterial = source.overrideMaterial.clone(); } + } else if ( array instanceof Uint8Array ) { - this.autoUpdate = source.autoUpdate; - this.matrixAutoUpdate = source.matrixAutoUpdate; + type = gl.UNSIGNED_BYTE; - return this; + } else if ( array instanceof Uint8ClampedArray ) { - }, + type = gl.UNSIGNED_BYTE; - toJSON: function ( meta ) { + } else { - var data = Object3D.prototype.toJSON.call( this, meta ); + throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); - if ( this.background !== null ) { data.object.background = this.background.toJSON( meta ); } - if ( this.fog !== null ) { data.object.fog = this.fog.toJSON(); } + } - return data; + return { + buffer: buffer, + type: type, + bytesPerElement: array.BYTES_PER_ELEMENT, + version: attribute.version, + size: size + }; } -} ); + function updateBuffer( buffer, attribute, bufferType ) { -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + const array = attribute.array; + const updateRange = attribute._updateRange; // @deprecated, r159 + const updateRanges = attribute.updateRanges; -function LensFlare( texture, size, distance, blending, color ) { + gl.bindBuffer( bufferType, buffer ); - Object3D.call( this ); + if ( updateRange.count === - 1 && updateRanges.length === 0 ) { - this.lensFlares = []; + // Not using update ranges + gl.bufferSubData( bufferType, 0, array ); - this.positionScreen = new Vector3(); - this.customUpdateCallback = undefined; + } - if ( texture !== undefined ) { + if ( updateRanges.length !== 0 ) { - this.add( texture, size, distance, blending, color ); + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { - } + const range = updateRanges[ i ]; -} + gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, + array, range.start, range.count ); -LensFlare.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: LensFlare, + attribute.clearUpdateRanges(); - isLensFlare: true, + } - copy: function ( source ) { + // @deprecated, r159 + if ( updateRange.count !== - 1 ) { - Object3D.prototype.copy.call( this, source ); + gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, + array, updateRange.offset, updateRange.count ); - this.positionScreen.copy( source.positionScreen ); - this.customUpdateCallback = source.customUpdateCallback; + updateRange.count = - 1; // reset range - for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) { + } - this.lensFlares.push( source.lensFlares[ i ] ); + attribute.onUploadCallback(); - } + } - return this; + // - }, + function get( attribute ) { - add: function ( texture, size, distance, blending, color, opacity ) { - - if ( size === undefined ) { size = - 1; } - if ( distance === undefined ) { distance = 0; } - if ( opacity === undefined ) { opacity = 1; } - if ( color === undefined ) { color = new Color( 0xffffff ); } - if ( blending === undefined ) { blending = NormalBlending; } - - distance = Math.min( distance, Math.max( 0, distance ) ); - - this.lensFlares.push( { - texture: texture, // THREE.Texture - size: size, // size in pixels (-1 = use texture.width) - distance: distance, // distance (0-1) from light source (0=at light source) - x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is in front z = 1 is back - scale: 1, // scale - rotation: 0, // rotation - opacity: opacity, // opacity - color: color, // color - blending: blending // blending - } ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - }, + return buffers.get( attribute ); - /* - * Update lens flares update positions on all flares based on the screen position - * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way. - */ + } - updateLensFlares: function () { + function remove( attribute ) { - var f, fl = this.lensFlares.length; - var flare; - var vecX = - this.positionScreen.x * 2; - var vecY = - this.positionScreen.y * 2; + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - for ( f = 0; f < fl; f ++ ) { + const data = buffers.get( attribute ); - flare = this.lensFlares[ f ]; + if ( data ) { - flare.x = this.positionScreen.x + vecX * flare.distance; - flare.y = this.positionScreen.y + vecY * flare.distance; + gl.deleteBuffer( data.buffer ); - flare.wantedRotation = flare.x * Math.PI * 0.25; - flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25; + buffers.delete( attribute ); } } -} ); + function update( attribute, bufferType ) { -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * uvOffset: new THREE.Vector2(), - * uvScale: new THREE.Vector2() - * } - */ + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; -function SpriteMaterial( parameters ) { + if ( attribute.isGLBufferAttribute ) { - Material.call( this ); + const cached = buffers.get( attribute ); - this.type = 'SpriteMaterial'; + if ( ! cached || cached.version < attribute.version ) { - this.color = new Color( 0xffffff ); - this.map = null; + buffers.set( attribute, { + buffer: attribute.buffer, + type: attribute.type, + bytesPerElement: attribute.elementSize, + version: attribute.version + } ); - this.rotation = 0; + } - this.fog = false; - this.lights = false; + return; - this.setValues( parameters ); + } -} + const data = buffers.get( attribute ); -SpriteMaterial.prototype = Object.create( Material.prototype ); -SpriteMaterial.prototype.constructor = SpriteMaterial; -SpriteMaterial.prototype.isSpriteMaterial = true; + if ( data === undefined ) { -SpriteMaterial.prototype.copy = function ( source ) { + buffers.set( attribute, createBuffer( attribute, bufferType ) ); - Material.prototype.copy.call( this, source ); + } else if ( data.version < attribute.version ) { - this.color.copy( source.color ); - this.map = source.map; + if ( data.size !== attribute.array.byteLength ) { - this.rotation = source.rotation; + throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' ); - return this; + } -}; + updateBuffer( data.buffer, attribute, bufferType ); -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + data.version = attribute.version; -function Sprite( material ) { + } + + } - Object3D.call( this ); + return { - this.type = 'Sprite'; + get: get, + remove: remove, + update: update - this.material = ( material !== undefined ) ? material : new SpriteMaterial(); + }; } -Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { +class PlaneGeometry extends BufferGeometry { - constructor: Sprite, + constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { - isSprite: true, + super(); - raycast: ( function () { + this.type = 'PlaneGeometry'; - var intersectPoint = new Vector3(); - var worldPosition = new Vector3(); - var worldScale = new Vector3(); + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; - return function raycast( raycaster, intersects ) { + const width_half = width / 2; + const height_half = height / 2; - worldPosition.setFromMatrixPosition( this.matrixWorld ); - raycaster.ray.closestPointToPoint( worldPosition, intersectPoint ); + const gridX = Math.floor( widthSegments ); + const gridY = Math.floor( heightSegments ); - worldScale.setFromMatrixScale( this.matrixWorld ); - var guessSizeSq = worldScale.x * worldScale.y / 4; + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; - if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) { return; } + const segment_width = width / gridX; + const segment_height = height / gridY; - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); + // - if ( distance < raycaster.near || distance > raycaster.far ) { return; } + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - intersects.push( { + for ( let iy = 0; iy < gridY1; iy ++ ) { - distance: distance, - point: intersectPoint.clone(), - face: null, - object: this + const y = iy * segment_height - height_half; - } ); + for ( let ix = 0; ix < gridX1; ix ++ ) { - }; + const x = ix * segment_width - width_half; - }() ), + vertices.push( x, - y, 0 ); - clone: function () { + normals.push( 0, 0, 1 ); - return new this.constructor( this.material ).copy( this ); + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - } + } -} ); + } -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + for ( let iy = 0; iy < gridY; iy ++ ) { + + for ( let ix = 0; ix < gridX; ix ++ ) { -function LOD() { + const a = ix + gridX1 * iy; + const b = ix + gridX1 * ( iy + 1 ); + const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = ( ix + 1 ) + gridX1 * iy; - Object3D.call( this ); + indices.push( a, b, d ); + indices.push( b, c, d ); - this.type = 'LOD'; + } - Object.defineProperties( this, { - levels: { - enumerable: true, - value: [] } - } ); -} + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); -LOD.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: LOD, + copy( source ) { - copy: function ( source ) { + super.copy( source ); - Object3D.prototype.copy.call( this, source, false ); + this.parameters = Object.assign( {}, source.parameters ); - var levels = source.levels; + return this; - for ( var i = 0, l = levels.length; i < l; i ++ ) { + } - var level = levels[ i ]; + static fromJSON( data ) { - this.addLevel( level.object.clone(), level.distance ); + return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); - } + } - return this; +} - }, +var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif"; - addLevel: function ( object, distance ) { +var alphahash_pars_fragment = "#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif"; - if ( distance === undefined ) { distance = 0; } +var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; - distance = Math.abs( distance ); +var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - var levels = this.levels; +var alphatest_fragment = "#ifdef USE_ALPHATEST\n\t#ifdef ALPHA_TO_COVERAGE\n\tdiffuseColor.a = smoothstep( alphaTest, alphaTest + fwidth( diffuseColor.a ), diffuseColor.a );\n\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\tif ( diffuseColor.a < alphaTest ) discard;\n\t#endif\n#endif"; - for ( var l = 0; l < levels.length; l ++ ) { +var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; - if ( distance < levels[ l ].distance ) { +var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; - break; +var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; - } +var batching_pars_vertex = "#ifdef USE_BATCHING\n\t#if ! defined( GL_ANGLE_multi_draw )\n\t#define gl_DrawID _gl_DrawID\n\tuniform int _gl_DrawID;\n\t#endif\n\tuniform highp sampler2D batchingTexture;\n\tuniform highp usampler2D batchingIdTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n\tfloat getIndirectIndex( const in int i ) {\n\t\tint size = textureSize( batchingIdTexture, 0 ).x;\n\t\tint x = i % size;\n\t\tint y = i / size;\n\t\treturn float( texelFetch( batchingIdTexture, ivec2( x, y ), 0 ).r );\n\t}\n#endif\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec3 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb;\n\t}\n#endif"; - } +var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( getIndirectIndex( gl_DrawID ) );\n#endif"; - levels.splice( l, 0, { distance: distance, object: object } ); +var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif"; - this.add( object ); +var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; - }, +var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated"; - getObjectForDistance: function ( distance ) { +var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.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\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; - var levels = this.levels; +var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; - for ( var i = 1, l = levels.length; i < l; i ++ ) { +var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif"; - if ( distance < levels[ i ].distance ) { +var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; - break; +var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; - } +var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; - } +var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; - return levels[ i - 1 ].object; +var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; - }, +var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif"; - raycast: ( function () { +var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif"; - var matrixPosition = new Vector3(); +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\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; - return function raycast( raycaster, intersects ) { +var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; - matrixPosition.setFromMatrixPosition( this.matrixWorld ); +var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; - var distance = raycaster.ray.origin.distanceTo( matrixPosition ); +var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; - this.getObjectForDistance( distance ).raycast( raycaster, intersects ); +var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; - }; +var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; - }() ), +var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; - update: function () { +var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; - var v1 = new Vector3(); - var v2 = new Vector3(); +var colorspace_pars_fragment = "\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn 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}"; - return function update( camera ) { +var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; - var levels = this.levels; +var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; - if ( levels.length > 1 ) { +var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif"; - v1.setFromMatrixPosition( camera.matrixWorld ); - v2.setFromMatrixPosition( this.matrixWorld ); +var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif"; - var distance = v1.distanceTo( v2 ); +var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif"; - levels[ 0 ].object.visible = true; +var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; - for ( var i = 1, l = levels.length; i < l; i ++ ) { +var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; - if ( distance >= levels[ i ].distance ) { +var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"; - levels[ i - 1 ].object.visible = false; - levels[ i ].object.visible = true; +var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif"; - } else { +var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; - break; +var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; - } +var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; - } +var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; - for ( ; i < l; i ++ ) { +var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; - levels[ i ].object.visible = false; +var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; - } +var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; - } +var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon"; - }; +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\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; - toJSON: function ( meta ) { +var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; - var data = Object3D.prototype.toJSON.call( this, meta ); +var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; - data.object.levels = []; +var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; - var levels = this.levels; +var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; - for ( var i = 0, l = levels.length; i < l; i ++ ) { +var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif"; - var level = levels[ i ]; +var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; - data.object.levels.push( { - object: level.object.uuid, - distance: level.distance - } ); +var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; - } +var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; - return data; +var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif"; - } +var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = 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\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; -} ); +var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author michael guerrero / http://realitymeltdown.com - * @author ikerr / http://verold.com - */ +var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; -function Skeleton( bones, boneInverses ) { +var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - // copy the bone array +var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; - bones = bones || []; +var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; - this.bones = bones.slice( 0 ); - this.boneMatrices = new Float32Array( this.bones.length * 16 ); +var morphinstance_vertex = "#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif"; - // use the supplied bone inverses or calculate the inverses +var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif"; - if ( boneInverses === undefined ) { +var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; - this.calculateInverses(); +var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif"; - } else { +var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; - if ( this.bones.length === boneInverses.length ) { +var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;"; - this.boneInverses = boneInverses.slice( 0 ); +var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; - } else { +var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; - console.warn( 'THREE.Skeleton boneInverses is the wrong length.' ); +var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; - this.boneInverses = []; +var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { +var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; - this.boneInverses.push( new Matrix4() ); +var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif"; - } +var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; - } +var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; - } +var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; -} +var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; -Object.assign( Skeleton.prototype, { +var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn 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\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; - calculateInverses: function () { +var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; - this.boneInverses = []; +var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { +var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; - var inverse = new Matrix4(); +var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; - if ( this.bones[ i ] ) { +var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; - inverse.getInverse( this.bones[ i ].matrixWorld ); +var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; - } +var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif"; - this.boneInverses.push( inverse ); +var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; - } +var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; - }, +var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}"; - pose: function () { +var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; - var bone, i, il; +var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif"; - // recover the bind-time world matrices +var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif"; - for ( i = 0, il = this.bones.length; i < il; i ++ ) { +var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; - bone = this.bones[ i ]; +var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; - if ( bone ) { +var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; - bone.matrixWorld.getInverse( this.boneInverses[ i ] ); +var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_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\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - } +var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; - // compute the local matrices, positions, rotations and scales +var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; - for ( i = 0, il = this.bones.length; i < il; i ++ ) { +var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - bone = this.bones[ i ]; +var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - if ( bone ) { +var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; - if ( bone.parent && bone.parent.isBone ) { +var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; - bone.matrix.getInverse( bone.parent.matrixWorld ); - bone.matrix.multiply( bone.matrixWorld ); +const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; - } else { +const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; - bone.matrix.copy( bone.matrixWorld ); +const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; - } +const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); +const vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; - } +const fragment$f = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}"; - } +const vertex$e = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}"; - }, +const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}"; - update: ( function () { +const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}"; - var offsetMatrix = new Matrix4(); - var identityMatrix = new Matrix4(); +const 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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; - return function update() { +const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}"; - var bones = this.bones; - var boneInverses = this.boneInverses; - var boneMatrices = this.boneMatrices; - var boneTexture = this.boneTexture; +const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; - // flatten bone matrices to array +const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - for ( var i = 0, il = bones.length; i < il; i ++ ) { +const 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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - // compute the offset between the current and the original transform +const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix; +const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); - offsetMatrix.toArray( boneMatrices, i * 16 ); +const vertex$9 = "#define LAMBERT\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } +const fragment$9 = "#define LAMBERT\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - if ( boneTexture !== undefined ) { +const 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 \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; - boneTexture.needsUpdate = true; +const 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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } +const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; - }; +const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; - } )(), +const 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - clone: function () { +const 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - return new Skeleton( this.bones, this.boneInverses ); +const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; - } +const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -} ); +const 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author ikerr / http://verold.com - */ +const 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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -function Bone() { +const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - Object3D.call( this ); +const fragment$3 = "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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - this.type = 'Bone'; +const vertex$2 = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -} +const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; -Bone.prototype = Object.assign( Object.create( Object3D.prototype ), { +const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"; - constructor: Bone, +const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - isBone: true +const ShaderChunk = { + alphahash_fragment: alphahash_fragment, + alphahash_pars_fragment: alphahash_pars_fragment, + alphamap_fragment: alphamap_fragment, + alphamap_pars_fragment: alphamap_pars_fragment, + alphatest_fragment: alphatest_fragment, + alphatest_pars_fragment: alphatest_pars_fragment, + aomap_fragment: aomap_fragment, + aomap_pars_fragment: aomap_pars_fragment, + batching_pars_vertex: batching_pars_vertex, + batching_vertex: batching_vertex, + begin_vertex: begin_vertex, + beginnormal_vertex: beginnormal_vertex, + bsdfs: bsdfs, + iridescence_fragment: iridescence_fragment, + bumpmap_pars_fragment: bumpmap_pars_fragment, + clipping_planes_fragment: clipping_planes_fragment, + clipping_planes_pars_fragment: clipping_planes_pars_fragment, + clipping_planes_pars_vertex: clipping_planes_pars_vertex, + clipping_planes_vertex: clipping_planes_vertex, + color_fragment: color_fragment, + color_pars_fragment: color_pars_fragment, + color_pars_vertex: color_pars_vertex, + color_vertex: color_vertex, + common: common, + cube_uv_reflection_fragment: cube_uv_reflection_fragment, + defaultnormal_vertex: defaultnormal_vertex, + displacementmap_pars_vertex: displacementmap_pars_vertex, + displacementmap_vertex: displacementmap_vertex, + emissivemap_fragment: emissivemap_fragment, + emissivemap_pars_fragment: emissivemap_pars_fragment, + colorspace_fragment: colorspace_fragment, + colorspace_pars_fragment: colorspace_pars_fragment, + envmap_fragment: envmap_fragment, + envmap_common_pars_fragment: envmap_common_pars_fragment, + envmap_pars_fragment: envmap_pars_fragment, + envmap_pars_vertex: envmap_pars_vertex, + envmap_physical_pars_fragment: envmap_physical_pars_fragment, + envmap_vertex: envmap_vertex, + fog_vertex: fog_vertex, + fog_pars_vertex: fog_pars_vertex, + fog_fragment: fog_fragment, + fog_pars_fragment: fog_pars_fragment, + gradientmap_pars_fragment: gradientmap_pars_fragment, + lightmap_pars_fragment: lightmap_pars_fragment, + lights_lambert_fragment: lights_lambert_fragment, + lights_lambert_pars_fragment: lights_lambert_pars_fragment, + lights_pars_begin: lights_pars_begin, + lights_toon_fragment: lights_toon_fragment, + lights_toon_pars_fragment: lights_toon_pars_fragment, + lights_phong_fragment: lights_phong_fragment, + lights_phong_pars_fragment: lights_phong_pars_fragment, + lights_physical_fragment: lights_physical_fragment, + lights_physical_pars_fragment: lights_physical_pars_fragment, + lights_fragment_begin: lights_fragment_begin, + lights_fragment_maps: lights_fragment_maps, + lights_fragment_end: lights_fragment_end, + logdepthbuf_fragment: logdepthbuf_fragment, + logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, + logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, + logdepthbuf_vertex: logdepthbuf_vertex, + map_fragment: map_fragment, + map_pars_fragment: map_pars_fragment, + map_particle_fragment: map_particle_fragment, + map_particle_pars_fragment: map_particle_pars_fragment, + metalnessmap_fragment: metalnessmap_fragment, + metalnessmap_pars_fragment: metalnessmap_pars_fragment, + morphinstance_vertex: morphinstance_vertex, + morphcolor_vertex: morphcolor_vertex, + morphnormal_vertex: morphnormal_vertex, + morphtarget_pars_vertex: morphtarget_pars_vertex, + morphtarget_vertex: morphtarget_vertex, + normal_fragment_begin: normal_fragment_begin, + normal_fragment_maps: normal_fragment_maps, + normal_pars_fragment: normal_pars_fragment, + normal_pars_vertex: normal_pars_vertex, + normal_vertex: normal_vertex, + normalmap_pars_fragment: normalmap_pars_fragment, + clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, + clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, + clearcoat_pars_fragment: clearcoat_pars_fragment, + iridescence_pars_fragment: iridescence_pars_fragment, + opaque_fragment: opaque_fragment, + packing: packing, + premultiplied_alpha_fragment: premultiplied_alpha_fragment, + project_vertex: project_vertex, + dithering_fragment: dithering_fragment, + dithering_pars_fragment: dithering_pars_fragment, + roughnessmap_fragment: roughnessmap_fragment, + roughnessmap_pars_fragment: roughnessmap_pars_fragment, + shadowmap_pars_fragment: shadowmap_pars_fragment, + shadowmap_pars_vertex: shadowmap_pars_vertex, + shadowmap_vertex: shadowmap_vertex, + shadowmask_pars_fragment: shadowmask_pars_fragment, + skinbase_vertex: skinbase_vertex, + skinning_pars_vertex: skinning_pars_vertex, + skinning_vertex: skinning_vertex, + skinnormal_vertex: skinnormal_vertex, + specularmap_fragment: specularmap_fragment, + specularmap_pars_fragment: specularmap_pars_fragment, + tonemapping_fragment: tonemapping_fragment, + tonemapping_pars_fragment: tonemapping_pars_fragment, + transmission_fragment: transmission_fragment, + transmission_pars_fragment: transmission_pars_fragment, + uv_pars_fragment: uv_pars_fragment, + uv_pars_vertex: uv_pars_vertex, + uv_vertex: uv_vertex, + worldpos_vertex: worldpos_vertex, -} ); + background_vert: vertex$h, + background_frag: fragment$h, + backgroundCube_vert: vertex$g, + backgroundCube_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 +}; /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author ikerr / http://verold.com + * Uniforms library for shared webgl shaders */ -function SkinnedMesh( geometry, material ) { - - Mesh.call( this, geometry, material ); - - this.type = 'SkinnedMesh'; - - this.bindMode = 'attached'; - this.bindMatrix = new Matrix4(); - this.bindMatrixInverse = new Matrix4(); - - var bones = this.initBones(); - var skeleton = new Skeleton( bones ); +const UniformsLib = { - this.bind( skeleton, this.matrixWorld ); - - this.normalizeSkinWeights(); - -} - -SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { - - constructor: SkinnedMesh, - - isSkinnedMesh: true, - - initBones: function () { - - var bones = [], bone, gbone; - var i, il; - - if ( this.geometry && this.geometry.bones !== undefined ) { - - // first, create array of 'Bone' objects from geometry data - - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { - - gbone = this.geometry.bones[ i ]; - - // create new 'Bone' object + common: { - bone = new Bone(); - bones.push( bone ); + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, - // apply values + map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, - bone.name = gbone.name; - bone.position.fromArray( gbone.pos ); - bone.quaternion.fromArray( gbone.rotq ); - if ( gbone.scl !== undefined ) { bone.scale.fromArray( gbone.scl ); } + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, - } + alphaTest: { value: 0 } - // second, create bone hierarchy + }, - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { + specularmap: { - gbone = this.geometry.bones[ i ]; + specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } - if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { + }, - // subsequent bones in the hierarchy + envmap: { - bones[ gbone.parent ].add( bones[ i ] ); + envMap: { value: null }, + envMapRotation: { value: /*@__PURE__*/ new Matrix3() }, + flipEnvMap: { value: - 1 }, + reflectivity: { value: 1.0 }, // basic, lambert, phong + ior: { value: 1.5 }, // physical + refractionRatio: { value: 0.98 }, // basic, lambert, phong - } else { + }, - // topmost bone, immediate child of the skinned mesh + aomap: { - this.add( bones[ i ] ); + aoMap: { value: null }, + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } - } + }, - } + lightmap: { - } + lightMap: { value: null }, + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } - // now the bones are part of the scene graph and children of the skinned mesh. - // let's update the corresponding matrices + }, - this.updateMatrixWorld( true ); + bumpmap: { - return bones; + bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + bumpScale: { value: 1 } }, - bind: function ( skeleton, bindMatrix ) { + normalmap: { - this.skeleton = skeleton; + normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } - if ( bindMatrix === undefined ) { + }, - this.updateMatrixWorld( true ); + displacementmap: { - this.skeleton.calculateInverses(); + displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + displacementScale: { value: 1 }, + displacementBias: { value: 0 } - bindMatrix = this.matrixWorld; + }, - } + emissivemap: { - this.bindMatrix.copy( bindMatrix ); - this.bindMatrixInverse.getInverse( bindMatrix ); + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, - pose: function () { + metalnessmap: { - this.skeleton.pose(); + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, - normalizeSkinWeights: function () { - - var scale, i; - - if ( this.geometry && this.geometry.isGeometry ) { + roughnessmap: { - for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) { + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } - var sw = this.geometry.skinWeights[ i ]; + }, - scale = 1.0 / sw.manhattanLength(); + gradientmap: { - if ( scale !== Infinity ) { + gradientMap: { value: null } - sw.multiplyScalar( scale ); + }, - } else { + fog: { - sw.set( 1, 0, 0, 0 ); // do something reasonable + fogDensity: { value: 0.00025 }, + fogNear: { value: 1 }, + fogFar: { value: 2000 }, + fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } - } + }, - } + lights: { - } else if ( this.geometry && this.geometry.isBufferGeometry ) { + ambientLightColor: { value: [] }, - var vec = new Vector4(); + lightProbe: { value: [] }, - var skinWeight = this.geometry.attributes.skinWeight; + directionalLights: { value: [], properties: { + direction: {}, + color: {} + } }, - for ( i = 0; i < skinWeight.count; i ++ ) { + directionalLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, - vec.x = skinWeight.getX( i ); - vec.y = skinWeight.getY( i ); - vec.z = skinWeight.getZ( i ); - vec.w = skinWeight.getW( i ); + directionalShadowMap: { value: [] }, + directionalShadowMatrix: { value: [] }, - scale = 1.0 / vec.manhattanLength(); + spotLights: { value: [], properties: { + color: {}, + position: {}, + direction: {}, + distance: {}, + coneCos: {}, + penumbraCos: {}, + decay: {} + } }, - if ( scale !== Infinity ) { + spotLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, - vec.multiplyScalar( scale ); + spotLightMap: { value: [] }, + spotShadowMap: { value: [] }, + spotLightMatrix: { value: [] }, - } else { + pointLights: { value: [], properties: { + color: {}, + position: {}, + decay: {}, + distance: {} + } }, - vec.set( 1, 0, 0, 0 ); // do something reasonable + pointLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} + } }, - } + pointShadowMap: { value: [] }, + pointShadowMatrix: { value: [] }, - skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w ); + hemisphereLights: { value: [], properties: { + direction: {}, + skyColor: {}, + groundColor: {} + } }, - } + // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src + rectAreaLights: { value: [], properties: { + color: {}, + position: {}, + width: {}, + height: {} + } }, - } + ltc_1: { value: null }, + ltc_2: { value: null } }, - updateMatrixWorld: function ( force ) { - - Mesh.prototype.updateMatrixWorld.call( this, force ); - - if ( this.bindMode === 'attached' ) { - - this.bindMatrixInverse.getInverse( this.matrixWorld ); - - } else if ( this.bindMode === 'detached' ) { - - this.bindMatrixInverse.getInverse( this.bindMatrix ); - - } else { - - console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); + points: { - } + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, + size: { value: 1.0 }, + scale: { value: 1.0 }, + map: { value: null }, + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 }, + uvTransform: { value: /*@__PURE__*/ new Matrix3() } }, - clone: function () { + sprite: { - return new this.constructor( this.geometry, this.material ).copy( this ); + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, + center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, + rotation: { value: 0.0 }, + map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * linecap: "round", - * linejoin: "round" - * } - */ - -function LineBasicMaterial( parameters ) { +}; - Material.call( this ); +const ShaderLib = { - this.type = 'LineBasicMaterial'; + basic: { - this.color = new Color( 0xffffff ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.fog + ] ), - this.linewidth = 1; - this.linecap = 'round'; - this.linejoin = 'round'; + vertexShader: ShaderChunk.meshbasic_vert, + fragmentShader: ShaderChunk.meshbasic_frag - this.lights = false; + }, - this.setValues( parameters ); + lambert: { -} + 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 Color( 0x000000 ) } + } + ] ), -LineBasicMaterial.prototype = Object.create( Material.prototype ); -LineBasicMaterial.prototype.constructor = LineBasicMaterial; + vertexShader: ShaderChunk.meshlambert_vert, + fragmentShader: ShaderChunk.meshlambert_frag -LineBasicMaterial.prototype.isLineBasicMaterial = true; + }, -LineBasicMaterial.prototype.copy = function ( source ) { + phong: { - Material.prototype.copy.call( this, source ); + 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 Color( 0x000000 ) }, + specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, + shininess: { value: 30 } + } + ] ), - this.color.copy( source.color ); + vertexShader: ShaderChunk.meshphong_vert, + fragmentShader: ShaderChunk.meshphong_frag - this.linewidth = source.linewidth; - this.linecap = source.linecap; - this.linejoin = source.linejoin; + }, - return this; + 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 Color( 0x000000 ) }, + roughness: { value: 1.0 }, + metalness: { value: 0.0 }, + envMapIntensity: { value: 1 } + } + ] ), -/** - * @author mrdoob / http://mrdoob.com/ - */ + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag -function Line( geometry, material, mode ) { + }, - if ( mode === 1 ) { + toon: { - console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' ); - return new LineSegments( geometry, material ); + 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 Color( 0x000000 ) } + } + ] ), - } + vertexShader: ShaderChunk.meshtoon_vert, + fragmentShader: ShaderChunk.meshtoon_frag - Object3D.call( this ); + }, - this.type = 'Line'; + matcap: { - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.fog, + { + matcap: { value: null } + } + ] ), -} + vertexShader: ShaderChunk.meshmatcap_vert, + fragmentShader: ShaderChunk.meshmatcap_frag -Line.prototype = Object.assign( Object.create( Object3D.prototype ), { + }, - constructor: Line, + points: { - isLine: true, + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.points, + UniformsLib.fog + ] ), - raycast: ( function () { + vertexShader: ShaderChunk.points_vert, + fragmentShader: ShaderChunk.points_frag - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + }, - return function raycast( raycaster, intersects ) { + dashed: { - var precision = raycaster.linePrecision; - var precisionSq = precision * precision; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.fog, + { + scale: { value: 1 }, + dashSize: { value: 1 }, + totalSize: { value: 2 } + } + ] ), - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; + vertexShader: ShaderChunk.linedashed_vert, + fragmentShader: ShaderChunk.linedashed_frag - // Checking boundingSphere distance to ray + }, - if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); } + depth: { - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.displacementmap + ] ), - if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; } + vertexShader: ShaderChunk.depth_vert, + fragmentShader: ShaderChunk.depth_frag - // + }, - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + normal: { - var vStart = new Vector3(); - var vEnd = new Vector3(); - var interSegment = new Vector3(); - var interRay = new Vector3(); - var step = ( this && this.isLineSegments ) ? 2 : 1; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + { + opacity: { value: 1.0 } + } + ] ), - if ( geometry.isBufferGeometry ) { + vertexShader: ShaderChunk.meshnormal_vert, + fragmentShader: ShaderChunk.meshnormal_frag - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; + }, - if ( index !== null ) { + sprite: { - var indices = index.array; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.sprite, + UniformsLib.fog + ] ), - for ( var i = 0, l = indices.length - 1; i < l; i += step ) { + vertexShader: ShaderChunk.sprite_vert, + fragmentShader: ShaderChunk.sprite_frag - var a = indices[ i ]; - var b = indices[ i + 1 ]; + }, - vStart.fromArray( positions, a * 3 ); - vEnd.fromArray( positions, b * 3 ); + background: { - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + uniforms: { + uvTransform: { value: /*@__PURE__*/ new Matrix3() }, + t2D: { value: null }, + backgroundIntensity: { value: 1 } + }, - if ( distSq > precisionSq ) { continue; } + vertexShader: ShaderChunk.background_vert, + fragmentShader: ShaderChunk.background_frag - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + }, - var distance = raycaster.ray.origin.distanceTo( interRay ); + backgroundCube: { - if ( distance < raycaster.near || distance > raycaster.far ) { continue; } + uniforms: { + envMap: { value: null }, + flipEnvMap: { value: - 1 }, + backgroundBlurriness: { value: 0 }, + backgroundIntensity: { value: 1 }, + backgroundRotation: { value: /*@__PURE__*/ new Matrix3() } + }, - intersects.push( { + vertexShader: ShaderChunk.backgroundCube_vert, + fragmentShader: ShaderChunk.backgroundCube_frag - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + }, - } ); + cube: { - } + uniforms: { + tCube: { value: null }, + tFlip: { value: - 1 }, + opacity: { value: 1.0 } + }, - } else { + vertexShader: ShaderChunk.cube_vert, + fragmentShader: ShaderChunk.cube_frag - for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) { + }, - vStart.fromArray( positions, 3 * i ); - vEnd.fromArray( positions, 3 * i + 3 ); + equirect: { - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + uniforms: { + tEquirect: { value: null }, + }, - if ( distSq > precisionSq ) { continue; } + vertexShader: ShaderChunk.equirect_vert, + fragmentShader: ShaderChunk.equirect_frag - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + }, - var distance = raycaster.ray.origin.distanceTo( interRay ); + distanceRGBA: { - if ( distance < raycaster.near || distance > raycaster.far ) { continue; } + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.displacementmap, + { + referencePosition: { value: /*@__PURE__*/ new Vector3() }, + nearDistance: { value: 1 }, + farDistance: { value: 1000 } + } + ] ), - intersects.push( { + vertexShader: ShaderChunk.distanceRGBA_vert, + fragmentShader: ShaderChunk.distanceRGBA_frag - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + }, - } ); + shadow: { - } + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.lights, + UniformsLib.fog, + { + color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, + opacity: { value: 1.0 } + }, + ] ), - } + vertexShader: ShaderChunk.shadow_vert, + fragmentShader: ShaderChunk.shadow_frag - } else if ( geometry.isGeometry ) { + } - var vertices = geometry.vertices; - var nbVertices = vertices.length; +}; - for ( var i = 0; i < nbVertices - 1; i += step ) { +ShaderLib.physical = { - var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + ShaderLib.standard.uniforms, + { + clearcoat: { value: 0 }, + clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, + clearcoatRoughness: { value: 0 }, + clearcoatRoughnessMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + dispersion: { value: 0 }, + iridescence: { value: 0 }, + iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + iridescenceIOR: { value: 1.3 }, + iridescenceThicknessMinimum: { value: 100 }, + iridescenceThicknessMaximum: { value: 400 }, + iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + sheen: { value: 0 }, + sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, + sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + sheenRoughness: { value: 1 }, + sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + transmission: { value: 0 }, + transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, + transmissionSamplerMap: { value: null }, + thickness: { value: 0 }, + thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + attenuationDistance: { value: 0 }, + attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, + specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, + specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + } + ] ), - if ( distSq > precisionSq ) { continue; } + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation +}; - var distance = raycaster.ray.origin.distanceTo( interRay ); +const _rgb = { r: 0, b: 0, g: 0 }; +const _e1$1 = /*@__PURE__*/ new Euler(); +const _m1$1 = /*@__PURE__*/ new Matrix4(); - if ( distance < raycaster.near || distance > raycaster.far ) { continue; } +function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { - intersects.push( { + const clearColor = new Color( 0x000000 ); + let clearAlpha = alpha === true ? 0 : 1; - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + let planeMesh; + let boxMesh; - } ); + let currentBackground = null; + let currentBackgroundVersion = 0; + let currentTonemapping = null; - } + function getBackground( scene ) { - } + let background = scene.isScene === true ? scene.background : null; - }; + if ( background && background.isTexture ) { - }() ), + const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background + background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); - clone: function () { + } - return new this.constructor( this.geometry, this.material ).copy( this ); + return background; } -} ); + function render( scene ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function LineSegments( geometry, material ) { - - Line.call( this, geometry, material ); + let forceClear = false; + const background = getBackground( scene ); - this.type = 'LineSegments'; + if ( background === null ) { -} + setClear( clearColor, clearAlpha ); -LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { + } else if ( background && background.isColor ) { - constructor: LineSegments, + setClear( background, 1 ); + forceClear = true; - isLineSegments: true + } -} ); + const environmentBlendMode = renderer.xr.getEnvironmentBlendMode(); -/** - * @author mgreter / http://github.com/mgreter - */ + if ( environmentBlendMode === 'additive' ) { -function LineLoop( geometry, material ) { + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); - Line.call( this, geometry, material ); + } else if ( environmentBlendMode === 'alpha-blend' ) { - this.type = 'LineLoop'; + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); -} + } -LineLoop.prototype = Object.assign( Object.create( Line.prototype ), { + if ( renderer.autoClear || forceClear ) { - constructor: LineLoop, + // buffers might not be writable which is required to ensure a correct clear - isLineLoop: true, + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); -} ); + renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * size: , - * sizeAttenuation: - * } - */ + } -function PointsMaterial( parameters ) { + } - Material.call( this ); + function addToRenderList( renderList, scene ) { - this.type = 'PointsMaterial'; + const background = getBackground( scene ); - this.color = new Color( 0xffffff ); + if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { - this.map = null; + if ( boxMesh === undefined ) { - this.size = 1; - this.sizeAttenuation = true; + boxMesh = new Mesh( + new BoxGeometry( 1, 1, 1 ), + new ShaderMaterial( { + name: 'BackgroundCubeMaterial', + uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), + vertexShader: ShaderLib.backgroundCube.vertexShader, + fragmentShader: ShaderLib.backgroundCube.fragmentShader, + side: BackSide, + depthTest: false, + depthWrite: false, + fog: false + } ) + ); - this.lights = false; + boxMesh.geometry.deleteAttribute( 'normal' ); + boxMesh.geometry.deleteAttribute( 'uv' ); - this.setValues( parameters ); + boxMesh.onBeforeRender = function ( renderer, scene, camera ) { -} + this.matrixWorld.copyPosition( camera.matrixWorld ); -PointsMaterial.prototype = Object.create( Material.prototype ); -PointsMaterial.prototype.constructor = PointsMaterial; + }; -PointsMaterial.prototype.isPointsMaterial = true; + // add "envMap" material property so the renderer can evaluate it like for built-in materials + Object.defineProperty( boxMesh.material, 'envMap', { -PointsMaterial.prototype.copy = function ( source ) { + get: function () { - Material.prototype.copy.call( this, source ); + return this.uniforms.envMap.value; - this.color.copy( source.color ); + } - this.map = source.map; + } ); - this.size = source.size; - this.sizeAttenuation = source.sizeAttenuation; + objects.update( boxMesh ); - return this; + } -}; + _e1$1.copy( scene.backgroundRotation ); -/** - * @author alteredq / http://alteredqualia.com/ - */ + // accommodate left-handed frame + _e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1; -function Points$1( geometry, material ) { + if ( background.isCubeTexture && background.isRenderTargetTexture === false ) { - Object3D.call( this ); + // environment maps which are not cube render targets or PMREMs follow a different convention + _e1$1.y *= - 1; + _e1$1.z *= - 1; - this.type = 'Points'; + } - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } ); + boxMesh.material.uniforms.envMap.value = background; + boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; + boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; + boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; + boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) ); + boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; -} + if ( currentBackground !== background || + currentBackgroundVersion !== background.version || + currentTonemapping !== renderer.toneMapping ) { -Points$1.prototype = Object.assign( Object.create( Object3D.prototype ), { + boxMesh.material.needsUpdate = true; - constructor: Points$1, + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; - isPoints: true, + } - raycast: ( function () { + boxMesh.layers.enableAll(); - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + // push to the pre-sorted opaque render list + renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); - return function raycast( raycaster, intersects ) { + } else if ( background && background.isTexture ) { - var object = this; - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; - var threshold = raycaster.params.Points.threshold; + if ( planeMesh === undefined ) { - // Checking boundingSphere distance to ray + 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 + } ) + ); - if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); } + planeMesh.geometry.deleteAttribute( 'normal' ); - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - sphere.radius += threshold; + // add "map" material property so the renderer can evaluate it like for built-in materials + Object.defineProperty( planeMesh.material, 'map', { - if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; } + get: function () { - // + return this.uniforms.t2D.value; - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + } - var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); - var localThresholdSq = localThreshold * localThreshold; - var position = new Vector3(); + } ); - function testPoint( point, index ) { + objects.update( planeMesh ); - var rayPointDistanceSq = ray.distanceSqToPoint( point ); + } - if ( rayPointDistanceSq < localThresholdSq ) { + planeMesh.material.uniforms.t2D.value = background; + planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; + planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; - var intersectPoint = ray.closestPointToPoint( point ); - intersectPoint.applyMatrix4( matrixWorld ); + if ( background.matrixAutoUpdate === true ) { - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); + background.updateMatrix(); - if ( distance < raycaster.near || distance > raycaster.far ) { return; } + } - intersects.push( { + planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); - distance: distance, - distanceToRay: Math.sqrt( rayPointDistanceSq ), - point: intersectPoint.clone(), - index: index, - face: null, - object: object + if ( currentBackground !== background || + currentBackgroundVersion !== background.version || + currentTonemapping !== renderer.toneMapping ) { - } ); + planeMesh.material.needsUpdate = true; - } + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; } - if ( geometry.isBufferGeometry ) { - - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; + planeMesh.layers.enableAll(); - if ( index !== null ) { + // push to the pre-sorted opaque render list + renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); - var indices = index.array; - - for ( var i = 0, il = indices.length; i < il; i ++ ) { + } - var a = indices[ i ]; + } - position.fromArray( positions, a * 3 ); + function setClear( color, alpha ) { - testPoint( position, a ); + color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); - } + state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); - } else { + } - for ( var i = 0, l = positions.length / 3; i < l; i ++ ) { + return { - position.fromArray( positions, i * 3 ); + getClearColor: function () { - testPoint( position, i ); + return clearColor; - } + }, + setClearColor: function ( color, alpha = 1 ) { - } + clearColor.set( color ); + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); - } else { + }, + getClearAlpha: function () { - var vertices = geometry.vertices; + return clearAlpha; - for ( var i = 0, l = vertices.length; i < l; i ++ ) { + }, + setClearAlpha: function ( alpha ) { - testPoint( vertices[ i ], i ); + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); - } + }, + render: render, + addToRenderList: addToRenderList - } + }; - }; +} - }() ), +function WebGLBindingStates( gl, attributes ) { - clone: function () { + const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - return new this.constructor( this.geometry, this.material ).copy( this ); + const bindingStates = {}; - } + const defaultState = createBindingState( null ); + let currentState = defaultState; + let forceUpdate = false; -} ); + function setup( object, material, program, geometry, index ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + let updateBuffers = false; -function Group() { + const state = getBindingState( geometry, program, material ); - Object3D.call( this ); + if ( currentState !== state ) { - this.type = 'Group'; + currentState = state; + bindVertexArrayObject( currentState.object ); -} + } -Group.prototype = Object.assign( Object.create( Object3D.prototype ), { + updateBuffers = needsUpdate( object, geometry, program, index ); - constructor: Group, + if ( updateBuffers ) saveCache( object, geometry, program, index ); - isGroup: true + if ( index !== null ) { -} ); + attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + if ( updateBuffers || forceUpdate ) { - Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + forceUpdate = false; - this.generateMipmaps = false; + setupVertexAttributes( object, material, program, geometry ); - // Set needsUpdate when first frame is ready + if ( index !== null ) { - var scope = this; + gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); - function onLoaded() { + } - video.removeEventListener( 'loadeddata', onLoaded, false ); - scope.needsUpdate = true; + } } - video.addEventListener( 'loadeddata', onLoaded, false ); - -} - -VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), { + function createVertexArrayObject() { - constructor: VideoTexture, + return gl.createVertexArray(); - isVideoTexture: true, + } - update: function () { + function bindVertexArrayObject( vao ) { - var video = this.image; + return gl.bindVertexArray( vao ); - if ( video.readyState >= video.HAVE_CURRENT_DATA ) { + } - this.needsUpdate = true; + function deleteVertexArrayObject( vao ) { - } + return gl.deleteVertexArray( vao ); } -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - */ - -function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + function getBindingState( geometry, program, material ) { - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + const wireframe = ( material.wireframe === true ); - this.image = { width: width, height: height }; - this.mipmaps = mipmaps; + let programMap = bindingStates[ geometry.id ]; - // no flipping for cube textures - // (also flipping doesn't work for compressed textures ) + if ( programMap === undefined ) { - this.flipY = false; + programMap = {}; + bindingStates[ geometry.id ] = programMap; - // can't generate mipmaps for compressed textures - // mips must be embedded in DDS files + } - this.generateMipmaps = false; + let stateMap = programMap[ program.id ]; -} + if ( stateMap === undefined ) { -CompressedTexture.prototype = Object.create( Texture.prototype ); -CompressedTexture.prototype.constructor = CompressedTexture; + stateMap = {}; + programMap[ program.id ] = stateMap; -CompressedTexture.prototype.isCompressedTexture = true; + } -/** - * @author Matt DesLauriers / @mattdesl - * @author atix / arthursilber.de - */ + let state = stateMap[ wireframe ]; -function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { + if ( state === undefined ) { - format = format !== undefined ? format : DepthFormat; + state = createBindingState( createVertexArrayObject() ); + stateMap[ wireframe ] = state; - if ( format !== DepthFormat && format !== DepthStencilFormat ) { + } - throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); + return state; } - if ( type === undefined && format === DepthFormat ) { type = UnsignedShortType; } - if ( type === undefined && format === DepthStencilFormat ) { type = UnsignedInt248Type; } - - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + function createBindingState( vao ) { - this.image = { width: width, height: height }; + const newAttributes = []; + const enabledAttributes = []; + const attributeDivisors = []; - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + for ( let i = 0; i < maxVertexAttributes; i ++ ) { - this.flipY = false; - this.generateMipmaps = false; - -} + newAttributes[ i ] = 0; + enabledAttributes[ i ] = 0; + attributeDivisors[ i ] = 0; -DepthTexture.prototype = Object.create( Texture.prototype ); -DepthTexture.prototype.constructor = DepthTexture; -DepthTexture.prototype.isDepthTexture = true; + } -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + return { -function WireframeGeometry( geometry ) { + // for backward compatibility on non-VAO support browser + geometry: null, + program: null, + wireframe: false, - BufferGeometry.call( this ); + newAttributes: newAttributes, + enabledAttributes: enabledAttributes, + attributeDivisors: attributeDivisors, + object: vao, + attributes: {}, + index: null - this.type = 'WireframeGeometry'; + }; - // buffer + } - var vertices = []; + function needsUpdate( object, geometry, program, index ) { - // helper variables + const cachedAttributes = currentState.attributes; + const geometryAttributes = geometry.attributes; - var i, j, l, o, ol; - var edge = [ 0, 0 ], edges = {}, e, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; - var vertex; + let attributesNum = 0; - // different logic for Geometry and BufferGeometry + const programAttributes = program.getAttributes(); - if ( geometry && geometry.isGeometry ) { + for ( const name in programAttributes ) { - // create a data structure that contains all edges without duplicates + const programAttribute = programAttributes[ name ]; - var faces = geometry.faces; + if ( programAttribute.location >= 0 ) { - for ( i = 0, l = faces.length; i < l; i ++ ) { + const cachedAttribute = cachedAttributes[ name ]; + let geometryAttribute = geometryAttributes[ name ]; - var face = faces[ i ]; + if ( geometryAttribute === undefined ) { - for ( j = 0; j < 3; j ++ ) { + if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); + } - key = edge[ 0 ] + ',' + edge[ 1 ]; + if ( cachedAttribute === undefined ) return true; - if ( edges[ key ] === undefined ) { + if ( cachedAttribute.attribute !== geometryAttribute ) return true; - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; + if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; - } + attributesNum ++; } } - // generate vertices - - for ( key in edges ) { + if ( currentState.attributesNum !== attributesNum ) return true; - e = edges[ key ]; + if ( currentState.index !== index ) return true; - vertex = geometry.vertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - vertex = geometry.vertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } + return false; - } else if ( geometry && geometry.isBufferGeometry ) { + } - var position, indices, groups; - var group, start, count; - var index1, index2; + function saveCache( object, geometry, program, index ) { - vertex = new Vector3(); + const cache = {}; + const attributes = geometry.attributes; + let attributesNum = 0; - if ( geometry.index !== null ) { + const programAttributes = program.getAttributes(); - // indexed BufferGeometry + for ( const name in programAttributes ) { - position = geometry.attributes.position; - indices = geometry.index; - groups = geometry.groups; + const programAttribute = programAttributes[ name ]; - if ( groups.length === 0 ) { + if ( programAttribute.location >= 0 ) { - groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; + let attribute = attributes[ name ]; - } + if ( attribute === undefined ) { - // create a data structure that contains all eges without duplicates + if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; - for ( o = 0, ol = groups.length; o < ol; ++ o ) { + } - group = groups[ o ]; + const data = {}; + data.attribute = attribute; - start = group.start; - count = group.count; + if ( attribute && attribute.data ) { - for ( i = start, l = ( start + count ); i < l; i += 3 ) { + data.data = attribute.data; - for ( j = 0; j < 3; j ++ ) { + } - edge1 = indices.getX( i + j ); - edge2 = indices.getX( i + ( j + 1 ) % 3 ); - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); + cache[ name ] = data; - key = edge[ 0 ] + ',' + edge[ 1 ]; + attributesNum ++; - if ( edges[ key ] === undefined ) { + } - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; + } - } + currentState.attributes = cache; + currentState.attributesNum = attributesNum; - } + currentState.index = index; - } + } - } + function initAttributes() { - // generate vertices + const newAttributes = currentState.newAttributes; - for ( key in edges ) { + for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { - e = edges[ key ]; + newAttributes[ i ] = 0; - vertex.fromBufferAttribute( position, e.index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - vertex.fromBufferAttribute( position, e.index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - } + function enableAttribute( attribute ) { - } else { + enableAttributeAndDivisor( attribute, 0 ); - // non-indexed BufferGeometry + } - position = geometry.attributes.position; + function enableAttributeAndDivisor( attribute, meshPerAttribute ) { - for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) { + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + const attributeDivisors = currentState.attributeDivisors; - for ( j = 0; j < 3; j ++ ) { + newAttributes[ attribute ] = 1; - // three edges per triangle, an edge is represented as (index1, index2) - // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) + if ( enabledAttributes[ attribute ] === 0 ) { - index1 = 3 * i + j; - vertex.fromBufferAttribute( position, index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + gl.enableVertexAttribArray( attribute ); + enabledAttributes[ attribute ] = 1; - index2 = 3 * i + ( ( j + 1 ) % 3 ); - vertex.fromBufferAttribute( position, index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - } + if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { - } + gl.vertexAttribDivisor( attribute, meshPerAttribute ); + attributeDivisors[ attribute ] = meshPerAttribute; } } - // build geometry - - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - -} + function disableUnusedAttributes() { -WireframeGeometry.prototype = Object.create( BufferGeometry.prototype ); -WireframeGeometry.prototype.constructor = WireframeGeometry; + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; -/** - * @author zz85 / https://github.com/zz85 - * @author Mugen87 / https://github.com/Mugen87 - * - * Parametric Surfaces Geometry - * based on the brilliant article by @prideout http://prideout.net/blog/?p=44 - */ + for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { -// ParametricGeometry + if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { -function ParametricGeometry( func, slices, stacks ) { + gl.disableVertexAttribArray( i ); + enabledAttributes[ i ] = 0; - Geometry.call( this ); + } - this.type = 'ParametricGeometry'; + } - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + } - this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) ); - this.mergeVertices(); + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { -} + if ( integer === true ) { -ParametricGeometry.prototype = Object.create( Geometry.prototype ); -ParametricGeometry.prototype.constructor = ParametricGeometry; + gl.vertexAttribIPointer( index, size, type, stride, offset ); -// ParametricBufferGeometry + } else { -function ParametricBufferGeometry( func, slices, stacks ) { + gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); - BufferGeometry.call( this ); + } - this.type = 'ParametricBufferGeometry'; + } - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + function setupVertexAttributes( object, material, program, geometry ) { - // buffers + initAttributes(); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + const geometryAttributes = geometry.attributes; - var EPS = 0.00001; + const programAttributes = program.getAttributes(); - var normal = new Vector3(); + const materialDefaultAttributeValues = material.defaultAttributeValues; - var p0 = new Vector3(), p1 = new Vector3(); - var pu = new Vector3(), pv = new Vector3(); + for ( const name in programAttributes ) { - var i, j; + const programAttribute = programAttributes[ name ]; - // generate vertices, normals and uvs + if ( programAttribute.location >= 0 ) { - var sliceCount = slices + 1; + let geometryAttribute = geometryAttributes[ name ]; - for ( i = 0; i <= stacks; i ++ ) { + if ( geometryAttribute === undefined ) { - var v = i / stacks; + if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; - for ( j = 0; j <= slices; j ++ ) { + } - var u = j / slices; + if ( geometryAttribute !== undefined ) { - // vertex + const normalized = geometryAttribute.normalized; + const size = geometryAttribute.itemSize; - p0 = func( u, v, p0 ); - vertices.push( p0.x, p0.y, p0.z ); + const attribute = attributes.get( geometryAttribute ); - // normal + // TODO Attribute may not be available on context restore - // approximate tangent vectors via finite differences + if ( attribute === undefined ) continue; - if ( u - EPS >= 0 ) { + const buffer = attribute.buffer; + const type = attribute.type; + const bytesPerElement = attribute.bytesPerElement; - p1 = func( u - EPS, v, p1 ); - pu.subVectors( p0, p1 ); + // check for integer attributes - } else { + const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ); - p1 = func( u + EPS, v, p1 ); - pu.subVectors( p1, p0 ); + if ( geometryAttribute.isInterleavedBufferAttribute ) { - } + const data = geometryAttribute.data; + const stride = data.stride; + const offset = geometryAttribute.offset; - if ( v - EPS >= 0 ) { + if ( data.isInstancedInterleavedBuffer ) { - p1 = func( u, v - EPS, p1 ); - pv.subVectors( p0, p1 ); + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - } else { + enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); - p1 = func( u, v + EPS, p1 ); - pv.subVectors( p1, p0 ); + } - } + if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { - // cross product of tangent vectors returns surface normal + geometry._maxInstanceCount = data.meshPerAttribute * data.count; - normal.crossVectors( pu, pv ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + } - // uv + } else { - uvs.push( u, v ); + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - } + enableAttribute( programAttribute.location + i ); - } + } - // generate indices + } - for ( i = 0; i < stacks; i ++ ) { + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); - for ( j = 0; j < slices; j ++ ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - var a = i * sliceCount + j; - var b = i * sliceCount + j + 1; - var c = ( i + 1 ) * sliceCount + j + 1; - var d = ( i + 1 ) * sliceCount + j; + vertexAttribPointer( + programAttribute.location + i, + size / programAttribute.locationSize, + type, + normalized, + stride * bytesPerElement, + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer + ); - // faces one and two + } - indices.push( a, b, d ); - indices.push( b, c, d ); + } else { - } + if ( geometryAttribute.isInstancedBufferAttribute ) { - } + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - // build geometry + enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + } -} + if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { -ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry; + geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; -/** - * @author clockworkgeek / https://github.com/clockworkgeek - * @author timothypratley / https://github.com/timothypratley - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ + } -// PolyhedronGeometry + } else { -function PolyhedronGeometry( vertices, indices, radius, detail ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - Geometry.call( this ); + enableAttribute( programAttribute.location + i ); - this.type = 'PolyhedronGeometry'; + } - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; + } - this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) ); - this.mergeVertices(); + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); -} + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { -PolyhedronGeometry.prototype = Object.create( Geometry.prototype ); -PolyhedronGeometry.prototype.constructor = PolyhedronGeometry; + vertexAttribPointer( + programAttribute.location + i, + size / programAttribute.locationSize, + type, + normalized, + size * bytesPerElement, + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer + ); -// PolyhedronBufferGeometry + } -function PolyhedronBufferGeometry( vertices, indices, radius, detail ) { + } - BufferGeometry.call( this ); + } else if ( materialDefaultAttributeValues !== undefined ) { - this.type = 'PolyhedronBufferGeometry'; + const value = materialDefaultAttributeValues[ name ]; - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; + if ( value !== undefined ) { - radius = radius || 1; - detail = detail || 0; + switch ( value.length ) { - // default buffer data + case 2: + gl.vertexAttrib2fv( programAttribute.location, value ); + break; - var vertexBuffer = []; - var uvBuffer = []; + case 3: + gl.vertexAttrib3fv( programAttribute.location, value ); + break; - // the subdivision creates the vertex buffer data + case 4: + gl.vertexAttrib4fv( programAttribute.location, value ); + break; - subdivide( detail ); + default: + gl.vertexAttrib1fv( programAttribute.location, value ); - // all vertices should lie on a conceptual sphere with a given radius + } - appplyRadius( radius ); + } - // finally, create the uv data + } - generateUVs(); + } - // build non-indexed geometry + } - this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); + disableUnusedAttributes(); - if ( detail === 0 ) { + } - this.computeVertexNormals(); // flat normals + function dispose() { - } else { + reset(); - this.normalizeNormals(); // smooth normals + for ( const geometryId in bindingStates ) { - } + const programMap = bindingStates[ geometryId ]; - // helper functions + for ( const programId in programMap ) { - function subdivide( detail ) { + const stateMap = programMap[ programId ]; - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); + for ( const wireframe in stateMap ) { - // iterate over all faces and apply a subdivison with the given detail value + deleteVertexArrayObject( stateMap[ wireframe ].object ); - for ( var i = 0; i < indices.length; i += 3 ) { + delete stateMap[ wireframe ]; - // get the vertices of the face + } - getVertexByIndex( indices[ i + 0 ], a ); - getVertexByIndex( indices[ i + 1 ], b ); - getVertexByIndex( indices[ i + 2 ], c ); + delete programMap[ programId ]; - // perform subdivision + } - subdivideFace( a, b, c, detail ); + delete bindingStates[ geometryId ]; } } - function subdivideFace( a, b, c, detail ) { + function releaseStatesOfGeometry( geometry ) { - var cols = Math.pow( 2, detail ); + if ( bindingStates[ geometry.id ] === undefined ) return; - // we use this multidimensional array as a data structure for creating the subdivision + const programMap = bindingStates[ geometry.id ]; - var v = []; + for ( const programId in programMap ) { - var i, j; + const stateMap = programMap[ programId ]; - // construct all of the vertices for this subdivision + for ( const wireframe in stateMap ) { - for ( i = 0; i <= cols; i ++ ) { + deleteVertexArrayObject( stateMap[ wireframe ].object ); - v[ i ] = []; + delete stateMap[ wireframe ]; - var aj = a.clone().lerp( c, i / cols ); - var bj = b.clone().lerp( c, i / cols ); + } - var rows = cols - i; + delete programMap[ programId ]; - for ( j = 0; j <= rows; j ++ ) { + } - if ( j === 0 && i === cols ) { + delete bindingStates[ geometry.id ]; - v[ i ][ j ] = aj; + } - } else { + function releaseStatesOfProgram( program ) { - v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); + for ( const geometryId in bindingStates ) { - } + const programMap = bindingStates[ geometryId ]; - } + if ( programMap[ program.id ] === undefined ) continue; - } + const stateMap = programMap[ program.id ]; - // construct all of the faces + for ( const wireframe in stateMap ) { - for ( i = 0; i < cols; i ++ ) { + deleteVertexArrayObject( stateMap[ wireframe ].object ); - for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { + delete stateMap[ wireframe ]; - var k = Math.floor( j / 2 ); + } - if ( j % 2 === 0 ) { + delete programMap[ program.id ]; - 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 reset() { - } + resetDefaultState(); + forceUpdate = true; - } + if ( currentState === defaultState ) return; - } + currentState = defaultState; + bindVertexArrayObject( currentState.object ); } - function appplyRadius( radius ) { + // for backward-compatibility - var vertex = new Vector3(); + function resetDefaultState() { - // iterate over the entire buffer and apply the radius to each vertex + defaultState.geometry = null; + defaultState.program = null; + defaultState.wireframe = false; - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { + } - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; + return { - vertex.normalize().multiplyScalar( radius ); + setup: setup, + reset: reset, + resetDefaultState: resetDefaultState, + dispose: dispose, + releaseStatesOfGeometry: releaseStatesOfGeometry, + releaseStatesOfProgram: releaseStatesOfProgram, - vertexBuffer[ i + 0 ] = vertex.x; - vertexBuffer[ i + 1 ] = vertex.y; - vertexBuffer[ i + 2 ] = vertex.z; + initAttributes: initAttributes, + enableAttribute: enableAttribute, + disableUnusedAttributes: disableUnusedAttributes - } + }; - } +} - function generateUVs() { +function WebGLBufferRenderer( gl, extensions, info ) { - var vertex = new Vector3(); + let mode; - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { + function setMode( value ) { - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; + mode = value; - var u = azimuth( vertex ) / 2 / Math.PI + 0.5; - var v = inclination( vertex ) / Math.PI + 0.5; - uvBuffer.push( u, 1 - v ); + } - } + function render( start, count ) { - correctUVs(); + gl.drawArrays( mode, start, count ); - correctSeam(); + info.update( count, mode, 1 ); } - function correctSeam() { + function renderInstances( start, count, primcount ) { - // handle case when face straddles the seam, see #3269 + if ( primcount === 0 ) return; - for ( var i = 0; i < uvBuffer.length; i += 6 ) { + gl.drawArraysInstanced( mode, start, count, primcount ); - // uv data of a single face + info.update( count, mode, primcount ); - var x0 = uvBuffer[ i + 0 ]; - var x1 = uvBuffer[ i + 2 ]; - var x2 = uvBuffer[ i + 4 ]; + } - var max = Math.max( x0, x1, x2 ); - var min = Math.min( x0, x1, x2 ); + function renderMultiDraw( starts, counts, drawCount ) { - // 0.9 is somewhat arbitrary + if ( drawCount === 0 ) return; - if ( max > 0.9 && min < 0.1 ) { + const extension = extensions.get( 'WEBGL_multi_draw' ); + extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); - if ( x0 < 0.2 ) { uvBuffer[ i + 0 ] += 1; } - if ( x1 < 0.2 ) { uvBuffer[ i + 2 ] += 1; } - if ( x2 < 0.2 ) { uvBuffer[ i + 4 ] += 1; } + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - } + elementCount += counts[ i ]; } - } - - function pushVertex( vertex ) { - - vertexBuffer.push( vertex.x, vertex.y, vertex.z ); + info.update( elementCount, mode, 1 ); } - function getVertexByIndex( index, vertex ) { + function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { - var stride = index * 3; + if ( drawCount === 0 ) return; - vertex.x = vertices[ stride + 0 ]; - vertex.y = vertices[ stride + 1 ]; - vertex.z = vertices[ stride + 2 ]; + const extension = extensions.get( 'WEBGL_multi_draw' ); - } + if ( extension === null ) { - function correctUVs() { + for ( let i = 0; i < starts.length; i ++ ) { - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); + renderInstances( starts[ i ], counts[ i ], primcount[ i ] ); + + } - var centroid = new Vector3(); + } else { - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount ); - for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); - b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); - c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); + elementCount += counts[ i ]; - 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( a ).add( b ).add( c ).divideScalar( 3 ); + for ( let i = 0; i < primcount.length; i ++ ) { - var azi = azimuth( centroid ); + info.update( elementCount, mode, primcount[ i ] ); - correctUV( uvA, j + 0, a, azi ); - correctUV( uvB, j + 2, b, azi ); - correctUV( uvC, j + 4, c, azi ); + } } } - function correctUV( uv, stride, vector, azimuth ) { + // - if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { + this.setMode = setMode; + this.render = render; + this.renderInstances = renderInstances; + this.renderMultiDraw = renderMultiDraw; + this.renderMultiDrawInstances = renderMultiDrawInstances; - uvBuffer[ stride ] = uv.x - 1; +} - } +function WebGLCapabilities( gl, extensions, parameters, utils ) { - if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { + let maxAnisotropy; - uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; + function getMaxAnisotropy() { - } + if ( maxAnisotropy !== undefined ) return maxAnisotropy; - } + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { - // Angle around the Y axis, counter-clockwise when looking from above. + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); - function azimuth( vector ) { + maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); - return Math.atan2( vector.z, - vector.x ); + } else { - } + maxAnisotropy = 0; + } - // Angle above the XZ plane. + return maxAnisotropy; - function inclination( vector ) { + } - return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); + function textureFormatReadable( textureFormat ) { - } + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { -} + return false; -PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry; + } -/** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + return true; -// TetrahedronGeometry + } -function TetrahedronGeometry( radius, detail ) { + function textureTypeReadable( textureType ) { - Geometry.call( this ); + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ); - this.type = 'TetrahedronGeometry'; + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + textureType !== FloatType && ! halfFloatSupportedByExt ) { - this.parameters = { - radius: radius, - detail: detail - }; + return false; - this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + } -} + return true; -TetrahedronGeometry.prototype = Object.create( Geometry.prototype ); -TetrahedronGeometry.prototype.constructor = TetrahedronGeometry; + } -// TetrahedronBufferGeometry + function getMaxPrecision( precision ) { -function TetrahedronBufferGeometry( radius, detail ) { + if ( precision === 'highp' ) { - var vertices = [ - 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 - ]; + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { - var indices = [ - 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 - ]; + return 'highp'; - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + } - this.type = 'TetrahedronBufferGeometry'; + precision = 'mediump'; - this.parameters = { - radius: radius, - detail: detail - }; + } -} + if ( precision === 'mediump' ) { -TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry; + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { -/** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + return 'mediump'; -// OctahedronGeometry + } -function OctahedronGeometry( radius, detail ) { + } - Geometry.call( this ); + return 'lowp'; - this.type = 'OctahedronGeometry'; + } - this.parameters = { - radius: radius, - detail: detail - }; + let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; + const maxPrecision = getMaxPrecision( precision ); - this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + if ( maxPrecision !== precision ) { -} + console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); + precision = maxPrecision; -OctahedronGeometry.prototype = Object.create( Geometry.prototype ); -OctahedronGeometry.prototype.constructor = OctahedronGeometry; + } -// OctahedronBufferGeometry + const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; -function OctahedronBufferGeometry( radius, detail ) { + 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 ); - var vertices = [ - 1, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, - 1, 0, 0, 0, 1, 0, 0, - 1 - ]; + 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 ); - var 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 - ]; + const vertexTextures = maxVertexTextures > 0; - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + const maxSamples = gl.getParameter( gl.MAX_SAMPLES ); - this.type = 'OctahedronBufferGeometry'; + return { - this.parameters = { - radius: radius, - detail: detail - }; + isWebGL2: true, // keeping this for backwards compatibility -} + getMaxAnisotropy: getMaxAnisotropy, + getMaxPrecision: getMaxPrecision, -OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry; + textureFormatReadable: textureFormatReadable, + textureTypeReadable: textureTypeReadable, -/** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + precision: precision, + logarithmicDepthBuffer: logarithmicDepthBuffer, -// IcosahedronGeometry + maxTextures: maxTextures, + maxVertexTextures: maxVertexTextures, + maxTextureSize: maxTextureSize, + maxCubemapSize: maxCubemapSize, -function IcosahedronGeometry( radius, detail ) { + maxAttributes: maxAttributes, + maxVertexUniforms: maxVertexUniforms, + maxVaryings: maxVaryings, + maxFragmentUniforms: maxFragmentUniforms, - Geometry.call( this ); + vertexTextures: vertexTextures, - this.type = 'IcosahedronGeometry'; + maxSamples: maxSamples - this.parameters = { - radius: radius, - detail: detail }; - this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - } -IcosahedronGeometry.prototype = Object.create( Geometry.prototype ); -IcosahedronGeometry.prototype.constructor = IcosahedronGeometry; +function WebGLClipping( properties ) { -// IcosahedronBufferGeometry + const scope = this; -function IcosahedronBufferGeometry( radius, detail ) { - - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - - var 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 - ]; + let globalState = null, + numGlobalPlanes = 0, + localClippingEnabled = false, + renderingShadows = false; - var 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 - ]; + const plane = new Plane(), + viewNormalMatrix = new Matrix3(), - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + uniform = { value: null, needsUpdate: false }; - this.type = 'IcosahedronBufferGeometry'; + this.uniform = uniform; + this.numPlanes = 0; + this.numIntersection = 0; - this.parameters = { - radius: radius, - detail: detail - }; + this.init = function ( planes, enableLocalClipping ) { -} + const enabled = + planes.length !== 0 || + enableLocalClipping || + // enable state of previous frame - the clipping code has to + // run another frame in order to reset the state: + numGlobalPlanes !== 0 || + localClippingEnabled; -IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry; + localClippingEnabled = enableLocalClipping; -/** - * @author Abe Pazos / https://hamoid.com - * @author Mugen87 / https://github.com/Mugen87 - */ + numGlobalPlanes = planes.length; -// DodecahedronGeometry + return enabled; -function DodecahedronGeometry( radius, detail ) { + }; - Geometry.call( this ); + this.beginShadows = function () { - this.type = 'DodecahedronGeometry'; + renderingShadows = true; + projectPlanes( null ); - this.parameters = { - radius: radius, - detail: detail }; - this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - -} - -DodecahedronGeometry.prototype = Object.create( Geometry.prototype ); -DodecahedronGeometry.prototype.constructor = DodecahedronGeometry; + this.endShadows = function () { -// DodecahedronBufferGeometry + renderingShadows = false; -function DodecahedronBufferGeometry( radius, detail ) { + }; - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - var r = 1 / t; + this.setGlobalState = function ( planes, camera ) { - var vertices = [ + globalState = projectPlanes( planes, camera, 0 ); - // (±1, ±1, ±1) - - 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, ±1/φ, ±φ) - 0, - r, - t, 0, - r, t, - 0, r, - t, 0, r, t, + this.setState = function ( material, camera, useCache ) { - // (±1/φ, ±φ, 0) - - r, - t, 0, - r, t, 0, - r, - t, 0, r, t, 0, + const planes = material.clippingPlanes, + clipIntersection = material.clipIntersection, + clipShadows = material.clipShadows; - // (±φ, 0, ±1/φ) - - t, 0, - r, t, 0, - r, - - t, 0, r, t, 0, r - ]; + const materialProperties = properties.get( material ); - var 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 - ]; + if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + // there's no local clipping - this.type = 'DodecahedronBufferGeometry'; + if ( renderingShadows ) { - this.parameters = { - radius: radius, - detail: detail - }; + // there's no global clipping -} + projectPlanes( null ); -DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry; + } else { -/** - * @author oosmoxiecode / https://github.com/oosmoxiecode - * @author WestLangley / https://github.com/WestLangley - * @author zz85 / https://github.com/zz85 - * @author miningold / https://github.com/miningold - * @author jonobr1 / https://github.com/jonobr1 - * @author Mugen87 / https://github.com/Mugen87 - * - */ + resetGlobalState(); -// TubeGeometry + } -function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) { + } else { - Geometry.call( this ); + const nGlobal = renderingShadows ? 0 : numGlobalPlanes, + lGlobal = nGlobal * 4; - this.type = 'TubeGeometry'; + let dstArray = materialProperties.clippingState || null; - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; + uniform.value = dstArray; // ensure unique state - if ( taper !== undefined ) { console.warn( 'THREE.TubeGeometry: taper has been removed.' ); } + dstArray = projectPlanes( planes, camera, lGlobal, useCache ); - var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ); + for ( let i = 0; i !== lGlobal; ++ i ) { - // expose internals + dstArray[ i ] = globalState[ i ]; - this.tangents = bufferGeometry.tangents; - this.normals = bufferGeometry.normals; - this.binormals = bufferGeometry.binormals; + } - // create geometry + materialProperties.clippingState = dstArray; + this.numIntersection = clipIntersection ? this.numPlanes : 0; + this.numPlanes += nGlobal; - this.fromBufferGeometry( bufferGeometry ); - this.mergeVertices(); + } -} -TubeGeometry.prototype = Object.create( Geometry.prototype ); -TubeGeometry.prototype.constructor = TubeGeometry; + }; -// TubeBufferGeometry + function resetGlobalState() { -function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) { + if ( uniform.value !== globalState ) { - BufferGeometry.call( this ); + uniform.value = globalState; + uniform.needsUpdate = numGlobalPlanes > 0; - this.type = 'TubeBufferGeometry'; + } - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; + scope.numPlanes = numGlobalPlanes; + scope.numIntersection = 0; - tubularSegments = tubularSegments || 64; - radius = radius || 1; - radialSegments = radialSegments || 8; - closed = closed || false; + } - var frames = path.computeFrenetFrames( tubularSegments, closed ); + function projectPlanes( planes, camera, dstOffset, skipTransform ) { - // expose internals + const nPlanes = planes !== null ? planes.length : 0; + let dstArray = null; - this.tangents = frames.tangents; - this.normals = frames.normals; - this.binormals = frames.binormals; + if ( nPlanes !== 0 ) { - // helper variables + dstArray = uniform.value; - var vertex = new Vector3(); - var normal = new Vector3(); - var uv = new Vector2(); - var P = new Vector3(); + if ( skipTransform !== true || dstArray === null ) { - var i, j; + const flatSize = dstOffset + nPlanes * 4, + viewMatrix = camera.matrixWorldInverse; - // buffer + viewNormalMatrix.getNormalMatrix( viewMatrix ); - var vertices = []; - var normals = []; - var uvs = []; - var indices = []; + if ( dstArray === null || dstArray.length < flatSize ) { - // create buffer data + dstArray = new Float32Array( flatSize ); - generateBufferData(); + } - // build geometry + for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); - // functions + plane.normal.toArray( dstArray, i4 ); + dstArray[ i4 + 3 ] = plane.constant; - function generateBufferData() { + } - for ( i = 0; i < tubularSegments; i ++ ) { + } - generateSegment( i ); + uniform.value = dstArray; + uniform.needsUpdate = true; } - // if the geometry is not closed, generate the last row of vertices and normals - // at the regular position on the given path - // - // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) + scope.numPlanes = nPlanes; + scope.numIntersection = 0; - generateSegment( ( closed === false ) ? tubularSegments : 0 ); + return dstArray; - // uvs are generated in a separate function. - // this makes it easy compute correct values for closed geometries + } - generateUVs(); +} - // finally create faces +function WebGLCubeMaps( renderer ) { - generateIndices(); + let cubemaps = new WeakMap(); - } + function mapTextureMapping( texture, mapping ) { - function generateSegment( i ) { + if ( mapping === EquirectangularReflectionMapping ) { - // we use getPointAt to sample evenly distributed points from the given path + texture.mapping = CubeReflectionMapping; - P = path.getPointAt( i / tubularSegments, P ); + } else if ( mapping === EquirectangularRefractionMapping ) { - // retrieve corresponding normal and binormal + texture.mapping = CubeRefractionMapping; - var N = frames.normals[ i ]; - var B = frames.binormals[ i ]; + } - // generate normals and vertices for the current segment + return texture; - for ( j = 0; j <= radialSegments; j ++ ) { + } - var v = j / radialSegments * Math.PI * 2; + function get( texture ) { - var sin = Math.sin( v ); - var cos = - Math.cos( v ); + if ( texture && texture.isTexture ) { - // normal + const mapping = texture.mapping; - 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(); + if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { - normals.push( normal.x, normal.y, normal.z ); + if ( cubemaps.has( texture ) ) { - // vertex + const cubemap = cubemaps.get( texture ).texture; + return mapTextureMapping( cubemap, texture.mapping ); - vertex.x = P.x + radius * normal.x; - vertex.y = P.y + radius * normal.y; - vertex.z = P.z + radius * normal.z; + } else { - vertices.push( vertex.x, vertex.y, vertex.z ); + const image = texture.image; - } + if ( image && image.height > 0 ) { - } + const renderTarget = new WebGLCubeRenderTarget( image.height ); + renderTarget.fromEquirectangularTexture( renderer, texture ); + cubemaps.set( texture, renderTarget ); - function generateIndices() { + texture.addEventListener( 'dispose', onTextureDispose ); - for ( j = 1; j <= tubularSegments; j ++ ) { + return mapTextureMapping( renderTarget.texture, texture.mapping ); - for ( i = 1; i <= radialSegments; i ++ ) { + } else { - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; + // image not yet ready. try the conversion next frame - // faces + return null; - indices.push( a, b, d ); - indices.push( b, c, d ); + } + + } } } + return texture; + } - function generateUVs() { + function onTextureDispose( event ) { - for ( i = 0; i <= tubularSegments; i ++ ) { + const texture = event.target; - for ( j = 0; j <= radialSegments; j ++ ) { + texture.removeEventListener( 'dispose', onTextureDispose ); - uv.x = i / tubularSegments; - uv.y = j / radialSegments; + const cubemap = cubemaps.get( texture ); - uvs.push( uv.x, uv.y ); + if ( cubemap !== undefined ) { - } + cubemaps.delete( texture ); + cubemap.dispose(); } } -} - -TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -TubeBufferGeometry.prototype.constructor = TubeBufferGeometry; - -/** - * @author oosmoxiecode - * @author Mugen87 / https://github.com/Mugen87 - * - * based on http://www.blackpawn.com/texts/pqtorus/ - */ - -// TorusKnotGeometry - -function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) { + function dispose() { - Geometry.call( this ); + cubemaps = new WeakMap(); - this.type = 'TorusKnotGeometry'; + } - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q + return { + get: get, + dispose: dispose }; - if ( heightScale !== undefined ) { console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); } - - this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) ); - this.mergeVertices(); - } -TorusKnotGeometry.prototype = Object.create( Geometry.prototype ); -TorusKnotGeometry.prototype.constructor = TorusKnotGeometry; +class OrthographicCamera extends Camera { -// TorusKnotBufferGeometry + constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { -function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) { + super(); - BufferGeometry.call( this ); + this.isOrthographicCamera = true; - this.type = 'TorusKnotBufferGeometry'; + this.type = 'OrthographicCamera'; - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q - }; + this.zoom = 1; + this.view = null; - radius = radius || 1; - tube = tube || 0.4; - tubularSegments = Math.floor( tubularSegments ) || 64; - radialSegments = Math.floor( radialSegments ) || 8; - p = p || 2; - q = q || 3; + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; - // buffers + this.near = near; + this.far = far; - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + this.updateProjectionMatrix(); - // helper variables + } - var i, j; + copy( source, recursive ) { - var vertex = new Vector3(); - var normal = new Vector3(); + super.copy( source, recursive ); - var P1 = new Vector3(); - var P2 = new Vector3(); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; - var B = new Vector3(); - var T = new Vector3(); - var N = new Vector3(); + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - // generate vertices, normals and uvs + return this; - for ( i = 0; i <= tubularSegments; ++ i ) { + } - // the radian "u" is used to calculate the position on the torus curve of the current tubular segement + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - var u = i / tubularSegments * p * Math.PI * 2; + if ( this.view === null ) { - // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. - // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - calculatePositionOnCurve( u, p, q, radius, P1 ); - calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); + } - // calculate orthonormal basis + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - T.subVectors( P2, P1 ); - N.addVectors( P2, P1 ); - B.crossVectors( T, N ); - N.crossVectors( B, T ); + this.updateProjectionMatrix(); - // normalize B, N. T can be ignored, we don't use it + } - B.normalize(); - N.normalize(); + clearViewOffset() { - for ( j = 0; j <= radialSegments; ++ j ) { + if ( this.view !== null ) { - // now calculate the vertices. they are nothing more than an extrusion of the torus curve. - // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. + this.view.enabled = false; - var v = j / radialSegments * Math.PI * 2; - var cx = - tube * Math.cos( v ); - var cy = tube * Math.sin( v ); + } - // now calculate the final vertex position. - // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve + this.updateProjectionMatrix(); - vertex.x = P1.x + ( cx * N.x + cy * B.x ); - vertex.y = P1.y + ( cx * N.y + cy * B.y ); - vertex.z = P1.z + ( cx * N.z + cy * B.z ); + } - vertices.push( vertex.x, vertex.y, vertex.z ); + updateProjectionMatrix() { - // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) + 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; - normal.subVectors( vertex, P1 ).normalize(); + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; - normals.push( normal.x, normal.y, normal.z ); + if ( this.view !== null && this.view.enabled ) { - // uv + const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; + const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; } - } - - // generate indices + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); - for ( j = 1; j <= tubularSegments; j ++ ) { + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - for ( i = 1; i <= radialSegments; i ++ ) { + } - // indices + toJSON( meta ) { - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; + const data = super.toJSON( meta ); - // faces + 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; - indices.push( a, b, d ); - indices.push( b, c, d ); + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - } + return data; } - // build geometry +} - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); +const LOD_MIN = 4; + +// The standard deviations (radians) associated with the extra mips. These are +// chosen to approximate a Trowbridge-Reitz distribution function times the +// geometric shadowing function. These sigma values squared must match the +// variance #defines in cube_uv_reflection_fragment.glsl.js. +const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; + +// The maximum length of the blur for loop. Smaller sigmas will use fewer +// samples and exit early, but not recompile the shader. +const MAX_SAMPLES = 20; + +const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); +const _clearColor = /*@__PURE__*/ new Color(); +let _oldTarget = null; +let _oldActiveCubeFace = 0; +let _oldActiveMipmapLevel = 0; +let _oldXrEnabled = false; + +// Golden Ratio +const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; +const INV_PHI = 1 / PHI; + +// Vertices of a dodecahedron (except the opposites, which represent the +// same axis), used as axis directions evenly spread on a sphere. +const _axisDirections = [ + /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), + /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( - 1, 1, 1 ), + /*@__PURE__*/ new Vector3( 1, 1, 1 ) ]; + +/** + * This class generates a Prefiltered, Mipmapped Radiance Environment Map + * (PMREM) from a cubeMap environment texture. This allows different levels of + * blur to be quickly accessed based on material roughness. It is packed into a + * special CubeUV format that allows us to perform custom interpolation so that + * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap + * chain, it only goes down to the LOD_MIN level (above), and then creates extra + * even more filtered 'mips' at the same LOD_MIN resolution, associated with + * higher roughness levels. In this way we maintain resolution to smoothly + * interpolate diffuse lighting while limiting sampling computation. + * + * Paper: Fast, Accurate Image-Based Lighting + * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view +*/ - // this function calculates the current position on the torus curve +class PMREMGenerator { - function calculatePositionOnCurve( u, p, q, radius, position ) { + constructor( renderer ) { - var cu = Math.cos( u ); - var su = Math.sin( u ); - var quOverP = q / p * u; - var cs = Math.cos( quOverP ); + this._renderer = renderer; + this._pingPongRenderTarget = null; - position.x = radius * ( 2 + cs ) * 0.5 * cu; - position.y = radius * ( 2 + cs ) * su * 0.5; - position.z = radius * Math.sin( quOverP ) * 0.5; + 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 ); -TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry; + } -/** - * @author oosmoxiecode - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + /** + * Generates a PMREM from a supplied Scene, which can be faster than using an + * image if networking bandwidth is low. Optional sigma specifies a blur radius + * in radians to be applied to the scene before PMREM generation. Optional near + * and far planes ensure the scene is rendered in its entirety (the cubeCamera + * is placed at the origin). + */ + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { -// TorusGeometry + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + _oldXrEnabled = this._renderer.xr.enabled; -function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) { + this._renderer.xr.enabled = false; - Geometry.call( this ); + this._setSize( 256 ); - this.type = 'TorusGeometry'; + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; + this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); - this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) ); - this.mergeVertices(); + if ( sigma > 0 ) { -} + this._blur( cubeUVRenderTarget, 0, 0, sigma ); -TorusGeometry.prototype = Object.create( Geometry.prototype ); -TorusGeometry.prototype.constructor = TorusGeometry; + } -// TorusBufferGeometry + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); -function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) { + return cubeUVRenderTarget; - BufferGeometry.call( this ); + } - this.type = 'TorusBufferGeometry'; + /** + * Generates a PMREM from an equirectangular texture, which can be either LDR + * or HDR. The ideal input image size is 1k (1024 x 512), + * as this matches best with the 256 x 256 cubemap output. + * The smallest supported equirectangular image size is 64 x 32. + */ + fromEquirectangular( equirectangular, renderTarget = null ) { - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; + return this._fromTexture( equirectangular, renderTarget ); - radius = radius || 1; - tube = tube || 0.4; - radialSegments = Math.floor( radialSegments ) || 8; - tubularSegments = Math.floor( tubularSegments ) || 6; - arc = arc || Math.PI * 2; + } - // buffers + /** + * Generates a PMREM from an cubemap texture, which can be either LDR + * or HDR. The ideal input cube size is 256 x 256, + * as this matches best with the 256 x 256 cubemap output. + * The smallest supported cube size is 16 x 16. + */ + fromCubemap( cubemap, renderTarget = null ) { - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + return this._fromTexture( cubemap, renderTarget ); - // helper variables + } - var center = new Vector3(); - var vertex = new Vector3(); - var normal = new Vector3(); + /** + * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + compileCubemapShader() { - var j, i; + if ( this._cubemapMaterial === null ) { - // generate vertices, normals and uvs + this._cubemapMaterial = _getCubemapMaterial(); + this._compileMaterial( this._cubemapMaterial ); - for ( j = 0; j <= radialSegments; j ++ ) { + } - for ( i = 0; i <= tubularSegments; i ++ ) { + } - var u = i / tubularSegments * arc; - var v = j / radialSegments * Math.PI * 2; + /** + * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + compileEquirectangularShader() { - // vertex + if ( this._equirectMaterial === null ) { - vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); - vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); - vertex.z = tube * Math.sin( v ); + this._equirectMaterial = _getEquirectMaterial(); + this._compileMaterial( this._equirectMaterial ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - // normal + } - center.x = radius * Math.cos( u ); - center.y = radius * Math.sin( u ); - normal.subVectors( vertex, center ).normalize(); + /** + * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, + * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on + * one of them will cause any others to also become unusable. + */ + dispose() { - normals.push( normal.x, normal.y, normal.z ); + this._dispose(); - // uv + if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); + if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); + } - } + // private interface - } + _setSize( cubeSize ) { - // generate indices + this._lodMax = Math.floor( Math.log2( cubeSize ) ); + this._cubeSize = Math.pow( 2, this._lodMax ); - for ( j = 1; j <= radialSegments; j ++ ) { + } - for ( i = 1; i <= tubularSegments; i ++ ) { + _dispose() { - // indices + if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); - var a = ( tubularSegments + 1 ) * j + i - 1; - var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; - var c = ( tubularSegments + 1 ) * ( j - 1 ) + i; - var d = ( tubularSegments + 1 ) * j + i; + if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); - // faces + for ( let i = 0; i < this._lodPlanes.length; i ++ ) { - indices.push( a, b, d ); - indices.push( b, c, d ); + this._lodPlanes[ i ].dispose(); } } - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - -} - -TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -TorusBufferGeometry.prototype.constructor = TorusBufferGeometry; - -/** - * @author Mugen87 / https://github.com/Mugen87 - * Port from https://github.com/mapbox/earcut (v2.1.2) - */ + _cleanup( outputTarget ) { -var Earcut = { + this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); + this._renderer.xr.enabled = _oldXrEnabled; - triangulate: function ( data, holeIndices, dim ) { + outputTarget.scissorTest = false; + _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); - dim = dim || 2; + } - var hasHoles = holeIndices && holeIndices.length, - outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length, - outerNode = linkedList( data, 0, outerLen, dim, true ), - triangles = []; + _fromTexture( texture, renderTarget ) { - if ( ! outerNode ) { return triangles; } + if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { - var minX, minY, maxX, maxY, x, y, invSize; + this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); - if ( hasHoles ) { outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); } + } else { // Equirectangular - // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + this._setSize( texture.image.width / 4 ); - if ( data.length > 80 * dim ) { + } - minX = maxX = data[ 0 ]; - minY = maxY = data[ 1 ]; + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + _oldXrEnabled = this._renderer.xr.enabled; - for ( var i = dim; i < outerLen; i += dim ) { + this._renderer.xr.enabled = false; - x = data[ i ]; - y = data[ i + 1 ]; - if ( x < minX ) { minX = x; } - if ( y < minY ) { minY = y; } - if ( x > maxX ) { maxX = x; } - if ( y > maxY ) { maxY = y; } + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV( texture, cubeUVRenderTarget ); + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); - } + return cubeUVRenderTarget; - // minX, minY and invSize are later used to transform coords into integers for z-order calculation + } - invSize = Math.max( maxX - minX, maxY - minY ); - invSize = invSize !== 0 ? 1 / invSize : 0; + _allocateTargets() { - } + const width = 3 * Math.max( this._cubeSize, 16 * 7 ); + const height = 4 * this._cubeSize; - earcutLinked( outerNode, triangles, dim, minX, minY, invSize ); + const params = { + magFilter: LinearFilter, + minFilter: LinearFilter, + generateMipmaps: false, + type: HalfFloatType, + format: RGBAFormat, + colorSpace: LinearSRGBColorSpace, + depthBuffer: false + }; - return triangles; + const cubeUVRenderTarget = _createRenderTarget( width, height, params ); - } + if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { -}; + if ( this._pingPongRenderTarget !== null ) { -// create a circular doubly linked list from polygon points in the specified winding order + this._dispose(); -function linkedList( data, start, end, dim, clockwise ) { + } - var i, last; + this._pingPongRenderTarget = _createRenderTarget( width, height, params ); - if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { + const { _lodMax } = this; + ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); - for ( i = start; i < end; i += dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); } + this._blurMaterial = _getBlurShader( _lodMax, width, height ); - } else { + } - for ( i = end - dim; i >= start; i -= dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); } + return cubeUVRenderTarget; } - if ( last && equals( last, last.next ) ) { + _compileMaterial( material ) { - removeNode( last ); - last = last.next; + const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); + this._renderer.compile( tmpMesh, _flatCamera ); } - return last; + _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { -} + const fov = 90; + const aspect = 1; + const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); + const upSign = [ 1, - 1, 1, 1, 1, 1 ]; + const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; + const renderer = this._renderer; -// eliminate colinear or duplicate points + const originalAutoClear = renderer.autoClear; + const toneMapping = renderer.toneMapping; + renderer.getClearColor( _clearColor ); -function filterPoints( start, end ) { + renderer.toneMapping = NoToneMapping; + renderer.autoClear = false; + + const backgroundMaterial = new MeshBasicMaterial( { + name: 'PMREM.Background', + side: BackSide, + depthWrite: false, + depthTest: false, + } ); - if ( ! start ) { return start; } - if ( ! end ) { end = start; } + const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); - var p = start, again; + let useSolidColor = false; + const background = scene.background; - do { + if ( background ) { - again = false; + if ( background.isColor ) { - if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { + backgroundMaterial.color.copy( background ); + scene.background = null; + useSolidColor = true; - removeNode( p ); - p = end = p.prev; - if ( p === p.next ) { break; } - again = true; + } } else { - p = p.next; + backgroundMaterial.color.copy( _clearColor ); + useSolidColor = true; } - } while ( again || p !== end ); - - return end; + for ( let i = 0; i < 6; i ++ ) { -} + const col = i % 3; -// main ear slicing loop which triangulates a polygon (given as a linked list) + if ( col === 0 ) { -function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); - if ( ! ear ) { return; } + } else if ( col === 1 ) { - // interlink polygon nodes in z-order + cubeCamera.up.set( 0, 0, upSign[ i ] ); + cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); - if ( ! pass && invSize ) { indexCurve( ear, minX, minY, invSize ); } + } else { - var stop = ear, prev, next; + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); - // iterate through ears, slicing them one by one + } - while ( ear.prev !== ear.next ) { + const size = this._cubeSize; - prev = ear.prev; - next = ear.next; + _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); - if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { + renderer.setRenderTarget( cubeUVRenderTarget ); - // cut off the triangle - triangles.push( prev.i / dim ); - triangles.push( ear.i / dim ); - triangles.push( next.i / dim ); + if ( useSolidColor ) { - removeNode( ear ); + renderer.render( backgroundBox, cubeCamera ); - // skipping the next vertice leads to less sliver triangles - ear = next.next; - stop = next.next; + } - continue; + renderer.render( scene, cubeCamera ); } - ear = next; - - // if we looped through the whole remaining polygon and can't find any more ears - - if ( ear === stop ) { + backgroundBox.geometry.dispose(); + backgroundBox.material.dispose(); - // try filtering points and slicing again + renderer.toneMapping = toneMapping; + renderer.autoClear = originalAutoClear; + scene.background = background; - if ( ! pass ) { - - earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); + } - // if this didn't work, try curing all small self-intersections locally + _textureToCubeUV( texture, cubeUVRenderTarget ) { - } else if ( pass === 1 ) { + const renderer = this._renderer; - ear = cureLocalIntersections( ear, triangles, dim ); - earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); + const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); - // as a last resort, try splitting the remaining polygon into two + if ( isCubeTexture ) { - } else if ( pass === 2 ) { + if ( this._cubemapMaterial === null ) { - splitEarcut( ear, triangles, dim, minX, minY, invSize ); + this._cubemapMaterial = _getCubemapMaterial(); } - break; - - } - - } + this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; -} + } else { -// check whether a polygon node forms a valid ear with adjacent nodes + if ( this._equirectMaterial === null ) { -function isEar( ear ) { + this._equirectMaterial = _getEquirectMaterial(); - var a = ear.prev, - b = ear, - c = ear.next; + } - if ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear + } - // now make sure we don't have other points inside the potential ear - var p = ear.next.next; + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + const mesh = new Mesh( this._lodPlanes[ 0 ], material ); - while ( p !== ear.prev ) { + const uniforms = material.uniforms; - if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) { + uniforms[ 'envMap' ].value = texture; - return false; + const size = this._cubeSize; - } + _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); - p = p.next; + renderer.setRenderTarget( cubeUVRenderTarget ); + renderer.render( mesh, _flatCamera ); } - return true; + _applyPMREM( cubeUVRenderTarget ) { -} + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + const n = this._lodPlanes.length; -function isEarHashed( ear, minX, minY, invSize ) { + for ( let i = 1; i < n; i ++ ) { - var a = ear.prev, - b = ear, - c = ear.next; + const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); - if ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear + const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; - // triangle bbox; min & max are calculated like this for speed + this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); - var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ), - minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ), - maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ), - maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y ); + } - // z-order range for the current triangle bbox; + renderer.autoClear = autoClear; - var minZ = zOrder( minTX, minTY, minX, minY, invSize ), - maxZ = zOrder( maxTX, maxTY, minX, minY, invSize ); + } - // first look for points inside the triangle in increasing z-order + /** + * This is a two-pass Gaussian blur for a cubemap. Normally this is done + * vertically and horizontally, but this breaks down on a cube. Here we apply + * the blur latitudinally (around the poles), and then longitudinally (towards + * the poles) to approximate the orthogonally-separable blur. It is least + * accurate at the poles, but still does a decent job. + */ + _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { - var p = ear.nextZ; + const pingPongRenderTarget = this._pingPongRenderTarget; - while ( p && p.z <= maxZ ) { + this._halfBlur( + cubeUVRenderTarget, + pingPongRenderTarget, + lodIn, + lodOut, + sigma, + 'latitudinal', + poleAxis ); - if ( p !== ear.prev && p !== ear.next && - pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && - area( p.prev, p, p.next ) >= 0 ) { return false; } - p = p.nextZ; + this._halfBlur( + pingPongRenderTarget, + cubeUVRenderTarget, + lodOut, + lodOut, + sigma, + 'longitudinal', + poleAxis ); } - // then look for points in decreasing z-order + _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { + + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; - p = ear.prevZ; + if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { - while ( p && p.z >= minZ ) { + console.error( + 'blur direction must be either latitudinal or longitudinal!' ); - if ( p !== ear.prev && p !== ear.next && - pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && - area( p.prev, p, p.next ) >= 0 ) { return false; } + } - p = p.prevZ; + // Number of standard deviations at which to cut off the discrete approximation. + const STANDARD_DEVIATIONS = 3; - } + const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); + const blurUniforms = blurMaterial.uniforms; - return true; + 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 ) { -// go through all polygon nodes and cure small local self-intersections + console.warn( `sigmaRadians, ${ + sigmaRadians}, is too large and will clip, as it requested ${ + samples} samples when the maximum is set to ${MAX_SAMPLES}` ); -function cureLocalIntersections( start, triangles, dim ) { + } - var p = start; + const weights = []; + let sum = 0; - do { + for ( let i = 0; i < MAX_SAMPLES; ++ i ) { - var a = p.prev, b = p.next.next; + const x = i / sigmaPixels; + const weight = Math.exp( - x * x / 2 ); + weights.push( weight ); - if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { + if ( i === 0 ) { - triangles.push( a.i / dim ); - triangles.push( p.i / dim ); - triangles.push( b.i / dim ); + sum += weight; - // remove two nodes involved + } else if ( i < samples ) { - removeNode( p ); - removeNode( p.next ); + sum += 2 * weight; - p = start = b; + } } - p = p.next; + for ( let i = 0; i < weights.length; i ++ ) { - } while ( p !== start ); + weights[ i ] = weights[ i ] / sum; - return p; + } -} + blurUniforms[ 'envMap' ].value = targetIn.texture; + blurUniforms[ 'samples' ].value = samples; + blurUniforms[ 'weights' ].value = weights; + blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; + + if ( poleAxis ) { -// try splitting polygon into two and triangulate them independently + blurUniforms[ 'poleAxis' ].value = poleAxis; + + } -function splitEarcut( start, triangles, dim, minX, minY, invSize ) { + const { _lodMax } = this; + blurUniforms[ 'dTheta' ].value = radiansPerPixel; + blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; - // look for a valid diagonal that divides the polygon into two + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); - var a = start; + _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( targetOut ); + renderer.render( blurMesh, _flatCamera ); - do { + } - var b = a.next.next; +} - while ( b !== a.prev ) { - if ( a.i !== b.i && isValidDiagonal( a, b ) ) { - // split the polygon in two by the diagonal +function _createPlanes( lodMax ) { - var c = splitPolygon( a, b ); + const lodPlanes = []; + const sizeLods = []; + const sigmas = []; - // filter colinear points around the cuts + let lod = lodMax; - a = filterPoints( a, a.next ); - c = filterPoints( c, c.next ); + const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; - // run earcut on each half + for ( let i = 0; i < totalLods; i ++ ) { - earcutLinked( a, triangles, dim, minX, minY, invSize ); - earcutLinked( c, triangles, dim, minX, minY, invSize ); - return; + const sizeLod = Math.pow( 2, lod ); + sizeLods.push( sizeLod ); + let sigma = 1.0 / sizeLod; - } + if ( i > lodMax - LOD_MIN ) { - b = b.next; + sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; - } + } else if ( i === 0 ) { - a = a.next; + sigma = 0; - } while ( a !== start ); + } -} + sigmas.push( sigma ); -// link every hole into the outer loop, producing a single-ring polygon without holes + const texelSize = 1.0 / ( sizeLod - 2 ); + const min = - texelSize; + const max = 1 + texelSize; + const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; -function eliminateHoles( data, holeIndices, outerNode, dim ) { + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; - var queue = [], i, len, start, end, list; + const position = new Float32Array( positionSize * vertices * cubeFaces ); + const uv = new Float32Array( uvSize * vertices * cubeFaces ); + const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); - for ( i = 0, len = holeIndices.length; i < len; i ++ ) { + for ( let face = 0; face < cubeFaces; face ++ ) { - start = holeIndices[ i ] * dim; - end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; - list = linkedList( data, start, end, dim, false ); - if ( list === list.next ) { list.steiner = true; } - queue.push( getLeftmost( list ) ); + const x = ( face % 3 ) * 2 / 3 - 1; + const y = face > 2 ? 0 : - 1; + const coordinates = [ + x, y, 0, + x + 2 / 3, y, 0, + x + 2 / 3, y + 1, 0, + x, y, 0, + x + 2 / 3, y + 1, 0, + x, y + 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 ); - } + } - queue.sort( compareX ); + 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 ); - // process holes from left to right + if ( lod > LOD_MIN ) { - for ( i = 0; i < queue.length; i ++ ) { + lod --; - eliminateHole( queue[ i ], outerNode ); - outerNode = filterPoints( outerNode, outerNode.next ); + } } - return outerNode; + return { lodPlanes, sizeLods, sigmas }; } -function compareX( a, b ) { +function _createRenderTarget( width, height, params ) { - return a.x - b.x; + const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; + cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; } -// find a bridge between vertices that connects hole with an outer ring and and link it - -function eliminateHole( hole, outerNode ) { - - outerNode = findHoleBridge( hole, outerNode ); - - if ( outerNode ) { - - var b = splitPolygon( outerNode, hole ); - - filterPoints( b, b.next ); +function _setViewport( target, x, y, width, height ) { - } + target.viewport.set( x, y, width, height ); + target.scissor.set( x, y, width, height ); } -// David Eberly's algorithm for finding a bridge between hole and outer polygon +function _getBlurShader( lodMax, width, height ) { + + const weights = new Float32Array( MAX_SAMPLES ); + const poleAxis = new Vector3( 0, 1, 0 ); + const shaderMaterial = new ShaderMaterial( { -function findHoleBridge( hole, outerNode ) { + name: 'SphericalGaussianBlur', - var p = outerNode, - hx = hole.x, - hy = hole.y, - qx = - Infinity, - m; + defines: { + 'n': MAX_SAMPLES, + 'CUBEUV_TEXEL_WIDTH': 1.0 / width, + 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, + 'CUBEUV_MAX_MIP': `${lodMax}.0`, + }, - // find a segment intersected by a ray from the hole's leftmost point to the left; - // segment's endpoint with lesser x will be potential connection point + uniforms: { + 'envMap': { value: null }, + 'samples': { value: 1 }, + 'weights': { value: weights }, + 'latitudinal': { value: false }, + 'dTheta': { value: 0 }, + 'mipInt': { value: 0 }, + 'poleAxis': { value: poleAxis } + }, - do { + vertexShader: _getCommonVertexShader(), - if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { + fragmentShader: /* glsl */` - var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); + precision mediump float; + precision mediump int; - if ( x <= hx && x > qx ) { + varying vec3 vOutputDirection; - qx = x; + uniform sampler2D envMap; + uniform int samples; + uniform float weights[ n ]; + uniform bool latitudinal; + uniform float dTheta; + uniform float mipInt; + uniform vec3 poleAxis; - if ( x === hx ) { + #define ENVMAP_TYPE_CUBE_UV + #include - if ( hy === p.y ) { return p; } - if ( hy === p.next.y ) { return p.next; } + 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 ); - m = p.x < p.next.x ? p : p.next; + return bilinearCubeUV( envMap, sampleDirection, mipInt ); } - } + void main() { - p = p.next; + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); - } while ( p !== outerNode ); + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { - if ( ! m ) { return null; } + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); - if ( hx === qx ) { return m.prev; } // hole touches outer segment; pick lower endpoint + } - // look for points inside the triangle of hole point, segment intersection and endpoint; - // if there are no points found, we have a valid connection; - // otherwise choose the point of the minimum angle with the ray as connection point + axis = normalize( axis ); - var stop = m, - mx = m.x, - my = m.y, - tanMin = Infinity, - tan; + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); - p = m.next; + for ( int i = 1; i < n; i++ ) { - while ( p !== stop ) { + if ( i >= samples ) { - 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 ) ) { + break; - tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential + } - if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) { + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); - m = p; - tanMin = tan; + } } + `, - } - - p = p.next; + blending: NoBlending, + depthTest: false, + depthWrite: false - } + } ); - return m; + return shaderMaterial; } -// interlink polygon nodes in z-order +function _getEquirectMaterial() { + + return new ShaderMaterial( { -function indexCurve( start, minX, minY, invSize ) { + name: 'EquirectangularToCubeUV', - var p = start; + uniforms: { + 'envMap': { value: null } + }, - do { + vertexShader: _getCommonVertexShader(), - 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; + fragmentShader: /* glsl */` - } while ( p !== start ); + precision mediump float; + precision mediump int; - p.prevZ.nextZ = null; - p.prevZ = null; + varying vec3 vOutputDirection; - sortLinked( p ); + uniform sampler2D envMap; -} + #include -// Simon Tatham's linked list merge sort algorithm -// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html + void main() { -function sortLinked( list ) { + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); - var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); - do { + } + `, - p = list; - list = null; - tail = null; - numMerges = 0; + blending: NoBlending, + depthTest: false, + depthWrite: false - while ( p ) { + } ); - numMerges ++; - q = p; - pSize = 0; +} - for ( i = 0; i < inSize; i ++ ) { +function _getCubemapMaterial() { - pSize ++; - q = q.nextZ; - if ( ! q ) { break; } + return new ShaderMaterial( { - } + name: 'CubemapToCubeUV', - qSize = inSize; + uniforms: { + 'envMap': { value: null }, + 'flipEnvMap': { value: - 1 } + }, - while ( pSize > 0 || ( qSize > 0 && q ) ) { + vertexShader: _getCommonVertexShader(), - if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { + fragmentShader: /* glsl */` - e = p; - p = p.nextZ; - pSize --; + precision mediump float; + precision mediump int; - } else { + uniform float flipEnvMap; - e = q; - q = q.nextZ; - qSize --; + varying vec3 vOutputDirection; - } + uniform samplerCube envMap; - if ( tail ) { tail.nextZ = e; } - else { list = e; } + void main() { - e.prevZ = tail; - tail = e; + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); } + `, - p = q; + blending: NoBlending, + depthTest: false, + depthWrite: false - } + } ); - tail.nextZ = null; - inSize *= 2; +} - } while ( numMerges > 1 ); +function _getCommonVertexShader() { - return list; + return /* glsl */` -} + precision mediump float; + precision mediump int; -// z-order of a point given coords and inverse of the longer side of data bbox + attribute float faceIndex; -function zOrder( x, y, minX, minY, invSize ) { + varying vec3 vOutputDirection; - // coords are transformed into non-negative 15-bit integer range + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { - x = 32767 * ( x - minX ) * invSize; - y = 32767 * ( y - minY ) * invSize; + uv = 2.0 * uv - 1.0; - x = ( x | ( x << 8 ) ) & 0x00FF00FF; - x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; - x = ( x | ( x << 2 ) ) & 0x33333333; - x = ( x | ( x << 1 ) ) & 0x55555555; + vec3 direction = vec3( uv, 1.0 ); - y = ( y | ( y << 8 ) ) & 0x00FF00FF; - y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; - y = ( y | ( y << 2 ) ) & 0x33333333; - y = ( y | ( y << 1 ) ) & 0x55555555; + if ( face == 0.0 ) { - return x | ( y << 1 ); + direction = direction.zyx; // ( 1, v, u ) pos x -} + } else if ( face == 1.0 ) { -// find the leftmost node of a polygon ring + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y -function getLeftmost( start ) { + } else if ( face == 2.0 ) { - var p = start, leftmost = start; + direction.x *= -1.0; // ( -u, v, 1 ) pos z - do { + } else if ( face == 3.0 ) { - if ( p.x < leftmost.x ) { leftmost = p; } - p = p.next; + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x - } while ( p !== start ); + } else if ( face == 4.0 ) { - return leftmost; + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y -} + } else if ( face == 5.0 ) { -// check if a point lies within a convex triangle + direction.z *= -1.0; // ( u, v, -1 ) neg z -function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { + } - return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 && - ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 && - ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0; + return direction; -} + } -// check if a diagonal between two polygon nodes is valid (lies in polygon interior) + void main() { -function isValidDiagonal( a, b ) { + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); - return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && - locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ); + } + `; } -// signed area of a triangle +function WebGLCubeUVMaps( renderer ) { -function area( p, q, r ) { + let cubeUVmaps = new WeakMap(); - return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); + let pmremGenerator = null; -} + function get( texture ) { -// check if two points are equal + if ( texture && texture.isTexture ) { -function equals( p1, p2 ) { + const mapping = texture.mapping; - return p1.x === p2.x && p1.y === p2.y; + const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); + const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); -} + // equirect/cube map to cubeUV conversion -// check if two segments intersect + if ( isEquirectMap || isCubeMap ) { -function intersects( p1, q1, p2, q2 ) { + let renderTarget = cubeUVmaps.get( texture ); - if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) || - ( equals( p1, q2 ) && equals( p2, q1 ) ) ) { return true; } + const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0; - return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 && - area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0; + if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) { -} + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); -// check if a polygon diagonal intersects any polygon segments + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); + renderTarget.texture.pmremVersion = texture.pmremVersion; -function intersectsPolygon( a, b ) { + cubeUVmaps.set( texture, renderTarget ); - var p = a; + return renderTarget.texture; - do { + } else { - if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && - intersects( p, p.next, a, b ) ) { + if ( renderTarget !== undefined ) { - return true; + return renderTarget.texture; - } + } else { - p = p.next; + const image = texture.image; - } while ( p !== a ); + if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { - return false; + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); -} + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); + renderTarget.texture.pmremVersion = texture.pmremVersion; -// check if a polygon diagonal is locally inside the polygon + cubeUVmaps.set( texture, renderTarget ); -function locallyInside( a, b ) { + texture.addEventListener( 'dispose', onTextureDispose ); - return area( a.prev, a, a.next ) < 0 ? - area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : - area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; + return renderTarget.texture; -} + } else { -// check if the middle point of a polygon diagonal is inside the polygon + // image not yet ready. try the conversion next frame -function middleInside( a, b ) { + return null; - var p = a, - inside = false, - px = ( a.x + b.x ) / 2, - py = ( a.y + b.y ) / 2; + } - do { + } - if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && - ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) { + } - inside = ! inside; + } } - p = p.next; + return texture; - } while ( p !== a ); + } - return inside; + function isCubeTextureComplete( image ) { -} + let count = 0; + const length = 6; -// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; -// if one belongs to the outer ring and another to a hole, it merges it into a single ring + for ( let i = 0; i < length; i ++ ) { -function splitPolygon( a, b ) { + if ( image[ i ] !== undefined ) count ++; - var a2 = new Node( a.i, a.x, a.y ), - b2 = new Node( b.i, b.x, b.y ), - an = a.next, - bp = b.prev; + } - a.next = b; - b.prev = a; + return count === length; - a2.next = an; - an.prev = a2; - b2.next = a2; - a2.prev = b2; + } - bp.next = b2; - b2.prev = bp; + function onTextureDispose( event ) { - return b2; + const texture = event.target; -} + texture.removeEventListener( 'dispose', onTextureDispose ); -// create a node and optionally link it with previous one (in a circular doubly linked list) + const cubemapUV = cubeUVmaps.get( texture ); -function insertNode( i, x, y, last ) { + if ( cubemapUV !== undefined ) { - var p = new Node( i, x, y ); + cubeUVmaps.delete( texture ); + cubemapUV.dispose(); - if ( ! last ) { + } - p.prev = p; - p.next = p; + } - } else { + function dispose() { - p.next = last.next; - p.prev = last; - last.next.prev = p; - last.next = p; + cubeUVmaps = new WeakMap(); + + if ( pmremGenerator !== null ) { + + pmremGenerator.dispose(); + pmremGenerator = null; + + } } - return p; + return { + get: get, + dispose: dispose + }; } -function removeNode( p ) { +function WebGLExtensions( gl ) { - p.next.prev = p.prev; - p.prev.next = p.next; + const extensions = {}; - if ( p.prevZ ) { p.prevZ.nextZ = p.nextZ; } - if ( p.nextZ ) { p.nextZ.prevZ = p.prevZ; } + function getExtension( name ) { -} + if ( extensions[ name ] !== undefined ) { -function Node( i, x, y ) { + return extensions[ name ]; - // vertice index in coordinates array - this.i = i; + } - // vertex coordinates - this.x = x; - this.y = y; + let extension; - // previous and next vertice nodes in a polygon ring - this.prev = null; - this.next = null; + switch ( name ) { - // z-order curve value - this.z = null; + case 'WEBGL_depth_texture': + extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); + break; - // previous and next nodes in z-order - this.prevZ = null; - this.nextZ = null; + 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; - // indicates whether this is a steiner point - this.steiner = false; + 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; -function signedArea( data, start, end, dim ) { + default: + extension = gl.getExtension( name ); - var sum = 0; + } - for ( var i = start, j = end - dim; i < end; i += dim ) { + extensions[ name ] = extension; - sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); - j = i; + return extension; } - return sum; + return { -} + has: function ( name ) { -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - */ + return getExtension( name ) !== null; + + }, -var ShapeUtils = { + init: function () { - // calculate area of the contour polygon + getExtension( 'EXT_color_buffer_float' ); + getExtension( 'WEBGL_clip_cull_distance' ); + getExtension( 'OES_texture_float_linear' ); + getExtension( 'EXT_color_buffer_half_float' ); + getExtension( 'WEBGL_multisampled_render_to_texture' ); + getExtension( 'WEBGL_render_shared_exponent' ); - area: function ( contour ) { + }, + + get: function ( name ) { + + const extension = getExtension( name ); - var n = contour.length; - var a = 0.0; + if ( extension === null ) { + + warnOnce( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); - for ( var p = n - 1, q = 0; q < n; p = q ++ ) { + } - a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; + return extension; } - return a * 0.5; + }; - }, +} - isClockWise: function ( pts ) { +function WebGLGeometries( gl, attributes, info, bindingStates ) { - return ShapeUtils.area( pts ) < 0; + const geometries = {}; + const wireframeAttributes = new WeakMap(); - }, + function onGeometryDispose( event ) { - triangulateShape: function ( contour, holes ) { + const geometry = event.target; - function removeDupEndPts( points ) { + if ( geometry.index !== null ) { - var l = points.length; + attributes.remove( geometry.index ); - if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { + } - points.pop(); + for ( const name in geometry.attributes ) { - } + attributes.remove( geometry.attributes[ name ] ); } - function addContour( vertices, contour ) { + for ( const name in geometry.morphAttributes ) { - for ( var i = 0; i < contour.length; i ++ ) { + const array = geometry.morphAttributes[ name ]; - vertices.push( contour[ i ].x ); - vertices.push( contour[ i ].y ); + for ( let i = 0, l = array.length; i < l; i ++ ) { + + attributes.remove( array[ i ] ); } } - var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] - var holeIndices = []; // array of hole indices - var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] + geometry.removeEventListener( 'dispose', onGeometryDispose ); - removeDupEndPts( contour ); - addContour( vertices, contour ); + delete geometries[ geometry.id ]; - // + const attribute = wireframeAttributes.get( geometry ); + + if ( attribute ) { + + attributes.remove( attribute ); + wireframeAttributes.delete( geometry ); - var holeIndex = contour.length; - holes.forEach( removeDupEndPts ); + } + + bindingStates.releaseStatesOfGeometry( geometry ); - for ( i = 0; i < holes.length; i ++ ) { + if ( geometry.isInstancedBufferGeometry === true ) { - holeIndices.push( holeIndex ); - holeIndex += holes[ i ].length; - addContour( vertices, holes[ i ] ); + delete geometry._maxInstanceCount; } // - var triangles = Earcut.triangulate( vertices, holeIndices ); + info.memory.geometries --; - // + } - for ( var i = 0; i < triangles.length; i += 3 ) { + function get( object, geometry ) { - faces.push( triangles.slice( i, i + 3 ) ); + if ( geometries[ geometry.id ] === true ) return geometry; - } + geometry.addEventListener( 'dispose', onGeometryDispose ); - return faces; + geometries[ geometry.id ] = true; - } + info.memory.geometries ++; -}; + return geometry; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Creates extruded geometry from a path shape. - * - * parameters = { - * - * curveSegments: , // number of points on the curves - * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too - * amount: , // Depth to extrude the shape - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into the original shape bevel goes - * bevelSize: , // how far from shape outline is bevel - * bevelSegments: , // number of bevel layers - * - * extrudePath: // curve to extrude shape along - * frames: // containing arrays of tangents, normals, binormals - * - * UVGenerator: // object that provides UV generator functions - * - * } - */ + } -// ExtrudeGeometry + function update( geometry ) { -function ExtrudeGeometry( shapes, options ) { + const geometryAttributes = geometry.attributes; - Geometry.call( this ); + // Updating index buffer in VAO now. See WebGLBindingStates. - this.type = 'ExtrudeGeometry'; + for ( const name in geometryAttributes ) { - this.parameters = { - shapes: shapes, - options: options - }; + attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); - this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) ); - this.mergeVertices(); + } -} + // morph targets -ExtrudeGeometry.prototype = Object.create( Geometry.prototype ); -ExtrudeGeometry.prototype.constructor = ExtrudeGeometry; + const morphAttributes = geometry.morphAttributes; -// ExtrudeBufferGeometry + for ( const name in morphAttributes ) { -function ExtrudeBufferGeometry( shapes, options ) { + const array = morphAttributes[ name ]; - if ( typeof ( shapes ) === "undefined" ) { + for ( let i = 0, l = array.length; i < l; i ++ ) { - return; + attributes.update( array[ i ], gl.ARRAY_BUFFER ); - } + } - BufferGeometry.call( this ); + } - this.type = 'ExtrudeBufferGeometry'; + } - shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; + function updateWireframeAttribute( geometry ) { - this.addShapeList( shapes, options ); + const indices = []; - this.computeVertexNormals(); + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; + let version = 0; - // can't really use automatic vertex normals - // as then front and back sides get smoothed too - // should do separate smoothing just for sides + if ( geometryIndex !== null ) { - //this.computeVertexNormals(); + const array = geometryIndex.array; + version = geometryIndex.version; - //console.log( "took", ( Date.now() - startTime ) ); + for ( let i = 0, l = array.length; i < l; i += 3 ) { -} + const a = array[ i + 0 ]; + const b = array[ i + 1 ]; + const c = array[ i + 2 ]; -ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry; + indices.push( a, b, b, c, c, a ); -ExtrudeBufferGeometry.prototype.getArrays = function () { + } - var positionAttribute = this.getAttribute( "position" ); - var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : []; + } else if ( geometryPosition !== undefined ) { - var uvAttribute = this.getAttribute( "uv" ); - var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : []; + const array = geometryPosition.array; + version = geometryPosition.version; - var IndexAttribute = this.index; - var indicesArray = IndexAttribute ? Array.prototype.slice.call( IndexAttribute.array ) : []; + for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { - return { - position: verticesArray, - uv: uvArray, - index: indicesArray - }; + const a = i + 0; + const b = i + 1; + const c = i + 2; -}; + indices.push( a, b, b, c, c, a ); -ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) { + } - var sl = shapes.length; - options.arrays = this.getArrays(); + } else { - for ( var s = 0; s < sl; s ++ ) { + return; - var shape = shapes[ s ]; - this.addShape( shape, options ); + } - } + const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + attribute.version = version; - this.setIndex( options.arrays.index ); - this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) ); + // Updating index buffer in VAO now. See WebGLBindingStates -}; + // -ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) { + const previousAttribute = wireframeAttributes.get( geometry ); - var arrays = options.arrays ? options.arrays : this.getArrays(); - var verticesArray = arrays.position; - var indicesArray = arrays.index; - var uvArray = arrays.uv; + if ( previousAttribute ) attributes.remove( previousAttribute ); - var placeholder = []; + // + wireframeAttributes.set( geometry, attribute ); - var amount = options.amount !== undefined ? options.amount : 100; + } - var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10 - var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8 - var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; + function getWireframeAttribute( geometry ) { - var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false + const currentAttribute = wireframeAttributes.get( geometry ); - var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; + if ( currentAttribute ) { - var steps = options.steps !== undefined ? options.steps : 1; + const geometryIndex = geometry.index; - var extrudePath = options.extrudePath; - var extrudePts, extrudeByPath = false; + if ( geometryIndex !== null ) { - // Use default WorldUVGenerator if no UV generators are specified. - var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator; + // if the attribute is obsolete, create a new one - var splineTube, binormal, normal, position2; - if ( extrudePath ) { + if ( currentAttribute.version < geometryIndex.version ) { - extrudePts = extrudePath.getSpacedPoints( steps ); + updateWireframeAttribute( geometry ); - extrudeByPath = true; - bevelEnabled = false; // bevels not supported for path extrusion + } - // SETUP TNB variables + } - // TODO1 - have a .isClosed in spline? + } else { - splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false ); + updateWireframeAttribute( geometry ); - // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); + } - binormal = new Vector3(); - normal = new Vector3(); - position2 = new Vector3(); + return wireframeAttributes.get( geometry ); } - // Safeguards if bevels are not enabled - - if ( ! bevelEnabled ) { + return { - bevelSegments = 0; - bevelThickness = 0; - bevelSize = 0; + get: get, + update: update, - } + getWireframeAttribute: getWireframeAttribute - // Variables initialization + }; - var ahole, h, hl; // looping of holes - var scope = this; +} - var shapePoints = shape.extractPoints( curveSegments ); +function WebGLIndexedBufferRenderer( gl, extensions, info ) { - var vertices = shapePoints.shape; - var holes = shapePoints.holes; + let mode; - var reverse = ! ShapeUtils.isClockWise( vertices ); + function setMode( value ) { - if ( reverse ) { + mode = value; - vertices = vertices.reverse(); + } - // Maybe we should also check if holes are in the opposite direction, just to be safe ... + let type, bytesPerElement; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + function setIndex( value ) { - ahole = holes[ h ]; + type = value.type; + bytesPerElement = value.bytesPerElement; - if ( ShapeUtils.isClockWise( ahole ) ) { + } - holes[ h ] = ahole.reverse(); + function render( start, count ) { - } + gl.drawElements( mode, count, type, start * bytesPerElement ); - } + info.update( count, mode, 1 ); } + function renderInstances( start, count, primcount ) { - var faces = ShapeUtils.triangulateShape( vertices, holes ); + if ( primcount === 0 ) return; - /* Vertices */ + gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount ); - var contour = vertices; // vertices has all points but contour has only points of circumference + info.update( count, mode, primcount ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + } - ahole = holes[ h ]; + function renderMultiDraw( starts, counts, drawCount ) { - vertices = vertices.concat( ahole ); + if ( drawCount === 0 ) return; - } + const extension = extensions.get( 'WEBGL_multi_draw' ); + extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount ); + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - function scalePt2( pt, vec, size ) { + elementCount += counts[ i ]; + + } - if ( ! vec ) { console.error( "THREE.ExtrudeGeometry: vec does not exist" ); } + info.update( elementCount, mode, 1 ); - return vec.clone().multiplyScalar( size ).add( pt ); } - var b, bs, t, z, - vert, vlen = vertices.length, - face, flen = faces.length; + function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { + if ( drawCount === 0 ) return; - // Find directions for point movement + const extension = extensions.get( 'WEBGL_multi_draw' ); + if ( extension === null ) { - function getBevelVec( inPt, inPrev, inNext ) { + for ( let i = 0; i < starts.length; i ++ ) { - // computes for inPt the corresponding point inPt' on a new contour - // shifted by 1 unit (length of normalized vector) to the left - // if we walk along contour clockwise, this new contour is outside the old one - // - // inPt' is the intersection of the two lines parallel to the two - // adjacent edges of inPt at a distance of 1 unit on the left side. + renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] ); - var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt + } - // good reading for geometry algorithms (here: line-line intersection) - // http://geomalgorithms.com/a05-_intersect-1.html + } else { - var v_prev_x = inPt.x - inPrev.x, - v_prev_y = inPt.y - inPrev.y; - var v_next_x = inNext.x - inPt.x, - v_next_y = inNext.y - inPt.y; + extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount ); - var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - // check for collinear edges - var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); + elementCount += counts[ i ]; - if ( Math.abs( collinear0 ) > Number.EPSILON ) { + } - // not collinear + for ( let i = 0; i < primcount.length; i ++ ) { - // length of vectors for normalizing + info.update( elementCount, mode, primcount[ i ] ); - var v_prev_len = Math.sqrt( v_prev_lensq ); - var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); + } - // shift adjacent points by unit vectors to the left + } - var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); - var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); + } - var ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); - var ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); + // - // scaling factor for v_prev to intersection point + this.setMode = setMode; + this.setIndex = setIndex; + this.render = render; + this.renderInstances = renderInstances; + this.renderMultiDraw = renderMultiDraw; + this.renderMultiDrawInstances = renderMultiDrawInstances; - var 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 ); +} - // vector from inPt to intersection point +function WebGLInfo( gl ) { - v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); - v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); + const memory = { + geometries: 0, + textures: 0 + }; - // Don't normalize!, otherwise sharp corners become ugly - // but prevent crazy spikes - var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); - if ( v_trans_lensq <= 2 ) { + const render = { + frame: 0, + calls: 0, + triangles: 0, + points: 0, + lines: 0 + }; - return new Vector2( v_trans_x, v_trans_y ); + function update( count, mode, instanceCount ) { - } else { + render.calls ++; - shrink_by = Math.sqrt( v_trans_lensq / 2 ); + switch ( mode ) { - } + case gl.TRIANGLES: + render.triangles += instanceCount * ( count / 3 ); + break; - } else { + case gl.LINES: + render.lines += instanceCount * ( count / 2 ); + break; - // handle special case of collinear edges + case gl.LINE_STRIP: + render.lines += instanceCount * ( count - 1 ); + break; - var direction_eq = false; // assumes: opposite - if ( v_prev_x > Number.EPSILON ) { + case gl.LINE_LOOP: + render.lines += instanceCount * count; + break; - if ( v_next_x > Number.EPSILON ) { + case gl.POINTS: + render.points += instanceCount * count; + break; - direction_eq = true; + default: + console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); + break; - } + } - } else { + } - if ( v_prev_x < - Number.EPSILON ) { + function reset() { - if ( v_next_x < - Number.EPSILON ) { + render.calls = 0; + render.triangles = 0; + render.points = 0; + render.lines = 0; - direction_eq = true; + } - } + return { + memory: memory, + render: render, + programs: null, + autoReset: true, + reset: reset, + update: update + }; - } else { +} - if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { +function WebGLMorphtargets( gl, capabilities, textures ) { - direction_eq = true; + const morphTextures = new WeakMap(); + const morph = new Vector4(); - } + function update( object, geometry, program ) { - } + const objectInfluences = object.morphTargetInfluences; - } + // the following encodes morph targets into an array of data textures. Each layer represents a single morph target. - if ( direction_eq ) { + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - // console.log("Warning: lines are a straight sequence"); - v_trans_x = - v_prev_y; - v_trans_y = v_prev_x; - shrink_by = Math.sqrt( v_prev_lensq ); + let entry = morphTextures.get( geometry ); - } else { + if ( entry === undefined || entry.count !== morphTargetsCount ) { - // console.log("Warning: lines are a straight spike"); - v_trans_x = v_prev_x; - v_trans_y = v_prev_y; - shrink_by = Math.sqrt( v_prev_lensq / 2 ); + if ( entry !== undefined ) entry.texture.dispose(); - } + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.morphAttributes.normal !== undefined; + const hasMorphColors = geometry.morphAttributes.color !== undefined; - } + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; - return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); + 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; - var contourMovements = []; + if ( width > capabilities.maxTextureSize ) { - for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + height = Math.ceil( width / capabilities.maxTextureSize ); + width = capabilities.maxTextureSize; - if ( j === il ) { j = 0; } - if ( k === il ) { k = 0; } + } - // (j)---(i)---(k) - // console.log('i,j,k', i, j , k) + const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); - contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); + const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); + texture.type = FloatType; + texture.needsUpdate = true; - } + // fill buffer - var holesMovements = [], - oneHoleMovements, verticesMovements = contourMovements.concat(); + const vertexDataStride = vertexDataCount * 4; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + for ( let i = 0; i < morphTargetsCount; i ++ ) { - ahole = holes[ h ]; + const morphTarget = morphTargets[ i ]; + const morphNormal = morphNormals[ i ]; + const morphColor = morphColors[ i ]; - oneHoleMovements = []; + const offset = width * height * 4 * i; - for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + for ( let j = 0; j < morphTarget.count; j ++ ) { - if ( j === il ) { j = 0; } - if ( k === il ) { k = 0; } + const stride = j * vertexDataStride; - // (j)---(i)---(k) - oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); + if ( hasMorphPosition === true ) { - } + morph.fromBufferAttribute( morphTarget, j ); - holesMovements.push( oneHoleMovements ); - verticesMovements = verticesMovements.concat( oneHoleMovements ); + 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 ) { - // Loop bevelSegments, 1 for the front, 1 for the back + morph.fromBufferAttribute( morphNormal, j ); - for ( b = 0; b < bevelSegments; b ++ ) { + buffer[ offset + stride + 4 ] = morph.x; + buffer[ offset + stride + 5 ] = morph.y; + buffer[ offset + stride + 6 ] = morph.z; + buffer[ offset + stride + 7 ] = 0; - //for ( b = bevelSegments; b > 0; b -- ) { + } - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); + if ( hasMorphColors === true ) { - // contract shape + morph.fromBufferAttribute( morphColor, j ); - for ( i = 0, il = contour.length; i < il; i ++ ) { + 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; - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); + } - v( vert.x, vert.y, - z ); + } - } + } - // expand holes + entry = { + count: morphTargetsCount, + texture: texture, + size: new Vector2( width, height ) + }; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + morphTextures.set( geometry, entry ); - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; + function disposeTexture() { - for ( i = 0, il = ahole.length; i < il; i ++ ) { + texture.dispose(); - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + morphTextures.delete( geometry ); - v( vert.x, vert.y, - z ); + geometry.removeEventListener( 'dispose', disposeTexture ); } - } - - } + geometry.addEventListener( 'dispose', disposeTexture ); - bs = bevelSize; + } - // Back facing vertices + // + if ( object.isInstancedMesh === true && object.morphTexture !== null ) { - for ( i = 0; i < vlen; i ++ ) { + program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures ); - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; + } else { - if ( ! extrudeByPath ) { + let morphInfluencesSum = 0; - v( vert.x, vert.y, 0 ); + for ( let i = 0; i < objectInfluences.length; i ++ ) { - } else { + morphInfluencesSum += objectInfluences[ i ]; - // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); + } - normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); + const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; - position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); - v( position2.x, position2.y, position2.z ); + 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 ); + } - // Add stepped vertices... - // Including front facing vertices + return { - var s; + update: update - for ( s = 1; s <= steps; s ++ ) { + }; - for ( i = 0; i < vlen; i ++ ) { +} - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; +function WebGLObjects( gl, geometries, attributes, info ) { - if ( ! extrudeByPath ) { + let updateMap = new WeakMap(); - v( vert.x, vert.y, amount / steps * s ); + function update( object ) { - } else { + const frame = info.render.frame; - // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); + const geometry = object.geometry; + const buffergeometry = geometries.get( object, geometry ); - normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); + // Update once per frame - position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); + if ( updateMap.get( buffergeometry ) !== frame ) { - v( position2.x, position2.y, position2.z ); + geometries.update( buffergeometry ); - } + updateMap.set( buffergeometry, frame ); } - } - + if ( object.isInstancedMesh ) { - // Add bevel segments planes + if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { - //for ( b = 1; b <= bevelSegments; b ++ ) { - for ( b = bevelSegments - 1; b >= 0; b -- ) { + object.addEventListener( 'dispose', onInstancedMeshDispose ); - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); - - // contract shape + } - for ( i = 0, il = contour.length; i < il; i ++ ) { + if ( updateMap.get( object ) !== frame ) { - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); - v( vert.x, vert.y, amount + z ); + attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); - } + if ( object.instanceColor !== null ) { - // expand holes + attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + } - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; + updateMap.set( object, frame ); - for ( i = 0, il = ahole.length; i < il; i ++ ) { + } - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + } - if ( ! extrudeByPath ) { + if ( object.isSkinnedMesh ) { - v( vert.x, vert.y, amount + z ); + const skeleton = object.skeleton; - } else { + if ( updateMap.get( skeleton ) !== frame ) { - v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); + skeleton.update(); - } + updateMap.set( skeleton, frame ); } } + return buffergeometry; + } - /* Faces */ + function dispose() { - // Top and bottom faces + updateMap = new WeakMap(); - buildLidFaces(); + } - // Sides faces + function onInstancedMeshDispose( event ) { - buildSideFaces(); + const instancedMesh = event.target; + instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); - ///// Internal functions + attributes.remove( instancedMesh.instanceMatrix ); - function buildLidFaces() { + if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); - var start = verticesArray.length / 3; + } - if ( bevelEnabled ) { + return { - var layer = 0; // steps + 1 - var offset = vlen * layer; + update: update, + dispose: dispose - // Bottom faces + }; - for ( i = 0; i < flen; i ++ ) { +} - face = faces[ i ]; - f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); +class DepthTexture extends Texture { - } + constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) { - layer = steps + bevelSegments * 2; - offset = vlen * layer; + if ( format !== DepthFormat && format !== DepthStencilFormat ) { - // Top faces + throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); - for ( i = 0; i < flen; i ++ ) { + } - face = faces[ i ]; - f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); + if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; + if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; - } + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - } else { + this.isDepthTexture = true; - // Bottom faces + this.image = { width: width, height: height }; - for ( i = 0; i < flen; i ++ ) { + this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; + this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; - face = faces[ i ]; - f3( face[ 2 ], face[ 1 ], face[ 0 ] ); + this.flipY = false; + this.generateMipmaps = false; - } + this.compareFunction = null; - // Top faces + } - for ( i = 0; i < flen; i ++ ) { - face = faces[ i ]; - f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); + copy( source ) { - } + super.copy( source ); - } + this.compareFunction = source.compareFunction; - scope.addGroup( start, verticesArray.length / 3 - start, options.material !== undefined ? options.material : 0 ); + return this; } - // Create faces for the z-sides of the shape - - function buildSideFaces() { + toJSON( meta ) { - var start = verticesArray.length / 3; - var layeroffset = 0; - sidewalls( contour, layeroffset ); - layeroffset += contour.length; + const data = super.toJSON( meta ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; - ahole = holes[ h ]; - sidewalls( ahole, layeroffset ); - - //, true - layeroffset += ahole.length; - - } + return data; + } - scope.addGroup( start, verticesArray.length / 3 - start, options.extrudeMaterial !== undefined ? options.extrudeMaterial : 1 ); +} +/** + * Uniforms of a program. + * Those form a tree structure with a special top-level container for the root, + * which you get by calling 'new WebGLUniforms( gl, program )'. + * + * + * Properties of inner nodes including the top-level container: + * + * .seq - array of nested uniforms + * .map - nested uniforms by name + * + * + * Methods of all nodes except the top-level container: + * + * .setValue( gl, value, [textures] ) + * + * uploads a uniform value(s) + * the 'textures' parameter is needed for sampler uniforms + * + * + * Static methods of the top-level container (textures factorizations): + * + * .upload( gl, seq, values, textures ) + * + * sets uniforms in 'seq' to 'values[id].value' + * + * .seqWithValue( seq, values ) : filteredSeq + * + * filters 'seq' entries with corresponding entry in values + * + * + * Methods of the top-level container (textures factorizations): + * + * .setValue( gl, name, value, textures ) + * + * sets uniform with name 'name' to 'value' + * + * .setOptional( gl, obj, prop ) + * + * like .set for an optional property of the object + * + */ - } - function sidewalls( contour, layeroffset ) { +const emptyTexture = /*@__PURE__*/ new Texture(); - var j, k; - i = contour.length; +const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 ); - while ( -- i >= 0 ) { +const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); +const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); +const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); - j = i; - k = i - 1; - if ( k < 0 ) { k = contour.length - 1; } +// --- Utilities --- - //console.log('b', i,j, i-1, k,vertices.length); +// Array Caches (provide typed arrays for temporary by size) - var s = 0, - sl = steps + bevelSegments * 2; +const arrayCacheF32 = []; +const arrayCacheI32 = []; - for ( s = 0; s < sl; s ++ ) { +// Float32Array caches used for uploading Matrix uniforms - var slen1 = vlen * s; - var slen2 = vlen * ( s + 1 ); +const mat4array = new Float32Array( 16 ); +const mat3array = new Float32Array( 9 ); +const mat2array = new Float32Array( 4 ); - var a = layeroffset + j + slen1, - b = layeroffset + k + slen1, - c = layeroffset + k + slen2, - d = layeroffset + j + slen2; +// Flattening for arrays of vectors and matrices - f4( a, b, c, d ); +function flatten( array, nBlocks, blockSize ) { - } + const firstElem = array[ 0 ]; - } + if ( firstElem <= 0 || firstElem > 0 ) return array; + // unoptimized: ! isNaN( firstElem ) + // see http://jacksondunstan.com/articles/983 - } + const n = nBlocks * blockSize; + let r = arrayCacheF32[ n ]; - function v( x, y, z ) { + if ( r === undefined ) { - placeholder.push( x ); - placeholder.push( y ); - placeholder.push( z ); + r = new Float32Array( n ); + arrayCacheF32[ n ] = r; } + if ( nBlocks !== 0 ) { - function f3( a, b, c ) { + firstElem.toArray( r, 0 ); - addVertex( a ); - addVertex( b ); - addVertex( c ); + for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + offset += blockSize; + array[ i ].toArray( r, offset ); - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); + } } - function f4( a, b, c, d ) { - - addVertex( a ); - addVertex( b ); - addVertex( d ); + return r; - addVertex( b ); - addVertex( c ); - addVertex( d ); +} +function arraysEqual( a, b ) { - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + if ( a.length !== b.length ) return false; - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 3 ] ); + for ( let i = 0, l = a.length; i < l; i ++ ) { - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); - addUV( uvs[ 3 ] ); + if ( a[ i ] !== b[ i ] ) return false; } - function addVertex( index ) { - - indicesArray.push( verticesArray.length / 3 ); - verticesArray.push( placeholder[ index * 3 + 0 ] ); - verticesArray.push( placeholder[ index * 3 + 1 ] ); - verticesArray.push( placeholder[ index * 3 + 2 ] ); + return true; - } +} +function copyArray( a, b ) { - function addUV( vector2 ) { + for ( let i = 0, l = b.length; i < l; i ++ ) { - uvArray.push( vector2.x ); - uvArray.push( vector2.y ); + a[ i ] = b[ i ]; } - if ( ! options.arrays ) { - - this.setIndex( indicesArray ); - this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); +} - } +// Texture unit allocation -}; +function allocTexUnits( textures, n ) { -ExtrudeGeometry.WorldUVGenerator = { + let r = arrayCacheI32[ n ]; - generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { + if ( r === undefined ) { - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; + r = new Int32Array( n ); + arrayCacheI32[ n ] = r; - return [ - new Vector2( a_x, a_y ), - new Vector2( b_x, b_y ), - new Vector2( c_x, c_y ) - ]; + } - }, + for ( let i = 0; i !== n; ++ i ) { - generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { - - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var a_z = vertices[ indexA * 3 + 2 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var b_z = vertices[ indexB * 3 + 2 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; - var c_z = vertices[ indexC * 3 + 2 ]; - var d_x = vertices[ indexD * 3 ]; - var d_y = vertices[ indexD * 3 + 1 ]; - var d_z = vertices[ indexD * 3 + 2 ]; - - if ( Math.abs( a_y - b_y ) < 0.01 ) { - - return [ - new Vector2( a_x, 1 - a_z ), - new Vector2( b_x, 1 - b_z ), - new Vector2( c_x, 1 - c_z ), - new Vector2( d_x, 1 - d_z ) - ]; + r[ i ] = textures.allocateTextureUnit(); - } else { + } - return [ - new Vector2( a_y, 1 - a_z ), - new Vector2( b_y, 1 - b_z ), - new Vector2( c_y, 1 - c_z ), - new Vector2( d_y, 1 - d_z ) - ]; + return r; - } +} - } -}; +// --- Setters --- -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author alteredq / http://alteredqualia.com/ - * - * Text = 3D Text - * - * parameters = { - * font: , // font - * - * size: , // size of the text - * height: , // thickness to extrude text - * curveSegments: , // number of points on the curves - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into text bevel goes - * bevelSize: // how far from text outline is bevel - * } - */ +// Note: Defining these methods externally, because they come in a bunch +// and this way their names minify. -// TextGeometry +// Single scalar -function TextGeometry( text, parameters ) { +function setValueV1f( gl, v ) { - Geometry.call( this ); + const cache = this.cache; - this.type = 'TextGeometry'; + if ( cache[ 0 ] === v ) return; - this.parameters = { - text: text, - parameters: parameters - }; + gl.uniform1f( this.addr, v ); - this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) ); - this.mergeVertices(); + cache[ 0 ] = v; } -TextGeometry.prototype = Object.create( Geometry.prototype ); -TextGeometry.prototype.constructor = TextGeometry; - -// TextBufferGeometry - -function TextBufferGeometry( text, parameters ) { +// Single float vector (from flat array or THREE.VectorN) - parameters = parameters || {}; +function setValueV2f( gl, v ) { - var font = parameters.font; + const cache = this.cache; - if ( ! ( font && font.isFont ) ) { + if ( v.x !== undefined ) { - console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); - return new Geometry(); + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - } + gl.uniform2f( this.addr, v.x, v.y ); - var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - // translate parameters to ExtrudeGeometry API + } - parameters.amount = parameters.height !== undefined ? parameters.height : 50; + } else { - // defaults + if ( arraysEqual( cache, v ) ) return; - if ( parameters.bevelThickness === undefined ) { parameters.bevelThickness = 10; } - if ( parameters.bevelSize === undefined ) { parameters.bevelSize = 8; } - if ( parameters.bevelEnabled === undefined ) { parameters.bevelEnabled = false; } + gl.uniform2fv( this.addr, v ); - ExtrudeBufferGeometry.call( this, shapes, parameters ); + copyArray( cache, v ); - this.type = 'TextBufferGeometry'; + } } -TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype ); -TextBufferGeometry.prototype.constructor = TextBufferGeometry; +function setValueV3f( gl, v ) { -/** - * @author mrdoob / http://mrdoob.com/ - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - */ + const cache = this.cache; -// SphereGeometry + if ( v.x !== undefined ) { -function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - Geometry.call( this ); + gl.uniform3f( this.addr, v.x, v.y, v.z ); - this.type = 'SphereGeometry'; + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + } - this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) ); - this.mergeVertices(); + } else if ( v.r !== undefined ) { -} + if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { -SphereGeometry.prototype = Object.create( Geometry.prototype ); -SphereGeometry.prototype.constructor = SphereGeometry; + gl.uniform3f( this.addr, v.r, v.g, v.b ); -// SphereBufferGeometry + cache[ 0 ] = v.r; + cache[ 1 ] = v.g; + cache[ 2 ] = v.b; -function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { + } - BufferGeometry.call( this ); + } else { - this.type = 'SphereBufferGeometry'; + if ( arraysEqual( cache, v ) ) return; - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + gl.uniform3fv( this.addr, v ); - radius = radius || 1; + copyArray( cache, v ); - widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 ); - heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 ); + } - phiStart = phiStart !== undefined ? phiStart : 0; - phiLength = phiLength !== undefined ? phiLength : Math.PI * 2; +} - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI; +function setValueV4f( gl, v ) { - var thetaEnd = thetaStart + thetaLength; + const cache = this.cache; - var ix, iy; + if ( v.x !== undefined ) { - var index = 0; - var grid = []; + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - var vertex = new Vector3(); - var normal = new Vector3(); + gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); - // buffers + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // generate vertices, normals and uvs + } else { - for ( iy = 0; iy <= heightSegments; iy ++ ) { + if ( arraysEqual( cache, v ) ) return; - var verticesRow = []; + gl.uniform4fv( this.addr, v ); - var v = iy / heightSegments; + copyArray( cache, v ); - for ( ix = 0; ix <= widthSegments; ix ++ ) { + } - var u = ix / widthSegments; +} - // vertex +// Single matrix (from flat array or THREE.MatrixN) - vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); - vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); +function setValueM2( gl, v ) { - vertices.push( vertex.x, vertex.y, vertex.z ); + const cache = this.cache; + const elements = v.elements; - // normal + if ( elements === undefined ) { - normal.set( vertex.x, vertex.y, vertex.z ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + if ( arraysEqual( cache, v ) ) return; - // uv + gl.uniformMatrix2fv( this.addr, false, v ); - uvs.push( u, 1 - v ); + copyArray( cache, v ); - verticesRow.push( index ++ ); + } else { - } + if ( arraysEqual( cache, elements ) ) return; - grid.push( verticesRow ); + mat2array.set( elements ); - } + gl.uniformMatrix2fv( this.addr, false, mat2array ); - // indices + copyArray( cache, elements ); - for ( iy = 0; iy < heightSegments; iy ++ ) { + } - for ( ix = 0; ix < widthSegments; ix ++ ) { +} - var a = grid[ iy ][ ix + 1 ]; - var b = grid[ iy ][ ix ]; - var c = grid[ iy + 1 ][ ix ]; - var d = grid[ iy + 1 ][ ix + 1 ]; +function setValueM3( gl, v ) { - if ( iy !== 0 || thetaStart > 0 ) { indices.push( a, b, d ); } - if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) { indices.push( b, c, d ); } + const cache = this.cache; + const elements = v.elements; - } + if ( elements === undefined ) { - } + if ( arraysEqual( cache, v ) ) return; - // build geometry + gl.uniformMatrix3fv( this.addr, false, v ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + copyArray( cache, v ); -} + } else { -SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -SphereBufferGeometry.prototype.constructor = SphereBufferGeometry; + if ( arraysEqual( cache, elements ) ) return; -/** - * @author Kaleb Murphy - * @author Mugen87 / https://github.com/Mugen87 - */ + mat3array.set( elements ); -// RingGeometry + gl.uniformMatrix3fv( this.addr, false, mat3array ); -function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { + copyArray( cache, elements ); - Geometry.call( this ); + } - this.type = 'RingGeometry'; +} - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; +function setValueM4( gl, v ) { - this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) ); - this.mergeVertices(); + const cache = this.cache; + const elements = v.elements; -} + if ( elements === undefined ) { -RingGeometry.prototype = Object.create( Geometry.prototype ); -RingGeometry.prototype.constructor = RingGeometry; + if ( arraysEqual( cache, v ) ) return; -// RingBufferGeometry + gl.uniformMatrix4fv( this.addr, false, v ); -function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { + copyArray( cache, v ); - BufferGeometry.call( this ); + } else { - this.type = 'RingBufferGeometry'; + if ( arraysEqual( cache, elements ) ) return; - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + mat4array.set( elements ); - innerRadius = innerRadius || 0.5; - outerRadius = outerRadius || 1; + gl.uniformMatrix4fv( this.addr, false, mat4array ); - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + copyArray( cache, elements ); - thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8; - phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1; + } - // buffers +} - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; +// Single integer / boolean - // some helper variables +function setValueV1i( gl, v ) { - var segment; - var radius = innerRadius; - var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); - var vertex = new Vector3(); - var uv = new Vector2(); - var j, i; + const cache = this.cache; - // generate vertices, normals and uvs + if ( cache[ 0 ] === v ) return; - for ( j = 0; j <= phiSegments; j ++ ) { + gl.uniform1i( this.addr, v ); - for ( i = 0; i <= thetaSegments; i ++ ) { + cache[ 0 ] = v; - // values are generate from the inside of the ring to the outside +} - segment = thetaStart + i / thetaSegments * thetaLength; +// Single integer / boolean vector (from flat array or THREE.VectorN) - // vertex +function setValueV2i( gl, v ) { - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); + const cache = this.cache; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( v.x !== undefined ) { - // normal + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - normals.push( 0, 0, 1 ); + gl.uniform2i( this.addr, v.x, v.y ); - // uv + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - uv.x = ( vertex.x / outerRadius + 1 ) / 2; - uv.y = ( vertex.y / outerRadius + 1 ) / 2; + } - uvs.push( uv.x, uv.y ); + } else { - } + if ( arraysEqual( cache, v ) ) return; - // increase the radius for next row of vertices + gl.uniform2iv( this.addr, v ); - radius += radiusStep; + copyArray( cache, v ); } - // indices - - for ( j = 0; j < phiSegments; j ++ ) { +} - var thetaSegmentLevel = j * ( thetaSegments + 1 ); +function setValueV3i( gl, v ) { - for ( i = 0; i < thetaSegments; i ++ ) { + const cache = this.cache; - segment = i + thetaSegmentLevel; + if ( v.x !== undefined ) { - var a = segment; - var b = segment + thetaSegments + 1; - var c = segment + thetaSegments + 2; - var d = segment + 1; + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - // faces + gl.uniform3i( this.addr, v.x, v.y, v.z ); - indices.push( a, b, d ); - indices.push( b, c, d ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; } - } + } else { + + if ( arraysEqual( cache, v ) ) return; - // build geometry + gl.uniform3iv( this.addr, v ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + copyArray( cache, v ); + + } } -RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -RingBufferGeometry.prototype.constructor = RingBufferGeometry; +function setValueV4i( gl, v ) { -/** - * @author astrodud / http://astrodud.isgreat.org/ - * @author zz85 / https://github.com/zz85 - * @author bhouston / http://clara.io - * @author Mugen87 / https://github.com/Mugen87 - */ + const cache = this.cache; -// LatheGeometry + if ( v.x !== undefined ) { -function LatheGeometry( points, segments, phiStart, phiLength ) { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - Geometry.call( this ); + gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); - this.type = 'LatheGeometry'; + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; + } - this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) ); - this.mergeVertices(); + } else { -} + if ( arraysEqual( cache, v ) ) return; -LatheGeometry.prototype = Object.create( Geometry.prototype ); -LatheGeometry.prototype.constructor = LatheGeometry; + gl.uniform4iv( this.addr, v ); -// LatheBufferGeometry + copyArray( cache, v ); -function LatheBufferGeometry( points, segments, phiStart, phiLength ) { + } - BufferGeometry.call( this ); +} - this.type = 'LatheBufferGeometry'; +// Single unsigned integer - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; +function setValueV1ui( gl, v ) { - segments = Math.floor( segments ) || 12; - phiStart = phiStart || 0; - phiLength = phiLength || Math.PI * 2; + const cache = this.cache; - // clamp phiLength so it's in range of [ 0, 2PI ] + if ( cache[ 0 ] === v ) return; - phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 ); + gl.uniform1ui( this.addr, v ); + cache[ 0 ] = v; - // buffers +} - var indices = []; - var vertices = []; - var uvs = []; +// Single unsigned integer vector (from flat array or THREE.VectorN) - // helper variables +function setValueV2ui( gl, v ) { - var base; - var inverseSegments = 1.0 / segments; - var vertex = new Vector3(); - var uv = new Vector2(); - var i, j; + const cache = this.cache; - // generate vertices and uvs + if ( v.x !== undefined ) { - for ( i = 0; i <= segments; i ++ ) { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - var phi = phiStart + i * inverseSegments * phiLength; + gl.uniform2ui( this.addr, v.x, v.y ); - var sin = Math.sin( phi ); - var cos = Math.cos( phi ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - for ( j = 0; j <= ( points.length - 1 ); j ++ ) { + } - // vertex + } else { - vertex.x = points[ j ].x * sin; - vertex.y = points[ j ].y; - vertex.z = points[ j ].x * cos; + if ( arraysEqual( cache, v ) ) return; - vertices.push( vertex.x, vertex.y, vertex.z ); + gl.uniform2uiv( this.addr, v ); - // uv + copyArray( cache, v ); - uv.x = i / segments; - uv.y = j / ( points.length - 1 ); + } - uvs.push( uv.x, uv.y ); +} +function setValueV3ui( gl, v ) { - } + const cache = this.cache; - } + if ( v.x !== undefined ) { - // indices + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - for ( i = 0; i < segments; i ++ ) { + gl.uniform3ui( this.addr, v.x, v.y, v.z ); - for ( j = 0; j < ( points.length - 1 ); j ++ ) { + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - base = j + i * points.length; + } - var a = base; - var b = base + points.length; - var c = base + points.length + 1; - var d = base + 1; + } else { - // faces + if ( arraysEqual( cache, v ) ) return; - indices.push( a, b, d ); - indices.push( b, c, d ); + gl.uniform3uiv( this.addr, v ); - } + copyArray( cache, v ); } - // build geometry +} + +function setValueV4ui( gl, v ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + const cache = this.cache; - // generate normals + if ( v.x !== undefined ) { - this.computeVertexNormals(); + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). + gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); - if ( phiLength === Math.PI * 2 ) { + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - var normals = this.attributes.normal.array; - var n1 = new Vector3(); - var n2 = new Vector3(); - var n = new Vector3(); + } - // this is the buffer offset for the last line of vertices + } else { - base = segments * points.length * 3; + if ( arraysEqual( cache, v ) ) return; - for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) { + gl.uniform4uiv( this.addr, v ); - // select the normal of the vertex in the first line + copyArray( cache, v ); - n1.x = normals[ j + 0 ]; - n1.y = normals[ j + 1 ]; - n1.z = normals[ j + 2 ]; + } - // select the normal of the vertex in the last line +} - n2.x = normals[ base + j + 0 ]; - n2.y = normals[ base + j + 1 ]; - n2.z = normals[ base + j + 2 ]; - // average normals +// Single texture (2D / Cube) - n.addVectors( n1, n2 ).normalize(); +function setValueT1( gl, v, textures ) { - // assign the new values to both normals + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; - normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; - normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; + if ( cache[ 0 ] !== unit ) { - } + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; } -} + let emptyTexture2D; -LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -LatheBufferGeometry.prototype.constructor = LatheBufferGeometry; + if ( this.type === gl.SAMPLER_2D_SHADOW ) { -/** - * @author jonobr1 / http://jonobr1.com - * @author Mugen87 / https://github.com/Mugen87 - */ + emptyShadowTexture.compareFunction = LessEqualCompare; // #28670 + emptyTexture2D = emptyShadowTexture; + + } else { -// ShapeGeometry + emptyTexture2D = emptyTexture; -function ShapeGeometry( shapes, curveSegments ) { + } - Geometry.call( this ); + textures.setTexture2D( v || emptyTexture2D, unit ); - this.type = 'ShapeGeometry'; +} - if ( typeof curveSegments === 'object' ) { +function setValueT3D1( gl, v, textures ) { - console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' ); + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - curveSegments = curveSegments.curveSegments; + if ( cache[ 0 ] !== unit ) { - } + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; + } - this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) ); - this.mergeVertices(); + textures.setTexture3D( v || empty3dTexture, unit ); } -ShapeGeometry.prototype = Object.create( Geometry.prototype ); -ShapeGeometry.prototype.constructor = ShapeGeometry; +function setValueT6( gl, v, textures ) { -ShapeGeometry.prototype.toJSON = function () { + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - var data = Geometry.prototype.toJSON.call( this ); + if ( cache[ 0 ] !== unit ) { - var shapes = this.parameters.shapes; + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - return toJSON( shapes, data ); + } -}; + textures.setTextureCube( v || emptyCubeTexture, unit ); -// ShapeBufferGeometry +} -function ShapeBufferGeometry( shapes, curveSegments ) { +function setValueT2DArray1( gl, v, textures ) { - BufferGeometry.call( this ); + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - this.type = 'ShapeBufferGeometry'; + if ( cache[ 0 ] !== unit ) { - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - curveSegments = curveSegments || 12; + } - // buffers + textures.setTexture2DArray( v || emptyArrayTexture, unit ); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; +} - // helper variables +// Helper to pick the right setter for the singular case - var groupStart = 0; - var groupCount = 0; +function getSingularSetter( type ) { - // allow single and array values for "shapes" parameter + switch ( type ) { - if ( Array.isArray( shapes ) === false ) { + case 0x1406: return setValueV1f; // FLOAT + case 0x8b50: return setValueV2f; // _VEC2 + case 0x8b51: return setValueV3f; // _VEC3 + case 0x8b52: return setValueV4f; // _VEC4 - addShape( shapes ); + case 0x8b5a: return setValueM2; // _MAT2 + case 0x8b5b: return setValueM3; // _MAT3 + case 0x8b5c: return setValueM4; // _MAT4 - } else { + case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL + case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 + case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 + case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 - for ( var i = 0; i < shapes.length; i ++ ) { + case 0x1405: return setValueV1ui; // UINT + case 0x8dc6: return setValueV2ui; // _VEC2 + case 0x8dc7: return setValueV3ui; // _VEC3 + case 0x8dc8: return setValueV4ui; // _VEC4 - addShape( shapes[ i ] ); + case 0x8b5e: // SAMPLER_2D + case 0x8d66: // SAMPLER_EXTERNAL_OES + case 0x8dca: // INT_SAMPLER_2D + case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D + case 0x8b62: // SAMPLER_2D_SHADOW + return setValueT1; - this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support + case 0x8b5f: // SAMPLER_3D + case 0x8dcb: // INT_SAMPLER_3D + case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D + return setValueT3D1; - groupStart += groupCount; - groupCount = 0; + case 0x8b60: // SAMPLER_CUBE + case 0x8dcc: // INT_SAMPLER_CUBE + case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE + case 0x8dc5: // SAMPLER_CUBE_SHADOW + return setValueT6; - } + case 0x8dc1: // SAMPLER_2D_ARRAY + case 0x8dcf: // INT_SAMPLER_2D_ARRAY + case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY + case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW + return setValueT2DArray1; } - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); +} - // helper functions +// Array of scalars - function addShape( shape ) { +function setValueV1fArray( gl, v ) { - var i, l, shapeHole; + gl.uniform1fv( this.addr, v ); - var indexOffset = vertices.length / 3; - var points = shape.extractPoints( curveSegments ); +} - var shapeVertices = points.shape; - var shapeHoles = points.holes; +// Array of vectors (from flat array or array of THREE.VectorN) - // check direction of vertices +function setValueV2fArray( gl, v ) { - if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { + const data = flatten( v, this.size, 2 ); - shapeVertices = shapeVertices.reverse(); + gl.uniform2fv( this.addr, data ); - // also check if holes are in the opposite direction +} - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { +function setValueV3fArray( gl, v ) { - shapeHole = shapeHoles[ i ]; + const data = flatten( v, this.size, 3 ); - if ( ShapeUtils.isClockWise( shapeHole ) === true ) { + gl.uniform3fv( this.addr, data ); - shapeHoles[ i ] = shapeHole.reverse(); +} - } +function setValueV4fArray( gl, v ) { - } + const data = flatten( v, this.size, 4 ); - } + gl.uniform4fv( this.addr, data ); - var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); +} - // join vertices of inner and outer paths to a single array +// Array of matrices (from flat array or array of THREE.MatrixN) - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { +function setValueM2Array( gl, v ) { - shapeHole = shapeHoles[ i ]; - shapeVertices = shapeVertices.concat( shapeHole ); + const data = flatten( v, this.size, 4 ); - } + gl.uniformMatrix2fv( this.addr, false, data ); - // vertices, normals, uvs +} - for ( i = 0, l = shapeVertices.length; i < l; i ++ ) { +function setValueM3Array( gl, v ) { - var vertex = shapeVertices[ i ]; + const data = flatten( v, this.size, 9 ); - vertices.push( vertex.x, vertex.y, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( vertex.x, vertex.y ); // world uvs + gl.uniformMatrix3fv( this.addr, false, data ); - } +} - // incides +function setValueM4Array( gl, v ) { - for ( i = 0, l = faces.length; i < l; i ++ ) { + const data = flatten( v, this.size, 16 ); - var face = faces[ i ]; + gl.uniformMatrix4fv( this.addr, false, data ); - var a = face[ 0 ] + indexOffset; - var b = face[ 1 ] + indexOffset; - var c = face[ 2 ] + indexOffset; +} - indices.push( a, b, c ); - groupCount += 3; +// Array of integer / boolean - } +function setValueV1iArray( gl, v ) { - } + gl.uniform1iv( this.addr, v ); } -ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry; +// Array of integer / boolean vectors (from flat array) -ShapeBufferGeometry.prototype.toJSON = function () { +function setValueV2iArray( gl, v ) { - var data = BufferGeometry.prototype.toJSON.call( this ); - - var shapes = this.parameters.shapes; + gl.uniform2iv( this.addr, v ); - return toJSON( shapes, data ); +} -}; +function setValueV3iArray( gl, v ) { -// + gl.uniform3iv( this.addr, v ); -function toJSON( shapes, data ) { +} - data.shapes = []; +function setValueV4iArray( gl, v ) { - if ( Array.isArray( shapes ) ) { + gl.uniform4iv( this.addr, v ); - for ( var i = 0, l = shapes.length; i < l; i ++ ) { +} - var shape = shapes[ i ]; +// Array of unsigned integer - data.shapes.push( shape.uuid ); +function setValueV1uiArray( gl, v ) { - } + gl.uniform1uiv( this.addr, v ); - } else { +} - data.shapes.push( shapes.uuid ); +// Array of unsigned integer vectors (from flat array) - } +function setValueV2uiArray( gl, v ) { - return data; + gl.uniform2uiv( this.addr, v ); } -/** - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ - -function EdgesGeometry( geometry, thresholdAngle ) { +function setValueV3uiArray( gl, v ) { - BufferGeometry.call( this ); + gl.uniform3uiv( this.addr, v ); - this.type = 'EdgesGeometry'; +} - this.parameters = { - thresholdAngle: thresholdAngle - }; +function setValueV4uiArray( gl, v ) { - thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1; + gl.uniform4uiv( this.addr, v ); - // buffer +} - var vertices = []; - // helper variables +// Array of textures (2D / 3D / Cube / 2DArray) - var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle ); - var edge = [ 0, 0 ], edges = {}, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; +function setValueT1Array( gl, v, textures ) { - // prepare source geometry + const cache = this.cache; - var geometry2; + const n = v.length; - if ( geometry.isBufferGeometry ) { + const units = allocTexUnits( textures, n ); - geometry2 = new Geometry(); - geometry2.fromBufferGeometry( geometry ); + if ( ! arraysEqual( cache, units ) ) { - } else { + gl.uniform1iv( this.addr, units ); - geometry2 = geometry.clone(); + copyArray( cache, units ); } - geometry2.mergeVertices(); - geometry2.computeFaceNormals(); + for ( let i = 0; i !== n; ++ i ) { - var sourceVertices = geometry2.vertices; - var faces = geometry2.faces; + textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); - // now create a data structure where each entry represents an edge with its adjoining faces + } - for ( var i = 0, l = faces.length; i < l; i ++ ) { +} - var face = faces[ i ]; +function setValueT3DArray( gl, v, textures ) { - for ( var j = 0; j < 3; j ++ ) { + const cache = this.cache; - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); - edge[ 1 ] = Math.max( edge1, edge2 ); + const n = v.length; - key = edge[ 0 ] + ',' + edge[ 1 ]; + const units = allocTexUnits( textures, n ); - if ( edges[ key ] === undefined ) { + if ( ! arraysEqual( cache, units ) ) { - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined }; + gl.uniform1iv( this.addr, units ); - } else { + copyArray( cache, units ); - edges[ key ].face2 = i; + } - } + for ( let i = 0; i !== n; ++ i ) { - } + textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); } - // generate vertices +} - for ( key in edges ) { +function setValueT6Array( gl, v, textures ) { - var e = edges[ key ]; + const cache = this.cache; - // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree. + const n = v.length; - if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) { + const units = allocTexUnits( textures, n ); - var vertex = sourceVertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( ! arraysEqual( cache, units ) ) { - vertex = sourceVertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + gl.uniform1iv( this.addr, units ); - } + copyArray( cache, units ); } - // build geometry + for ( let i = 0; i !== n; ++ i ) { - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); -} + } -EdgesGeometry.prototype = Object.create( BufferGeometry.prototype ); -EdgesGeometry.prototype.constructor = EdgesGeometry; +} -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ +function setValueT2DArrayArray( gl, v, textures ) { -// CylinderGeometry + const cache = this.cache; -function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + const n = v.length; - Geometry.call( this ); + const units = allocTexUnits( textures, n ); - this.type = 'CylinderGeometry'; + if ( ! arraysEqual( cache, units ) ) { - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + gl.uniform1iv( this.addr, units ); - this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) ); - this.mergeVertices(); + copyArray( cache, units ); -} + } -CylinderGeometry.prototype = Object.create( Geometry.prototype ); -CylinderGeometry.prototype.constructor = CylinderGeometry; + for ( let i = 0; i !== n; ++ i ) { -// CylinderBufferGeometry + textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); -function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + } - BufferGeometry.call( this ); +} - this.type = 'CylinderBufferGeometry'; - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; +// Helper to pick the right setter for a pure (bottom-level) array - var scope = this; +function getPureArraySetter( type ) { - radiusTop = radiusTop !== undefined ? radiusTop : 1; - radiusBottom = radiusBottom !== undefined ? radiusBottom : 1; - height = height || 1; + switch ( type ) { - radialSegments = Math.floor( radialSegments ) || 8; - heightSegments = Math.floor( heightSegments ) || 1; + case 0x1406: return setValueV1fArray; // FLOAT + case 0x8b50: return setValueV2fArray; // _VEC2 + case 0x8b51: return setValueV3fArray; // _VEC3 + case 0x8b52: return setValueV4fArray; // _VEC4 - openEnded = openEnded !== undefined ? openEnded : false; - thetaStart = thetaStart !== undefined ? thetaStart : 0.0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + case 0x8b5a: return setValueM2Array; // _MAT2 + case 0x8b5b: return setValueM3Array; // _MAT3 + case 0x8b5c: return setValueM4Array; // _MAT4 - // buffers + case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL + case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 + case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 + case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + case 0x1405: return setValueV1uiArray; // UINT + case 0x8dc6: return setValueV2uiArray; // _VEC2 + case 0x8dc7: return setValueV3uiArray; // _VEC3 + case 0x8dc8: return setValueV4uiArray; // _VEC4 - // helper variables + case 0x8b5e: // SAMPLER_2D + case 0x8d66: // SAMPLER_EXTERNAL_OES + case 0x8dca: // INT_SAMPLER_2D + case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D + case 0x8b62: // SAMPLER_2D_SHADOW + return setValueT1Array; - var index = 0; - var indexArray = []; - var halfHeight = height / 2; - var groupStart = 0; + case 0x8b5f: // SAMPLER_3D + case 0x8dcb: // INT_SAMPLER_3D + case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D + return setValueT3DArray; - // generate geometry + case 0x8b60: // SAMPLER_CUBE + case 0x8dcc: // INT_SAMPLER_CUBE + case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE + case 0x8dc5: // SAMPLER_CUBE_SHADOW + return setValueT6Array; - generateTorso(); + case 0x8dc1: // SAMPLER_2D_ARRAY + case 0x8dcf: // INT_SAMPLER_2D_ARRAY + case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY + case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW + return setValueT2DArrayArray; - if ( openEnded === false ) { + } - if ( radiusTop > 0 ) { generateCap( true ); } - if ( radiusBottom > 0 ) { generateCap( false ); } +} - } +// --- Uniform Classes --- - // build geometry +class SingleUniform { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + constructor( id, activeInfo, addr ) { - function generateTorso() { + this.id = id; + this.addr = addr; + this.cache = []; + this.type = activeInfo.type; + this.setValue = getSingularSetter( activeInfo.type ); - var x, y; - var normal = new Vector3(); - var vertex = new Vector3(); + // this.path = activeInfo.name; // DEBUG - var groupCount = 0; + } - // this will be used to calculate the normal - var slope = ( radiusBottom - radiusTop ) / height; +} - // generate vertices, normals and uvs +class PureArrayUniform { - for ( y = 0; y <= heightSegments; y ++ ) { + constructor( id, activeInfo, addr ) { - var indexRow = []; + this.id = id; + this.addr = addr; + this.cache = []; + this.type = activeInfo.type; + this.size = activeInfo.size; + this.setValue = getPureArraySetter( activeInfo.type ); - var v = y / heightSegments; + // this.path = activeInfo.name; // DEBUG - // calculate the radius of the current row + } - var radius = v * ( radiusBottom - radiusTop ) + radiusTop; +} - for ( x = 0; x <= radialSegments; x ++ ) { +class StructuredUniform { - var u = x / radialSegments; + constructor( id ) { - var theta = u * thetaLength + thetaStart; + this.id = id; - var sinTheta = Math.sin( theta ); - var cosTheta = Math.cos( theta ); + this.seq = []; + this.map = {}; - // vertex + } - vertex.x = radius * sinTheta; - vertex.y = - v * height + halfHeight; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); + setValue( gl, value, textures ) { - // normal + const seq = this.seq; - normal.set( sinTheta, slope, cosTheta ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - // uv + const u = seq[ i ]; + u.setValue( gl, value[ u.id ], textures ); - uvs.push( u, 1 - v ); + } - // save index of vertex in respective row + } - indexRow.push( index ++ ); +} - } +// --- Top-level --- - // now save vertices of the row in our index array +// Parser - builds up the property tree from the path strings - indexArray.push( indexRow ); +const RePathPart = /(\w+)(\])?(\[|\.)?/g; - } +// extracts +// - the identifier (member name or array index) +// - followed by an optional right bracket (found when array index) +// - followed by an optional left bracket or dot (type of subscript) +// +// Note: These portions can be read in a non-overlapping fashion and +// allow straightforward parsing of the hierarchy that WebGL encodes +// in the uniform names. - // generate indices +function addUniform( container, uniformObject ) { - for ( x = 0; x < radialSegments; x ++ ) { + container.seq.push( uniformObject ); + container.map[ uniformObject.id ] = uniformObject; - for ( y = 0; y < heightSegments; y ++ ) { +} - // we use the index array to access the correct indices +function parseUniform( activeInfo, addr, container ) { - var a = indexArray[ y ][ x ]; - var b = indexArray[ y + 1 ][ x ]; - var c = indexArray[ y + 1 ][ x + 1 ]; - var d = indexArray[ y ][ x + 1 ]; + const path = activeInfo.name, + pathLength = path.length; - // faces + // reset RegExp object, because of the early exit of a previous run + RePathPart.lastIndex = 0; - indices.push( a, b, d ); - indices.push( b, c, d ); + while ( true ) { - // update group counter + const match = RePathPart.exec( path ), + matchEnd = RePathPart.lastIndex; - groupCount += 6; + let id = match[ 1 ]; + const idIsIndex = match[ 2 ] === ']', + subscript = match[ 3 ]; - } + if ( idIsIndex ) id = id | 0; // convert to integer - } + if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { - // add a group to the geometry. this will ensure multi material support + // bare name or "pure" bottom-level array "[0]" suffix - scope.addGroup( groupStart, groupCount, 0 ); + addUniform( container, subscript === undefined ? + new SingleUniform( id, activeInfo, addr ) : + new PureArrayUniform( id, activeInfo, addr ) ); - // calculate new start value for groups + break; - groupStart += groupCount; + } else { - } + // step into inner node / create it in case it doesn't exist - function generateCap( top ) { + const map = container.map; + let next = map[ id ]; - var x, centerIndexStart, centerIndexEnd; + if ( next === undefined ) { - var uv = new Vector2(); - var vertex = new Vector3(); + next = new StructuredUniform( id ); + addUniform( container, next ); - var groupCount = 0; + } - var radius = ( top === true ) ? radiusTop : radiusBottom; - var sign = ( top === true ) ? 1 : - 1; + container = next; - // save the index of the first center vertex - centerIndexStart = index; + } - // first we generate the center vertex data of the cap. - // because the geometry needs one set of uvs per face, - // we must generate a center vertex per face/segment + } - for ( x = 1; x <= radialSegments; x ++ ) { +} - // vertex +// Root Container - vertices.push( 0, halfHeight * sign, 0 ); +class WebGLUniforms { - // normal + constructor( gl, program ) { - normals.push( 0, sign, 0 ); + this.seq = []; + this.map = {}; - // uv + const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); - uvs.push( 0.5, 0.5 ); + for ( let i = 0; i < n; ++ i ) { - // increase index + const info = gl.getActiveUniform( program, i ), + addr = gl.getUniformLocation( program, info.name ); - index ++; + parseUniform( info, addr, this ); } - // save the index of the last center vertex - - centerIndexEnd = index; + } - // now we generate the surrounding vertices, normals and uvs + setValue( gl, name, value, textures ) { - for ( x = 0; x <= radialSegments; x ++ ) { + const u = this.map[ name ]; - var u = x / radialSegments; - var theta = u * thetaLength + thetaStart; + if ( u !== undefined ) u.setValue( gl, value, textures ); - var cosTheta = Math.cos( theta ); - var sinTheta = Math.sin( theta ); + } - // vertex + setOptional( gl, object, name ) { - vertex.x = radius * sinTheta; - vertex.y = halfHeight * sign; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); + const v = object[ name ]; - // normal + if ( v !== undefined ) this.setValue( gl, name, v ); - normals.push( 0, sign, 0 ); + } - // uv + static upload( gl, seq, values, textures ) { - uv.x = ( cosTheta * 0.5 ) + 0.5; - uv.y = ( sinTheta * 0.5 * sign ) + 0.5; - uvs.push( uv.x, uv.y ); + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - // increase index + const u = seq[ i ], + v = values[ u.id ]; - index ++; + if ( v.needsUpdate !== false ) { - } + // note: always updating when .needsUpdate is undefined + u.setValue( gl, v.value, textures ); - // generate indices + } - for ( x = 0; x < radialSegments; x ++ ) { + } - var c = centerIndexStart + x; - var i = centerIndexEnd + x; + } - if ( top === true ) { + static seqWithValue( seq, values ) { - // face top + const r = []; - indices.push( i, i + 1, c ); + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - } else { + const u = seq[ i ]; + if ( u.id in values ) r.push( u ); - // face bottom + } - indices.push( i + 1, i, c ); + return r; - } + } - groupCount += 3; +} - } +function WebGLShader( gl, type, string ) { - // add a group to the geometry. this will ensure multi material support + const shader = gl.createShader( type ); - scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); + gl.shaderSource( shader, string ); + gl.compileShader( shader ); - // calculate new start value for groups + return shader; - groupStart += groupCount; +} - } +// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ +const COMPLETION_STATUS_KHR = 0x91B1; -} +let programIdCount = 0; -CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry; +function handleSource( string, errorLine ) { -/** - * @author abelnation / http://github.com/abelnation - */ + const lines = string.split( '\n' ); + const lines2 = []; -// ConeGeometry + const from = Math.max( errorLine - 6, 0 ); + const to = Math.min( errorLine + 6, lines.length ); -function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + for ( let i = from; i < to; i ++ ) { - CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + const line = i + 1; + lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); - this.type = 'ConeGeometry'; + } - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + return lines2.join( '\n' ); } -ConeGeometry.prototype = Object.create( CylinderGeometry.prototype ); -ConeGeometry.prototype.constructor = ConeGeometry; +function getEncodingComponents( colorSpace ) { -// ConeBufferGeometry + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const encodingPrimaries = ColorManagement.getPrimaries( colorSpace ); -function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + let gamutMapping; - CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + if ( workingPrimaries === encodingPrimaries ) { - this.type = 'ConeBufferGeometry'; + gamutMapping = ''; - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + } else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) { -} + gamutMapping = 'LinearDisplayP3ToLinearSRGB'; -ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype ); -ConeBufferGeometry.prototype.constructor = ConeBufferGeometry; + } else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - * @author hughes - */ + gamutMapping = 'LinearSRGBToLinearDisplayP3'; -// CircleGeometry + } -function CircleGeometry( radius, segments, thetaStart, thetaLength ) { + switch ( colorSpace ) { - Geometry.call( this ); + case LinearSRGBColorSpace: + case LinearDisplayP3ColorSpace: + return [ gamutMapping, 'LinearTransferOETF' ]; - this.type = 'CircleGeometry'; + case SRGBColorSpace: + case DisplayP3ColorSpace: + return [ gamutMapping, 'sRGBTransferOETF' ]; - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + default: + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); + return [ gamutMapping, 'LinearTransferOETF' ]; - this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) ); - this.mergeVertices(); + } } -CircleGeometry.prototype = Object.create( Geometry.prototype ); -CircleGeometry.prototype.constructor = CircleGeometry; +function getShaderErrors( gl, shader, type ) { -// CircleBufferGeometry + const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); + const errors = gl.getShaderInfoLog( shader ).trim(); -function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) { + if ( status && errors === '' ) return ''; - BufferGeometry.call( this ); + const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); + if ( errorMatches ) { - this.type = 'CircleBufferGeometry'; + // --enable-privileged-webgl-extension + // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + const errorLine = parseInt( errorMatches[ 1 ] ); + return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); - radius = radius || 1; - segments = segments !== undefined ? Math.max( 3, segments ) : 8; + } else { - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + return errors; - // buffers + } - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; +} - // helper variables +function getTexelEncodingFunction( functionName, colorSpace ) { - var i, s; - var vertex = new Vector3(); - var uv = new Vector2(); + const components = getEncodingComponents( colorSpace ); + return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`; - // center point +} - vertices.push( 0, 0, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( 0.5, 0.5 ); +function getToneMappingFunction( functionName, toneMapping ) { - for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) { + let toneMappingName; - var segment = thetaStart + s / segments * thetaLength; + switch ( toneMapping ) { - // vertex + case LinearToneMapping: + toneMappingName = 'Linear'; + break; - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); + case ReinhardToneMapping: + toneMappingName = 'Reinhard'; + break; - vertices.push( vertex.x, vertex.y, vertex.z ); + case CineonToneMapping: + toneMappingName = 'OptimizedCineon'; + break; - // normal + case ACESFilmicToneMapping: + toneMappingName = 'ACESFilmic'; + break; - normals.push( 0, 0, 1 ); + case AgXToneMapping: + toneMappingName = 'AgX'; + break; - // uvs + case NeutralToneMapping: + toneMappingName = 'Neutral'; + break; - uv.x = ( vertices[ i ] / radius + 1 ) / 2; - uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; + case CustomToneMapping: + toneMappingName = 'Custom'; + break; - uvs.push( uv.x, uv.y ); + default: + console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); + toneMappingName = 'Linear'; } - // indices + return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; - for ( i = 1; i <= segments; i ++ ) { +} - indices.push( i, i + 1, 0 ); +const _v0$1 = /*@__PURE__*/ new Vector3(); - } +function getLuminanceFunction() { - // build geometry + ColorManagement.getLuminanceCoefficients( _v0$1 ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + const r = _v0$1.x.toFixed( 4 ); + const g = _v0$1.y.toFixed( 4 ); + const b = _v0$1.z.toFixed( 4 ); -} + return [ -CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -CircleBufferGeometry.prototype.constructor = CircleBufferGeometry; + 'float luminance( const in vec3 rgb ) {', + ` const vec3 weights = vec3( ${ r }, ${ g }, ${ b } );`, + ' return dot( weights, rgb );', -var Geometries = Object.freeze({ - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry -}); + '}' -/** - * @author mrdoob / http://mrdoob.com/ - * - * parameters = { - * color: , - * opacity: - * } - */ + ].join( '\n' ); -function ShadowMaterial( parameters ) { +} - Material.call( this ); +function generateVertexExtensions( parameters ) { - this.type = 'ShadowMaterial'; + const chunks = [ + parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '', + parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '', + ]; - this.color = new Color( 0x000000 ); - this.opacity = 1.0; + return chunks.filter( filterEmptyLine ).join( '\n' ); - this.lights = true; - this.transparent = true; +} - this.setValues( parameters ); +function generateDefines( defines ) { -} + const chunks = []; -ShadowMaterial.prototype = Object.create( Material.prototype ); -ShadowMaterial.prototype.constructor = ShadowMaterial; + for ( const name in defines ) { -ShadowMaterial.prototype.isShadowMaterial = true; + const value = defines[ name ]; -/** - * @author mrdoob / http://mrdoob.com/ - */ + if ( value === false ) continue; -function RawShaderMaterial( parameters ) { + chunks.push( '#define ' + name + ' ' + value ); - ShaderMaterial.call( this, parameters ); + } - this.type = 'RawShaderMaterial'; + return chunks.join( '\n' ); } -RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype ); -RawShaderMaterial.prototype.constructor = RawShaderMaterial; +function fetchAttributeLocations( gl, program ) { -RawShaderMaterial.prototype.isRawShaderMaterial = true; + const attributes = {}; -/** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * color: , - * roughness: , - * metalness: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * roughnessMap: new THREE.Texture( ), - * - * metalnessMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), - * envMapIntensity: - * - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); + + for ( let i = 0; i < n; i ++ ) { -function MeshStandardMaterial( parameters ) { + const info = gl.getActiveAttrib( program, i ); + const name = info.name; - Material.call( this ); + 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; - this.defines = { 'STANDARD': '' }; + // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); + + attributes[ name ] = { + type: info.type, + location: gl.getAttribLocation( program, name ), + locationSize: locationSize + }; - this.type = 'MeshStandardMaterial'; + } - this.color = new Color( 0xffffff ); // diffuse - this.roughness = 0.5; - this.metalness = 0.5; + return attributes; - this.map = null; +} - this.lightMap = null; - this.lightMapIntensity = 1.0; +function filterEmptyLine( string ) { - this.aoMap = null; - this.aoMapIntensity = 1.0; + return string !== ''; - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; +} - this.bumpMap = null; - this.bumpScale = 1; +function replaceLightNums( string, parameters ) { - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + return string + .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) + .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) + .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) + .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) + .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_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) + .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) + .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); - this.roughnessMap = null; +} - this.metalnessMap = null; +function replaceClippingPlaneNums( string, parameters ) { - this.alphaMap = null; + return string + .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) + .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); - this.envMap = null; - this.envMapIntensity = 1.0; +} - this.refractionRatio = 0.98; +// Resolve Includes - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; +const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; +function resolveIncludes( string ) { - this.setValues( parameters ); + return string.replace( includePattern, includeReplacer ); } -MeshStandardMaterial.prototype = Object.create( Material.prototype ); -MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; +const shaderChunkMap = new Map(); -MeshStandardMaterial.prototype.isMeshStandardMaterial = true; +function includeReplacer( match, include ) { -MeshStandardMaterial.prototype.copy = function ( source ) { + let string = ShaderChunk[ include ]; - Material.prototype.copy.call( this, source ); + if ( string === undefined ) { - this.defines = { 'STANDARD': '' }; + const newInclude = shaderChunkMap.get( include ); - this.color.copy( source.color ); - this.roughness = source.roughness; - this.metalness = source.metalness; + if ( newInclude !== undefined ) { - this.map = source.map; + string = ShaderChunk[ newInclude ]; + console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + } else { - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + throw new Error( 'Can not resolve #include <' + include + '>' ); - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + } - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + } - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + return resolveIncludes( string ); - this.roughnessMap = source.roughnessMap; +} - this.metalnessMap = source.metalnessMap; +// Unroll Loops - this.alphaMap = source.alphaMap; +const 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; - this.envMap = source.envMap; - this.envMapIntensity = source.envMapIntensity; +function unrollLoops( string ) { - this.refractionRatio = source.refractionRatio; + return string.replace( unrollLoopPattern, loopReplacer ); - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; +} - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; +function loopReplacer( match, start, end, snippet ) { - return this; + let string = ''; -}; + for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { -/** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * reflectivity: - * } - */ + string += snippet + .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) + .replace( /UNROLLED_LOOP_INDEX/g, i ); -function MeshPhysicalMaterial( parameters ) { + } - MeshStandardMaterial.call( this ); + return string; - this.defines = { 'PHYSICAL': '' }; +} - this.type = 'MeshPhysicalMaterial'; +// - this.reflectivity = 0.5; // maps to F0 = 0.04 +function generatePrecision( parameters ) { - this.clearCoat = 0.0; - this.clearCoatRoughness = 0.0; + let precisionstring = `precision ${parameters.precision} float; + precision ${parameters.precision} int; + precision ${parameters.precision} sampler2D; + precision ${parameters.precision} samplerCube; + precision ${parameters.precision} sampler3D; + precision ${parameters.precision} sampler2DArray; + precision ${parameters.precision} sampler2DShadow; + precision ${parameters.precision} samplerCubeShadow; + precision ${parameters.precision} sampler2DArrayShadow; + precision ${parameters.precision} isampler2D; + precision ${parameters.precision} isampler3D; + precision ${parameters.precision} isamplerCube; + precision ${parameters.precision} isampler2DArray; + precision ${parameters.precision} usampler2D; + precision ${parameters.precision} usampler3D; + precision ${parameters.precision} usamplerCube; + precision ${parameters.precision} usampler2DArray; + `; - this.setValues( parameters ); + if ( parameters.precision === 'highp' ) { -} + precisionstring += '\n#define HIGH_PRECISION'; -MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); -MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; + } else if ( parameters.precision === 'mediump' ) { -MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; + precisionstring += '\n#define MEDIUM_PRECISION'; -MeshPhysicalMaterial.prototype.copy = function ( source ) { + } else if ( parameters.precision === 'lowp' ) { - MeshStandardMaterial.prototype.copy.call( this, source ); + precisionstring += '\n#define LOW_PRECISION'; - this.defines = { 'PHYSICAL': '' }; + } - this.reflectivity = source.reflectivity; + return precisionstring; - this.clearCoat = source.clearCoat; - this.clearCoatRoughness = source.clearCoatRoughness; +} - return this; +function generateShadowMapTypeDefine( parameters ) { -}; + let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * specular: , - * shininess: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + if ( parameters.shadowMapType === PCFShadowMap ) { -function MeshPhongMaterial( parameters ) { + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; - Material.call( this ); + } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { - this.type = 'MeshPhongMaterial'; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; - this.color = new Color( 0xffffff ); // diffuse - this.specular = new Color( 0x111111 ); - this.shininess = 30; + } else if ( parameters.shadowMapType === VSMShadowMap ) { - this.map = null; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; - this.lightMap = null; - this.lightMapIntensity = 1.0; + } - this.aoMap = null; - this.aoMapIntensity = 1.0; + return shadowMapTypeDefine; - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; +} - this.bumpMap = null; - this.bumpScale = 1; +function generateEnvMapTypeDefine( parameters ) { - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + if ( parameters.envMap ) { - this.specularMap = null; + switch ( parameters.envMapMode ) { - this.alphaMap = null; + case CubeReflectionMapping: + case CubeRefractionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; + break; - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + case CubeUVReflectionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; + break; - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + } - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + } - this.setValues( parameters ); + return envMapTypeDefine; } -MeshPhongMaterial.prototype = Object.create( Material.prototype ); -MeshPhongMaterial.prototype.constructor = MeshPhongMaterial; +function generateEnvMapModeDefine( parameters ) { -MeshPhongMaterial.prototype.isMeshPhongMaterial = true; + let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; -MeshPhongMaterial.prototype.copy = function ( source ) { + if ( parameters.envMap ) { - Material.prototype.copy.call( this, source ); + switch ( parameters.envMapMode ) { - this.color.copy( source.color ); - this.specular.copy( source.specular ); - this.shininess = source.shininess; + case CubeRefractionMapping: - this.map = source.map; + envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; + break; - 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; + return envMapModeDefine; - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; +} - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); +function generateEnvMapBlendingDefine( parameters ) { - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; - this.specularMap = source.specularMap; + if ( parameters.envMap ) { - this.alphaMap = source.alphaMap; + switch ( parameters.combine ) { - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + case MultiplyOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + break; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + case MixOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; + break; - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + case AddOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; + break; - return this; + } -}; + } -/** - * @author takahirox / http://github.com/takahirox - * - * parameters = { - * gradientMap: new THREE.Texture( ) - * } - */ + return envMapBlendingDefine; -function MeshToonMaterial( parameters ) { +} - MeshPhongMaterial.call( this ); +function generateCubeUVSize( parameters ) { - this.defines = { 'TOON': '' }; + const imageHeight = parameters.envMapCubeUVHeight; - this.type = 'MeshToonMaterial'; + if ( imageHeight === null ) return null; - this.gradientMap = null; + const maxMip = Math.log2( imageHeight ) - 2; - this.setValues( parameters ); + const texelHeight = 1.0 / imageHeight; -} + const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); -MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype ); -MeshToonMaterial.prototype.constructor = MeshToonMaterial; + return { texelWidth, texelHeight, maxMip }; -MeshToonMaterial.prototype.isMeshToonMaterial = true; +} -MeshToonMaterial.prototype.copy = function ( source ) { +function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { - MeshPhongMaterial.prototype.copy.call( this, source ); + // TODO Send this event to Three.js DevTools + // console.log( 'WebGLProgram', cacheKey ); - this.gradientMap = source.gradientMap; + const gl = renderer.getContext(); - return this; + const defines = parameters.defines; -}; + let vertexShader = parameters.vertexShader; + let fragmentShader = parameters.fragmentShader; -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * opacity: , - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * wireframe: , - * wireframeLinewidth: - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); + const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); + const envMapModeDefine = generateEnvMapModeDefine( parameters ); + const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); + const envMapCubeUVSize = generateCubeUVSize( parameters ); -function MeshNormalMaterial( parameters ) { + const customVertexExtensions = generateVertexExtensions( parameters ); - Material.call( this ); + const customDefines = generateDefines( defines ); - this.type = 'MeshNormalMaterial'; + const program = gl.createProgram(); - this.bumpMap = null; - this.bumpScale = 1; + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + if ( parameters.isRawShaderMaterial ) { - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + prefixVertex = [ - this.wireframe = false; - this.wireframeLinewidth = 1; + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - this.fog = false; - this.lights = false; + customDefines - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + ].filter( filterEmptyLine ).join( '\n' ); - this.setValues( parameters ); + if ( prefixVertex.length > 0 ) { -} + prefixVertex += '\n'; -MeshNormalMaterial.prototype = Object.create( Material.prototype ); -MeshNormalMaterial.prototype.constructor = MeshNormalMaterial; + } -MeshNormalMaterial.prototype.isMeshNormalMaterial = true; + prefixFragment = [ -MeshNormalMaterial.prototype.copy = function ( source ) { + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - Material.prototype.copy.call( this, source ); + customDefines - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + ].filter( filterEmptyLine ).join( '\n' ); - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + if ( prefixFragment.length > 0 ) { - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + prefixFragment += '\n'; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; + } - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + } else { - return this; + prefixVertex = [ -}; + generatePrecision( parameters ), -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, -function MeshLambertMaterial( parameters ) { + customDefines, - Material.call( this ); + parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', + parameters.batching ? '#define USE_BATCHING' : '', + parameters.batchingColor ? '#define USE_BATCHING_COLOR' : '', + parameters.instancing ? '#define USE_INSTANCING' : '', + parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', + parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '', - this.type = 'MeshLambertMaterial'; + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', - this.color = new Color( 0xffffff ); // diffuse + 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.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', - this.map = null; + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', - this.lightMap = null; - this.lightMapIntensity = 1.0; + parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', + parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', + parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', - this.aoMap = null; - this.aoMapIntensity = 1.0; + parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', + parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', - this.specularMap = null; + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', + parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.alphaHash ? '#define USE_ALPHAHASH' : '', - this.alphaMap = null; + parameters.transmission ? '#define USE_TRANSMISSION' : '', + parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', + parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + // - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', - this.setValues( parameters ); + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', -} + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', -MeshLambertMaterial.prototype = Object.create( Material.prototype ); -MeshLambertMaterial.prototype.constructor = MeshLambertMaterial; + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', -MeshLambertMaterial.prototype.isMeshLambertMaterial = true; + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', -MeshLambertMaterial.prototype.copy = function ( source ) { + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', - Material.prototype.copy.call( this, source ); + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', - this.color.copy( source.color ); + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', - this.map = source.map; + // - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', + parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + parameters.flatShading ? '#define FLAT_SHADED' : '', - this.specularMap = source.specularMap; + parameters.skinning ? '#define USE_SKINNING' : '', - this.alphaMap = source.alphaMap; + parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', + parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', + ( parameters.morphColors ) ? '#define USE_MORPHCOLORS' : '', + ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', + ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', - return this; + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', -}; + 'uniform mat4 modelMatrix;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'uniform mat4 viewMatrix;', + 'uniform mat3 normalMatrix;', + 'uniform vec3 cameraPosition;', + 'uniform bool isOrthographic;', -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * - * scale: , - * dashSize: , - * gapSize: - * } - */ + '#ifdef USE_INSTANCING', -function LineDashedMaterial( parameters ) { + ' attribute mat4 instanceMatrix;', - LineBasicMaterial.call( this ); + '#endif', - this.type = 'LineDashedMaterial'; + '#ifdef USE_INSTANCING_COLOR', - this.scale = 1; - this.dashSize = 3; - this.gapSize = 1; + ' attribute vec3 instanceColor;', - this.setValues( parameters ); + '#endif', -} + '#ifdef USE_INSTANCING_MORPH', -LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); -LineDashedMaterial.prototype.constructor = LineDashedMaterial; + ' uniform sampler2D morphTexture;', -LineDashedMaterial.prototype.isLineDashedMaterial = true; + '#endif', -LineDashedMaterial.prototype.copy = function ( source ) { + 'attribute vec3 position;', + 'attribute vec3 normal;', + 'attribute vec2 uv;', - LineBasicMaterial.prototype.copy.call( this, source ); + '#ifdef USE_UV1', - this.scale = source.scale; - this.dashSize = source.dashSize; - this.gapSize = source.gapSize; + ' attribute vec2 uv1;', - return this; + '#endif', -}; + '#ifdef USE_UV2', + ' attribute vec2 uv2;', + '#endif', -var Materials = Object.freeze({ - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material -}); + '#ifdef USE_UV3', -/** - * @author mrdoob / http://mrdoob.com/ - */ + ' attribute vec2 uv3;', -var Cache = { + '#endif', - enabled: false, + '#ifdef USE_TANGENT', - files: {}, + ' attribute vec4 tangent;', - add: function ( key, file ) { + '#endif', - if ( this.enabled === false ) { return; } + '#if defined( USE_COLOR_ALPHA )', - // console.log( 'THREE.Cache', 'Adding key:', key ); + ' attribute vec4 color;', - this.files[ key ] = file; + '#elif defined( USE_COLOR )', - }, + ' attribute vec3 color;', - get: function ( key ) { + '#endif', - if ( this.enabled === false ) { return; } + '#ifdef USE_SKINNING', - // console.log( 'THREE.Cache', 'Checking key:', key ); + ' attribute vec4 skinIndex;', + ' attribute vec4 skinWeight;', - return this.files[ key ]; + '#endif', - }, + '\n' - remove: function ( key ) { + ].filter( filterEmptyLine ).join( '\n' ); - delete this.files[ key ]; + prefixFragment = [ - }, + generatePrecision( parameters ), - clear: function () { + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - this.files = {}; + customDefines, - } + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', -}; + parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '', + 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.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', -/** - * @author mrdoob / http://mrdoob.com/ - */ + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', -function LoadingManager( onLoad, onProgress, onError ) { + parameters.clearcoat ? '#define USE_CLEARCOAT' : '', + parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', + parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', + parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', - var scope = this; + parameters.dispersion ? '#define USE_DISPERSION' : '', - var isLoading = false; - var itemsLoaded = 0; - var itemsTotal = 0; - var urlModifier = undefined; + parameters.iridescence ? '#define USE_IRIDESCENCE' : '', + parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', + parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', - this.itemStart = function ( url ) { + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', + parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - itemsTotal ++; + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.alphaTest ? '#define USE_ALPHATEST' : '', + parameters.alphaHash ? '#define USE_ALPHAHASH' : '', - if ( isLoading === false ) { + parameters.sheen ? '#define USE_SHEEN' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', - if ( scope.onStart !== undefined ) { + parameters.transmission ? '#define USE_TRANSMISSION' : '', + parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', + parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - scope.onStart( url, itemsLoaded, itemsTotal ); + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', + parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '', + parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', - } + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', - } + parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', - isLoading = true; + parameters.flatShading ? '#define FLAT_SHADED' : '', - }; + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - this.itemEnd = function ( url ) { + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - itemsLoaded ++; + parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - if ( scope.onProgress !== undefined ) { + parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', - scope.onProgress( url, itemsLoaded, itemsTotal ); + parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - } + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - if ( itemsLoaded === itemsTotal ) { + 'uniform mat4 viewMatrix;', + 'uniform vec3 cameraPosition;', + 'uniform bool isOrthographic;', - isLoading = false; + ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', + ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below + ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', - if ( scope.onLoad !== undefined ) { + parameters.dithering ? '#define DITHERING' : '', + parameters.opaque ? '#define OPAQUE' : '', - scope.onLoad(); + ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), + getLuminanceFunction(), - } + parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', - } + '\n' - }; + ].filter( filterEmptyLine ).join( '\n' ); - this.itemError = function ( url ) { + } - if ( scope.onError !== undefined ) { + vertexShader = resolveIncludes( vertexShader ); + vertexShader = replaceLightNums( vertexShader, parameters ); + vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); - scope.onError( url ); + fragmentShader = resolveIncludes( fragmentShader ); + fragmentShader = replaceLightNums( fragmentShader, parameters ); + fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); - } + vertexShader = unrollLoops( vertexShader ); + fragmentShader = unrollLoops( fragmentShader ); - }; + if ( parameters.isRawShaderMaterial !== true ) { - this.resolveURL = function ( url ) { + // GLSL 3.0 conversion for built-in materials and ShaderMaterial - if ( urlModifier ) { + versionString = '#version 300 es\n'; - return urlModifier( url ); + prefixVertex = [ + customVertexExtensions, + '#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; - return url; + // console.log( '*VERTEX*', vertexGlsl ); + // console.log( '*FRAGMENT*', fragmentGlsl ); - }; + const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); + const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); - this.setURLModifier = function ( transform ) { + gl.attachShader( program, glVertexShader ); + gl.attachShader( program, glFragmentShader ); - urlModifier = transform; - return this; + // Force a particular attribute to index 0. - }; + if ( parameters.index0AttributeName !== undefined ) { -} + gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); -var DefaultLoadingManager = new LoadingManager(); + } else if ( parameters.morphTargets === true ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + // programs with morphTargets displace position out of attribute 0 + gl.bindAttribLocation( program, 0, 'position' ); -var loading = {}; + } -function FileLoader( manager ) { + gl.linkProgram( program ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + function onFirstUse( self ) { -} + // check for link errors + if ( renderer.debug.checkShaderErrors ) { -Object.assign( FileLoader.prototype, { + const programLog = gl.getProgramInfoLog( program ).trim(); + const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); + const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); - load: function ( url, onLoad, onProgress, onError ) { + let runnable = true; + let haveDiagnostics = true; - if ( url === undefined ) { url = ''; } + if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { - if ( this.path !== undefined ) { url = this.path + url; } + runnable = false; - url = this.manager.resolveURL( url ); + if ( typeof renderer.debug.onShaderError === 'function' ) { - var scope = this; + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); - var cached = Cache.get( url ); + } else { - if ( cached !== undefined ) { + // default error reporting - scope.manager.itemStart( url ); + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); - setTimeout( function () { + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Material Name: ' + self.name + '\n' + + 'Material Type: ' + self.type + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); - if ( onLoad ) { onLoad( cached ); } + } - scope.manager.itemEnd( url ); + } else if ( programLog !== '' ) { - }, 0 ); + console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); - return cached; + } else if ( vertexLog === '' || fragmentLog === '' ) { - } + haveDiagnostics = false; - // Check if request is duplicate + } - if ( loading[ url ] !== undefined ) { + if ( haveDiagnostics ) { - loading[ url ].push( { + self.diagnostics = { - onLoad: onLoad, - onProgress: onProgress, - onError: onError + runnable: runnable, - } ); + programLog: programLog, - return; + vertexShader: { - } + log: vertexLog, + prefix: prefixVertex - // Check for data: URI - var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/; - var dataUriRegexResult = url.match( dataUriRegex ); + }, - // Safari can not handle Data URIs through XMLHttpRequest so process manually - if ( dataUriRegexResult ) { + fragmentShader: { - var mimeType = dataUriRegexResult[ 1 ]; - var isBase64 = !! dataUriRegexResult[ 2 ]; - var data = dataUriRegexResult[ 3 ]; + log: fragmentLog, + prefix: prefixFragment - data = window.decodeURIComponent( data ); + } - if ( isBase64 ) { data = window.atob( data ); } + }; - try { + } - var response; - var responseType = ( this.responseType || '' ).toLowerCase(); + } - switch ( responseType ) { + // Clean up - case 'arraybuffer': - case 'blob': + // Crashes in iOS9 and iOS10. #18402 + // gl.detachShader( program, glVertexShader ); + // gl.detachShader( program, glFragmentShader ); - var view = new Uint8Array( data.length ); + gl.deleteShader( glVertexShader ); + gl.deleteShader( glFragmentShader ); - for ( var i = 0; i < data.length; i ++ ) { + cachedUniforms = new WebGLUniforms( gl, program ); + cachedAttributes = fetchAttributeLocations( gl, program ); - view[ i ] = data.charCodeAt( i ); + } - } + // set up caching for uniform locations - if ( responseType === 'blob' ) { + let cachedUniforms; - response = new Blob( [ view.buffer ], { type: mimeType } ); + this.getUniforms = function () { - } else { + if ( cachedUniforms === undefined ) { - response = view.buffer; + // Populates cachedUniforms and cachedAttributes + onFirstUse( this ); - } + } - break; + return cachedUniforms; - case 'document': + }; - var parser = new DOMParser(); - response = parser.parseFromString( data, mimeType ); + // set up caching for attribute locations - break; + let cachedAttributes; - case 'json': + this.getAttributes = function () { - response = JSON.parse( data ); + if ( cachedAttributes === undefined ) { - break; + // Populates cachedAttributes and cachedUniforms + onFirstUse( this ); - default: // 'text' or other + } - response = data; + return cachedAttributes; - break; + }; - } + // indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported, + // flag the program as ready immediately. It may cause a stall when it's first used. - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { + let programReady = ( parameters.rendererExtensionParallelShaderCompile === false ); - if ( onLoad ) { onLoad( response ); } + this.isReady = function () { - scope.manager.itemEnd( url ); + if ( programReady === false ) { - }, 0 ); + programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR ); - } catch ( error ) { + } - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { + return programReady; - if ( onError ) { onError( error ); } + }; - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + // free resource - }, 0 ); + this.destroy = function () { - } + bindingStates.releaseStatesOfProgram( this ); - } else { + gl.deleteProgram( program ); + this.program = undefined; - // Initialise array for duplicate requests + }; - loading[ url ] = []; + // - loading[ url ].push( { + this.type = parameters.shaderType; + this.name = parameters.shaderName; + this.id = programIdCount ++; + this.cacheKey = cacheKey; + this.usedTimes = 1; + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; - onLoad: onLoad, - onProgress: onProgress, - onError: onError + return this; - } ); +} - var request = new XMLHttpRequest(); +let _id$1 = 0; - request.open( 'GET', url, true ); +class WebGLShaderCache { - request.addEventListener( 'load', function ( event ) { + constructor() { - var response = this.response; + this.shaderCache = new Map(); + this.materialCache = new Map(); - Cache.add( url, response ); + } - var callbacks = loading[ url ]; + update( material ) { - delete loading[ url ]; + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; - if ( this.status === 200 ) { + const vertexShaderStage = this._getShaderStage( vertexShader ); + const fragmentShaderStage = this._getShaderStage( fragmentShader ); - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + const materialShaders = this._getShaderCacheForMaterial( material ); - var callback = callbacks[ i ]; - if ( callback.onLoad ) { callback.onLoad( response ); } + if ( materialShaders.has( vertexShaderStage ) === false ) { - } + materialShaders.add( vertexShaderStage ); + vertexShaderStage.usedTimes ++; - scope.manager.itemEnd( url ); + } - } else if ( this.status === 0 ) { + if ( materialShaders.has( fragmentShaderStage ) === false ) { - // Some browsers return HTTP Status 0 when using non-http protocol - // e.g. 'file://' or 'data://'. Handle as success. + materialShaders.add( fragmentShaderStage ); + fragmentShaderStage.usedTimes ++; - console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); + } - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + return this; - var callback = callbacks[ i ]; - if ( callback.onLoad ) { callback.onLoad( response ); } + } - } + remove( material ) { - scope.manager.itemEnd( url ); + const materialShaders = this.materialCache.get( material ); - } else { + for ( const shaderStage of materialShaders ) { - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + shaderStage.usedTimes --; - var callback = callbacks[ i ]; - if ( callback.onError ) { callback.onError( event ); } + if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); - } + } - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + this.materialCache.delete( material ); - } + return this; - }, false ); + } - request.addEventListener( 'progress', function ( event ) { + getVertexShaderID( material ) { - var callbacks = loading[ url ]; + return this._getShaderStage( material.vertexShader ).id; - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + } - var callback = callbacks[ i ]; - if ( callback.onProgress ) { callback.onProgress( event ); } + getFragmentShaderID( material ) { - } + return this._getShaderStage( material.fragmentShader ).id; - }, false ); + } - request.addEventListener( 'error', function ( event ) { + dispose() { - var callbacks = loading[ url ]; + this.shaderCache.clear(); + this.materialCache.clear(); - delete loading[ url ]; + } - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + _getShaderCacheForMaterial( material ) { - var callback = callbacks[ i ]; - if ( callback.onError ) { callback.onError( event ); } + const cache = this.materialCache; + let set = cache.get( material ); - } + if ( set === undefined ) { - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + set = new Set(); + cache.set( material, set ); - }, false ); + } - if ( this.responseType !== undefined ) { request.responseType = this.responseType; } - if ( this.withCredentials !== undefined ) { request.withCredentials = this.withCredentials; } + return set; - if ( request.overrideMimeType ) { request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); } + } - for ( var header in this.requestHeader ) { + _getShaderStage( code ) { - request.setRequestHeader( header, this.requestHeader[ header ] ); + const cache = this.shaderCache; + let stage = cache.get( code ); - } + if ( stage === undefined ) { - request.send( null ); + stage = new WebGLShaderStage( code ); + cache.set( code, stage ); } - scope.manager.itemStart( url ); + return stage; - return request; + } - }, +} - setPath: function ( value ) { +class WebGLShaderStage { - this.path = value; - return this; + constructor( code ) { - }, + this.id = _id$1 ++; - setResponseType: function ( value ) { + this.code = code; + this.usedTimes = 0; - this.responseType = value; - return this; + } - }, +} - setWithCredentials: function ( value ) { +function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { - this.withCredentials = value; - return this; + const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); + const _activeChannels = new Set(); + const programs = []; - }, + const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; - setMimeType: function ( value ) { + let precision = capabilities.precision; - this.mimeType = value; - return this; + 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 getChannel( value ) { - setRequestHeader: function ( value ) { + _activeChannels.add( value ); - this.requestHeader = value; - return this; + if ( value === 0 ) return 'uv'; + + return `uv${ value }`; } -} ); + function getParameters( material, lights, shadows, scene, object ) { -/** - * @author mrdoob / http://mrdoob.com/ - * - * Abstract Base class to block based textures loader (dds, pvr, ...) - */ + 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; -function CompressedTextureLoader( manager ) { + const shaderID = shaderIDs[ material.type ]; - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + // heuristics to create shader parameters according to lights in the scene + // (not to blow over maxLights budget) - // override in sub classes - this._parser = null; + if ( material.precision !== null ) { -} + precision = capabilities.getMaxPrecision( material.precision ); -Object.assign( CompressedTextureLoader.prototype, { + if ( precision !== material.precision ) { - load: function ( url, onLoad, onProgress, onError ) { + console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); - var scope = this; + } - var images = []; + } - var texture = new CompressedTexture(); - texture.image = images; + // - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - function loadTexture( i ) { + let morphTextureStride = 0; - loader.load( url[ i ], function ( buffer ) { + if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; + if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; + if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; - var texDatas = scope._parser( buffer, true ); + // - images[ i ] = { - width: texDatas.width, - height: texDatas.height, - format: texDatas.format, - mipmaps: texDatas.mipmaps - }; + let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; - loaded += 1; + if ( shaderID ) { - if ( loaded === 6 ) { + const shader = ShaderLib[ shaderID ]; - if ( texDatas.mipmapCount === 1 ) - { texture.minFilter = LinearFilter; } + vertexShader = shader.vertexShader; + fragmentShader = shader.fragmentShader; - texture.format = texDatas.format; - texture.needsUpdate = true; + } else { - if ( onLoad ) { onLoad( texture ); } + vertexShader = material.vertexShader; + fragmentShader = material.fragmentShader; - } + _customShaders.update( material ); - }, onProgress, onError ); + customVertexShaderID = _customShaders.getVertexShaderID( material ); + customFragmentShaderID = _customShaders.getFragmentShaderID( material ); } - if ( Array.isArray( url ) ) { + const currentRenderTarget = renderer.getRenderTarget(); - var loaded = 0; + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + const IS_BATCHEDMESH = object.isBatchedMesh === true; - for ( var i = 0, il = url.length; i < il; ++ i ) { + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; - loadTexture( i ); + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; - } + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_DISPERSION = material.dispersion > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; - } else { + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; - // compressed cubemap texture stored in a single DDS file + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; - loader.load( url, function ( buffer ) { + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; - var texDatas = scope._parser( buffer, true ); + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; - if ( texDatas.isCubemap ) { + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; - var faces = texDatas.mipmaps.length / texDatas.mipmapCount; + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; - for ( var f = 0; f < faces; f ++ ) { + const HAS_GRADIENTMAP = !! material.gradientMap; - images[ f ] = { mipmaps: [] }; + const HAS_ALPHAMAP = !! material.alphaMap; - for ( var i = 0; i < texDatas.mipmapCount; i ++ ) { + const HAS_ALPHATEST = material.alphaTest > 0; - 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; + const HAS_ALPHAHASH = !! material.alphaHash; - } + const HAS_EXTENSIONS = !! material.extensions; - } + let toneMapping = NoToneMapping; - } else { + if ( material.toneMapped ) { - texture.image.width = texDatas.width; - texture.image.height = texDatas.height; - texture.mipmaps = texDatas.mipmaps; + if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) { - } + toneMapping = renderer.toneMapping; - if ( texDatas.mipmapCount === 1 ) { + } - texture.minFilter = LinearFilter; + } - } + const parameters = { - texture.format = texDatas.format; - texture.needsUpdate = true; + shaderID: shaderID, + shaderType: material.type, + shaderName: material.name, - if ( onLoad ) { onLoad( texture ); } + vertexShader: vertexShader, + fragmentShader: fragmentShader, + defines: material.defines, - }, onProgress, onError ); + customVertexShaderID: customVertexShaderID, + customFragmentShaderID: customFragmentShaderID, - } + isRawShaderMaterial: material.isRawShaderMaterial === true, + glslVersion: material.glslVersion, - return texture; + precision: precision, - }, + batching: IS_BATCHEDMESH, + batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, + instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, - setPath: function ( value ) { + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), + alphaToCoverage: !! material.alphaToCoverage, - this.path = value; - return this; + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, + envMapCubeUVHeight: envMapCubeUVHeight, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - } + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, -} ); + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, -/** - * @author Nikos M. / https://github.com/foo123/ - * - * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) - */ + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, -function DataTextureLoader( manager ) { + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + dispersion: HAS_DISPERSION, - // override in sub classes - this._parser = null; + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, -} + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, -Object.assign( DataTextureLoader.prototype, { + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, - load: function ( url, onLoad, onProgress, onError ) { + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, - var scope = this; + gradientMap: HAS_GRADIENTMAP, - var texture = new DataTexture(); + opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false, - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, + alphaHash: HAS_ALPHAHASH, - loader.load( url, function ( buffer ) { + combine: material.combine, - var texData = scope._parser( buffer ); + // - if ( ! texData ) { return; } + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), - if ( undefined !== texData.image ) { + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), - texture.image = texData.image; + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), - } else if ( undefined !== texData.data ) { + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), - texture.image.width = texData.width; - texture.image.height = texData.height; - texture.image.data = texData.data; + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), - } + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), - texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping; - texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping; + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), - texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter; - texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter; + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), - texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1; + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), - if ( undefined !== texData.format ) { + // - texture.format = texData.format; + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), + vertexColors: material.vertexColors, + vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - } - if ( undefined !== texData.type ) { + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), - texture.type = texData.type; + fog: !! fog, + useFog: material.fog === true, + fogExp2: ( !! fog && fog.isFogExp2 ), - } + flatShading: material.flatShading === true, - if ( undefined !== texData.mipmaps ) { + sizeAttenuation: material.sizeAttenuation === true, + logarithmicDepthBuffer: logarithmicDepthBuffer, - texture.mipmaps = texData.mipmaps; + skinning: object.isSkinnedMesh === true, - } + morphTargets: geometry.morphAttributes.position !== undefined, + morphNormals: geometry.morphAttributes.normal !== undefined, + morphColors: geometry.morphAttributes.color !== undefined, + morphTargetsCount: morphTargetsCount, + morphTextureStride: morphTextureStride, - if ( 1 === texData.mipmapCount ) { + numDirLights: lights.directional.length, + numPointLights: lights.point.length, + numSpotLights: lights.spot.length, + numSpotLightMaps: lights.spotLightMap.length, + numRectAreaLights: lights.rectArea.length, + numHemiLights: lights.hemi.length, - texture.minFilter = LinearFilter; + numDirLightShadows: lights.directionalShadowMap.length, + numPointLightShadows: lights.pointShadowMap.length, + numSpotLightShadows: lights.spotShadowMap.length, + numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, - } + numLightProbes: lights.numLightProbes, - texture.needsUpdate = true; + numClippingPlanes: clipping.numPlanes, + numClipIntersection: clipping.numIntersection, - if ( onLoad ) { onLoad( texture, texData ); } + dithering: material.dithering, - }, onProgress, onError ); + shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, + shadowMapType: renderer.shadowMap.type, + toneMapping: toneMapping, - return texture; + decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ), - } + premultipliedAlpha: material.premultipliedAlpha, -} ); + doubleSided: material.side === DoubleSide, + flipSided: material.side === BackSide, -/** - * @author mrdoob / http://mrdoob.com/ - */ + useDepthPacking: material.depthPacking >= 0, + depthPacking: material.depthPacking || 0, -function ImageLoader( manager ) { + index0AttributeName: material.index0AttributeName, - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ), + extensionMultiDraw: ( HAS_EXTENSIONS && material.extensions.multiDraw === true || IS_BATCHEDMESH ) && extensions.has( 'WEBGL_multi_draw' ), -} + rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ), -Object.assign( ImageLoader.prototype, { + customProgramCacheKey: material.customProgramCacheKey() - crossOrigin: 'Anonymous', + }; - load: function ( url, onLoad, onProgress, onError ) { + // the usage of getChannel() determines the active texture channels for this shader - if ( url === undefined ) { url = ''; } + parameters.vertexUv1s = _activeChannels.has( 1 ); + parameters.vertexUv2s = _activeChannels.has( 2 ); + parameters.vertexUv3s = _activeChannels.has( 3 ); - if ( this.path !== undefined ) { url = this.path + url; } + _activeChannels.clear(); - url = this.manager.resolveURL( url ); + return parameters; - var scope = this; + } - var cached = Cache.get( url ); + function getProgramCacheKey( parameters ) { - if ( cached !== undefined ) { + const array = []; - scope.manager.itemStart( url ); + if ( parameters.shaderID ) { - setTimeout( function () { + array.push( parameters.shaderID ); - if ( onLoad ) { onLoad( cached ); } + } else { - scope.manager.itemEnd( url ); + array.push( parameters.customVertexShaderID ); + array.push( parameters.customFragmentShaderID ); - }, 0 ); + } - return cached; + if ( parameters.defines !== undefined ) { - } + for ( const name in parameters.defines ) { - var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' ); + array.push( name ); + array.push( parameters.defines[ name ] ); - image.addEventListener( 'load', function () { + } - Cache.add( url, this ); + } - if ( onLoad ) { onLoad( this ); } + if ( parameters.isRawShaderMaterial === false ) { - scope.manager.itemEnd( url ); + getProgramCacheKeyParameters( array, parameters ); + getProgramCacheKeyBooleans( array, parameters ); + array.push( renderer.outputColorSpace ); - }, false ); + } - /* - image.addEventListener( 'progress', function ( event ) { + array.push( parameters.customProgramCacheKey ); - if ( onProgress ) onProgress( event ); + return array.join(); - }, false ); - */ + } - image.addEventListener( 'error', function ( event ) { + function getProgramCacheKeyParameters( array, parameters ) { + + array.push( parameters.precision ); + array.push( parameters.outputColorSpace ); + array.push( parameters.envMapMode ); + array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); + array.push( parameters.combine ); + array.push( parameters.fogExp2 ); + array.push( parameters.sizeAttenuation ); + array.push( parameters.morphTargetsCount ); + array.push( parameters.morphAttributeCount ); + array.push( parameters.numDirLights ); + array.push( parameters.numPointLights ); + array.push( parameters.numSpotLights ); + array.push( parameters.numSpotLightMaps ); + array.push( parameters.numHemiLights ); + array.push( parameters.numRectAreaLights ); + array.push( parameters.numDirLightShadows ); + array.push( parameters.numPointLightShadows ); + array.push( parameters.numSpotLightShadows ); + array.push( parameters.numSpotLightShadowsWithMaps ); + array.push( parameters.numLightProbes ); + array.push( parameters.shadowMapType ); + array.push( parameters.toneMapping ); + array.push( parameters.numClippingPlanes ); + array.push( parameters.numClipIntersection ); + array.push( parameters.depthPacking ); + + } + + function getProgramCacheKeyBooleans( array, parameters ) { + + _programLayers.disableAll(); + + if ( parameters.supportsVertexTextures ) + _programLayers.enable( 0 ); + if ( parameters.instancing ) + _programLayers.enable( 1 ); + if ( parameters.instancingColor ) + _programLayers.enable( 2 ); + if ( parameters.instancingMorph ) + _programLayers.enable( 3 ); + if ( parameters.matcap ) + _programLayers.enable( 4 ); + if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) + _programLayers.enable( 6 ); + if ( parameters.normalMapTangentSpace ) + _programLayers.enable( 7 ); + if ( parameters.clearcoat ) + _programLayers.enable( 8 ); + if ( parameters.iridescence ) + _programLayers.enable( 9 ); + if ( parameters.alphaTest ) + _programLayers.enable( 10 ); + if ( parameters.vertexColors ) + _programLayers.enable( 11 ); + if ( parameters.vertexAlphas ) + _programLayers.enable( 12 ); + if ( parameters.vertexUv1s ) + _programLayers.enable( 13 ); + if ( parameters.vertexUv2s ) + _programLayers.enable( 14 ); + if ( parameters.vertexUv3s ) + _programLayers.enable( 15 ); + if ( parameters.vertexTangents ) + _programLayers.enable( 16 ); + if ( parameters.anisotropy ) + _programLayers.enable( 17 ); + if ( parameters.alphaHash ) + _programLayers.enable( 18 ); + if ( parameters.batching ) + _programLayers.enable( 19 ); + if ( parameters.dispersion ) + _programLayers.enable( 20 ); + if ( parameters.batchingColor ) + _programLayers.enable( 21 ); + + array.push( _programLayers.mask ); + _programLayers.disableAll(); + + if ( parameters.fog ) + _programLayers.enable( 0 ); + if ( parameters.useFog ) + _programLayers.enable( 1 ); + if ( parameters.flatShading ) + _programLayers.enable( 2 ); + if ( parameters.logarithmicDepthBuffer ) + _programLayers.enable( 3 ); + if ( parameters.skinning ) + _programLayers.enable( 4 ); + if ( parameters.morphTargets ) + _programLayers.enable( 5 ); + if ( parameters.morphNormals ) + _programLayers.enable( 6 ); + if ( parameters.morphColors ) + _programLayers.enable( 7 ); + if ( parameters.premultipliedAlpha ) + _programLayers.enable( 8 ); + if ( parameters.shadowMapEnabled ) + _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.transmission ) + _programLayers.enable( 14 ); + if ( parameters.sheen ) + _programLayers.enable( 15 ); + if ( parameters.opaque ) + _programLayers.enable( 16 ); + if ( parameters.pointsUvs ) + _programLayers.enable( 17 ); + if ( parameters.decodeVideoTexture ) + _programLayers.enable( 18 ); + if ( parameters.alphaToCoverage ) + _programLayers.enable( 19 ); + + array.push( _programLayers.mask ); + + } + + function getUniforms( material ) { + + const shaderID = shaderIDs[ material.type ]; + let uniforms; + + if ( shaderID ) { + + const shader = ShaderLib[ shaderID ]; + uniforms = UniformsUtils.clone( shader.uniforms ); - if ( onError ) { onError( event ); } + } else { - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + uniforms = material.uniforms; - }, false ); + } - if ( url.substr( 0, 5 ) !== 'data:' ) { + return uniforms; - if ( this.crossOrigin !== undefined ) { image.crossOrigin = this.crossOrigin; } + } - } + function acquireProgram( parameters, cacheKey ) { - scope.manager.itemStart( url ); + let program; - image.src = url; + // Check if code has been already compiled + for ( let p = 0, pl = programs.length; p < pl; p ++ ) { - return image; + const preexistingProgram = programs[ p ]; - }, + if ( preexistingProgram.cacheKey === cacheKey ) { - setCrossOrigin: function ( value ) { + program = preexistingProgram; + ++ program.usedTimes; - this.crossOrigin = value; - return this; + break; - }, + } - setPath: function ( value ) { + } - this.path = value; - return this; + if ( program === undefined ) { - } + program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); + programs.push( program ); -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + return program; -function CubeTextureLoader( manager ) { + } - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + function releaseProgram( program ) { -} + if ( -- program.usedTimes === 0 ) { -Object.assign( CubeTextureLoader.prototype, { + // Remove from unordered set + const i = programs.indexOf( program ); + programs[ i ] = programs[ programs.length - 1 ]; + programs.pop(); - crossOrigin: 'Anonymous', + // Free WebGL resources + program.destroy(); - load: function ( urls, onLoad, onProgress, onError ) { + } - var texture = new CubeTexture(); + } - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); + function releaseShaderCache( material ) { - var loaded = 0; + _customShaders.remove( material ); - function loadTexture( i ) { + } - loader.load( urls[ i ], function ( image ) { + function dispose() { - texture.images[ i ] = image; + _customShaders.dispose(); - loaded ++; + } - if ( loaded === 6 ) { + return { + getParameters: getParameters, + getProgramCacheKey: getProgramCacheKey, + getUniforms: getUniforms, + acquireProgram: acquireProgram, + releaseProgram: releaseProgram, + releaseShaderCache: releaseShaderCache, + // Exposed for resource monitoring & error feedback via renderer.info: + programs: programs, + dispose: dispose + }; - texture.needsUpdate = true; +} - if ( onLoad ) { onLoad( texture ); } +function WebGLProperties() { - } + let properties = new WeakMap(); - }, undefined, onError ); + function get( object ) { - } + let map = properties.get( object ); - for ( var i = 0; i < urls.length; ++ i ) { + if ( map === undefined ) { - loadTexture( i ); + map = {}; + properties.set( object, map ); } - return texture; + return map; - }, + } - setCrossOrigin: function ( value ) { + function remove( object ) { - this.crossOrigin = value; - return this; + properties.delete( object ); - }, + } - setPath: function ( value ) { + function update( object, key, value ) { - this.path = value; - return this; + properties.get( object )[ key ] = value; } -} ); + function dispose() { -/** - * @author mrdoob / http://mrdoob.com/ - */ + properties = new WeakMap(); -function TextureLoader( manager ) { + } - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + return { + get: get, + remove: remove, + update: update, + dispose: dispose + }; } -Object.assign( TextureLoader.prototype, { - - crossOrigin: 'Anonymous', - - load: function ( url, onLoad, onProgress, onError ) { - - var texture = new Texture(); - - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); +function painterSortStable( a, b ) { - loader.load( url, function ( image ) { + if ( a.groupOrder !== b.groupOrder ) { - texture.image = image; + return a.groupOrder - b.groupOrder; - // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB. - var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0; + } else if ( a.renderOrder !== b.renderOrder ) { - texture.format = isJPEG ? RGBFormat : RGBAFormat; - texture.needsUpdate = true; + return a.renderOrder - b.renderOrder; - if ( onLoad !== undefined ) { + } else if ( a.material.id !== b.material.id ) { - onLoad( texture ); + return a.material.id - b.material.id; - } + } else if ( a.z !== b.z ) { - }, onProgress, onError ); + return a.z - b.z; - return texture; + } else { - }, + return a.id - b.id; - setCrossOrigin: function ( value ) { + } - this.crossOrigin = value; - return this; +} - }, +function reversePainterSortStable( a, b ) { - setPath: function ( value ) { + if ( a.groupOrder !== b.groupOrder ) { - this.path = value; - return this; + return a.groupOrder - b.groupOrder; - } + } else if ( a.renderOrder !== b.renderOrder ) { -} ); + return a.renderOrder - b.renderOrder; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Extensible curve object - * - * Some common of curve methods: - * .getPoint( t, optionalTarget ), .getTangent( t ) - * .getPointAt( u, optionalTarget ), .getTangentAt( u ) - * .getPoints(), .getSpacedPoints() - * .getLength() - * .updateArcLengths() - * - * This following curves inherit from THREE.Curve: - * - * -- 2D curves -- - * THREE.ArcCurve - * THREE.CubicBezierCurve - * THREE.EllipseCurve - * THREE.LineCurve - * THREE.QuadraticBezierCurve - * THREE.SplineCurve - * - * -- 3D curves -- - * THREE.CatmullRomCurve3 - * THREE.CubicBezierCurve3 - * THREE.LineCurve3 - * THREE.QuadraticBezierCurve3 - * - * A series of curves can be represented as a THREE.CurvePath. - * - **/ + } else if ( a.z !== b.z ) { -/************************************************************** - * Abstract Curve base class - **************************************************************/ + return b.z - a.z; -function Curve() { + } else { - this.type = 'Curve'; + return a.id - b.id; - this.arcLengthDivisions = 200; + } } -Object.assign( Curve.prototype, { - // Virtual base class method to overwrite and implement in subclasses - // - t [0 .. 1] +function WebGLRenderList() { - getPoint: function ( /* t, optionalTarget */ ) { + const renderItems = []; + let renderItemsIndex = 0; - console.warn( 'THREE.Curve: .getPoint() not implemented.' ); - return null; + const opaque = []; + const transmissive = []; + const transparent = []; - }, + function init() { - // Get point at relative position in curve according to arc length - // - u [0 .. 1] + renderItemsIndex = 0; - getPointAt: function ( u, optionalTarget ) { + opaque.length = 0; + transmissive.length = 0; + transparent.length = 0; - var t = this.getUtoTmapping( u ); - return this.getPoint( t, optionalTarget ); + } - }, + function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { - // Get sequence of points using getPoint( t ) + let renderItem = renderItems[ renderItemsIndex ]; - getPoints: function ( divisions ) { + if ( renderItem === undefined ) { - if ( divisions === undefined ) { divisions = 5; } + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + groupOrder: groupOrder, + renderOrder: object.renderOrder, + z: z, + group: group + }; - var points = []; + renderItems[ renderItemsIndex ] = renderItem; - for ( var d = 0; d <= divisions; d ++ ) { + } else { - points.push( this.getPoint( d / divisions ) ); + 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; } - return points; + renderItemsIndex ++; - }, + return renderItem; - // Get sequence of points using getPointAt( u ) + } - getSpacedPoints: function ( divisions ) { + function push( object, geometry, material, groupOrder, z, group ) { - if ( divisions === undefined ) { divisions = 5; } + const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); - var points = []; + if ( material.transmission > 0.0 ) { - for ( var d = 0; d <= divisions; d ++ ) { + transmissive.push( renderItem ); - points.push( this.getPointAt( d / divisions ) ); + } else if ( material.transparent === true ) { - } + transparent.push( renderItem ); - return points; + } else { - }, + opaque.push( renderItem ); + + } - // Get total curve arc length + } - getLength: function () { + function unshift( object, geometry, material, groupOrder, z, group ) { - var lengths = this.getLengths(); - return lengths[ lengths.length - 1 ]; + const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); - }, + if ( material.transmission > 0.0 ) { - // Get list of cumulative segment lengths + transmissive.unshift( renderItem ); - getLengths: function ( divisions ) { + } else if ( material.transparent === true ) { - if ( divisions === undefined ) { divisions = this.arcLengthDivisions; } + transparent.unshift( renderItem ); - if ( this.cacheArcLengths && - ( this.cacheArcLengths.length === divisions + 1 ) && - ! this.needsUpdate ) { + } else { - return this.cacheArcLengths; + opaque.unshift( renderItem ); } - this.needsUpdate = false; + } - var cache = []; - var current, last = this.getPoint( 0 ); - var p, sum = 0; + function sort( customOpaqueSort, customTransparentSort ) { - cache.push( 0 ); + if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable ); + if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable ); + if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable ); - for ( p = 1; p <= divisions; p ++ ) { + } - current = this.getPoint( p / divisions ); - sum += current.distanceTo( last ); - cache.push( sum ); - last = current; + function finish() { - } + // Clear references from inactive renderItems in the list - this.cacheArcLengths = cache; + for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { - return cache; // { sums: cache, sum: sum }; Sum is in the last element. + const renderItem = renderItems[ i ]; - }, + if ( renderItem.id === null ) break; - updateArcLengths: function () { + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.group = null; - this.needsUpdate = true; - this.getLengths(); + } - }, + } - // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant + return { - getUtoTmapping: function ( u, distance ) { + opaque: opaque, + transmissive: transmissive, + transparent: transparent, - var arcLengths = this.getLengths(); + init: init, + push: push, + unshift: unshift, + finish: finish, - var i = 0, il = arcLengths.length; + sort: sort + }; - var targetArcLength; // The targeted u distance value to get +} - if ( distance ) { +function WebGLRenderLists() { - targetArcLength = distance; + let lists = new WeakMap(); - } else { + function get( scene, renderCallDepth ) { - targetArcLength = u * arcLengths[ il - 1 ]; + const listArray = lists.get( scene ); + let list; - } + if ( listArray === undefined ) { - // binary search for the index with largest value smaller than target u distance + list = new WebGLRenderList(); + lists.set( scene, [ list ] ); - var low = 0, high = il - 1, comparison; + } else { - while ( low <= high ) { + if ( renderCallDepth >= listArray.length ) { - i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats + list = new WebGLRenderList(); + listArray.push( list ); - comparison = arcLengths[ i ] - targetArcLength; + } else { - if ( comparison < 0 ) { + list = listArray[ renderCallDepth ]; - low = i + 1; + } - } else if ( comparison > 0 ) { + } - high = i - 1; + return list; - } else { + } - high = i; - break; + function dispose() { - // DONE + lists = new WeakMap(); - } + } - } + return { + get: get, + dispose: dispose + }; - i = high; +} - if ( arcLengths[ i ] === targetArcLength ) { +function UniformsCache() { - return i / ( il - 1 ); + const lights = {}; - } + return { - // we could get finer grain at lengths, or use simple interpolation between two points + get: function ( light ) { - var lengthBefore = arcLengths[ i ]; - var lengthAfter = arcLengths[ i + 1 ]; + if ( lights[ light.id ] !== undefined ) { - var segmentLength = lengthAfter - lengthBefore; + return lights[ light.id ]; - // determine where we are between the 'before' and 'after' points + } - var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; + let uniforms; - // add that fractional amount to t + switch ( light.type ) { - var t = ( i + segmentFraction ) / ( il - 1 ); + case 'DirectionalLight': + uniforms = { + direction: new Vector3(), + color: new Color() + }; + break; - return t; + case 'SpotLight': + uniforms = { + position: new Vector3(), + direction: new Vector3(), + color: new Color(), + distance: 0, + coneCos: 0, + penumbraCos: 0, + decay: 0 + }; + break; - }, + case 'PointLight': + uniforms = { + position: new Vector3(), + color: new Color(), + distance: 0, + decay: 0 + }; + break; - // Returns a unit vector tangent at t - // In case any sub curve does not implement its tangent derivation, - // 2 points a small delta apart will be used to find its gradient - // which seems to give a reasonable approximation + case 'HemisphereLight': + uniforms = { + direction: new Vector3(), + skyColor: new Color(), + groundColor: new Color() + }; + break; - getTangent: function ( t ) { + case 'RectAreaLight': + uniforms = { + color: new Color(), + position: new Vector3(), + halfWidth: new Vector3(), + halfHeight: new Vector3() + }; + break; - var delta = 0.0001; - var t1 = t - delta; - var t2 = t + delta; + } - // Capping in case of danger + lights[ light.id ] = uniforms; - if ( t1 < 0 ) { t1 = 0; } - if ( t2 > 1 ) { t2 = 1; } + return uniforms; - var pt1 = this.getPoint( t1 ); - var pt2 = this.getPoint( t2 ); + } - var vec = pt2.clone().sub( pt1 ); - return vec.normalize(); + }; - }, +} - getTangentAt: function ( u ) { +function ShadowUniformsCache() { - var t = this.getUtoTmapping( u ); - return this.getTangent( t ); + const lights = {}; - }, + return { - computeFrenetFrames: function ( segments, closed ) { + get: function ( light ) { - // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf + if ( lights[ light.id ] !== undefined ) { - var normal = new Vector3(); + return lights[ light.id ]; - var tangents = []; - var normals = []; - var binormals = []; + } - var vec = new Vector3(); - var mat = new Matrix4(); + let uniforms; - var i, u, theta; + switch ( light.type ) { - // compute the tangent vectors for each segment on the curve + case 'DirectionalLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; - for ( i = 0; i <= segments; i ++ ) { + case 'SpotLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; - u = i / segments; + case 'PointLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2(), + shadowCameraNear: 1, + shadowCameraFar: 1000 + }; + break; - tangents[ i ] = this.getTangentAt( u ); - tangents[ i ].normalize(); + // TODO (abelnation): set RectAreaLight shadow uniforms - } + } - // select an initial normal vector perpendicular to the first tangent vector, - // and in the direction of the minimum tangent xyz component + lights[ light.id ] = uniforms; - normals[ 0 ] = new Vector3(); - binormals[ 0 ] = new Vector3(); - var min = Number.MAX_VALUE; - var tx = Math.abs( tangents[ 0 ].x ); - var ty = Math.abs( tangents[ 0 ].y ); - var tz = Math.abs( tangents[ 0 ].z ); + return uniforms; - if ( tx <= min ) { + } - min = tx; - normal.set( 1, 0, 0 ); + }; - } +} - if ( ty <= min ) { - min = ty; - normal.set( 0, 1, 0 ); - } +let nextVersion = 0; - if ( tz <= min ) { +function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { - normal.set( 0, 0, 1 ); + return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); - } +} - vec.crossVectors( tangents[ 0 ], normal ).normalize(); +function WebGLLights( extensions ) { - normals[ 0 ].crossVectors( tangents[ 0 ], vec ); - binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); + const cache = new UniformsCache(); + const shadowCache = ShadowUniformsCache(); - // compute the slowly-varying normal and binormal vectors for each segment on the curve + const state = { - for ( i = 1; i <= segments; i ++ ) { + version: 0, - normals[ i ] = normals[ i - 1 ].clone(); + hash: { + directionalLength: - 1, + pointLength: - 1, + spotLength: - 1, + rectAreaLength: - 1, + hemiLength: - 1, - binormals[ i ] = binormals[ i - 1 ].clone(); + numDirectionalShadows: - 1, + numPointShadows: - 1, + numSpotShadows: - 1, + numSpotMaps: - 1, - vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); + numLightProbes: - 1 + }, - if ( vec.length() > Number.EPSILON ) { + ambient: [ 0, 0, 0 ], + probe: [], + directional: [], + directionalShadow: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotLightMap: [], + spotShadow: [], + spotShadowMap: [], + spotLightMatrix: [], + rectArea: [], + rectAreaLTC1: null, + rectAreaLTC2: null, + point: [], + pointShadow: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [], + numSpotLightShadowsWithMaps: 0, + numLightProbes: 0 - vec.normalize(); + }; - theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors + for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); - normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); + const vector3 = new Vector3(); + const matrix4 = new Matrix4(); + const matrix42 = new Matrix4(); - } + function setup( lights ) { - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + let r = 0, g = 0, b = 0; - } + for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 ); - // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; - if ( closed === true ) { + let numDirectionalShadows = 0; + let numPointShadows = 0; + let numSpotShadows = 0; + let numSpotMaps = 0; + let numSpotShadowsWithMaps = 0; - theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); - theta /= segments; + let numLightProbes = 0; - if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { + // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] + lights.sort( shadowCastingAndTexturingLightsFirst ); - theta = - theta; + for ( let i = 0, l = lights.length; i < l; i ++ ) { - } + const light = lights[ i ]; - for ( i = 1; i <= segments; i ++ ) { + const color = light.color; + const intensity = light.intensity; + const distance = light.distance; - // twist a little... - normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; - } + if ( light.isAmbientLight ) { - } + r += color.r * intensity; + g += color.g * intensity; + b += color.b * intensity; - return { - tangents: tangents, - normals: normals, - binormals: binormals - }; + } else if ( light.isLightProbe ) { - }, + for ( let j = 0; j < 9; j ++ ) { - clone: function () { + state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); - return new this.constructor().copy( this ); + } - }, + numLightProbes ++; - copy: function ( source ) { + } else if ( light.isDirectionalLight ) { - this.arcLengthDivisions = source.arcLengthDivisions; + const uniforms = cache.get( light ); - return this; + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - }, + if ( light.castShadow ) { - toJSON: function () { + const shadow = light.shadow; - var data = { - metadata: { - version: 4.5, - type: 'Curve', - generator: 'Curve.toJSON' - } - }; + const shadowUniforms = shadowCache.get( light ); - data.arcLengthDivisions = this.arcLengthDivisions; - data.type = this.type; + shadowUniforms.shadowIntensity = shadow.intensity; + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; - return data; + state.directionalShadow[ directionalLength ] = shadowUniforms; + state.directionalShadowMap[ directionalLength ] = shadowMap; + state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - }, + numDirectionalShadows ++; - fromJSON: function ( json ) { + } - this.arcLengthDivisions = json.arcLengthDivisions; + state.directional[ directionalLength ] = uniforms; - return this; + directionalLength ++; - } + } else if ( light.isSpotLight ) { -} ); + const uniforms = cache.get( light ); -function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + uniforms.position.setFromMatrixPosition( light.matrixWorld ); - Curve.call( this ); + uniforms.color.copy( color ).multiplyScalar( intensity ); + uniforms.distance = distance; - this.type = 'EllipseCurve'; + uniforms.coneCos = Math.cos( light.angle ); + uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); + uniforms.decay = light.decay; - this.aX = aX || 0; - this.aY = aY || 0; + state.spot[ spotLength ] = uniforms; - this.xRadius = xRadius || 1; - this.yRadius = yRadius || 1; + const shadow = light.shadow; - this.aStartAngle = aStartAngle || 0; - this.aEndAngle = aEndAngle || 2 * Math.PI; + if ( light.map ) { - this.aClockwise = aClockwise || false; + state.spotLightMap[ numSpotMaps ] = light.map; + numSpotMaps ++; - this.aRotation = aRotation || 0; + // make sure the lightMatrix is up to date + // TODO : do it if required only + shadow.updateMatrices( light ); -} + if ( light.castShadow ) numSpotShadowsWithMaps ++; -EllipseCurve.prototype = Object.create( Curve.prototype ); -EllipseCurve.prototype.constructor = EllipseCurve; + } -EllipseCurve.prototype.isEllipseCurve = true; + state.spotLightMatrix[ spotLength ] = shadow.matrix; -EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) { + if ( light.castShadow ) { - var point = optionalTarget || new Vector2(); + const shadowUniforms = shadowCache.get( light ); - var twoPi = Math.PI * 2; - var deltaAngle = this.aEndAngle - this.aStartAngle; - var samePoints = Math.abs( deltaAngle ) < Number.EPSILON; + shadowUniforms.shadowIntensity = shadow.intensity; + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; - // ensures that deltaAngle is 0 .. 2 PI - while ( deltaAngle < 0 ) { deltaAngle += twoPi; } - while ( deltaAngle > twoPi ) { deltaAngle -= twoPi; } + state.spotShadow[ spotLength ] = shadowUniforms; + state.spotShadowMap[ spotLength ] = shadowMap; - if ( deltaAngle < Number.EPSILON ) { + numSpotShadows ++; - if ( samePoints ) { + } - deltaAngle = 0; + spotLength ++; - } else { + } else if ( light.isRectAreaLight ) { - deltaAngle = twoPi; + const uniforms = cache.get( light ); - } + uniforms.color.copy( color ).multiplyScalar( intensity ); - } + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - if ( this.aClockwise === true && ! samePoints ) { + state.rectArea[ rectAreaLength ] = uniforms; - if ( deltaAngle === twoPi ) { + rectAreaLength ++; - deltaAngle = - twoPi; + } else if ( light.isPointLight ) { - } else { + const uniforms = cache.get( light ); - deltaAngle = deltaAngle - twoPi; + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.distance = light.distance; + uniforms.decay = light.decay; - } + if ( light.castShadow ) { - } + const shadow = light.shadow; - var angle = this.aStartAngle + t * deltaAngle; - var x = this.aX + this.xRadius * Math.cos( angle ); - var y = this.aY + this.yRadius * Math.sin( angle ); + const shadowUniforms = shadowCache.get( light ); - if ( this.aRotation !== 0 ) { + shadowUniforms.shadowIntensity = shadow.intensity; + 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; - var cos = Math.cos( this.aRotation ); - var sin = Math.sin( this.aRotation ); + state.pointShadow[ pointLength ] = shadowUniforms; + state.pointShadowMap[ pointLength ] = shadowMap; + state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - var tx = x - this.aX; - var ty = y - this.aY; + numPointShadows ++; - // Rotate the point about the center of the ellipse. - x = tx * cos - ty * sin + this.aX; - y = tx * sin + ty * cos + this.aY; + } - } + state.point[ pointLength ] = uniforms; - return point.set( x, y ); + pointLength ++; -}; + } else if ( light.isHemisphereLight ) { -EllipseCurve.prototype.copy = function ( source ) { + const uniforms = cache.get( light ); - Curve.prototype.copy.call( this, source ); + uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); + uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); - this.aX = source.aX; - this.aY = source.aY; + state.hemi[ hemiLength ] = uniforms; - this.xRadius = source.xRadius; - this.yRadius = source.yRadius; + hemiLength ++; - this.aStartAngle = source.aStartAngle; - this.aEndAngle = source.aEndAngle; + } - this.aClockwise = source.aClockwise; + } - this.aRotation = source.aRotation; + if ( rectAreaLength > 0 ) { - return this; + if ( extensions.has( 'OES_texture_float_linear' ) === true ) { -}; + state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; + } else { -EllipseCurve.prototype.toJSON = function () { + state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; + state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; - var data = Curve.prototype.toJSON.call( this ); + } - data.aX = this.aX; - data.aY = this.aY; + } - data.xRadius = this.xRadius; - data.yRadius = this.yRadius; + state.ambient[ 0 ] = r; + state.ambient[ 1 ] = g; + state.ambient[ 2 ] = b; - data.aStartAngle = this.aStartAngle; - data.aEndAngle = this.aEndAngle; + const hash = state.hash; - data.aClockwise = this.aClockwise; + 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 || + hash.numSpotMaps !== numSpotMaps || + hash.numLightProbes !== numLightProbes ) { - data.aRotation = this.aRotation; + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; - return data; + 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.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; + state.spotLightMap.length = numSpotMaps; + state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; + state.numLightProbes = numLightProbes; -}; + hash.directionalLength = directionalLength; + hash.pointLength = pointLength; + hash.spotLength = spotLength; + hash.rectAreaLength = rectAreaLength; + hash.hemiLength = hemiLength; -EllipseCurve.prototype.fromJSON = function ( json ) { + hash.numDirectionalShadows = numDirectionalShadows; + hash.numPointShadows = numPointShadows; + hash.numSpotShadows = numSpotShadows; + hash.numSpotMaps = numSpotMaps; - Curve.prototype.fromJSON.call( this, json ); + hash.numLightProbes = numLightProbes; - this.aX = json.aX; - this.aY = json.aY; + state.version = nextVersion ++; - this.xRadius = json.xRadius; - this.yRadius = json.yRadius; + } - this.aStartAngle = json.aStartAngle; - this.aEndAngle = json.aEndAngle; + } - this.aClockwise = json.aClockwise; + function setupView( lights, camera ) { - this.aRotation = json.aRotation; + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; - return this; + const viewMatrix = camera.matrixWorldInverse; -}; + for ( let i = 0, l = lights.length; i < l; i ++ ) { -function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + const light = lights[ i ]; - EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + if ( light.isDirectionalLight ) { - this.type = 'ArcCurve'; + const uniforms = state.directional[ directionalLength ]; -} + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); -ArcCurve.prototype = Object.create( EllipseCurve.prototype ); -ArcCurve.prototype.constructor = ArcCurve; + directionalLength ++; -ArcCurve.prototype.isArcCurve = true; + } else if ( light.isSpotLight ) { -/** - * @author zz85 https://github.com/zz85 - * - * Centripetal CatmullRom Curve - which is useful for avoiding - * cusps and self-intersections in non-uniform catmull rom curves. - * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf - * - * curve.type accepts centripetal(default), chordal and catmullrom - * curve.tension is used for catmullrom which defaults to 0.5 - */ + const uniforms = state.spot[ spotLength ]; + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); -/* -Based on an optimized c++ solution in - - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ - - http://ideone.com/NoEbVM + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); -This CubicPoly class could be used for reusing some variables and calculations, -but for three.js curve use, it could be possible inlined and flatten into a single function call -which can be placed in CurveUtils. -*/ + spotLength ++; -function CubicPoly() { + } else if ( light.isRectAreaLight ) { - var c0 = 0, c1 = 0, c2 = 0, c3 = 0; + const uniforms = state.rectArea[ rectAreaLength ]; - /* - * Compute coefficients for a cubic polynomial - * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 - * such that - * p(0) = x0, p(1) = x1 - * and - * p'(0) = t0, p'(1) = t1. - */ - function init( x0, x1, t0, t1 ) { + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - c0 = x0; - c1 = t0; - c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; - c3 = 2 * x0 - 2 * x1 + t0 + t1; + // extract local rotation of light to derive width/height half vectors + matrix42.identity(); + matrix4.copy( light.matrixWorld ); + matrix4.premultiply( viewMatrix ); + matrix42.extractRotation( matrix4 ); - } + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - return { + uniforms.halfWidth.applyMatrix4( matrix42 ); + uniforms.halfHeight.applyMatrix4( matrix42 ); - initCatmullRom: function ( x0, x1, x2, x3, tension ) { + rectAreaLength ++; - init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); + } else if ( light.isPointLight ) { - }, + const uniforms = state.point[ pointLength ]; - initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - // compute tangents when parameterized in [t1,t2] - var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; - var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; + pointLength ++; - // rescale tangents for parametrization in [0,1] - t1 *= dt1; - t2 *= dt1; + } else if ( light.isHemisphereLight ) { - init( x1, x2, t1, t2 ); + const uniforms = state.hemi[ hemiLength ]; - }, + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + uniforms.direction.transformDirection( viewMatrix ); - calc: function ( t ) { + hemiLength ++; - var t2 = t * t; - var t3 = t2 * t; - return c0 + c1 * t + c2 * t2 + c3 * t3; + } } + } + + return { + setup: setup, + setupView: setupView, + state: state }; } -// - -var tmp = new Vector3(); -var px = new CubicPoly(); -var py = new CubicPoly(); -var pz = new CubicPoly(); - -function CatmullRomCurve3( points, closed, curveType, tension ) { - - Curve.call( this ); - - this.type = 'CatmullRomCurve3'; +function WebGLRenderState( extensions ) { - this.points = points || []; - this.closed = closed || false; - this.curveType = curveType || 'centripetal'; - this.tension = tension || 0.5; + const lights = new WebGLLights( extensions ); -} - -CatmullRomCurve3.prototype = Object.create( Curve.prototype ); -CatmullRomCurve3.prototype.constructor = CatmullRomCurve3; + const lightsArray = []; + const shadowsArray = []; -CatmullRomCurve3.prototype.isCatmullRomCurve3 = true; + function init( camera ) { -CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) { + state.camera = camera; - var point = optionalTarget || new Vector3(); + lightsArray.length = 0; + shadowsArray.length = 0; - var points = this.points; - var l = points.length; + } - var p = ( l - ( this.closed ? 0 : 1 ) ) * t; - var intPoint = Math.floor( p ); - var weight = p - intPoint; + function pushLight( light ) { - if ( this.closed ) { + lightsArray.push( light ); - intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length; + } - } else if ( weight === 0 && intPoint === l - 1 ) { + function pushShadow( shadowLight ) { - intPoint = l - 2; - weight = 1; + shadowsArray.push( shadowLight ); } - var p0, p1, p2, p3; // 4 points + function setupLights() { - if ( this.closed || intPoint > 0 ) { + lights.setup( lightsArray ); - p0 = points[ ( intPoint - 1 ) % l ]; + } - } else { + function setupLightsView( camera ) { - // extrapolate first point - tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); - p0 = tmp; + lights.setupView( lightsArray, camera ); } - p1 = points[ intPoint % l ]; - p2 = points[ ( intPoint + 1 ) % l ]; + const state = { + lightsArray: lightsArray, + shadowsArray: shadowsArray, - if ( this.closed || intPoint + 2 < l ) { + camera: null, - p3 = points[ ( intPoint + 2 ) % l ]; + lights: lights, - } else { - - // extrapolate last point - tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); - p3 = tmp; + transmissionRenderTarget: {} + }; - } + return { + init: init, + state: state, + setupLights: setupLights, + setupLightsView: setupLightsView, - if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { + pushLight: pushLight, + pushShadow: pushShadow + }; - // init Centripetal / Chordal Catmull-Rom - var pow = this.curveType === 'chordal' ? 0.5 : 0.25; - var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); - var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); - var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); +} - // safety check for repeated points - if ( dt1 < 1e-4 ) { dt1 = 1.0; } - if ( dt0 < 1e-4 ) { dt0 = dt1; } - if ( dt2 < 1e-4 ) { dt2 = dt1; } +function WebGLRenderStates( extensions ) { - 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 ); + let renderStates = new WeakMap(); - } else if ( this.curveType === 'catmullrom' ) { + function get( scene, renderCallDepth = 0 ) { - 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 ); + const renderStateArray = renderStates.get( scene ); + let renderState; - } + if ( renderStateArray === undefined ) { - point.set( - px.calc( weight ), - py.calc( weight ), - pz.calc( weight ) - ); + renderState = new WebGLRenderState( extensions ); + renderStates.set( scene, [ renderState ] ); - return point; + } else { -}; + if ( renderCallDepth >= renderStateArray.length ) { -CatmullRomCurve3.prototype.copy = function ( source ) { + renderState = new WebGLRenderState( extensions ); + renderStateArray.push( renderState ); - Curve.prototype.copy.call( this, source ); + } else { - this.points = []; + renderState = renderStateArray[ renderCallDepth ]; - for ( var i = 0, l = source.points.length; i < l; i ++ ) { + } - var point = source.points[ i ]; + } - this.points.push( point.clone() ); + return renderState; } - this.closed = source.closed; - this.curveType = source.curveType; - this.tension = source.tension; - - return this; + function dispose() { -}; + renderStates = new WeakMap(); -CatmullRomCurve3.prototype.toJSON = function () { + } - var data = Curve.prototype.toJSON.call( this ); + return { + get: get, + dispose: dispose + }; - data.points = []; +} - for ( var i = 0, l = this.points.length; i < l; i ++ ) { +class MeshDepthMaterial extends Material { - var point = this.points[ i ]; - data.points.push( point.toArray() ); + constructor( parameters ) { - } + super(); - data.closed = this.closed; - data.curveType = this.curveType; - data.tension = this.tension; + this.isMeshDepthMaterial = true; - return data; + this.type = 'MeshDepthMaterial'; -}; + this.depthPacking = BasicDepthPacking; -CatmullRomCurve3.prototype.fromJSON = function ( json ) { + this.map = null; - Curve.prototype.fromJSON.call( this, json ); + this.alphaMap = null; - this.points = []; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - for ( var i = 0, l = json.points.length; i < l; i ++ ) { + this.wireframe = false; + this.wireframeLinewidth = 1; - var point = json.points[ i ]; - this.points.push( new Vector3().fromArray( point ) ); + this.setValues( parameters ); } - this.closed = json.closed; - this.curveType = json.curveType; - this.tension = json.tension; + copy( source ) { - return this; - -}; + super.copy( source ); -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve - */ + this.depthPacking = source.depthPacking; -function CatmullRom( t, p0, p1, p2, p3 ) { + this.map = source.map; - var v0 = ( p2 - p0 ) * 0.5; - var v1 = ( p3 - p1 ) * 0.5; - var t2 = t * t; - var t3 = t * t2; - return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; + this.alphaMap = source.alphaMap; -} + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; -// + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; -function QuadraticBezierP0( t, p ) { + return this; - var k = 1 - t; - return k * k * p; + } } -function QuadraticBezierP1( t, p ) { +class MeshDistanceMaterial extends Material { - return 2 * ( 1 - t ) * t * p; - -} + constructor( parameters ) { -function QuadraticBezierP2( t, p ) { + super(); - return t * t * p; + this.isMeshDistanceMaterial = true; -} + this.type = 'MeshDistanceMaterial'; -function QuadraticBezier( t, p0, p1, p2 ) { + this.map = null; - return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + - QuadraticBezierP2( t, p2 ); + this.alphaMap = null; -} + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; -// + this.setValues( parameters ); -function CubicBezierP0( t, p ) { + } - var k = 1 - t; - return k * k * k * p; + copy( source ) { -} + super.copy( source ); -function CubicBezierP1( t, p ) { + this.map = source.map; - var k = 1 - t; - return 3 * k * k * t * p; + this.alphaMap = source.alphaMap; -} + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; -function CubicBezierP2( t, p ) { + return this; - return 3 * ( 1 - t ) * t * t * p; + } } -function CubicBezierP3( t, p ) { - - return t * t * t * p; - -} +const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; -function CubicBezier( t, p0, p1, p2, p3 ) { +const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; - return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + - CubicBezierP3( t, p3 ); +function WebGLShadowMap( renderer, objects, capabilities ) { -} + let _frustum = new Frustum(); -function CubicBezierCurve( v0, v1, v2, v3 ) { + const _shadowMapSize = new Vector2(), + _viewportSize = new Vector2(), - Curve.call( this ); + _viewport = new Vector4(), - this.type = 'CubicBezierCurve'; + _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), + _distanceMaterial = new MeshDistanceMaterial(), - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); - this.v3 = v3 || new Vector2(); + _materialCache = {}, -} + _maxTextureSize = capabilities.maxTextureSize; -CubicBezierCurve.prototype = Object.create( Curve.prototype ); -CubicBezierCurve.prototype.constructor = CubicBezierCurve; + const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; -CubicBezierCurve.prototype.isCubicBezierCurve = true; + const shadowMaterialVertical = new ShaderMaterial( { + defines: { + VSM_SAMPLES: 8 + }, + uniforms: { + shadow_pass: { value: null }, + resolution: { value: new Vector2() }, + radius: { value: 4.0 } + }, -CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { + vertexShader: vertex, + fragmentShader: fragment - var point = optionalTarget || new Vector2(); + } ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + const shadowMaterialHorizontal = shadowMaterialVertical.clone(); + shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; - point.set( - CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), - CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) + const fullScreenTri = new BufferGeometry(); + fullScreenTri.setAttribute( + 'position', + new BufferAttribute( + new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ), + 3 + ) ); - return point; - -}; - -CubicBezierCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); - - return this; - -}; - -CubicBezierCurve.prototype.toJSON = function () { + const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); - var data = Curve.prototype.toJSON.call( this ); + const scope = this; - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); - data.v3 = this.v3.toArray(); - - return data; - -}; - -CubicBezierCurve.prototype.fromJSON = function ( json ) { - - Curve.prototype.fromJSON.call( this, json ); - - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); - this.v3.fromArray( json.v3 ); + this.enabled = false; - return this; + this.autoUpdate = true; + this.needsUpdate = false; -}; + this.type = PCFShadowMap; + let _previousType = this.type; -function CubicBezierCurve3( v0, v1, v2, v3 ) { + this.render = function ( lights, scene, camera ) { - Curve.call( this ); + if ( scope.enabled === false ) return; + if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; - this.type = 'CubicBezierCurve3'; + if ( lights.length === 0 ) return; - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); - this.v3 = v3 || new Vector3(); + const currentRenderTarget = renderer.getRenderTarget(); + const activeCubeFace = renderer.getActiveCubeFace(); + const activeMipmapLevel = renderer.getActiveMipmapLevel(); -} + const _state = renderer.state; -CubicBezierCurve3.prototype = Object.create( Curve.prototype ); -CubicBezierCurve3.prototype.constructor = CubicBezierCurve3; + // Set GL state for depth map. + _state.setBlending( NoBlending ); + _state.buffers.color.setClear( 1, 1, 1, 1 ); + _state.buffers.depth.setTest( true ); + _state.setScissorTest( false ); -CubicBezierCurve3.prototype.isCubicBezierCurve3 = true; + // check for shadow map type changes -CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); - var point = optionalTarget || new Vector3(); + // render depth map - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + for ( let i = 0, il = lights.length; i < il; i ++ ) { - 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 ) - ); + const light = lights[ i ]; + const shadow = light.shadow; - return point; + if ( shadow === undefined ) { -}; + console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); + continue; -CubicBezierCurve3.prototype.copy = function ( source ) { + } - Curve.prototype.copy.call( this, source ); + if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); + _shadowMapSize.copy( shadow.mapSize ); - return this; + const shadowFrameExtents = shadow.getFrameExtents(); -}; + _shadowMapSize.multiply( shadowFrameExtents ); -CubicBezierCurve3.prototype.toJSON = function () { + _viewportSize.copy( shadow.mapSize ); - var data = Curve.prototype.toJSON.call( this ); + if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); - data.v3 = this.v3.toArray(); + if ( _shadowMapSize.x > _maxTextureSize ) { - return data; + _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); + _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; + shadow.mapSize.x = _viewportSize.x; -}; + } -CubicBezierCurve3.prototype.fromJSON = function ( json ) { + if ( _shadowMapSize.y > _maxTextureSize ) { - Curve.prototype.fromJSON.call( this, json ); + _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); + _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; + shadow.mapSize.y = _viewportSize.y; - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); - this.v3.fromArray( json.v3 ); + } - return this; + } -}; + if ( shadow.map === null || toVSM === true || fromVSM === true ) { -function LineCurve( v1, v2 ) { + const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; - Curve.call( this ); + if ( shadow.map !== null ) { - this.type = 'LineCurve'; + shadow.map.dispose(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); + } -} + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); + shadow.map.texture.name = light.name + '.shadowMap'; -LineCurve.prototype = Object.create( Curve.prototype ); -LineCurve.prototype.constructor = LineCurve; + shadow.camera.updateProjectionMatrix(); -LineCurve.prototype.isLineCurve = true; + } -LineCurve.prototype.getPoint = function ( t, optionalTarget ) { + renderer.setRenderTarget( shadow.map ); + renderer.clear(); - var point = optionalTarget || new Vector2(); + const viewportCount = shadow.getViewportCount(); - if ( t === 1 ) { + for ( let vp = 0; vp < viewportCount; vp ++ ) { - point.copy( this.v2 ); + const viewport = shadow.getViewport( vp ); - } else { + _viewport.set( + _viewportSize.x * viewport.x, + _viewportSize.y * viewport.y, + _viewportSize.x * viewport.z, + _viewportSize.y * viewport.w + ); - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); + _state.viewport( _viewport ); - } + shadow.updateMatrices( light, vp ); - return point; + _frustum = shadow.getFrustum(); -}; + renderObject( scene, camera, shadow.camera, light, this.type ); -// Line curve is linear, so we can overwrite default getPointAt + } -LineCurve.prototype.getPointAt = function ( u, optionalTarget ) { + // do blur pass for VSM - return this.getPoint( u, optionalTarget ); + if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { -}; + VSMPass( shadow, camera ); -LineCurve.prototype.getTangent = function ( /* t */ ) { + } - var tangent = this.v2.clone().sub( this.v1 ); + shadow.needsUpdate = false; - return tangent.normalize(); + } -}; + _previousType = this.type; -LineCurve.prototype.copy = function ( source ) { + scope.needsUpdate = false; - Curve.prototype.copy.call( this, source ); + renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + }; - return this; + function VSMPass( shadow, camera ) { -}; + const geometry = objects.update( fullScreenMesh ); -LineCurve.prototype.toJSON = function () { + if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { - var data = Curve.prototype.toJSON.call( this ); + shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + shadowMaterialVertical.needsUpdate = true; + shadowMaterialHorizontal.needsUpdate = true; - return data; + } -}; + if ( shadow.mapPass === null ) { -LineCurve.prototype.fromJSON = function ( json ) { + shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); - Curve.prototype.fromJSON.call( this, json ); + } - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + // vertical pass - return this; + 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 ); -}; + // horizontal pass -function LineCurve3( v1, v2 ) { + 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 ); - Curve.call( this ); + } - this.type = 'LineCurve3'; + function getDepthMaterial( object, material, light, type ) { - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); + let result = null; -} + const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; -LineCurve3.prototype = Object.create( Curve.prototype ); -LineCurve3.prototype.constructor = LineCurve3; + if ( customMaterial !== undefined ) { -LineCurve3.prototype.isLineCurve3 = true; + result = customMaterial; -LineCurve3.prototype.getPoint = function ( t, optionalTarget ) { + } else { - var point = optionalTarget || new Vector3(); + result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial; - if ( t === 1 ) { + if ( ( renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || + ( material.displacementMap && material.displacementScale !== 0 ) || + ( material.alphaMap && material.alphaTest > 0 ) || + ( material.map && material.alphaTest > 0 ) ) { - point.copy( this.v2 ); + // in this case we need a unique material instance reflecting the + // appropriate state - } else { + const keyA = result.uuid, keyB = material.uuid; - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); + let materialsForVariant = _materialCache[ keyA ]; - } + if ( materialsForVariant === undefined ) { - return point; + materialsForVariant = {}; + _materialCache[ keyA ] = materialsForVariant; -}; + } -// Line curve is linear, so we can overwrite default getPointAt + let cachedMaterial = materialsForVariant[ keyB ]; -LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) { + if ( cachedMaterial === undefined ) { - return this.getPoint( u, optionalTarget ); + cachedMaterial = result.clone(); + materialsForVariant[ keyB ] = cachedMaterial; + material.addEventListener( 'dispose', onMaterialDispose ); -}; + } -LineCurve3.prototype.copy = function ( source ) { + result = cachedMaterial; - Curve.prototype.copy.call( this, source ); + } - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + } - return this; + result.visible = material.visible; + result.wireframe = material.wireframe; -}; + if ( type === VSMShadowMap ) { -LineCurve3.prototype.toJSON = function () { + result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; - var data = Curve.prototype.toJSON.call( this ); + } else { - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; - return data; + } -}; + result.alphaMap = material.alphaMap; + result.alphaTest = material.alphaTest; + result.map = material.map; -LineCurve3.prototype.fromJSON = function ( json ) { + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; - Curve.prototype.fromJSON.call( this, json ); + result.displacementMap = material.displacementMap; + result.displacementScale = material.displacementScale; + result.displacementBias = material.displacementBias; - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; - return this; + if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { -}; + const materialProperties = renderer.properties.get( result ); + materialProperties.light = light; -function QuadraticBezierCurve( v0, v1, v2 ) { + } - Curve.call( this ); + return result; - this.type = 'QuadraticBezierCurve'; + } - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); + function renderObject( object, camera, shadowCamera, light, type ) { -} + if ( object.visible === false ) return; -QuadraticBezierCurve.prototype = Object.create( Curve.prototype ); -QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve; + const visible = object.layers.test( camera.layers ); -QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true; + if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { -QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { + if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - var point = optionalTarget || new Vector2(); + object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2; + const geometry = objects.update( object ); + const material = object.material; - point.set( - QuadraticBezier( t, v0.x, v1.x, v2.x ), - QuadraticBezier( t, v0.y, v1.y, v2.y ) - ); + if ( Array.isArray( material ) ) { - return point; + const groups = geometry.groups; -}; + for ( let k = 0, kl = groups.length; k < kl; k ++ ) { -QuadraticBezierCurve.prototype.copy = function ( source ) { + const group = groups[ k ]; + const groupMaterial = material[ group.materialIndex ]; - Curve.prototype.copy.call( this, source ); + if ( groupMaterial && groupMaterial.visible ) { - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); - return this; + object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); -}; + renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); -QuadraticBezierCurve.prototype.toJSON = function () { + object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); - var data = Curve.prototype.toJSON.call( this ); + } - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + } - return data; + } else if ( material.visible ) { -}; + const depthMaterial = getDepthMaterial( object, material, light, type ); -QuadraticBezierCurve.prototype.fromJSON = function ( json ) { + object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); - Curve.prototype.fromJSON.call( this, json ); + renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); - return this; + } -}; + } -function QuadraticBezierCurve3( v0, v1, v2 ) { + } - Curve.call( this ); + const children = object.children; - this.type = 'QuadraticBezierCurve3'; + for ( let i = 0, l = children.length; i < l; i ++ ) { - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); + renderObject( children[ i ], camera, shadowCamera, light, type ); -} + } -QuadraticBezierCurve3.prototype = Object.create( Curve.prototype ); -QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3; + } -QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true; + function onMaterialDispose( event ) { -QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { + const material = event.target; - var point = optionalTarget || new Vector3(); + material.removeEventListener( 'dispose', onMaterialDispose ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2; + // make sure to remove the unique distance/depth materials used for shadow map rendering - 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 ) - ); + for ( const id in _materialCache ) { - return point; + const cache = _materialCache[ id ]; -}; + const uuid = event.target.uuid; -QuadraticBezierCurve3.prototype.copy = function ( source ) { + if ( uuid in cache ) { - Curve.prototype.copy.call( this, source ); + const shadowMaterial = cache[ uuid ]; + shadowMaterial.dispose(); + delete cache[ uuid ]; - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + } - return this; + } -}; + } -QuadraticBezierCurve3.prototype.toJSON = function () { +} - var data = Curve.prototype.toJSON.call( this ); +function WebGLState( gl ) { - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + function ColorBuffer() { - return data; + let locked = false; -}; + const color = new Vector4(); + let currentColorMask = null; + const currentColorClear = new Vector4( 0, 0, 0, 0 ); -QuadraticBezierCurve3.prototype.fromJSON = function ( json ) { + return { - Curve.prototype.fromJSON.call( this, json ); + setMask: function ( colorMask ) { - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + if ( currentColorMask !== colorMask && ! locked ) { - return this; + gl.colorMask( colorMask, colorMask, colorMask, colorMask ); + currentColorMask = colorMask; -}; + } -function SplineCurve( points /* array of Vector2 */ ) { + }, - Curve.call( this ); + setLocked: function ( lock ) { - this.type = 'SplineCurve'; + locked = lock; - this.points = points || []; + }, -} + setClear: function ( r, g, b, a, premultipliedAlpha ) { -SplineCurve.prototype = Object.create( Curve.prototype ); -SplineCurve.prototype.constructor = SplineCurve; + if ( premultipliedAlpha === true ) { -SplineCurve.prototype.isSplineCurve = true; + r *= a; g *= a; b *= a; -SplineCurve.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new Vector2(); + color.set( r, g, b, a ); - var points = this.points; - var p = ( points.length - 1 ) * t; + if ( currentColorClear.equals( color ) === false ) { - var intPoint = Math.floor( p ); - var weight = p - intPoint; + gl.clearColor( r, g, b, a ); + currentColorClear.copy( color ); - var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; - var p1 = points[ intPoint ]; - var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; - var 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; + reset: function () { -}; + locked = false; -SplineCurve.prototype.copy = function ( source ) { + currentColorMask = null; + currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state - Curve.prototype.copy.call( this, source ); + } - this.points = []; + }; - for ( var i = 0, l = source.points.length; i < l; i ++ ) { + } - var point = source.points[ i ]; + function DepthBuffer() { - this.points.push( point.clone() ); + let locked = false; - } + let currentDepthMask = null; + let currentDepthFunc = null; + let currentDepthClear = null; - return this; + return { -}; + setTest: function ( depthTest ) { -SplineCurve.prototype.toJSON = function () { + if ( depthTest ) { - var data = Curve.prototype.toJSON.call( this ); + enable( gl.DEPTH_TEST ); - data.points = []; + } else { - for ( var i = 0, l = this.points.length; i < l; i ++ ) { + disable( gl.DEPTH_TEST ); - var point = this.points[ i ]; - data.points.push( point.toArray() ); + } - } + }, - return data; + setMask: function ( depthMask ) { -}; + if ( currentDepthMask !== depthMask && ! locked ) { -SplineCurve.prototype.fromJSON = function ( json ) { + gl.depthMask( depthMask ); + currentDepthMask = depthMask; - Curve.prototype.fromJSON.call( this, json ); + } - this.points = []; + }, - for ( var i = 0, l = json.points.length; i < l; i ++ ) { + setFunc: function ( depthFunc ) { - var point = json.points[ i ]; - this.points.push( new Vector2().fromArray( point ) ); + if ( currentDepthFunc !== depthFunc ) { - } + switch ( depthFunc ) { - return this; + case NeverDepth: -}; + gl.depthFunc( gl.NEVER ); + break; + case AlwaysDepth: + gl.depthFunc( gl.ALWAYS ); + break; -var Curves = Object.freeze({ - ArcCurve: ArcCurve, - CatmullRomCurve3: CatmullRomCurve3, - CubicBezierCurve: CubicBezierCurve, - CubicBezierCurve3: CubicBezierCurve3, - EllipseCurve: EllipseCurve, - LineCurve: LineCurve, - LineCurve3: LineCurve3, - QuadraticBezierCurve: QuadraticBezierCurve, - QuadraticBezierCurve3: QuadraticBezierCurve3, - SplineCurve: SplineCurve -}); + case LessDepth: -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - **/ + gl.depthFunc( gl.LESS ); + break; -/************************************************************** - * Curved Path - a curve path is simply a array of connected - * curves, but retains the api of a curve - **************************************************************/ + case LessEqualDepth: -function CurvePath() { + gl.depthFunc( gl.LEQUAL ); + break; - Curve.call( this ); + case EqualDepth: - this.type = 'CurvePath'; + gl.depthFunc( gl.EQUAL ); + break; - this.curves = []; - this.autoClose = false; // Automatically closes the path + case GreaterEqualDepth: -} + gl.depthFunc( gl.GEQUAL ); + break; -CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), { + case GreaterDepth: - constructor: CurvePath, + gl.depthFunc( gl.GREATER ); + break; - add: function ( curve ) { + case NotEqualDepth: - this.curves.push( curve ); + gl.depthFunc( gl.NOTEQUAL ); + break; - }, + default: - closePath: function () { + gl.depthFunc( gl.LEQUAL ); - // Add a line curve if start and end of lines are not connected - var startPoint = this.curves[ 0 ].getPoint( 0 ); - var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); + } - if ( ! startPoint.equals( endPoint ) ) { + currentDepthFunc = depthFunc; - this.curves.push( new LineCurve( endPoint, startPoint ) ); + } - } + }, - }, + setLocked: function ( lock ) { - // To get accurate point with reference to - // entire path distance at time t, - // following has to be done: + locked = lock; - // 1. Length of each sub path have to be known - // 2. Locate and identify type of curve - // 3. Get t for the curve - // 4. Return curve.getPointAt(t') + }, - getPoint: function ( t ) { + setClear: function ( depth ) { - var d = t * this.getLength(); - var curveLengths = this.getCurveLengths(); - var i = 0; + if ( currentDepthClear !== depth ) { - // To think about boundaries points. + gl.clearDepth( depth ); + currentDepthClear = depth; - while ( i < curveLengths.length ) { + } - if ( curveLengths[ i ] >= d ) { + }, - var diff = curveLengths[ i ] - d; - var curve = this.curves[ i ]; + reset: function () { - var segmentLength = curve.getLength(); - var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; + locked = false; - return curve.getPointAt( u ); + currentDepthMask = null; + currentDepthFunc = null; + currentDepthClear = null; } - i ++; - - } - - return null; + }; - // loop where sum != 0, sum > d , sum+1 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { + const colorBuffer = new ColorBuffer(); + const depthBuffer = new DepthBuffer(); + const stencilBuffer = new StencilBuffer(); - points.push( points[ 0 ] ); + const uboBindings = new WeakMap(); + const uboProgramMap = new WeakMap(); - } + let enabledCapabilities = {}; - return points; + let currentBoundFramebuffers = {}; + let currentDrawbuffers = new WeakMap(); + let defaultDrawbuffers = []; - }, + let currentProgram = null; - copy: function ( source ) { + 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 currentBlendColor = new Color( 0, 0, 0 ); + let currentBlendAlpha = 0; + let currentPremultipledAlpha = false; - Curve.prototype.copy.call( this, source ); + let currentFlipSided = null; + let currentCullFace = null; - this.curves = []; + let currentLineWidth = null; - for ( var i = 0, l = source.curves.length; i < l; i ++ ) { + let currentPolygonOffsetFactor = null; + let currentPolygonOffsetUnits = null; - var curve = source.curves[ i ]; + const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); - this.curves.push( curve.clone() ); + let lineWidthAvailable = false; + let version = 0; + const glVersion = gl.getParameter( gl.VERSION ); - } + if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { - this.autoClose = source.autoClose; + version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); + lineWidthAvailable = ( version >= 1.0 ); - return this; + } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { - }, + version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); + lineWidthAvailable = ( version >= 2.0 ); - toJSON: function () { + } - var data = Curve.prototype.toJSON.call( this ); + let currentTextureSlot = null; + let currentBoundTextures = {}; - data.autoClose = this.autoClose; - data.curves = []; + const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); + const viewportParam = gl.getParameter( gl.VIEWPORT ); - for ( var i = 0, l = this.curves.length; i < l; i ++ ) { + const currentScissor = new Vector4().fromArray( scissorParam ); + const currentViewport = new Vector4().fromArray( viewportParam ); - var curve = this.curves[ i ]; - data.curves.push( curve.toJSON() ); + function createTexture( type, target, count, dimensions ) { - } + const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. + const texture = gl.createTexture(); - return data; + gl.bindTexture( type, texture ); + gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - }, + for ( let i = 0; i < count; i ++ ) { - fromJSON: function ( json ) { + if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) { - Curve.prototype.fromJSON.call( this, json ); + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); - this.autoClose = json.autoClose; - this.curves = []; + } else { - for ( var i = 0, l = json.curves.length; i < l; i ++ ) { + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); - var curve = json.curves[ i ]; - this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); + } } - return this; + return texture; } -} ); - -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Creates free form 2d path using series of points, lines or curves. - **/ + 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 ); + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); -function Path$1( points ) { + // init - CurvePath.call( this ); + colorBuffer.setClear( 0, 0, 0, 1 ); + depthBuffer.setClear( 1 ); + stencilBuffer.setClear( 0 ); - this.type = 'Path'; + enable( gl.DEPTH_TEST ); + depthBuffer.setFunc( LessEqualDepth ); - this.currentPoint = new Vector2(); + setFlipSided( false ); + setCullFace( CullFaceBack ); + enable( gl.CULL_FACE ); - if ( points ) { + setBlending( NoBlending ); - this.setFromPoints( points ); + // - } + function enable( id ) { -} + if ( enabledCapabilities[ id ] !== true ) { -Path$1.prototype = Object.assign( Object.create( CurvePath.prototype ), { + gl.enable( id ); + enabledCapabilities[ id ] = true; - constructor: Path$1, + } - setFromPoints: function ( points ) { + } - this.moveTo( points[ 0 ].x, points[ 0 ].y ); + function disable( id ) { - for ( var i = 1, l = points.length; i < l; i ++ ) { + if ( enabledCapabilities[ id ] !== false ) { - this.lineTo( points[ i ].x, points[ i ].y ); + gl.disable( id ); + enabledCapabilities[ id ] = false; } - }, - - moveTo: function ( x, y ) { + } - this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? + function bindFramebuffer( target, framebuffer ) { - }, + if ( currentBoundFramebuffers[ target ] !== framebuffer ) { - lineTo: function ( x, y ) { + gl.bindFramebuffer( target, framebuffer ); - var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); - this.curves.push( curve ); + currentBoundFramebuffers[ target ] = framebuffer; - this.currentPoint.set( x, y ); + // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER - }, + if ( target === gl.DRAW_FRAMEBUFFER ) { - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { + currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; - var curve = new QuadraticBezierCurve( - this.currentPoint.clone(), - new Vector2( aCPx, aCPy ), - new Vector2( aX, aY ) - ); + } - this.curves.push( curve ); + if ( target === gl.FRAMEBUFFER ) { - this.currentPoint.set( aX, aY ); + currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; - }, + } - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + return true; - var curve = new CubicBezierCurve( - this.currentPoint.clone(), - new Vector2( aCP1x, aCP1y ), - new Vector2( aCP2x, aCP2y ), - new Vector2( aX, aY ) - ); + } - this.curves.push( curve ); + return false; - this.currentPoint.set( aX, aY ); + } - }, + function drawBuffers( renderTarget, framebuffer ) { - splineThru: function ( pts /*Array of Vector*/ ) { + let drawBuffers = defaultDrawbuffers; - var npts = [ this.currentPoint.clone() ].concat( pts ); + let needsUpdate = false; - var curve = new SplineCurve( npts ); - this.curves.push( curve ); + if ( renderTarget ) { - this.currentPoint.copy( pts[ pts.length - 1 ] ); + drawBuffers = currentDrawbuffers.get( framebuffer ); - }, + if ( drawBuffers === undefined ) { - arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + drawBuffers = []; + currentDrawbuffers.set( framebuffer, drawBuffers ); - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; + } - this.absarc( aX + x0, aY + y0, aRadius, - aStartAngle, aEndAngle, aClockwise ); + const textures = renderTarget.textures; - }, + if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { - absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; - }, + } - ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + drawBuffers.length = textures.length; - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; + needsUpdate = true; - this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + } - }, + } else { - absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + if ( drawBuffers[ 0 ] !== gl.BACK ) { - var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + drawBuffers[ 0 ] = gl.BACK; - if ( this.curves.length > 0 ) { + needsUpdate = true; - // if a previous curve is present, attempt to join - var firstPoint = curve.getPoint( 0 ); + } - if ( ! firstPoint.equals( this.currentPoint ) ) { + } - this.lineTo( firstPoint.x, firstPoint.y ); + if ( needsUpdate ) { - } + gl.drawBuffers( drawBuffers ); } - this.curves.push( curve ); + } - var lastPoint = curve.getPoint( 1 ); - this.currentPoint.copy( lastPoint ); + function useProgram( program ) { - }, + if ( currentProgram !== program ) { - copy: function ( source ) { + gl.useProgram( program ); - CurvePath.prototype.copy.call( this, source ); + currentProgram = program; - this.currentPoint.copy( source.currentPoint ); + return true; - return this; + } - }, + return false; - toJSON: function () { + } - var data = CurvePath.prototype.toJSON.call( this ); + const equationToGL = { + [ AddEquation ]: gl.FUNC_ADD, + [ SubtractEquation ]: gl.FUNC_SUBTRACT, + [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT + }; - data.currentPoint = this.currentPoint.toArray(); + equationToGL[ MinEquation ] = gl.MIN; + equationToGL[ MaxEquation ] = gl.MAX; + + const factorToGL = { + [ ZeroFactor ]: gl.ZERO, + [ OneFactor ]: gl.ONE, + [ SrcColorFactor ]: gl.SRC_COLOR, + [ SrcAlphaFactor ]: gl.SRC_ALPHA, + [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, + [ DstColorFactor ]: gl.DST_COLOR, + [ DstAlphaFactor ]: gl.DST_ALPHA, + [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, + [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, + [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, + [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, + [ ConstantColorFactor ]: gl.CONSTANT_COLOR, + [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, + [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, + [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA + }; - return data; + function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { - }, + if ( blending === NoBlending ) { - fromJSON: function ( json ) { + if ( currentBlendingEnabled === true ) { - CurvePath.prototype.fromJSON.call( this, json ); + disable( gl.BLEND ); + currentBlendingEnabled = false; - this.currentPoint.fromArray( json.currentPoint ); + } - return this; + return; - } + } -} ); + if ( currentBlendingEnabled === false ) { -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Defines a 2d shape plane using paths. - **/ + enable( gl.BLEND ); + currentBlendingEnabled = true; -// STEP 1 Create a path. -// STEP 2 Turn path into shape. -// STEP 3 ExtrudeGeometry takes in Shape/Shapes -// STEP 3a - Extract points from each shape, turn to vertices -// STEP 3b - Triangulate each shape, add faces. + } -function Shape( points ) { + if ( blending !== CustomBlending ) { - Path$1.call( this, points ); + if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { - this.uuid = _Math.generateUUID(); + if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { - this.type = 'Shape'; + gl.blendEquation( gl.FUNC_ADD ); - this.holes = []; + currentBlendEquation = AddEquation; + currentBlendEquationAlpha = AddEquation; -} + } -Shape.prototype = Object.assign( Object.create( Path$1.prototype ), { + if ( premultipliedAlpha ) { - constructor: Shape, + switch ( blending ) { - getPointsHoles: function ( divisions ) { + case NormalBlending: + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; - var holesPts = []; + case AdditiveBlending: + gl.blendFunc( gl.ONE, gl.ONE ); + break; - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; - holesPts[ i ] = this.holes[ i ].getPoints( divisions ); + case MultiplyBlending: + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + break; - } + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; - return holesPts; + } - }, + } else { - // get points of shape and holes (keypoints based on segments parameter) + switch ( blending ) { - extractPoints: function ( divisions ) { + case NormalBlending: + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; - return { + case AdditiveBlending: + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + break; - shape: this.getPoints( divisions ), - holes: this.getPointsHoles( divisions ) + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; - }; + case MultiplyBlending: + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + break; - }, + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; - copy: function ( source ) { + } - Path$1.prototype.copy.call( this, source ); + } - this.holes = []; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlendColor.set( 0, 0, 0 ); + currentBlendAlpha = 0; - for ( var i = 0, l = source.holes.length; i < l; i ++ ) { + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; - var hole = source.holes[ i ]; + } - this.holes.push( hole.clone() ); + return; } - return this; - - }, - - toJSON: function () { + // custom blending - var data = Path$1.prototype.toJSON.call( this ); + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; - data.uuid = this.uuid; - data.holes = []; + if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { + gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); - var hole = this.holes[ i ]; - data.holes.push( hole.toJSON() ); + currentBlendEquation = blendEquation; + currentBlendEquationAlpha = blendEquationAlpha; } - return data; + if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { - }, + gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); - fromJSON: function ( json ) { + currentBlendSrc = blendSrc; + currentBlendDst = blendDst; + currentBlendSrcAlpha = blendSrcAlpha; + currentBlendDstAlpha = blendDstAlpha; - Path$1.prototype.fromJSON.call( this, json ); + } - this.uuid = json.uuid; - this.holes = []; + if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) { - for ( var i = 0, l = json.holes.length; i < l; i ++ ) { + gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); - var hole = json.holes[ i ]; - this.holes.push( new Path$1().fromJSON( hole ) ); + currentBlendColor.copy( blendColor ); + currentBlendAlpha = blendAlpha; } - return this; + currentBlending = blending; + currentPremultipledAlpha = false; } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + function setMaterial( material, frontFaceCW ) { -function Light( color, intensity ) { + material.side === DoubleSide + ? disable( gl.CULL_FACE ) + : enable( gl.CULL_FACE ); - Object3D.call( this ); + let flipSided = ( material.side === BackSide ); + if ( frontFaceCW ) flipSided = ! flipSided; - this.type = 'Light'; + setFlipSided( flipSided ); - this.color = new Color( color ); - this.intensity = intensity !== undefined ? intensity : 1; + ( material.blending === NormalBlending && material.transparent === false ) + ? setBlending( NoBlending ) + : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); - this.receiveShadow = undefined; + 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 ) { -Light.prototype = Object.assign( Object.create( Object3D.prototype ), { + stencilBuffer.setMask( material.stencilWriteMask ); + stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); + stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); - constructor: Light, + } - isLight: true, + setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - copy: function ( source ) { + material.alphaToCoverage === true + ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) + : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); - Object3D.prototype.copy.call( this, source ); + } - this.color.copy( source.color ); - this.intensity = source.intensity; + // - return this; + function setFlipSided( flipSided ) { - }, + if ( currentFlipSided !== flipSided ) { - toJSON: function ( meta ) { + if ( flipSided ) { - var data = Object3D.prototype.toJSON.call( this, meta ); + gl.frontFace( gl.CW ); - data.object.color = this.color.getHex(); - data.object.intensity = this.intensity; + } else { - if ( this.groundColor !== undefined ) { data.object.groundColor = this.groundColor.getHex(); } + gl.frontFace( gl.CCW ); - if ( this.distance !== undefined ) { data.object.distance = this.distance; } - if ( this.angle !== undefined ) { data.object.angle = this.angle; } - if ( this.decay !== undefined ) { data.object.decay = this.decay; } - if ( this.penumbra !== undefined ) { data.object.penumbra = this.penumbra; } + } - if ( this.shadow !== undefined ) { data.object.shadow = this.shadow.toJSON(); } + currentFlipSided = flipSided; - return data; + } } -} ); + function setCullFace( cullFace ) { -/** - * @author alteredq / http://alteredqualia.com/ - */ + if ( cullFace !== CullFaceNone ) { -function HemisphereLight( skyColor, groundColor, intensity ) { + enable( gl.CULL_FACE ); - Light.call( this, skyColor, intensity ); + if ( cullFace !== currentCullFace ) { - this.type = 'HemisphereLight'; + if ( cullFace === CullFaceBack ) { - this.castShadow = undefined; + gl.cullFace( gl.BACK ); - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + } else if ( cullFace === CullFaceFront ) { - this.groundColor = new Color( groundColor ); + gl.cullFace( gl.FRONT ); -} + } else { -HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), { + gl.cullFace( gl.FRONT_AND_BACK ); - constructor: HemisphereLight, + } - isHemisphereLight: true, + } - copy: function ( source ) { + } else { - Light.prototype.copy.call( this, source ); + disable( gl.CULL_FACE ); - this.groundColor.copy( source.groundColor ); + } - return this; + currentCullFace = cullFace; } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function LightShadow( camera ) { - - this.camera = camera; - - this.bias = 0; - this.radius = 1; - - this.mapSize = new Vector2( 512, 512 ); - - this.map = null; - this.matrix = new Matrix4(); - -} + function setLineWidth( width ) { -Object.assign( LightShadow.prototype, { + if ( width !== currentLineWidth ) { - copy: function ( source ) { + if ( lineWidthAvailable ) gl.lineWidth( width ); - this.camera = source.camera.clone(); + currentLineWidth = width; - this.bias = source.bias; - this.radius = source.radius; + } - this.mapSize.copy( source.mapSize ); + } - return this; + function setPolygonOffset( polygonOffset, factor, units ) { - }, + if ( polygonOffset ) { - clone: function () { + enable( gl.POLYGON_OFFSET_FILL ); - return new this.constructor().copy( this ); + if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { - }, + gl.polygonOffset( factor, units ); - toJSON: function () { + currentPolygonOffsetFactor = factor; + currentPolygonOffsetUnits = units; - var object = {}; + } - if ( this.bias !== 0 ) { object.bias = this.bias; } - if ( this.radius !== 1 ) { object.radius = this.radius; } - if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) { object.mapSize = this.mapSize.toArray(); } + } else { - object.camera = this.camera.toJSON( false ).object; - delete object.camera.matrix; + disable( gl.POLYGON_OFFSET_FILL ); - return object; + } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ + function setScissorTest( scissorTest ) { -function SpotLightShadow() { + if ( scissorTest ) { - LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) ); + enable( gl.SCISSOR_TEST ); -} + } else { -SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { + disable( gl.SCISSOR_TEST ); - constructor: SpotLightShadow, + } - isSpotLightShadow: true, + } - update: function ( light ) { + // texture - var camera = this.camera; + function activeTexture( webglSlot ) { - var fov = _Math.RAD2DEG * 2 * light.angle; - var aspect = this.mapSize.width / this.mapSize.height; - var far = light.distance || camera.far; + if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; - if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { + if ( currentTextureSlot !== webglSlot ) { - camera.fov = fov; - camera.aspect = aspect; - camera.far = far; - camera.updateProjectionMatrix(); + gl.activeTexture( webglSlot ); + currentTextureSlot = webglSlot; } } -} ); + function bindTexture( webglType, webglTexture, webglSlot ) { -/** - * @author alteredq / http://alteredqualia.com/ - */ + if ( webglSlot === undefined ) { -function SpotLight( color, intensity, distance, angle, penumbra, decay ) { + if ( currentTextureSlot === null ) { - Light.call( this, color, intensity ); + webglSlot = gl.TEXTURE0 + maxTextures - 1; - this.type = 'SpotLight'; + } else { - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + webglSlot = currentTextureSlot; - this.target = new Object3D(); + } - Object.defineProperty( this, 'power', { - get: function () { + } - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * Math.PI; + let boundTexture = currentBoundTextures[ webglSlot ]; - }, - set: function ( power ) { + if ( boundTexture === undefined ) { - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / Math.PI; + boundTexture = { type: undefined, texture: undefined }; + currentBoundTextures[ webglSlot ] = boundTexture; } - } ); - this.distance = ( distance !== undefined ) ? distance : 0; - this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; - this.penumbra = ( penumbra !== undefined ) ? penumbra : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. + if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { - this.shadow = new SpotLightShadow(); + if ( currentTextureSlot !== webglSlot ) { -} + gl.activeTexture( webglSlot ); + currentTextureSlot = webglSlot; -SpotLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: SpotLight, + gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); - isSpotLight: true, + boundTexture.type = webglType; + boundTexture.texture = webglTexture; - copy: function ( source ) { + } - Light.prototype.copy.call( this, source ); + } - this.distance = source.distance; - this.angle = source.angle; - this.penumbra = source.penumbra; - this.decay = source.decay; + function unbindTexture() { - this.target = source.target.clone(); + const boundTexture = currentBoundTextures[ currentTextureSlot ]; - this.shadow = source.shadow.clone(); + if ( boundTexture !== undefined && boundTexture.type !== undefined ) { - return this; + gl.bindTexture( boundTexture.type, null ); - } + boundTexture.type = undefined; + boundTexture.texture = undefined; -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + } + function compressedTexImage2D() { -function PointLight( color, intensity, distance, decay ) { + try { - Light.call( this, color, intensity ); + gl.compressedTexImage2D.apply( gl, arguments ); - this.type = 'PointLight'; + } catch ( error ) { - Object.defineProperty( this, 'power', { - get: function () { + console.error( 'THREE.WebGLState:', error ); - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * 4 * Math.PI; + } - }, - set: function ( power ) { + } - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / ( 4 * Math.PI ); + function compressedTexImage3D() { - } - } ); + try { - this.distance = ( distance !== undefined ) ? distance : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. + gl.compressedTexImage3D.apply( gl, arguments ); - this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -PointLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: PointLight, + } - isPointLight: true, + function texSubImage2D() { - copy: function ( source ) { + try { - Light.prototype.copy.call( this, source ); + gl.texSubImage2D.apply( gl, arguments ); - this.distance = source.distance; - this.decay = source.decay; + } catch ( error ) { - this.shadow = source.shadow.clone(); + console.error( 'THREE.WebGLState:', error ); - return this; + } } -} ); + function texSubImage3D() { -/** - * @author mrdoob / http://mrdoob.com/ - */ + try { -function DirectionalLightShadow( ) { + gl.texSubImage3D.apply( gl, arguments ); - LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { + } - constructor: DirectionalLightShadow + } -} ); + function compressedTexSubImage2D() { -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + try { + + gl.compressedTexSubImage2D.apply( gl, arguments ); -function DirectionalLight( color, intensity ) { + } catch ( error ) { - Light.call( this, color, intensity ); + console.error( 'THREE.WebGLState:', error ); - this.type = 'DirectionalLight'; + } - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + } - this.target = new Object3D(); + function compressedTexSubImage3D() { - this.shadow = new DirectionalLightShadow(); + try { -} + gl.compressedTexSubImage3D.apply( gl, arguments ); -DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), { + } catch ( error ) { - constructor: DirectionalLight, + console.error( 'THREE.WebGLState:', error ); - isDirectionalLight: true, + } - copy: function ( source ) { + } - Light.prototype.copy.call( this, source ); + function texStorage2D() { - this.target = source.target.clone(); + try { - this.shadow = source.shadow.clone(); + gl.texStorage2D.apply( gl, arguments ); - return this; + } catch ( error ) { - } + console.error( 'THREE.WebGLState:', error ); -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function AmbientLight( color, intensity ) { + function texStorage3D() { - Light.call( this, color, intensity ); + try { - this.type = 'AmbientLight'; + gl.texStorage3D.apply( gl, arguments ); - this.castShadow = undefined; + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: AmbientLight, + } - isAmbientLight: true + function texImage2D() { -} ); + try { -/** - * @author abelnation / http://github.com/abelnation - */ + gl.texImage2D.apply( gl, arguments ); -function RectAreaLight( color, intensity, width, height ) { + } catch ( error ) { - Light.call( this, color, intensity ); + console.error( 'THREE.WebGLState:', error ); - this.type = 'RectAreaLight'; + } - this.position.set( 0, 1, 0 ); - this.updateMatrix(); + } - this.width = ( width !== undefined ) ? width : 10; - this.height = ( height !== undefined ) ? height : 10; + function texImage3D() { - // TODO (abelnation): distance/decay + try { - // TODO (abelnation): update method for RectAreaLight to update transform to lookat target + gl.texImage3D.apply( gl, arguments ); - // TODO (abelnation): shadows + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -// TODO (abelnation): RectAreaLight update when light shape is changed -RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: RectAreaLight, + } - isRectAreaLight: true, + // - copy: function ( source ) { + function scissor( scissor ) { - Light.prototype.copy.call( this, source ); + if ( currentScissor.equals( scissor ) === false ) { - this.width = source.width; - this.height = source.height; + gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); + currentScissor.copy( scissor ); - return this; + } - }, + } - toJSON: function ( meta ) { + function viewport( viewport ) { - var data = Light.prototype.toJSON.call( this, meta ); + if ( currentViewport.equals( viewport ) === false ) { - data.object.width = this.width; - data.object.height = this.height; + gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); + currentViewport.copy( viewport ); - return data; + } } -} ); + function updateUBOMapping( uniformsGroup, program ) { -/** - * - * A Track that interpolates Strings - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + let mapping = uboProgramMap.get( program ); -function StringKeyframeTrack( name, times, values, interpolation ) { + if ( mapping === undefined ) { - KeyframeTrack.call( this, name, times, values, interpolation ); + mapping = new WeakMap(); -} + uboProgramMap.set( program, mapping ); -StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + } - constructor: StringKeyframeTrack, + let blockIndex = mapping.get( uniformsGroup ); - ValueTypeName: 'string', - ValueBufferType: Array, + if ( blockIndex === undefined ) { - DefaultInterpolation: InterpolateDiscrete, + blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); - InterpolantFactoryMethodLinear: undefined, + mapping.set( uniformsGroup, blockIndex ); - InterpolantFactoryMethodSmooth: undefined + } -} ); + } -/** - * - * A Track of Boolean keyframe values. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + function uniformBlockBinding( uniformsGroup, program ) { -function BooleanKeyframeTrack( name, times, values ) { + const mapping = uboProgramMap.get( program ); + const blockIndex = mapping.get( uniformsGroup ); - KeyframeTrack.call( this, name, times, values ); + if ( uboBindings.get( program ) !== blockIndex ) { -} + // bind shader specific block index to global block point + gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); -BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + uboBindings.set( program, blockIndex ); - constructor: BooleanKeyframeTrack, + } - ValueTypeName: 'bool', - ValueBufferType: Array, + } - DefaultInterpolation: InterpolateDiscrete, + // - InterpolantFactoryMethodLinear: undefined, - InterpolantFactoryMethodSmooth: undefined + function reset() { - // Note: Actually this track could have a optimized / compressed - // representation of a single value and a custom interpolant that - // computes "firstValue ^ isOdd( index )". + // reset state -} ); + 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 ); -/** - * Abstract base class of interpolants over parametric samples. - * - * The parameter domain is one dimensional, typically the time or a path - * along a curve defined by the data. - * - * The sample values can have any dimensionality and derived classes may - * apply special interpretations to the data. - * - * This class provides the interval seek in a Template Method, deferring - * the actual interpolation to derived classes. - * - * Time complexity is O(1) for linear access crossing at most two points - * and O(log N) for random access, where N is the number of positions. - * - * References: - * - * http://www.oodesign.com/template-method-pattern.html - * - * @author tschw - */ + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ONE, gl.ZERO ); + gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); + gl.blendColor( 0, 0, 0, 0 ); -function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + gl.colorMask( true, true, true, true ); + gl.clearColor( 0, 0, 0, 0 ); - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; + gl.depthMask( true ); + gl.depthFunc( gl.LESS ); + gl.clearDepth( 1 ); - this.resultBuffer = resultBuffer !== undefined ? - resultBuffer : new sampleValues.constructor( sampleSize ); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; + gl.stencilMask( 0xffffffff ); + gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); + gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); + gl.clearStencil( 0 ); -} + gl.cullFace( gl.BACK ); + gl.frontFace( gl.CCW ); -Object.assign( Interpolant.prototype, { + gl.polygonOffset( 0, 0 ); - evaluate: function ( t ) { + gl.activeTexture( gl.TEXTURE0 ); - var pp = this.parameterPositions, - i1 = this._cachedIndex, + gl.bindFramebuffer( gl.FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); - t1 = pp[ i1 ], - t0 = pp[ i1 - 1 ]; + gl.useProgram( null ); - validate_interval: { + gl.lineWidth( 1 ); - seek: { + gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); + gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); - var right; + // reset internals - linear_scan: { + enabledCapabilities = {}; - //- See http://jsperf.com/comparison-to-undefined/3 - //- slower code: - //- - //- if ( t >= t1 || t1 === undefined ) { - forward_scan: if ( ! ( t < t1 ) ) { + currentTextureSlot = null; + currentBoundTextures = {}; - for ( var giveUpAt = i1 + 2; ; ) { + currentBoundFramebuffers = {}; + currentDrawbuffers = new WeakMap(); + defaultDrawbuffers = []; - if ( t1 === undefined ) { + currentProgram = null; - if ( t < t0 ) { break forward_scan; } + currentBlendingEnabled = false; + currentBlending = null; + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlendColor = new Color( 0, 0, 0 ); + currentBlendAlpha = 0; + currentPremultipledAlpha = false; - // after end + currentFlipSided = null; + currentCullFace = null; - i1 = pp.length; - this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t, t0 ); + currentLineWidth = null; - } + currentPolygonOffsetFactor = null; + currentPolygonOffsetUnits = null; - if ( i1 === giveUpAt ) { break; } // this loop + currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); + currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); - t0 = t1; - t1 = pp[ ++ i1 ]; + colorBuffer.reset(); + depthBuffer.reset(); + stencilBuffer.reset(); - if ( t < t1 ) { + } - // we have arrived at the sought interval - break seek; + return { - } + buffers: { + color: colorBuffer, + depth: depthBuffer, + stencil: stencilBuffer + }, - } + enable: enable, + disable: disable, - // prepare binary search on the right side of the index - right = pp.length; - break linear_scan; + bindFramebuffer: bindFramebuffer, + drawBuffers: drawBuffers, - } + useProgram: useProgram, - //- slower code: - //- if ( t < t0 || t0 === undefined ) { - if ( ! ( t >= t0 ) ) { + setBlending: setBlending, + setMaterial: setMaterial, - // looping? + setFlipSided: setFlipSided, + setCullFace: setCullFace, - var t1global = pp[ 1 ]; + setLineWidth: setLineWidth, + setPolygonOffset: setPolygonOffset, - if ( t < t1global ) { + setScissorTest: setScissorTest, - i1 = 2; // + 1, using the scan for the details - t0 = t1global; + activeTexture: activeTexture, + bindTexture: bindTexture, + unbindTexture: unbindTexture, + compressedTexImage2D: compressedTexImage2D, + compressedTexImage3D: compressedTexImage3D, + texImage2D: texImage2D, + texImage3D: texImage3D, - } + updateUBOMapping: updateUBOMapping, + uniformBlockBinding: uniformBlockBinding, - // linear reverse scan + texStorage2D: texStorage2D, + texStorage3D: texStorage3D, + texSubImage2D: texSubImage2D, + texSubImage3D: texSubImage3D, + compressedTexSubImage2D: compressedTexSubImage2D, + compressedTexSubImage3D: compressedTexSubImage3D, - for ( var giveUpAt = i1 - 2; ; ) { + scissor: scissor, + viewport: viewport, - if ( t0 === undefined ) { + reset: reset - // before start + }; - this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); +} - } - if ( i1 === giveUpAt ) { break; } // this loop - t1 = t0; - t0 = pp[ -- i1 - 1 ]; +/** + * Given the width, height, format, and type of a texture. Determines how many + * bytes must be used to represent the texture. + */ +function getByteLength( width, height, format, type ) { + + const typeByteLength = getTextureTypeByteLength( type ); + + switch ( format ) { + + // https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml + case AlphaFormat: + return width * height; + case LuminanceFormat: + return width * height; + case LuminanceAlphaFormat: + return width * height * 2; + case RedFormat: + return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength; + case RedIntegerFormat: + return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGFormat: + return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGIntegerFormat: + return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBFormat: + return ( ( width * height * 3 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBAFormat: + return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBAIntegerFormat: + return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_s3tc_srgb/ + case RGB_S3TC_DXT1_Format: + case RGBA_S3TC_DXT1_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; + case RGBA_S3TC_DXT3_Format: + case RGBA_S3TC_DXT5_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_pvrtc/ + case RGB_PVRTC_2BPPV1_Format: + case RGBA_PVRTC_2BPPV1_Format: + return ( Math.max( width, 16 ) * Math.max( height, 8 ) ) / 4; + case RGB_PVRTC_4BPPV1_Format: + case RGBA_PVRTC_4BPPV1_Format: + return ( Math.max( width, 8 ) * Math.max( height, 8 ) ) / 2; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_etc/ + case RGB_ETC1_Format: + case RGB_ETC2_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; + case RGBA_ETC2_EAC_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/ + case RGBA_ASTC_4x4_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + case RGBA_ASTC_5x4_Format: + return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + case RGBA_ASTC_5x5_Format: + return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_6x5_Format: + return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_6x6_Format: + return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_8x5_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_8x6_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_8x8_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 7 ) / 8 ) * 16; + case RGBA_ASTC_10x5_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_10x6_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_10x8_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 7 ) / 8 ) * 16; + case RGBA_ASTC_10x10_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 9 ) / 10 ) * 16; + case RGBA_ASTC_12x10_Format: + return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 9 ) / 10 ) * 16; + case RGBA_ASTC_12x12_Format: + return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 11 ) / 12 ) * 16; + + // https://registry.khronos.org/webgl/extensions/EXT_texture_compression_bptc/ + case RGBA_BPTC_Format: + case RGB_BPTC_SIGNED_Format: + case RGB_BPTC_UNSIGNED_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/EXT_texture_compression_rgtc/ + case RED_RGTC1_Format: + case SIGNED_RED_RGTC1_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 8; + case RED_GREEN_RGTC2_Format: + case SIGNED_RED_GREEN_RGTC2_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16; + + } + + throw new Error( + `Unable to determine texture byte length for ${format} format.`, + ); - if ( t >= t0 ) { +} - // we have arrived at the sought interval - break seek; +function getTextureTypeByteLength( type ) { - } + switch ( type ) { - } + case UnsignedByteType: + case ByteType: + return { byteLength: 1, components: 1 }; + case UnsignedShortType: + case ShortType: + case HalfFloatType: + return { byteLength: 2, components: 1 }; + case UnsignedShort4444Type: + case UnsignedShort5551Type: + return { byteLength: 2, components: 4 }; + case UnsignedIntType: + case IntType: + case FloatType: + return { byteLength: 4, components: 1 }; + case UnsignedInt5999Type: + return { byteLength: 4, components: 3 }; - // prepare binary search on the left side of the index - right = i1; - i1 = 0; - break linear_scan; + } - } + throw new Error( `Unknown texture type ${type}.` ); - // the interval is valid +} - break validate_interval; +function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { - } // linear scan + const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; + const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); - // binary search + const _imageDimensions = new Vector2(); + const _videoTextures = new WeakMap(); + let _canvas; - while ( i1 < right ) { + const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source - var mid = ( i1 + right ) >>> 1; + // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, + // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! + // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). - if ( t < pp[ mid ] ) { + let useOffscreenCanvas = false; - right = mid; + try { - } else { + useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' + // eslint-disable-next-line compat/compat + && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; - i1 = mid + 1; + } catch ( err ) { - } + // Ignore any errors - } + } - t1 = pp[ i1 ]; - t0 = pp[ i1 - 1 ]; + function createCanvas( width, height ) { - // check boundary cases, again + // Use OffscreenCanvas when available. Specially needed in web workers - if ( t0 === undefined ) { + return useOffscreenCanvas ? + // eslint-disable-next-line compat/compat + new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); - this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); + } - } + function resizeImage( image, needsNewCanvas, maxSize ) { - if ( t1 === undefined ) { + let scale = 1; - i1 = pp.length; - this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t0, t ); + const dimensions = getDimensions( image ); - } + // handle case if texture exceeds max size - } // seek + if ( dimensions.width > maxSize || dimensions.height > maxSize ) { - this._cachedIndex = i1; + scale = maxSize / Math.max( dimensions.width, dimensions.height ); - this.intervalChanged_( i1, t0, t1 ); + } - } // validate_interval + // only perform resize if necessary - return this.interpolate_( i1, t0, t, t1 ); + if ( scale < 1 ) { - }, + // only perform resize for certain image types - settings: null, // optional, subclass-specific settings structure - // Note: The indirection allows central control of many interpolants. + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) || + ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) { - // --- Protected interface + const width = Math.floor( scale * dimensions.width ); + const height = Math.floor( scale * dimensions.height ); - DefaultSettings_: {}, + if ( _canvas === undefined ) _canvas = createCanvas( width, height ); - getSettings_: function () { + // cube textures can't reuse the same canvas - return this.settings || this.DefaultSettings_; + const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; - }, + canvas.width = width; + canvas.height = height; - copySampleValue_: function ( index ) { + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, width, height ); - // copies a sample value to the result buffer + console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - offset = index * stride; + return canvas; - for ( var i = 0; i !== stride; ++ i ) { + } else { - result[ i ] = values[ offset + i ]; + if ( 'data' in image ) { - } + console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); - return result; + } - }, + return image; - // Template methods for derived classes: + } - interpolate_: function ( /* i1, t0, t, t1 */ ) { + } - throw new Error( 'call to abstract method' ); - // implementations shall return this.resultBuffer + return image; - }, + } - intervalChanged_: function ( /* i1, t0, t1 */ ) { + function textureNeedsGenerateMipmaps( texture ) { - // empty + return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; } -} ); + function generateMipmap( target ) { -//!\ DECLARE ALIAS AFTER assign prototype ! -Object.assign( Interpolant.prototype, { + _gl.generateMipmap( target ); - //( 0, t, t0 ), returns this.resultBuffer - beforeStart_: Interpolant.prototype.copySampleValue_, + } - //( N-1, tN-1, t ), returns this.resultBuffer - afterEnd_: Interpolant.prototype.copySampleValue_, + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { -} ); + if ( internalFormatName !== null ) { -/** - * Spherical linear unit quaternion interpolant. - * - * @author tschw - */ + if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; -function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + } -} + let internalFormat = glFormat; -QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + if ( glFormat === _gl.RED ) { - constructor: QuaternionLinearInterpolant, + if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; - interpolate_: function ( i1, t0, t, t1 ) { + } - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + if ( glFormat === _gl.RED_INTEGER ) { - offset = i1 * stride, + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.R8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.R16I; + if ( glType === _gl.INT ) internalFormat = _gl.R32I; - alpha = ( t - t0 ) / ( t1 - t0 ); + } - for ( var end = offset + stride; offset !== end; offset += 4 ) { + if ( glFormat === _gl.RG ) { - Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); + if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; } - return result; + if ( glFormat === _gl.RG_INTEGER ) { - } + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I; + if ( glType === _gl.INT ) internalFormat = _gl.RG32I; -} ); + } -/** - * - * A Track of quaternion keyframe values. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + if ( glFormat === _gl.RGB ) { -function QuaternionKeyframeTrack( name, times, values, interpolation ) { + if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; - KeyframeTrack.call( this, name, times, values, interpolation ); + } -} + if ( glFormat === _gl.RGBA ) { -QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace ); - constructor: QuaternionKeyframeTrack, + if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _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; - ValueTypeName: 'quaternion', + } - // ValueBufferType is inherited + if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || + internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || + internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { - DefaultInterpolation: InterpolateLinear, + extensions.get( 'EXT_color_buffer_float' ); - InterpolantFactoryMethodLinear: function ( result ) { + } - return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); + return internalFormat; - }, + } - InterpolantFactoryMethodSmooth: undefined // not yet implemented + function getInternalDepthFormat( useStencil, depthType ) { -} ); + let glInternalFormat; + if ( useStencil ) { -/** - * - * A Track of keyframe values that represent color. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { -function ColorKeyframeTrack( name, times, values, interpolation ) { + glInternalFormat = _gl.DEPTH24_STENCIL8; - KeyframeTrack.call( this, name, times, values, interpolation ); + } else if ( depthType === FloatType ) { -} + glInternalFormat = _gl.DEPTH32F_STENCIL8; -ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + } else if ( depthType === UnsignedShortType ) { - constructor: ColorKeyframeTrack, + glInternalFormat = _gl.DEPTH24_STENCIL8; + console.warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' ); - ValueTypeName: 'color' + } - // ValueBufferType is inherited + } else { - // DefaultInterpolation is inherited + if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { - // Note: Very basic implementation and nothing special yet. - // However, this is the place for color space parameterization. + glInternalFormat = _gl.DEPTH_COMPONENT24; -} ); + } else if ( depthType === FloatType ) { -/** - * - * A Track of numeric keyframe values. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + glInternalFormat = _gl.DEPTH_COMPONENT32F; -function NumberKeyframeTrack( name, times, values, interpolation ) { + } else if ( depthType === UnsignedShortType ) { - KeyframeTrack.call( this, name, times, values, interpolation ); + glInternalFormat = _gl.DEPTH_COMPONENT16; -} + } -NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + } - constructor: NumberKeyframeTrack, + return glInternalFormat; - ValueTypeName: 'number' + } - // ValueBufferType is inherited + function getMipLevels( texture, image ) { - // DefaultInterpolation is inherited + if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { -} ); + return Math.log2( Math.max( image.width, image.height ) ) + 1; -/** - * Fast and simple cubic spline interpolant. - * - * It was derived from a Hermitian construction setting the first derivative - * at each sample position to the linear slope between neighboring positions - * over their parameter interval. - * - * @author tschw - */ + } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { -function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + // user-defined mipmaps - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + return texture.mipmaps.length; - this._weightPrev = - 0; - this._offsetPrev = - 0; - this._weightNext = - 0; - this._offsetNext = - 0; + } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { -} + return image.mipmaps.length; -CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + } else { - constructor: CubicInterpolant, + // texture without mipmaps (only base level) - DefaultSettings_: { + return 1; - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding + } - }, + } - intervalChanged_: function ( i1, t0, t1 ) { + // - var pp = this.parameterPositions, - iPrev = i1 - 2, - iNext = i1 + 1, + function onTextureDispose( event ) { - tPrev = pp[ iPrev ], - tNext = pp[ iNext ]; + const texture = event.target; - if ( tPrev === undefined ) { + texture.removeEventListener( 'dispose', onTextureDispose ); - switch ( this.getSettings_().endingStart ) { + deallocateTexture( texture ); - case ZeroSlopeEnding: + if ( texture.isVideoTexture ) { - // f'(t0) = 0 - iPrev = i1; - tPrev = 2 * t0 - t1; + _videoTextures.delete( texture ); - break; + } - case WrapAroundEnding: + } - // use the other end of the curve - iPrev = pp.length - 2; - tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; + function onRenderTargetDispose( event ) { - break; + const renderTarget = event.target; - default: // ZeroCurvatureEnding + renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); - // f''(t0) = 0 a.k.a. Natural Spline - iPrev = i1; - tPrev = t1; + deallocateRenderTarget( renderTarget ); - } + } - } + // - if ( tNext === undefined ) { + function deallocateTexture( texture ) { - switch ( this.getSettings_().endingEnd ) { + const textureProperties = properties.get( texture ); - case ZeroSlopeEnding: + if ( textureProperties.__webglInit === undefined ) return; - // f'(tN) = 0 - iNext = i1; - tNext = 2 * t1 - t0; + // check if it's necessary to remove the WebGLTexture object - break; + const source = texture.source; + const webglTextures = _sources.get( source ); - case WrapAroundEnding: + if ( webglTextures ) { - // use the other end of the curve - iNext = 1; - tNext = t1 + pp[ 1 ] - pp[ 0 ]; + const webglTexture = webglTextures[ textureProperties.__cacheKey ]; + webglTexture.usedTimes --; - break; + // the WebGLTexture object is not used anymore, remove it - default: // ZeroCurvatureEnding + if ( webglTexture.usedTimes === 0 ) { - // f''(tN) = 0, a.k.a. Natural Spline - iNext = i1 - 1; - tNext = t0; + deleteTexture( texture ); } - } + // remove the weak map entry if no WebGLTexture uses the source anymore - var halfDt = ( t1 - t0 ) * 0.5, - stride = this.valueSize; + if ( Object.keys( webglTextures ).length === 0 ) { - this._weightPrev = halfDt / ( t0 - tPrev ); - this._weightNext = halfDt / ( tNext - t1 ); - this._offsetPrev = iPrev * stride; - this._offsetNext = iNext * stride; + _sources.delete( source ); - }, + } - interpolate_: function ( i1, t0, t, t1 ) { + } - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + properties.remove( texture ); - 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; + function deleteTexture( texture ) { - // evaluate polynomials + const textureProperties = properties.get( texture ); + _gl.deleteTexture( textureProperties.__webglTexture ); - var sP = - wP * ppp + 2 * wP * pp - wP * p; - var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; - var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; - var sN = wN * ppp - wN * pp; + const source = texture.source; + const webglTextures = _sources.get( source ); + delete webglTextures[ textureProperties.__cacheKey ]; - // combine data linearly + info.memory.textures --; - for ( var i = 0; i !== stride; ++ i ) { + } - result[ i ] = - sP * values[ oP + i ] + - s0 * values[ o0 + i ] + - s1 * values[ o1 + i ] + - sN * values[ oN + i ]; + function deallocateRenderTarget( renderTarget ) { - } + const renderTargetProperties = properties.get( renderTarget ); - return result; + if ( renderTarget.depthTexture ) { - } + renderTarget.depthTexture.dispose(); -} ); + } -/** - * @author tschw - */ + if ( renderTarget.isWebGLCubeRenderTarget ) { -function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + for ( let i = 0; i < 6; i ++ ) { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) { -} + for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] ); -LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + } else { - constructor: LinearInterpolant, + _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - interpolate_: function ( i1, t0, t, t1 ) { + } - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); - offset1 = i1 * stride, - offset0 = offset1 - stride, + } - weight1 = ( t - t0 ) / ( t1 - t0 ), - weight0 = 1 - weight1; + } else { - for ( var i = 0; i !== stride; ++ i ) { + if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) { - result[ i ] = - values[ offset0 + i ] * weight0 + - values[ offset1 + i ] * weight1; + for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] ); - } + } else { - return result; + _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - } + } -} ); + if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); + if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); -/** - * - * Interpolant that evaluates to the sample value at the position preceeding - * the parameter. - * - * @author tschw - */ + if ( renderTargetProperties.__webglColorRenderbuffer ) { -function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); -} + } -DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + } - constructor: DiscreteInterpolant, + if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); - interpolate_: function ( i1 /*, t0, t, t1 */ ) { + } - return this.copySampleValue_( i1 - 1 ); + const textures = renderTarget.textures; - } + for ( let i = 0, il = textures.length; i < il; i ++ ) { -} ); + const attachmentProperties = properties.get( textures[ i ] ); -/** - * @author tschw - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ + if ( attachmentProperties.__webglTexture ) { -var AnimationUtils = { + _gl.deleteTexture( attachmentProperties.__webglTexture ); - // same as Array.prototype.slice, but also works on typed arrays - arraySlice: function ( array, from, to ) { + info.memory.textures --; - if ( AnimationUtils.isTypedArray( array ) ) { + } - // in ios9 array.subarray(from, undefined) will return empty array - // but array.subarray(from) or array.subarray(from, len) is correct - return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) ); + properties.remove( textures[ i ] ); } - return array.slice( from, to ); - - }, + properties.remove( renderTarget ); - // converts an array to a specific type - convertArray: function ( array, type, forceClone ) { + } - if ( ! array || // let 'undefined' and 'null' pass - ! forceClone && array.constructor === type ) { return array; } + // - if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { + let textureUnits = 0; - return new type( array ); // create typed array + function resetTextureUnits() { - } + textureUnits = 0; - return Array.prototype.slice.call( array ); // create Array + } - }, + function allocateTextureUnit() { - isTypedArray: function ( object ) { + const textureUnit = textureUnits; - return ArrayBuffer.isView( object ) && - ! ( object instanceof DataView ); + if ( textureUnit >= capabilities.maxTextures ) { - }, + console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); - // returns an array by which times and values can be sorted - getKeyframeOrder: function ( times ) { + } - function compareTime( i, j ) { + textureUnits += 1; - return times[ i ] - times[ j ]; + return textureUnit; - } + } - var n = times.length; - var result = new Array( n ); - for ( var i = 0; i !== n; ++ i ) { result[ i ] = i; } + function getTextureCacheKey( texture ) { - result.sort( compareTime ); + const array = []; - return result; + array.push( texture.wrapS ); + array.push( texture.wrapT ); + array.push( texture.wrapR || 0 ); + array.push( texture.magFilter ); + array.push( texture.minFilter ); + array.push( texture.anisotropy ); + array.push( texture.internalFormat ); + array.push( texture.format ); + array.push( texture.type ); + array.push( texture.generateMipmaps ); + array.push( texture.premultiplyAlpha ); + array.push( texture.flipY ); + array.push( texture.unpackAlignment ); + array.push( texture.colorSpace ); - }, + return array.join(); - // uses the array previously returned by 'getKeyframeOrder' to sort data - sortedArray: function ( values, stride, order ) { + } - var nValues = values.length; - var result = new values.constructor( nValues ); + // - for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { + function setTexture2D( texture, slot ) { - var srcOffset = order[ i ] * stride; + const textureProperties = properties.get( texture ); - for ( var j = 0; j !== stride; ++ j ) { + if ( texture.isVideoTexture ) updateVideoTexture( texture ); - result[ dstOffset ++ ] = values[ srcOffset + j ]; + if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { - } + const image = texture.image; - } + if ( image === null ) { - return result; + console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); - }, + } else if ( image.complete === false ) { - // function for parsing AOS keyframe formats - flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) { + console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); - var i = 1, key = jsonKeys[ 0 ]; + } else { - while ( key !== undefined && key[ valuePropertyName ] === undefined ) { + uploadTexture( textureProperties, texture, slot ); + return; - key = jsonKeys[ i ++ ]; + } } - if ( key === undefined ) { return; } // no data - - var value = key[ valuePropertyName ]; - if ( value === undefined ) { return; } // no data + state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - if ( Array.isArray( value ) ) { + } - do { + function setTexture2DArray( texture, slot ) { - value = key[ valuePropertyName ]; + const textureProperties = properties.get( texture ); - if ( value !== undefined ) { + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - times.push( key.time ); - values.push.apply( values, value ); // push all elements + uploadTexture( textureProperties, texture, slot ); + return; - } + } - key = jsonKeys[ i ++ ]; + state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } while ( key !== undefined ); + } - } else if ( value.toArray !== undefined ) { + function setTexture3D( texture, slot ) { - // ...assume THREE.Math-ish + const textureProperties = properties.get( texture ); - do { + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - value = key[ valuePropertyName ]; + uploadTexture( textureProperties, texture, slot ); + return; - if ( value !== undefined ) { + } - times.push( key.time ); - value.toArray( values, values.length ); + state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } + } - key = jsonKeys[ i ++ ]; + function setTextureCube( texture, slot ) { - } while ( key !== undefined ); + const textureProperties = properties.get( texture ); - } else { + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - // otherwise push as-is + uploadCubeTexture( textureProperties, texture, slot ); + return; - do { + } - value = key[ valuePropertyName ]; + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - if ( value !== undefined ) { + } - times.push( key.time ); - values.push( value ); + const wrappingToGL = { + [ RepeatWrapping ]: _gl.REPEAT, + [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, + [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT + }; - } + const filterToGL = { + [ NearestFilter ]: _gl.NEAREST, + [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, + [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, - key = jsonKeys[ i ++ ]; + [ LinearFilter ]: _gl.LINEAR, + [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, + [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR + }; - } while ( key !== undefined ); + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL + }; - } + function setTextureParameters( textureType, texture ) { - } + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false && + ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || + texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) { -}; + console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); -/** - * - * A timed sequence of keyframes for a specific property. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + } -function KeyframeTrack( name, times, values, interpolation ) { + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); - if ( name === undefined ) { throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); } - if ( times === undefined || times.length === 0 ) { throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); } + if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { - this.name = name; + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); - this.times = AnimationUtils.convertArray( times, this.TimeBufferType ); - this.values = AnimationUtils.convertArray( values, this.ValueBufferType ); + } - this.setInterpolation( interpolation || this.DefaultInterpolation ); + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] ); - this.validate(); - this.optimize(); + if ( texture.compareFunction ) { -} + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); -// Static methods: + } -Object.assign( KeyframeTrack, { + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { - // Serialization (in static context, because of constructor invocation - // and automatic invocation of .toJSON): + if ( texture.magFilter === NearestFilter ) return; + if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension - parse: function ( json ) { + if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { - if ( json.type === undefined ) { + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); + properties.get( texture ).__currentAnisotropy = texture.anisotropy; - throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); + } } - var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type ); + } + + function initTexture( textureProperties, texture ) { - if ( json.times === undefined ) { + let forceUpload = false; - var times = [], values = []; + if ( textureProperties.__webglInit === undefined ) { - AnimationUtils.flattenJSON( json.keys, times, values, 'value' ); + textureProperties.__webglInit = true; - json.times = times; - json.values = values; + texture.addEventListener( 'dispose', onTextureDispose ); } - // derived classes can define a static parse method - if ( trackType.parse !== undefined ) { + // create Source <-> WebGLTextures mapping if necessary - return trackType.parse( json ); + const source = texture.source; + let webglTextures = _sources.get( source ); - } else { + if ( webglTextures === undefined ) { - // by default, we assume a constructor compatible with the base - return new trackType( json.name, json.times, json.values, json.interpolation ); + webglTextures = {}; + _sources.set( source, webglTextures ); } - }, + // check if there is already a WebGLTexture object for the given texture parameters - toJSON: function ( track ) { + const textureCacheKey = getTextureCacheKey( texture ); - var trackType = track.constructor; + if ( textureCacheKey !== textureProperties.__cacheKey ) { - var json; + // if not, create a new instance of WebGLTexture - // derived classes can define a static toJSON method - if ( trackType.toJSON !== undefined ) { + if ( webglTextures[ textureCacheKey ] === undefined ) { - json = trackType.toJSON( track ); + // create new entry - } else { + webglTextures[ textureCacheKey ] = { + texture: _gl.createTexture(), + usedTimes: 0 + }; - // by default, we assume the data can be serialized as-is - json = { + info.memory.textures ++; - 'name': track.name, - 'times': AnimationUtils.convertArray( track.times, Array ), - 'values': AnimationUtils.convertArray( track.values, Array ) + // when a new instance of WebGLTexture was created, a texture upload is required + // even if the image contents are identical - }; + forceUpload = true; - var interpolation = track.getInterpolation(); + } - if ( interpolation !== track.DefaultInterpolation ) { + webglTextures[ textureCacheKey ].usedTimes ++; - json.interpolation = interpolation; + // every time the texture cache key changes, it's necessary to check if an instance of + // WebGLTexture can be deleted in order to avoid a memory leak. - } + const webglTexture = webglTextures[ textureProperties.__cacheKey ]; - } + if ( webglTexture !== undefined ) { - json.type = track.ValueTypeName; // mandatory + webglTextures[ textureProperties.__cacheKey ].usedTimes --; - return json; + if ( webglTexture.usedTimes === 0 ) { - }, + deleteTexture( texture ); - _getTrackTypeForValueTypeName: function ( typeName ) { + } - switch ( typeName.toLowerCase() ) { + } - case 'scalar': - case 'double': - case 'float': - case 'number': - case 'integer': + // store references to cache key and WebGLTexture object - return NumberKeyframeTrack; + textureProperties.__cacheKey = textureCacheKey; + textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; - case 'vector': - case 'vector2': - case 'vector3': - case 'vector4': + } - return VectorKeyframeTrack; + return forceUpload; - case 'color': + } - return ColorKeyframeTrack; + function uploadTexture( textureProperties, texture, slot ) { - case 'quaternion': + let textureType = _gl.TEXTURE_2D; - return QuaternionKeyframeTrack; + if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; + if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; - case 'bool': - case 'boolean': + const forceUpload = initTexture( textureProperties, texture ); + const source = texture.source; - return BooleanKeyframeTrack; + state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - case 'string': + const sourceProperties = properties.get( source ); - return StringKeyframeTrack; + if ( source.version !== sourceProperties.__version || forceUpload === true ) { - } + state.activeTexture( _gl.TEXTURE0 + slot ); - throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); + const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - } + _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, unpackConversion ); -} ); + let image = resizeImage( texture.image, false, capabilities.maxTextureSize ); + image = verifyColorSpace( texture, image ); -Object.assign( KeyframeTrack.prototype, { + const glFormat = utils.convert( texture.format, texture.colorSpace ); - constructor: KeyframeTrack, + const glType = utils.convert( texture.type ); + let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); - TimeBufferType: Float32Array, + setTextureParameters( textureType, texture ); - ValueBufferType: Float32Array, + let mipmap; + const mipmaps = texture.mipmaps; - DefaultInterpolation: InterpolateLinear, + const useTexStorage = ( texture.isVideoTexture !== true ); + const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); + const dataReady = source.dataReady; + const levels = getMipLevels( texture, image ); - InterpolantFactoryMethodDiscrete: function ( result ) { + if ( texture.isDepthTexture ) { - return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); + glInternalFormat = getInternalDepthFormat( texture.format === DepthStencilFormat, texture.type ); - }, + // - InterpolantFactoryMethodLinear: function ( result ) { + if ( allocateMemory ) { - return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); + if ( useTexStorage ) { - }, + state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); - InterpolantFactoryMethodSmooth: function ( result ) { + } else { - return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); - }, + } - setInterpolation: function ( interpolation ) { + } - var factoryMethod; + } else if ( texture.isDataTexture ) { - switch ( interpolation ) { + // use manually created mipmaps if available + // if there are no manual mipmaps + // set 0 level mipmap and then use GL to generate other mipmap levels - case InterpolateDiscrete: + if ( mipmaps.length > 0 ) { - factoryMethod = this.InterpolantFactoryMethodDiscrete; + if ( useTexStorage && allocateMemory ) { - break; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); - case InterpolateLinear: + } - factoryMethod = this.InterpolantFactoryMethodLinear; + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - break; + mipmap = mipmaps[ i ]; - case InterpolateSmooth: + if ( useTexStorage ) { - factoryMethod = this.InterpolantFactoryMethodSmooth; + if ( dataReady ) { - break; + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - } + } - if ( factoryMethod === undefined ) { + } else { - var message = "unsupported interpolation for " + - this.ValueTypeName + " keyframe track named " + this.name; + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - if ( this.createInterpolant === undefined ) { + } - // fall back to default, unless the default itself is messed up - if ( interpolation !== this.DefaultInterpolation ) { + } - this.setInterpolation( this.DefaultInterpolation ); + texture.generateMipmaps = false; } else { - throw new Error( message ); // fatal, in this case + if ( useTexStorage ) { - } + if ( allocateMemory ) { - } + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); - console.warn( 'THREE.KeyframeTrack:', message ); - return; + } - } + if ( dataReady ) { - this.createInterpolant = factoryMethod; + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); - }, + } - getInterpolation: function () { + } else { - switch ( this.createInterpolant ) { + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); - case this.InterpolantFactoryMethodDiscrete: + } - return InterpolateDiscrete; + } - case this.InterpolantFactoryMethodLinear: + } else if ( texture.isCompressedTexture ) { - return InterpolateLinear; + if ( texture.isCompressedArrayTexture ) { - case this.InterpolantFactoryMethodSmooth: + if ( useTexStorage && allocateMemory ) { - return InterpolateSmooth; + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); - } + } - }, + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - getValueSize: function () { + mipmap = mipmaps[ i ]; - return this.values.length / this.times.length; + if ( texture.format !== RGBAFormat ) { - }, + if ( glFormat !== null ) { - // move all keyframes either forwards or backwards in time - shift: function ( timeOffset ) { + if ( useTexStorage ) { - if ( timeOffset !== 0.0 ) { + if ( dataReady ) { - var times = this.times; + if ( texture.layerUpdates.size > 0 ) { - for ( var i = 0, n = times.length; i !== n; ++ i ) { + const layerByteLength = getByteLength( mipmap.width, mipmap.height, texture.format, texture.type ); - times[ i ] += timeOffset; + for ( const layerIndex of texture.layerUpdates ) { - } + const layerData = mipmap.data.subarray( + layerIndex * layerByteLength / mipmap.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / mipmap.data.BYTES_PER_ELEMENT + ); + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, layerData, 0, 0 ); - } + } - return this; + texture.clearLayerUpdates(); - }, + } else { - // scale all keyframe times by a factor (useful for frame <-> seconds conversions) - scale: function ( timeScale ) { + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); - if ( timeScale !== 1.0 ) { + } - var times = this.times; + } - for ( var i = 0, n = times.length; i !== n; ++ i ) { + } else { - times[ i ] *= timeScale; + state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); - } + } - } + } else { - return this; + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - }, + } - // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. - // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values - trim: function ( startTime, endTime ) { + } else { - var times = this.times, - nKeys = times.length, - from = 0, - to = nKeys - 1; + if ( useTexStorage ) { - while ( from !== nKeys && times[ from ] < startTime ) { + if ( dataReady ) { - ++ from; + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); - } + } - while ( to !== - 1 && times[ to ] > endTime ) { + } else { - -- to; + state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); - } + } - ++ to; // inclusive -> exclusive bound + } - if ( from !== 0 || to !== nKeys ) { + } - // empty tracks are forbidden, so keep at least one keyframe - if ( from >= to ) { to = Math.max( to, 1 ), from = to - 1; } + } else { - var stride = this.getValueSize(); - this.times = AnimationUtils.arraySlice( times, from, to ); - this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride ); + if ( useTexStorage && allocateMemory ) { - } + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); - return this; + } - }, + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable - validate: function () { + mipmap = mipmaps[ i ]; - var valid = true; + if ( texture.format !== RGBAFormat ) { - var valueSize = this.getValueSize(); - if ( valueSize - Math.floor( valueSize ) !== 0 ) { + if ( glFormat !== null ) { - console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); - valid = false; + if ( useTexStorage ) { - } + if ( dataReady ) { - var times = this.times, - values = this.values, + state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); - nKeys = times.length; + } - if ( nKeys === 0 ) { + } else { - console.error( 'THREE.KeyframeTrack: Track is empty.', this ); - valid = false; + state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - } + } - var prevTime = null; + } else { - for ( var i = 0; i !== nKeys; i ++ ) { + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - var currTime = times[ i ]; + } - if ( typeof currTime === 'number' && isNaN( currTime ) ) { + } else { - console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); - valid = false; - break; + if ( useTexStorage ) { - } + if ( dataReady ) { - if ( prevTime !== null && prevTime > currTime ) { + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); - valid = false; - break; + } - } + } else { - prevTime = currTime; + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - } + } - if ( values !== undefined ) { + } + + } - if ( AnimationUtils.isTypedArray( values ) ) { + } - for ( var i = 0, n = values.length; i !== n; ++ i ) { + } else if ( texture.isDataArrayTexture ) { - var value = values[ i ]; + if ( useTexStorage ) { - if ( isNaN( value ) ) { + if ( allocateMemory ) { - console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); - valid = false; - break; + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); } - } - - } + if ( dataReady ) { - } + if ( texture.layerUpdates.size > 0 ) { - return valid; + const layerByteLength = getByteLength( image.width, image.height, texture.format, texture.type ); - }, + for ( const layerIndex of texture.layerUpdates ) { - // removes equivalent sequential keys as common in morph target sequences - // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) - optimize: function () { + const layerData = image.data.subarray( + layerIndex * layerByteLength / image.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / image.data.BYTES_PER_ELEMENT + ); + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, layerData ); - var times = this.times, - values = this.values, - stride = this.getValueSize(), + } - smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + texture.clearLayerUpdates(); - writeIndex = 1, - lastIndex = times.length - 1; + } else { - for ( var i = 1; i < lastIndex; ++ i ) { + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); - var keep = false; + } - var time = times[ i ]; - var timeNext = times[ i + 1 ]; + } - // remove adjacent keyframes scheduled at the same time + } else { - if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) { + state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); - if ( ! smoothInterpolation ) { + } - // remove unnecessary keyframes same as their neighbors + } else if ( texture.isData3DTexture ) { - var offset = i * stride, - offsetP = offset - stride, - offsetN = offset + stride; + if ( useTexStorage ) { - for ( var j = 0; j !== stride; ++ j ) { + if ( allocateMemory ) { - var value = values[ offset + j ]; + state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); - if ( value !== values[ offsetP + j ] || - value !== values[ offsetN + j ] ) { + } - keep = true; - break; + if ( dataReady ) { - } + state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); } } else { - keep = true; + state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); } - } - - // in-place compaction + } else if ( texture.isFramebufferTexture ) { - if ( keep ) { + if ( allocateMemory ) { - if ( i !== writeIndex ) { + if ( useTexStorage ) { - times[ writeIndex ] = times[ i ]; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); - var readOffset = i * stride, - writeOffset = writeIndex * stride; + } else { - for ( var j = 0; j !== stride; ++ j ) { + let width = image.width, height = image.height; - values[ writeOffset + j ] = values[ readOffset + j ]; + for ( let i = 0; i < levels; i ++ ) { - } + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); - } + width >>= 1; + height >>= 1; - ++ writeIndex; + } - } + } - } + } - // flush last keyframe (compaction looks ahead) + } else { - if ( lastIndex > 0 ) { + // regular Texture (image, video, canvas) - times[ writeIndex ] = times[ lastIndex ]; + // use manually created mipmaps if available + // if there are no manual mipmaps + // set 0 level mipmap and then use GL to generate other mipmap levels - for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { + if ( mipmaps.length > 0 ) { - values[ writeOffset + j ] = values[ readOffset + j ]; + if ( useTexStorage && allocateMemory ) { - } + const dimensions = getDimensions( mipmaps[ 0 ] ); - ++ writeIndex; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); - } + } - if ( writeIndex !== times.length ) { + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - this.times = AnimationUtils.arraySlice( times, 0, writeIndex ); - this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride ); + mipmap = mipmaps[ i ]; - } + if ( useTexStorage ) { - return this; + if ( dataReady ) { - } + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); -} ); + } -/** - * - * A Track of vectored keyframe values. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + } else { -function VectorKeyframeTrack( name, times, values, interpolation ) { + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); - KeyframeTrack.call( this, name, times, values, interpolation ); + } -} + } -VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + texture.generateMipmaps = false; - constructor: VectorKeyframeTrack, + } else { - ValueTypeName: 'vector' + if ( useTexStorage ) { - // ValueBufferType is inherited + if ( allocateMemory ) { - // DefaultInterpolation is inherited + const dimensions = getDimensions( image ); -} ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); -/** - * - * Reusable set of Tracks that represent an animation. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ + } -function AnimationClip( name, duration, tracks ) { + if ( dataReady ) { - this.name = name; - this.tracks = tracks; - this.duration = ( duration !== undefined ) ? duration : - 1; + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); - this.uuid = _Math.generateUUID(); + } - // this means it should figure out its duration by scanning the tracks - if ( this.duration < 0 ) { + } else { - this.resetDuration(); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); - } + } - this.optimize(); + } -} + } -Object.assign( AnimationClip, { + if ( textureNeedsGenerateMipmaps( texture ) ) { - parse: function ( json ) { + generateMipmap( textureType ); - var tracks = [], - jsonTracks = json.tracks, - frameTime = 1.0 / ( json.fps || 1.0 ); + } - for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) { + sourceProperties.__version = source.version; - tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) ); + if ( texture.onUpdate ) texture.onUpdate( texture ); } - return new AnimationClip( json.name, json.duration, tracks ); - - }, + textureProperties.__version = texture.version; - toJSON: function ( clip ) { + } - var tracks = [], - clipTracks = clip.tracks; + function uploadCubeTexture( textureProperties, texture, slot ) { - var json = { + if ( texture.image.length !== 6 ) return; - 'name': clip.name, - 'duration': clip.duration, - 'tracks': tracks + const forceUpload = initTexture( textureProperties, texture ); + const source = texture.source; - }; + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) { + const sourceProperties = properties.get( source ); - tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); + if ( source.version !== sourceProperties.__version || forceUpload === true ) { - } + state.activeTexture( _gl.TEXTURE0 + slot ); - return json; + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); + const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - }, + _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, unpackConversion ); - CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) { + const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); + const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); - var numMorphTargets = morphTargetSequence.length; - var tracks = []; + const cubeImage = []; - for ( var i = 0; i < numMorphTargets; i ++ ) { + for ( let i = 0; i < 6; i ++ ) { - var times = []; - var values = []; + if ( ! isCompressed && ! isDataTexture ) { - times.push( - ( i + numMorphTargets - 1 ) % numMorphTargets, - i, - ( i + 1 ) % numMorphTargets ); + cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize ); - values.push( 0, 1, 0 ); + } else { - var order = AnimationUtils.getKeyframeOrder( times ); - times = AnimationUtils.sortedArray( times, 1, order ); - values = AnimationUtils.sortedArray( values, 1, order ); + cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; - // if there is a key at the first frame, duplicate it as the - // last frame as well for perfect loop. - if ( ! noLoop && times[ 0 ] === 0 ) { + } - times.push( numMorphTargets ); - values.push( values[ 0 ] ); + cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); } - tracks.push( - new NumberKeyframeTrack( - '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', - times, values - ).scale( 1.0 / fps ) ); + const image = cubeImage[ 0 ], + glFormat = utils.convert( texture.format, texture.colorSpace ), + glType = utils.convert( texture.type ), + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); - } + const useTexStorage = ( texture.isVideoTexture !== true ); + const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); + const dataReady = source.dataReady; + let levels = getMipLevels( texture, image ); - return new AnimationClip( name, - 1, tracks ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); - }, + let mipmaps; - findByName: function ( objectOrClipArray, name ) { + if ( isCompressed ) { - var clipArray = objectOrClipArray; + if ( useTexStorage && allocateMemory ) { - if ( ! Array.isArray( objectOrClipArray ) ) { + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); - var o = objectOrClipArray; - clipArray = o.geometry && o.geometry.animations || o.animations; + } - } + for ( let i = 0; i < 6; i ++ ) { - for ( var i = 0; i < clipArray.length; i ++ ) { + mipmaps = cubeImage[ i ].mipmaps; - if ( clipArray[ i ].name === name ) { + for ( let j = 0; j < mipmaps.length; j ++ ) { - return clipArray[ i ]; + const mipmap = mipmaps[ j ]; - } + if ( texture.format !== RGBAFormat ) { - } + if ( glFormat !== null ) { - return null; + if ( useTexStorage ) { - }, + if ( dataReady ) { - CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) { + state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); - var animationToMorphTargets = {}; + } - // tested with https://regex101.com/ on trick sequences - // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 - var pattern = /^([\w-]*?)([\d]+)$/; + } else { - // sort morph target names into animation groups based - // patterns like Walk_001, Walk_002, Run_001, Run_002 - for ( var i = 0, il = morphTargets.length; i < il; i ++ ) { + state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - var morphTarget = morphTargets[ i ]; - var parts = morphTarget.name.match( pattern ); + } - if ( parts && parts.length > 1 ) { + } else { - var name = parts[ 1 ]; + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); - var animationMorphTargets = animationToMorphTargets[ name ]; - if ( ! animationMorphTargets ) { + } - animationToMorphTargets[ name ] = animationMorphTargets = []; + } else { - } + if ( useTexStorage ) { - animationMorphTargets.push( morphTarget ); + if ( dataReady ) { - } + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - } + } - var clips = []; + } else { - for ( var name in animationToMorphTargets ) { + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); + } - } + } - return clips; + } - }, + } - // parse the animation.hierarchy format - parseAnimation: function ( animation, bones ) { + } else { - if ( ! animation ) { + mipmaps = texture.mipmaps; - console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); - return null; + if ( useTexStorage && allocateMemory ) { - } + // TODO: Uniformly handle mipmap definitions + // Normal textures and compressed cube textures define base level + mips with their mipmap array + // Uncompressed cube textures use their mipmap array only for mips (no base level) - var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { + if ( mipmaps.length > 0 ) levels ++; - // only return track if there are actually keys. - if ( animationKeys.length !== 0 ) { + const dimensions = getDimensions( cubeImage[ 0 ] ); - var times = []; - var values = []; + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height ); - AnimationUtils.flattenJSON( animationKeys, times, values, propertyName ); + } - // empty keys are filtered out, so check again - if ( times.length !== 0 ) { + for ( let i = 0; i < 6; i ++ ) { - destTracks.push( new trackType( trackName, times, values ) ); + if ( isDataTexture ) { - } + if ( useTexStorage ) { - } + if ( dataReady ) { - }; + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); - var tracks = []; + } - var clipName = animation.name || 'default'; - // automatic length determination in AnimationClip. - var duration = animation.length || - 1; - var fps = animation.fps || 30; + } else { - var hierarchyTracks = animation.hierarchy || []; + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); - for ( var h = 0; h < hierarchyTracks.length; h ++ ) { + } - var animationKeys = hierarchyTracks[ h ].keys; + for ( let j = 0; j < mipmaps.length; j ++ ) { - // skip empty tracks - if ( ! animationKeys || animationKeys.length === 0 ) { continue; } + const mipmap = mipmaps[ j ]; + const mipmapImage = mipmap.image[ i ].image; - // process morph targets - if ( animationKeys[ 0 ].morphTargets ) { + if ( useTexStorage ) { - // figure out all morph targets used in this track - var morphTargetNames = {}; + if ( dataReady ) { - for ( var k = 0; k < animationKeys.length; k ++ ) { + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); - if ( animationKeys[ k ].morphTargets ) { + } - for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { + } else { - morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); + + } } - } + } else { - } + if ( useTexStorage ) { - // create a track for each morph target with all zero - // morphTargetInfluences except for the keys in which - // the morphTarget is named. - for ( var morphTargetName in morphTargetNames ) { + if ( dataReady ) { - var times = []; - var values = []; + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); - for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { + } - var animationKey = animationKeys[ k ]; + } else { - times.push( animationKey.time ); - values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); - } + } - tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); + for ( let j = 0; j < mipmaps.length; j ++ ) { - } + const mipmap = mipmaps[ j ]; - duration = morphTargetNames.length * ( fps || 1.0 ); + if ( useTexStorage ) { - } else { + if ( dataReady ) { - // ...assume skeletal animation + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); - var boneName = '.bones[' + bones[ h ].name + ']'; + } - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.position', - animationKeys, 'pos', tracks ); + } else { - addNonemptyTrack( - QuaternionKeyframeTrack, boneName + '.quaternion', - animationKeys, 'rot', tracks ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.scale', - animationKeys, 'scl', tracks ); + } - } + } - } + } - if ( tracks.length === 0 ) { + } - return null; + } - } + if ( textureNeedsGenerateMipmaps( texture ) ) { - var clip = new AnimationClip( clipName, duration, tracks ); + // We assume images for cube map have the same size. + generateMipmap( _gl.TEXTURE_CUBE_MAP ); - return clip; + } - } + sourceProperties.__version = source.version; -} ); + if ( texture.onUpdate ) texture.onUpdate( texture ); -Object.assign( AnimationClip.prototype, { + } + + textureProperties.__version = texture.version; - resetDuration: function () { + } - var tracks = this.tracks, duration = 0; + // Render targets - for ( var i = 0, n = tracks.length; i !== n; ++ i ) { + // Setup storage for target texture and bind it to correct framebuffer + function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) { - var track = this.tracks[ i ]; + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const renderTargetProperties = properties.get( renderTarget ); - duration = Math.max( duration, track.times[ track.times.length - 1 ] ); + if ( ! renderTargetProperties.__hasExternalTextures ) { - } + const width = Math.max( 1, renderTarget.width >> level ); + const height = Math.max( 1, renderTarget.height >> level ); - this.duration = duration; + if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { - }, + state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null ); - trim: function () { + } else { - for ( var i = 0; i < this.tracks.length; i ++ ) { + state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null ); - this.tracks[ i ].trim( 0, this.duration ); + } } - return this; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - }, + if ( useMultisampledRTT( renderTarget ) ) { - optimize: function () { + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); - for ( var i = 0; i < this.tracks.length; i ++ ) { + } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 - this.tracks[ i ].optimize(); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); } - return this; + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ + // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { -function MaterialLoader( manager ) { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.textures = {}; + if ( renderTarget.depthBuffer ) { -} + // retrieve the depth attachment types + const depthTexture = renderTarget.depthTexture; + const depthType = depthTexture && depthTexture.isDepthTexture ? depthTexture.type : null; + const glInternalFormat = getInternalDepthFormat( renderTarget.stencilBuffer, depthType ); + const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; -Object.assign( MaterialLoader.prototype, { + // set up the attachment + const samples = getRenderTargetSamples( renderTarget ); + const isUseMultisampledRTT = useMultisampledRTT( renderTarget ); + if ( isUseMultisampledRTT ) { - load: function ( url, onLoad, onProgress, onError ) { + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - var scope = this; + } else if ( isMultisample ) { - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - onLoad( scope.parse( JSON.parse( text ) ) ); + } else { - }, onProgress, onError ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); - }, + } - setTextures: function ( value ) { + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer ); - this.textures = value; + } else { - }, + const textures = renderTarget.textures; - parse: function ( json ) { + for ( let i = 0; i < textures.length; i ++ ) { - var textures = this.textures; + const texture = textures[ i ]; - function getTexture( name ) { + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const samples = getRenderTargetSamples( renderTarget ); - if ( textures[ name ] === undefined ) { + if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { - console.warn( 'THREE.MaterialLoader: Undefined texture', name ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - } + } else if ( useMultisampledRTT( renderTarget ) ) { - return textures[ name ]; + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - } + } else { - var material = new Materials[ json.type ](); + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); - if ( json.uuid !== undefined ) { material.uuid = json.uuid; } - if ( json.name !== undefined ) { material.name = json.name; } - if ( json.color !== undefined ) { material.color.setHex( json.color ); } - if ( json.roughness !== undefined ) { material.roughness = json.roughness; } - if ( json.metalness !== undefined ) { material.metalness = json.metalness; } - if ( json.emissive !== undefined ) { material.emissive.setHex( json.emissive ); } - if ( json.specular !== undefined ) { material.specular.setHex( json.specular ); } - if ( json.shininess !== undefined ) { material.shininess = json.shininess; } - if ( json.clearCoat !== undefined ) { material.clearCoat = json.clearCoat; } - if ( json.clearCoatRoughness !== undefined ) { material.clearCoatRoughness = json.clearCoatRoughness; } - if ( json.uniforms !== undefined ) { material.uniforms = json.uniforms; } - if ( json.vertexShader !== undefined ) { material.vertexShader = json.vertexShader; } - if ( json.fragmentShader !== undefined ) { material.fragmentShader = json.fragmentShader; } - if ( json.vertexColors !== undefined ) { material.vertexColors = json.vertexColors; } - if ( json.fog !== undefined ) { material.fog = json.fog; } - if ( json.flatShading !== undefined ) { material.flatShading = json.flatShading; } - if ( json.blending !== undefined ) { material.blending = json.blending; } - if ( json.side !== undefined ) { material.side = json.side; } - if ( json.opacity !== undefined ) { material.opacity = json.opacity; } - if ( json.transparent !== undefined ) { material.transparent = json.transparent; } - if ( json.alphaTest !== undefined ) { material.alphaTest = json.alphaTest; } - if ( json.depthTest !== undefined ) { material.depthTest = json.depthTest; } - if ( json.depthWrite !== undefined ) { material.depthWrite = json.depthWrite; } - if ( json.colorWrite !== undefined ) { material.colorWrite = json.colorWrite; } - if ( json.wireframe !== undefined ) { material.wireframe = json.wireframe; } - if ( json.wireframeLinewidth !== undefined ) { material.wireframeLinewidth = json.wireframeLinewidth; } - if ( json.wireframeLinecap !== undefined ) { material.wireframeLinecap = json.wireframeLinecap; } - if ( json.wireframeLinejoin !== undefined ) { material.wireframeLinejoin = json.wireframeLinejoin; } + } - if ( json.rotation !== undefined ) { material.rotation = json.rotation; } + } - if ( json.linewidth !== 1 ) { material.linewidth = json.linewidth; } - if ( json.dashSize !== undefined ) { material.dashSize = json.dashSize; } - if ( json.gapSize !== undefined ) { material.gapSize = json.gapSize; } - if ( json.scale !== undefined ) { material.scale = json.scale; } + } - if ( json.skinning !== undefined ) { material.skinning = json.skinning; } - if ( json.morphTargets !== undefined ) { material.morphTargets = json.morphTargets; } - if ( json.dithering !== undefined ) { material.dithering = json.dithering; } + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - if ( json.visible !== undefined ) { material.visible = json.visible; } - if ( json.userData !== undefined ) { material.userData = json.userData; } + } - // Deprecated + // Setup resources for a Depth Texture for a FBO (needs an extension) + function setupDepthTexture( framebuffer, renderTarget ) { - if ( json.shading !== undefined ) { material.flatShading = json.shading === 1; } // THREE.FlatShading + const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); + if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); - // for PointsMaterial + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( json.size !== undefined ) { material.size = json.size; } - if ( json.sizeAttenuation !== undefined ) { material.sizeAttenuation = json.sizeAttenuation; } + if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { - // maps + throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); - if ( json.map !== undefined ) { material.map = getTexture( json.map ); } + } - if ( json.alphaMap !== undefined ) { + // upload an empty depth texture with framebuffer size + if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || + renderTarget.depthTexture.image.width !== renderTarget.width || + renderTarget.depthTexture.image.height !== renderTarget.height ) { - material.alphaMap = getTexture( json.alphaMap ); - material.transparent = true; + renderTarget.depthTexture.image.width = renderTarget.width; + renderTarget.depthTexture.image.height = renderTarget.height; + renderTarget.depthTexture.needsUpdate = true; } - if ( json.bumpMap !== undefined ) { material.bumpMap = getTexture( json.bumpMap ); } - if ( json.bumpScale !== undefined ) { material.bumpScale = json.bumpScale; } - - if ( json.normalMap !== undefined ) { material.normalMap = getTexture( json.normalMap ); } - if ( json.normalScale !== undefined ) { - - var normalScale = json.normalScale; + setTexture2D( renderTarget.depthTexture, 0 ); - if ( Array.isArray( normalScale ) === false ) { + const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + const samples = getRenderTargetSamples( renderTarget ); - // Blender exporter used to export a scalar. See #7459 + if ( renderTarget.depthTexture.format === DepthFormat ) { - normalScale = [ normalScale, normalScale ]; + if ( useMultisampledRTT( renderTarget ) ) { - } + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); - material.normalScale = new Vector2().fromArray( normalScale ); + } else { - } + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - if ( json.displacementMap !== undefined ) { material.displacementMap = getTexture( json.displacementMap ); } - if ( json.displacementScale !== undefined ) { material.displacementScale = json.displacementScale; } - if ( json.displacementBias !== undefined ) { material.displacementBias = json.displacementBias; } + } - if ( json.roughnessMap !== undefined ) { material.roughnessMap = getTexture( json.roughnessMap ); } - if ( json.metalnessMap !== undefined ) { material.metalnessMap = getTexture( json.metalnessMap ); } + } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { - if ( json.emissiveMap !== undefined ) { material.emissiveMap = getTexture( json.emissiveMap ); } - if ( json.emissiveIntensity !== undefined ) { material.emissiveIntensity = json.emissiveIntensity; } + if ( useMultisampledRTT( renderTarget ) ) { - if ( json.specularMap !== undefined ) { material.specularMap = getTexture( json.specularMap ); } + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); - if ( json.envMap !== undefined ) { material.envMap = getTexture( json.envMap ); } + } else { - if ( json.reflectivity !== undefined ) { material.reflectivity = json.reflectivity; } + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - if ( json.lightMap !== undefined ) { material.lightMap = getTexture( json.lightMap ); } - if ( json.lightMapIntensity !== undefined ) { material.lightMapIntensity = json.lightMapIntensity; } + } - if ( json.aoMap !== undefined ) { material.aoMap = getTexture( json.aoMap ); } - if ( json.aoMapIntensity !== undefined ) { material.aoMapIntensity = json.aoMapIntensity; } + } else { - if ( json.gradientMap !== undefined ) { material.gradientMap = getTexture( json.gradientMap ); } + throw new Error( 'Unknown depthTexture format' ); - return material; + } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ + // Setup GL resources for a non-texture depth buffer + function setupDepthRenderbuffer( renderTarget ) { -function BufferGeometryLoader( manager ) { + const renderTargetProperties = properties.get( renderTarget ); + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { -} + if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); -Object.assign( BufferGeometryLoader.prototype, { + setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); - load: function ( url, onLoad, onProgress, onError ) { + } else { - var scope = this; + if ( isCube ) { - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + renderTargetProperties.__webglDepthbuffer = []; - onLoad( scope.parse( JSON.parse( text ) ) ); + for ( let i = 0; i < 6; i ++ ) { - }, onProgress, onError ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); + renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); - }, + } - parse: function ( json ) { + } else { - var geometry = new BufferGeometry(); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); - var index = json.data.index; + } - if ( index !== undefined ) { + } - var typedArray = new TYPED_ARRAYS[ index.type ]( index.array ); - geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - } + } - var attributes = json.data.attributes; + // rebind framebuffer with external textures + function rebindTextures( renderTarget, colorTexture, depthTexture ) { - for ( var key in attributes ) { + const renderTargetProperties = properties.get( renderTarget ); - var attribute = attributes[ key ]; - var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); + if ( colorTexture !== undefined ) { - geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 ); } - var groups = json.data.groups || json.data.drawcalls || json.data.offsets; + if ( depthTexture !== undefined ) { - if ( groups !== undefined ) { + setupDepthRenderbuffer( renderTarget ); - for ( var i = 0, n = groups.length; i !== n; ++ i ) { + } - var group = groups[ i ]; + } - geometry.addGroup( group.start, group.count, group.materialIndex ); + // Set up GL resources for the render target + function setupRenderTarget( renderTarget ) { - } + const texture = renderTarget.texture; - } + const renderTargetProperties = properties.get( renderTarget ); + const textureProperties = properties.get( texture ); + + renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); - var boundingSphere = json.data.boundingSphere; + const textures = renderTarget.textures; - if ( boundingSphere !== undefined ) { + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); + const isMultipleRenderTargets = ( textures.length > 1 ); - var center = new Vector3(); + if ( ! isMultipleRenderTargets ) { - if ( boundingSphere.center !== undefined ) { + if ( textureProperties.__webglTexture === undefined ) { - center.fromArray( boundingSphere.center ); + textureProperties.__webglTexture = _gl.createTexture(); } - geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); + textureProperties.__version = texture.version; + info.memory.textures ++; } - return geometry; - - } - -} ); - -var TYPED_ARRAYS = { - Int8Array: Int8Array, - Uint8Array: Uint8Array, - // Workaround for IE11 pre KB2929437. See #11440 - Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, - Int16Array: Int16Array, - Uint16Array: Uint16Array, - Int32Array: Int32Array, - Uint32Array: Uint32Array, - Float32Array: Float32Array, - Float64Array: Float64Array -}; + // Setup framebuffer -/** - * @author alteredq / http://alteredqualia.com/ - */ + if ( isCube ) { -function Loader() { + renderTargetProperties.__webglFramebuffer = []; - this.onLoadStart = function () {}; - this.onLoadProgress = function () {}; - this.onLoadComplete = function () {}; + for ( let i = 0; i < 6; i ++ ) { -} + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { -Loader.Handlers = { + renderTargetProperties.__webglFramebuffer[ i ] = []; - handlers: [], + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - add: function ( regex, loader ) { + renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer(); - this.handlers.push( regex, loader ); + } - }, + } else { - get: function ( file ) { + renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); - var handlers = this.handlers; + } - for ( var i = 0, l = handlers.length; i < l; i += 2 ) { + } - var regex = handlers[ i ]; - var loader = handlers[ i + 1 ]; + } else { - if ( regex.test( file ) ) { + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - return loader; + renderTargetProperties.__webglFramebuffer = []; - } + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - } + renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer(); - return null; + } - } + } else { -}; + renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); -Object.assign( Loader.prototype, { + } - crossOrigin: undefined, + if ( isMultipleRenderTargets ) { - initMaterials: function ( materials, texturePath, crossOrigin ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - var array = []; + const attachmentProperties = properties.get( textures[ i ] ); - for ( var i = 0; i < materials.length; ++ i ) { + if ( attachmentProperties.__webglTexture === undefined ) { - array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin ); + attachmentProperties.__webglTexture = _gl.createTexture(); - } + info.memory.textures ++; - return array; + } - }, + } - createMaterial: ( function () { + } - var BlendingMode = { - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending - }; + if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { - var color = new Color(); - var textureLoader = new TextureLoader(); - var materialLoader = new MaterialLoader(); + renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); + renderTargetProperties.__webglColorRenderbuffer = []; - return function createMaterial( m, texturePath, crossOrigin ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); - // convert from old material format + for ( let i = 0; i < textures.length; i ++ ) { - var textures = {}; + const texture = textures[ i ]; + renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); - function loadTexture( path, repeat, offset, wrap, anisotropy ) { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - var fullPath = texturePath + path; - var loader = Loader.Handlers.get( fullPath ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); + const samples = getRenderTargetSamples( renderTarget ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - var texture; + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - if ( loader !== null ) { + } - texture = loader.load( fullPath ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - } else { + if ( renderTarget.depthBuffer ) { - textureLoader.setCrossOrigin( crossOrigin ); - texture = textureLoader.load( fullPath ); + renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); } - if ( repeat !== undefined ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - texture.repeat.fromArray( repeat ); + } - if ( repeat[ 0 ] !== 1 ) { texture.wrapS = RepeatWrapping; } - if ( repeat[ 1 ] !== 1 ) { texture.wrapT = RepeatWrapping; } + } - } + // Setup color buffer - if ( offset !== undefined ) { + if ( isCube ) { - texture.offset.fromArray( offset ); + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); - } + for ( let i = 0; i < 6; i ++ ) { - if ( wrap !== undefined ) { + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - if ( wrap[ 0 ] === 'repeat' ) { texture.wrapS = RepeatWrapping; } - if ( wrap[ 0 ] === 'mirror' ) { texture.wrapS = MirroredRepeatWrapping; } + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - if ( wrap[ 1 ] === 'repeat' ) { texture.wrapT = RepeatWrapping; } - if ( wrap[ 1 ] === 'mirror' ) { texture.wrapT = MirroredRepeatWrapping; } + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level ); - } + } - if ( anisotropy !== undefined ) { + } else { - texture.anisotropy = anisotropy; + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 ); } - var uuid = _Math.generateUUID(); + } - textures[ uuid ] = texture; + if ( textureNeedsGenerateMipmaps( texture ) ) { - return uuid; + generateMipmap( _gl.TEXTURE_CUBE_MAP ); } - // + state.unbindTexture(); - var json = { - uuid: _Math.generateUUID(), - type: 'MeshLambertMaterial' - }; + } else if ( isMultipleRenderTargets ) { - for ( var name in m ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - var value = m[ name ]; + const attachment = textures[ i ]; + const attachmentProperties = properties.get( attachment ); - switch ( name ) { + state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_2D, attachment ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 ); - case 'DbgColor': - case 'DbgIndex': - case 'opticalDensity': - case 'illumination': - break; - case 'DbgName': - json.name = value; - break; - case 'blending': - json.blending = BlendingMode[ value ]; - break; - case 'colorAmbient': - case 'mapAmbient': - console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' ); - break; - case 'colorDiffuse': - json.color = color.fromArray( value ).getHex(); - break; - case 'colorSpecular': - json.specular = color.fromArray( value ).getHex(); - break; - case 'colorEmissive': - json.emissive = color.fromArray( value ).getHex(); - break; - case 'specularCoef': - json.shininess = value; - break; - case 'shading': - if ( value.toLowerCase() === 'basic' ) { json.type = 'MeshBasicMaterial'; } - if ( value.toLowerCase() === 'phong' ) { json.type = 'MeshPhongMaterial'; } - if ( value.toLowerCase() === 'standard' ) { json.type = 'MeshStandardMaterial'; } - break; - case 'mapDiffuse': - json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy ); - break; - case 'mapDiffuseRepeat': - case 'mapDiffuseOffset': - case 'mapDiffuseWrap': - case 'mapDiffuseAnisotropy': - break; - case 'mapEmissive': - json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy ); - break; - case 'mapEmissiveRepeat': - case 'mapEmissiveOffset': - case 'mapEmissiveWrap': - case 'mapEmissiveAnisotropy': - break; - case 'mapLight': - json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy ); - break; - case 'mapLightRepeat': - case 'mapLightOffset': - case 'mapLightWrap': - case 'mapLightAnisotropy': - break; - case 'mapAO': - json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy ); - break; - case 'mapAORepeat': - case 'mapAOOffset': - case 'mapAOWrap': - case 'mapAOAnisotropy': - break; - case 'mapBump': - json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy ); - break; - case 'mapBumpScale': - json.bumpScale = value; - break; - case 'mapBumpRepeat': - case 'mapBumpOffset': - case 'mapBumpWrap': - case 'mapBumpAnisotropy': - break; - case 'mapNormal': - json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy ); - break; - case 'mapNormalFactor': - json.normalScale = [ value, value ]; - break; - case 'mapNormalRepeat': - case 'mapNormalOffset': - case 'mapNormalWrap': - case 'mapNormalAnisotropy': - break; - case 'mapSpecular': - json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy ); - break; - case 'mapSpecularRepeat': - case 'mapSpecularOffset': - case 'mapSpecularWrap': - case 'mapSpecularAnisotropy': - break; - case 'mapMetalness': - json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy ); - break; - case 'mapMetalnessRepeat': - case 'mapMetalnessOffset': - case 'mapMetalnessWrap': - case 'mapMetalnessAnisotropy': - break; - case 'mapRoughness': - json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy ); - break; - case 'mapRoughnessRepeat': - case 'mapRoughnessOffset': - case 'mapRoughnessWrap': - case 'mapRoughnessAnisotropy': - break; - case 'mapAlpha': - json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy ); - break; - case 'mapAlphaRepeat': - case 'mapAlphaOffset': - case 'mapAlphaWrap': - case 'mapAlphaAnisotropy': - break; - case 'flipSided': - json.side = BackSide; - break; - case 'doubleSided': - json.side = DoubleSide; - break; - case 'transparency': - console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' ); - json.opacity = value; - break; - case 'depthTest': - case 'depthWrite': - case 'colorWrite': - case 'opacity': - case 'reflectivity': - case 'transparent': - case 'visible': - case 'wireframe': - json[ name ] = value; - break; - case 'vertexColors': - if ( value === true ) { json.vertexColors = VertexColors; } - if ( value === 'face' ) { json.vertexColors = FaceColors; } - break; - default: - console.error( 'THREE.Loader.createMaterial: Unsupported', name, value ); - break; + if ( textureNeedsGenerateMipmaps( attachment ) ) { + + generateMipmap( _gl.TEXTURE_2D ); } } - if ( json.type === 'MeshBasicMaterial' ) { delete json.emissive; } - if ( json.type !== 'MeshPhongMaterial' ) { delete json.specular; } + state.unbindTexture(); - if ( json.opacity < 1 ) { json.transparent = true; } + } else { - materialLoader.setTextures( textures ); + let glTextureType = _gl.TEXTURE_2D; - return materialLoader.parse( json ); + if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { - }; + glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; - } )() + } -} ); + state.bindTexture( glTextureType, textureProperties.__webglTexture ); + setTextureParameters( glTextureType, texture ); -/** - * @author Don McCurdy / https://www.donmccurdy.com - */ + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { -var LoaderUtils = { + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - decodeText: function ( array ) { + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level ); - if ( typeof TextDecoder !== 'undefined' ) { + } - return new TextDecoder().decode( array ); + } else { - } + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 ); - // Avoid the String.fromCharCode.apply(null, array) shortcut, which - // throws a "maximum call stack size exceeded" error for large arrays. + } - var s = ''; + if ( textureNeedsGenerateMipmaps( texture ) ) { - for ( var i = 0, il = array.length; i < il; i ++ ) { + generateMipmap( glTextureType ); - // Implicitly assumes little-endian. - s += String.fromCharCode( array[ i ] ); + } + + state.unbindTexture(); } - return s; + // Setup depth and stencil buffers + + if ( renderTarget.depthBuffer ) { - }, + setupDepthRenderbuffer( renderTarget ); - extractUrlBase: function ( url ) { + } - var parts = url.split( '/' ); + } - if ( parts.length === 1 ) { return './'; } + function updateRenderTargetMipmap( renderTarget ) { - parts.pop(); + const textures = renderTarget.textures; - return parts.join( '/' ) + '/'; + for ( let i = 0, il = textures.length; i < il; i ++ ) { - } + const texture = textures[ i ]; -}; + if ( textureNeedsGenerateMipmaps( texture ) ) { -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; + const webglTexture = properties.get( texture ).__webglTexture; -function JSONLoader( manager ) { + state.bindTexture( target, webglTexture ); + generateMipmap( target ); + state.unbindTexture(); - if ( typeof manager === 'boolean' ) { + } - console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' ); - manager = undefined; + } } - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + const invalidationArrayRead = []; + const invalidationArrayDraw = []; - this.withCredentials = false; + function updateMultisampleRenderTarget( renderTarget ) { -} + if ( renderTarget.samples > 0 ) { -Object.assign( JSONLoader.prototype, { + if ( useMultisampledRTT( renderTarget ) === false ) { - load: function ( url, onLoad, onProgress, onError ) { + const textures = renderTarget.textures; + const width = renderTarget.width; + const height = renderTarget.height; + let mask = _gl.COLOR_BUFFER_BIT; + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + const renderTargetProperties = properties.get( renderTarget ); + const isMultipleRenderTargets = ( textures.length > 1 ); - var scope = this; + // If MRT we need to remove FBO attachments + if ( isMultipleRenderTargets ) { - var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url ); + for ( let i = 0; i < textures.length; i ++ ) { - var loader = new FileLoader( this.manager ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); - var json = JSON.parse( text ); - var metadata = json.metadata; + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); - if ( metadata !== undefined ) { + } - var type = metadata.type; + } - if ( type !== undefined ) { + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - if ( type.toLowerCase() === 'object' ) { + for ( let i = 0; i < textures.length; i ++ ) { - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); - return; + if ( renderTarget.resolveDepthBuffer ) { - } + if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; - if ( type.toLowerCase() === 'scene' ) { + // resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' ); - return; + if ( renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; } - } - - } - - var object = scope.parse( json, texturePath ); - onLoad( object.geometry, object.materials ); + if ( isMultipleRenderTargets ) { - }, onProgress, onError ); + _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - }, + const webglTexture = properties.get( textures[ i ] ).__webglTexture; + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); - setTexturePath: function ( value ) { + } - this.texturePath = value; + _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); - }, + if ( supportsInvalidateFramebuffer === true ) { - parse: ( function () { + invalidationArrayRead.length = 0; + invalidationArrayDraw.length = 0; - function parseModel( json, geometry ) { + invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i ); - function isBitSet( value, position ) { + if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false ) { - return value & ( 1 << position ); + invalidationArrayRead.push( depthStyle ); + invalidationArrayDraw.push( depthStyle ); - } + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw ); - var i, j, fi, + } - offset, zLength, + _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArrayRead ); - colorIndex, normalIndex, uvIndex, materialIndex, + } - type, - isQuad, - hasMaterial, - hasFaceVertexUv, - hasFaceNormal, hasFaceVertexNormal, - hasFaceColor, hasFaceVertexColor, + } - vertex, face, faceA, faceB, hex, normal, + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); - uvLayer, uv, u, v, + // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments + if ( isMultipleRenderTargets ) { - faces = json.faces, - vertices = json.vertices, - normals = json.normals, - colors = json.colors, + for ( let i = 0; i < textures.length; i ++ ) { - scale = json.scale, + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - nUvLayers = 0; + 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 ); - if ( json.uvs !== undefined ) { + } - // disregard empty arrays + } - for ( i = 0; i < json.uvs.length; i ++ ) { + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); - if ( json.uvs[ i ].length ) { nUvLayers ++; } + } else { - } + if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false && supportsInvalidateFramebuffer ) { - for ( i = 0; i < nUvLayers; i ++ ) { + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; - geometry.faceVertexUvs[ i ] = []; + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); } } - offset = 0; - zLength = vertices.length; - - while ( offset < zLength ) { + } - vertex = new Vector3(); + } - vertex.x = vertices[ offset ++ ] * scale; - vertex.y = vertices[ offset ++ ] * scale; - vertex.z = vertices[ offset ++ ] * scale; + function getRenderTargetSamples( renderTarget ) { - geometry.vertices.push( vertex ); + return Math.min( capabilities.maxSamples, renderTarget.samples ); - } + } - offset = 0; - zLength = faces.length; + function useMultisampledRTT( renderTarget ) { - while ( offset < zLength ) { + const renderTargetProperties = properties.get( renderTarget ); - type = faces[ offset ++ ]; + return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; - isQuad = isBitSet( type, 0 ); - hasMaterial = isBitSet( type, 1 ); - hasFaceVertexUv = isBitSet( type, 3 ); - hasFaceNormal = isBitSet( type, 4 ); - hasFaceVertexNormal = isBitSet( type, 5 ); - hasFaceColor = isBitSet( type, 6 ); - hasFaceVertexColor = isBitSet( type, 7 ); + } - // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); + function updateVideoTexture( texture ) { - if ( isQuad ) { + const frame = info.render.frame; - faceA = new Face3(); - faceA.a = faces[ offset ]; - faceA.b = faces[ offset + 1 ]; - faceA.c = faces[ offset + 3 ]; + // Check the last frame we updated the VideoTexture - faceB = new Face3(); - faceB.a = faces[ offset + 1 ]; - faceB.b = faces[ offset + 2 ]; - faceB.c = faces[ offset + 3 ]; + if ( _videoTextures.get( texture ) !== frame ) { - offset += 4; + _videoTextures.set( texture, frame ); + texture.update(); - if ( hasMaterial ) { + } - materialIndex = faces[ offset ++ ]; - faceA.materialIndex = materialIndex; - faceB.materialIndex = materialIndex; + } - } + function verifyColorSpace( texture, image ) { - // to get face <=> uv index correspondence + const colorSpace = texture.colorSpace; + const format = texture.format; + const type = texture.type; - fi = geometry.faces.length; + if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image; - if ( hasFaceVertexUv ) { + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { - for ( i = 0; i < nUvLayers; i ++ ) { + // sRGB - uvLayer = json.uvs[ i ]; + if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) { - geometry.faceVertexUvs[ i ][ fi ] = []; - geometry.faceVertexUvs[ i ][ fi + 1 ] = []; + // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format - for ( j = 0; j < 4; j ++ ) { + if ( format !== RGBAFormat || type !== UnsignedByteType ) { - uvIndex = faces[ offset ++ ]; + console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; + } - uv = new Vector2( u, v ); + } else { - if ( j !== 2 ) { geometry.faceVertexUvs[ i ][ fi ].push( uv ); } - if ( j !== 0 ) { geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv ); } + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); - } + } - } + } - } + return image; - if ( hasFaceNormal ) { + } - normalIndex = faces[ offset ++ ] * 3; + function getDimensions( image ) { - faceA.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) { - faceB.normal.copy( faceA.normal ); + // if intrinsic data are not available, fallback to width/height - } + _imageDimensions.width = image.naturalWidth || image.width; + _imageDimensions.height = image.naturalHeight || image.height; - if ( hasFaceVertexNormal ) { + } else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) { - for ( i = 0; i < 4; i ++ ) { + _imageDimensions.width = image.displayWidth; + _imageDimensions.height = image.displayHeight; - normalIndex = faces[ offset ++ ] * 3; + } else { - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + _imageDimensions.width = image.width; + _imageDimensions.height = image.height; + } - if ( i !== 2 ) { faceA.vertexNormals.push( normal ); } - if ( i !== 0 ) { faceB.vertexNormals.push( normal ); } + return _imageDimensions; - } + } - } + // + this.allocateTextureUnit = allocateTextureUnit; + this.resetTextureUnits = resetTextureUnits; - if ( hasFaceColor ) { + 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; - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; +} - faceA.color.setHex( hex ); - faceB.color.setHex( hex ); +function WebGLUtils( gl, extensions ) { - } + function convert( p, colorSpace = NoColorSpace ) { + let extension; - if ( hasFaceVertexColor ) { + const transfer = ColorManagement.getTransfer( colorSpace ); - for ( i = 0; i < 4; i ++ ) { + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; + if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV; - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; + if ( p === HalfFloatType ) return gl.HALF_FLOAT; - if ( i !== 2 ) { faceA.vertexColors.push( new Color( hex ) ); } - if ( i !== 0 ) { faceB.vertexColors.push( new Color( hex ) ); } + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBFormat ) return gl.RGB; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; - } + // WebGL2 formats. - } + if ( p === RedFormat ) return gl.RED; + if ( p === RedIntegerFormat ) return gl.RED_INTEGER; + if ( p === RGFormat ) return gl.RG; + if ( p === RGIntegerFormat ) return gl.RG_INTEGER; + if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; - geometry.faces.push( faceA ); - geometry.faces.push( faceB ); + // S3TC - } else { + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - face = new Face3(); - face.a = faces[ offset ++ ]; - face.b = faces[ offset ++ ]; - face.c = faces[ offset ++ ]; + if ( transfer === SRGBTransfer ) { - if ( hasMaterial ) { + extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); - materialIndex = faces[ offset ++ ]; - face.materialIndex = materialIndex; + 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; - // to get face <=> uv index correspondence + } else { - fi = geometry.faces.length; + return null; - if ( hasFaceVertexUv ) { + } - for ( i = 0; i < nUvLayers; i ++ ) { + } else { - uvLayer = json.uvs[ i ]; + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); - geometry.faceVertexUvs[ i ][ fi ] = []; + if ( extension !== null ) { - for ( j = 0; j < 3; j ++ ) { + 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; - uvIndex = faces[ offset ++ ]; + } else { - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; + return null; - uv = new Vector2( u, v ); + } - geometry.faceVertexUvs[ i ][ fi ].push( uv ); + } - } + } - } + // PVRTC - } + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { - if ( hasFaceNormal ) { + extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - normalIndex = faces[ offset ++ ] * 3; + if ( extension !== null ) { - face.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + 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 { - if ( hasFaceVertexNormal ) { + return null; - for ( i = 0; i < 3; i ++ ) { + } - normalIndex = faces[ offset ++ ] * 3; + } - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + // ETC - face.vertexNormals.push( normal ); + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { - } + extension = extensions.get( 'WEBGL_compressed_texture_etc' ); - } + if ( extension !== null ) { + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; - if ( hasFaceColor ) { + } else { - colorIndex = faces[ offset ++ ]; - face.color.setHex( colors[ colorIndex ] ); + return null; - } + } + } - if ( hasFaceVertexColor ) { + // ASTC - for ( i = 0; i < 3; i ++ ) { + 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 ) { - colorIndex = faces[ offset ++ ]; - face.vertexColors.push( new Color( colors[ colorIndex ] ) ); + extension = extensions.get( 'WEBGL_compressed_texture_astc' ); - } + if ( extension !== null ) { - } + if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; - geometry.faces.push( face ); + } else { - } + return null; } } - function parseSkin( json, geometry ) { + // BPTC - var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2; + if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) { - if ( json.skinWeights ) { + extension = extensions.get( 'EXT_texture_compression_bptc' ); - for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) { + if ( extension !== null ) { - var x = json.skinWeights[ i ]; - var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0; - var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0; - var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0; + if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT; + if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT; - geometry.skinWeights.push( new Vector4( x, y, z, w ) ); + } else { - } + return null; } - if ( json.skinIndices ) { - - for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) { + } - var a = json.skinIndices[ i ]; - var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0; - var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0; - var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0; + // RGTC - geometry.skinIndices.push( new Vector4( a, b, c, d ) ); + if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { - } + extension = extensions.get( 'EXT_texture_compression_rgtc' ); - } + if ( extension !== null ) { - geometry.bones = json.bones; + if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; + if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; + if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; + if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; - if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { + } else { - console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + - geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); + return null; } } - function parseMorphing( json, geometry ) { + // - var scale = json.scale; + if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8; - if ( json.morphTargets !== undefined ) { + // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) - for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) { + return ( gl[ p ] !== undefined ) ? gl[ p ] : null; - geometry.morphTargets[ i ] = {}; - geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; - geometry.morphTargets[ i ].vertices = []; + } - var dstVertices = geometry.morphTargets[ i ].vertices; - var srcVertices = json.morphTargets[ i ].vertices; + return { convert: convert }; - for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) { +} - var vertex = new Vector3(); - vertex.x = srcVertices[ v ] * scale; - vertex.y = srcVertices[ v + 1 ] * scale; - vertex.z = srcVertices[ v + 2 ] * scale; +class ArrayCamera extends PerspectiveCamera { - dstVertices.push( vertex ); + constructor( array = [] ) { - } + super(); - } + this.isArrayCamera = true; - } + this.cameras = array; - if ( json.morphColors !== undefined && json.morphColors.length > 0 ) { + } - console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' ); +} - var faces = geometry.faces; - var morphColors = json.morphColors[ 0 ].colors; +class Group extends Object3D { - for ( var i = 0, l = faces.length; i < l; i ++ ) { + constructor() { - faces[ i ].color.fromArray( morphColors, i * 3 ); + super(); - } + this.isGroup = true; - } + this.type = 'Group'; - } + } + +} + +const _moveEvent = { type: 'move' }; + +class WebXRController { + + constructor() { + + this._targetRay = null; + this._grip = null; + this._hand = null; + + } - function parseAnimations( json, geometry ) { + getHandSpace() { - var outputAnimations = []; + if ( this._hand === null ) { - // parse old style Bone/Hierarchy animations - var animations = []; + this._hand = new Group(); + this._hand.matrixAutoUpdate = false; + this._hand.visible = false; - if ( json.animation !== undefined ) { + this._hand.joints = {}; + this._hand.inputState = { pinching: false }; - animations.push( json.animation ); + } - } + return this._hand; - if ( json.animations !== undefined ) { + } - if ( json.animations.length ) { + getTargetRaySpace() { - animations = animations.concat( json.animations ); + if ( this._targetRay === null ) { - } else { + 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(); - animations.push( json.animations ); + } - } + return this._targetRay; - } + } - for ( var i = 0; i < animations.length; i ++ ) { + getGripSpace() { - var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones ); - if ( clip ) { outputAnimations.push( clip ); } + 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(); - // parse implicit morph animations - if ( geometry.morphTargets ) { + } - // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary. - var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 ); - outputAnimations = outputAnimations.concat( morphAnimationClips ); + return this._grip; - } + } - if ( outputAnimations.length > 0 ) { geometry.animations = outputAnimations; } + dispatchEvent( event ) { - } + if ( this._targetRay !== null ) { - return function ( json, texturePath ) { + this._targetRay.dispatchEvent( event ); - if ( json.data !== undefined ) { + } - // Geometry 4.0 spec - json = json.data; + if ( this._grip !== null ) { - } + this._grip.dispatchEvent( event ); - if ( json.scale !== undefined ) { + } - json.scale = 1.0 / json.scale; + if ( this._hand !== null ) { - } else { + this._hand.dispatchEvent( event ); - json.scale = 1.0; + } - } + return this; - var geometry = new Geometry(); + } - parseModel( json, geometry ); - parseSkin( json, geometry ); - parseMorphing( json, geometry ); - parseAnimations( json, geometry ); + connect( inputSource ) { - geometry.computeFaceNormals(); - geometry.computeBoundingSphere(); + if ( inputSource && inputSource.hand ) { - if ( json.materials === undefined || json.materials.length === 0 ) { + const hand = this._hand; - return { geometry: geometry }; + if ( hand ) { - } else { + for ( const inputjoint of inputSource.hand.values() ) { - var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin ); + // Initialize hand with joints when connected + this._getHandJoint( hand, inputjoint ); - return { geometry: geometry, materials: materials }; + } } - }; + } - } )() + this.dispatchEvent( { type: 'connected', data: inputSource } ); -} ); + return this; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function ObjectLoader( manager ) { + disconnect( inputSource ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.texturePath = ''; + this.dispatchEvent( { type: 'disconnected', data: inputSource } ); -} + if ( this._targetRay !== null ) { -Object.assign( ObjectLoader.prototype, { + this._targetRay.visible = false; - load: function ( url, onLoad, onProgress, onError ) { + } - if ( this.texturePath === '' ) { + if ( this._grip !== null ) { - this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); + this._grip.visible = false; } - var scope = this; + if ( this._hand !== null ) { - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + this._hand.visible = false; - var json = null; + } - try { + return this; - json = JSON.parse( text ); + } - } catch ( error ) { + update( inputSource, frame, referenceSpace ) { - if ( onError !== undefined ) { onError( error ); } + let inputPose = null; + let gripPose = null; + let handPose = null; - console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); + const targetRay = this._targetRay; + const grip = this._grip; + const hand = this._hand; - return; + if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { - } + if ( hand && inputSource.hand ) { - var metadata = json.metadata; + handPose = true; - if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + for ( const inputjoint of inputSource.hand.values() ) { - console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' ); - return; + // Update the joints groups with the XRJoint poses + const jointPose = frame.getJointPose( inputjoint, referenceSpace ); - } + // The transform of this joint will be updated with the joint pose on each frame + const joint = this._getHandJoint( hand, inputjoint ); - scope.parse( json, onLoad ); + if ( jointPose !== null ) { - }, onProgress, onError ); + joint.matrix.fromArray( jointPose.transform.matrix ); + joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; + joint.jointRadius = jointPose.radius; - }, + } - setTexturePath: function ( value ) { + joint.visible = jointPose !== null; - this.texturePath = value; + } - }, + // Custom events - setCrossOrigin: function ( value ) { + // Check pinchz + const indexTip = hand.joints[ 'index-finger-tip' ]; + const thumbTip = hand.joints[ 'thumb-tip' ]; + const distance = indexTip.position.distanceTo( thumbTip.position ); - this.crossOrigin = value; + const distanceToPinch = 0.02; + const threshold = 0.005; - }, + if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { - parse: function ( json, onLoad ) { + hand.inputState.pinching = false; + this.dispatchEvent( { + type: 'pinchend', + handedness: inputSource.handedness, + target: this + } ); - var shapes = this.parseShape( json.shapes ); - var geometries = this.parseGeometries( json.geometries, shapes ); + } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { - var images = this.parseImages( json.images, function () { + hand.inputState.pinching = true; + this.dispatchEvent( { + type: 'pinchstart', + handedness: inputSource.handedness, + target: this + } ); - if ( onLoad !== undefined ) { onLoad( object ); } + } - } ); + } else { - var textures = this.parseTextures( json.textures, images ); - var materials = this.parseMaterials( json.materials, textures ); + if ( grip !== null && inputSource.gripSpace ) { - var object = this.parseObject( json.object, geometries, materials ); + gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); - if ( json.animations ) { + if ( gripPose !== null ) { - object.animations = this.parseAnimations( json.animations ); + grip.matrix.fromArray( gripPose.transform.matrix ); + grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; - } + if ( gripPose.linearVelocity ) { - if ( json.images === undefined || json.images.length === 0 ) { + grip.hasLinearVelocity = true; + grip.linearVelocity.copy( gripPose.linearVelocity ); - if ( onLoad !== undefined ) { onLoad( object ); } + } else { - } + grip.hasLinearVelocity = false; - return object; + } - }, + if ( gripPose.angularVelocity ) { - parseShape: function ( json ) { + grip.hasAngularVelocity = true; + grip.angularVelocity.copy( gripPose.angularVelocity ); - var shapes = {}; + } else { - if ( json !== undefined ) { + grip.hasAngularVelocity = false; - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var shape = new Shape().fromJSON( json[ i ] ); + } - shapes[ shape.uuid ] = shape; + } } - } - - return shapes; - - }, - - parseGeometries: function ( json, shapes ) { + if ( targetRay !== null ) { - var geometries = {}; + inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); - if ( json !== undefined ) { + // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it + if ( inputPose === null && gripPose !== null ) { - var geometryLoader = new JSONLoader(); - var bufferGeometryLoader = new BufferGeometryLoader(); + inputPose = gripPose; - for ( var i = 0, l = json.length; i < l; i ++ ) { - - var geometry; - var data = json[ i ]; - - switch ( data.type ) { + } - case 'PlaneGeometry': - case 'PlaneBufferGeometry': + if ( inputPose !== null ) { - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.widthSegments, - data.heightSegments - ); + targetRay.matrix.fromArray( inputPose.transform.matrix ); + targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; - break; + if ( inputPose.linearVelocity ) { - case 'BoxGeometry': - case 'BoxBufferGeometry': - case 'CubeGeometry': // backwards compatible - - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.depth, - data.widthSegments, - data.heightSegments, - data.depthSegments - ); + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy( inputPose.linearVelocity ); - break; + } else { - case 'CircleGeometry': - case 'CircleBufferGeometry': + targetRay.hasLinearVelocity = false; - geometry = new Geometries[ data.type ]( - data.radius, - data.segments, - data.thetaStart, - data.thetaLength - ); + } - break; + if ( inputPose.angularVelocity ) { - case 'CylinderGeometry': - case 'CylinderBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radiusTop, - data.radiusBottom, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy( inputPose.angularVelocity ); - break; + } else { - case 'ConeGeometry': - case 'ConeBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); + targetRay.hasAngularVelocity = false; - break; + } - case 'SphereGeometry': - case 'SphereBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.widthSegments, - data.heightSegments, - data.phiStart, - data.phiLength, - data.thetaStart, - data.thetaLength - ); + this.dispatchEvent( _moveEvent ); - break; + } - case 'DodecahedronGeometry': - case 'DodecahedronBufferGeometry': - case 'IcosahedronGeometry': - case 'IcosahedronBufferGeometry': - case 'OctahedronGeometry': - case 'OctahedronBufferGeometry': - case 'TetrahedronGeometry': - case 'TetrahedronBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.detail - ); + } - break; - case 'RingGeometry': - case 'RingBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.innerRadius, - data.outerRadius, - data.thetaSegments, - data.phiSegments, - data.thetaStart, - data.thetaLength - ); + if ( targetRay !== null ) { - break; + targetRay.visible = ( inputPose !== null ); - case 'TorusGeometry': - case 'TorusBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.radialSegments, - data.tubularSegments, - data.arc - ); + if ( grip !== null ) { - break; + grip.visible = ( gripPose !== null ); - case 'TorusKnotGeometry': - case 'TorusKnotBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.tubularSegments, - data.radialSegments, - data.p, - data.q - ); + if ( hand !== null ) { - break; + hand.visible = ( handPose !== null ); - case 'LatheGeometry': - case 'LatheBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.points, - data.segments, - data.phiStart, - data.phiLength - ); + return this; - break; + } - case 'PolyhedronGeometry': - case 'PolyhedronBufferGeometry': + // private method - geometry = new Geometries[ data.type ]( - data.vertices, - data.indices, - data.radius, - data.details - ); + _getHandJoint( hand, inputjoint ) { - break; + if ( hand.joints[ inputjoint.jointName ] === undefined ) { - case 'ShapeGeometry': - case 'ShapeBufferGeometry': + const joint = new Group(); + joint.matrixAutoUpdate = false; + joint.visible = false; + hand.joints[ inputjoint.jointName ] = joint; - var geometryShapes = []; + hand.add( joint ); - for ( var i = 0, l = data.shapes.length; i < l; i ++ ) { + } - var shape = shapes[ data.shapes[ i ] ]; + return hand.joints[ inputjoint.jointName ]; - geometryShapes.push( shape ); + } - } +} - geometry = new Geometries[ data.type ]( - geometryShapes, - data.curveSegments - ); +const _occlusion_vertex = ` +void main() { - break; + gl_Position = vec4( position, 1.0 ); - case 'BufferGeometry': +}`; - geometry = bufferGeometryLoader.parse( data ); +const _occlusion_fragment = ` +uniform sampler2DArray depthColor; +uniform float depthWidth; +uniform float depthHeight; - break; +void main() { - case 'Geometry': + vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); - geometry = geometryLoader.parse( data, this.texturePath ).geometry; + if ( coord.x >= 1.0 ) { - break; + gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; - default: + } else { - console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' ); + gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; - continue; + } - } +}`; - geometry.uuid = data.uuid; +class WebXRDepthSensing { - if ( data.name !== undefined ) { geometry.name = data.name; } + constructor() { - geometries[ data.uuid ] = geometry; + this.texture = null; + this.mesh = null; - } + this.depthNear = 0; + this.depthFar = 0; - } + } - return geometries; + init( renderer, depthData, renderState ) { - }, + if ( this.texture === null ) { - parseMaterials: function ( json, textures ) { + const texture = new Texture(); - var materials = {}; + const texProps = renderer.properties.get( texture ); + texProps.__webglTexture = depthData.texture; - if ( json !== undefined ) { + if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) { - var loader = new MaterialLoader(); - loader.setTextures( textures ); + this.depthNear = depthData.depthNear; + this.depthFar = depthData.depthFar; - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var data = json[ i ]; + this.texture = texture; - if ( data.type === 'MultiMaterial' ) { + } - // Deprecated + } - var array = []; + getMesh( cameraXR ) { - for ( var j = 0; j < data.materials.length; j ++ ) { + if ( this.texture !== null ) { - array.push( loader.parse( data.materials[ j ] ) ); + if ( this.mesh === null ) { + const viewport = cameraXR.cameras[ 0 ].viewport; + const material = new ShaderMaterial( { + vertexShader: _occlusion_vertex, + fragmentShader: _occlusion_fragment, + uniforms: { + depthColor: { value: this.texture }, + depthWidth: { value: viewport.z }, + depthHeight: { value: viewport.w } } + } ); - materials[ data.uuid ] = array; + this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material ); - } else { + } - materials[ data.uuid ] = loader.parse( data ); + } - } + return this.mesh; - } + } - } + reset() { - return materials; + this.texture = null; + this.mesh = null; - }, + } - parseAnimations: function ( json ) { + getDepthTexture() { - var animations = []; + return this.texture; - for ( var i = 0; i < json.length; i ++ ) { + } - var clip = AnimationClip.parse( json[ i ] ); +} - animations.push( clip ); +class WebXRManager extends EventDispatcher { - } + constructor( renderer, gl ) { - return animations; + super(); - }, + const scope = this; - parseImages: function ( json, onLoad ) { + let session = null; - var scope = this; - var images = {}; + let framebufferScaleFactor = 1.0; - function loadImage( url ) { + let referenceSpace = null; + let referenceSpaceType = 'local-floor'; + // Set default foveation to maximum. + let foveation = 1.0; + let customReferenceSpace = null; - scope.manager.itemStart( url ); + let pose = null; + let glBinding = null; + let glProjLayer = null; + let glBaseLayer = null; + let xrFrame = null; - return loader.load( url, function () { + const depthSensing = new WebXRDepthSensing(); + const attributes = gl.getContextAttributes(); - scope.manager.itemEnd( url ); + let initialRenderTarget = null; + let newRenderTarget = null; - }, undefined, function () { + const controllers = []; + const controllerInputSources = []; - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + const currentSize = new Vector2(); + let currentPixelRatio = null; - } ); + // - } + const cameraL = new PerspectiveCamera(); + cameraL.layers.enable( 1 ); + cameraL.viewport = new Vector4(); - if ( json !== undefined && json.length > 0 ) { + const cameraR = new PerspectiveCamera(); + cameraR.layers.enable( 2 ); + cameraR.viewport = new Vector4(); - var manager = new LoadingManager( onLoad ); + const cameras = [ cameraL, cameraR ]; - var loader = new ImageLoader( manager ); - loader.setCrossOrigin( this.crossOrigin ); + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); - for ( var i = 0, l = json.length; i < l; i ++ ) { + let _currentDepthNear = null; + let _currentDepthFar = null; - var image = json[ i ]; - var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; + // - images[ image.uuid ] = loadImage( path ); + this.cameraAutoUpdate = true; + this.enabled = false; - } + this.isPresenting = false; - } + this.getController = function ( index ) { - return images; + let controller = controllers[ index ]; - }, + if ( controller === undefined ) { - parseTextures: function ( json, images ) { + controller = new WebXRController(); + controllers[ index ] = controller; - function parseConstant( value, type ) { + } - if ( typeof value === 'number' ) { return value; } + return controller.getTargetRaySpace(); - console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); + }; - return type[ value ]; + this.getControllerGrip = function ( index ) { - } + let controller = controllers[ index ]; - var textures = {}; + if ( controller === undefined ) { - if ( json !== undefined ) { + controller = new WebXRController(); + controllers[ index ] = controller; - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var data = json[ i ]; + return controller.getGripSpace(); - if ( data.image === undefined ) { + }; - console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); + this.getHand = function ( index ) { - } + let controller = controllers[ index ]; - if ( images[ data.image ] === undefined ) { + if ( controller === undefined ) { - console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); + controller = new WebXRController(); + controllers[ index ] = controller; - } + } - var texture = new Texture( images[ data.image ] ); - texture.needsUpdate = true; + return controller.getHandSpace(); - texture.uuid = data.uuid; + }; - if ( data.name !== undefined ) { texture.name = data.name; } + // - if ( data.mapping !== undefined ) { texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); } + function onSessionEvent( event ) { - if ( data.offset !== undefined ) { texture.offset.fromArray( data.offset ); } - if ( data.repeat !== undefined ) { texture.repeat.fromArray( data.repeat ); } - if ( data.center !== undefined ) { texture.center.fromArray( data.center ); } - if ( data.rotation !== undefined ) { texture.rotation = data.rotation; } + const controllerIndex = controllerInputSources.indexOf( event.inputSource ); - if ( data.wrap !== undefined ) { + if ( controllerIndex === - 1 ) { - texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); - texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); + return; - } + } - if ( data.minFilter !== undefined ) { texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); } - if ( data.magFilter !== undefined ) { texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); } - if ( data.anisotropy !== undefined ) { texture.anisotropy = data.anisotropy; } + const controller = controllers[ controllerIndex ]; - if ( data.flipY !== undefined ) { texture.flipY = data.flipY; } + if ( controller !== undefined ) { - textures[ data.uuid ] = texture; + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); + controller.dispatchEvent( { type: event.type, data: event.inputSource } ); } } - return textures; + 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 ); - parseObject: function () { + for ( let i = 0; i < controllers.length; i ++ ) { - var matrix = new Matrix4(); + const inputSource = controllerInputSources[ i ]; - return function parseObject( data, geometries, materials ) { + if ( inputSource === null ) continue; - var object; + controllerInputSources[ i ] = null; - function getGeometry( name ) { + controllers[ i ].disconnect( inputSource ); - if ( geometries[ name ] === undefined ) { + } - console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); + _currentDepthNear = null; + _currentDepthFar = null; - } + depthSensing.reset(); - return geometries[ name ]; + // restore framebuffer/rendering state - } + renderer.setRenderTarget( initialRenderTarget ); - function getMaterial( name ) { + glBaseLayer = null; + glProjLayer = null; + glBinding = null; + session = null; + newRenderTarget = null; - if ( name === undefined ) { return undefined; } + // - if ( Array.isArray( name ) ) { + animation.stop(); - var array = []; + scope.isPresenting = false; - for ( var i = 0, l = name.length; i < l; i ++ ) { + renderer.setPixelRatio( currentPixelRatio ); + renderer.setSize( currentSize.width, currentSize.height, false ); - var uuid = name[ i ]; + scope.dispatchEvent( { type: 'sessionend' } ); - if ( materials[ uuid ] === undefined ) { + } - console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); + this.setFramebufferScaleFactor = function ( value ) { - } + framebufferScaleFactor = value; - array.push( materials[ uuid ] ); + if ( scope.isPresenting === true ) { - } + console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); - return array; + } - } + }; - if ( materials[ name ] === undefined ) { + this.setReferenceSpaceType = function ( value ) { - console.warn( 'THREE.ObjectLoader: Undefined material', name ); + referenceSpaceType = value; - } + if ( scope.isPresenting === true ) { - return materials[ name ]; + console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); } - switch ( data.type ) { - - case 'Scene': + }; - object = new Scene(); + this.getReferenceSpace = function () { - if ( data.background !== undefined ) { + return customReferenceSpace || referenceSpace; - if ( Number.isInteger( data.background ) ) { + }; - object.background = new Color( data.background ); + this.setReferenceSpace = function ( space ) { - } + customReferenceSpace = space; - } + }; - if ( data.fog !== undefined ) { + this.getBaseLayer = function () { - if ( data.fog.type === 'Fog' ) { + return glProjLayer !== null ? glProjLayer : glBaseLayer; - object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); + }; - } else if ( data.fog.type === 'FogExp2' ) { + this.getBinding = function () { - object.fog = new FogExp2( data.fog.color, data.fog.density ); + return glBinding; - } + }; - } + this.getFrame = function () { - break; + return xrFrame; - case 'PerspectiveCamera': + }; - object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); + this.getSession = function () { - if ( data.focus !== undefined ) { object.focus = data.focus; } - if ( data.zoom !== undefined ) { object.zoom = data.zoom; } - if ( data.filmGauge !== undefined ) { object.filmGauge = data.filmGauge; } - if ( data.filmOffset !== undefined ) { object.filmOffset = data.filmOffset; } - if ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); } + return session; - break; + }; - case 'OrthographicCamera': + this.setSession = async function ( value ) { - object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); + session = value; - break; + if ( session !== null ) { - case 'AmbientLight': + initialRenderTarget = renderer.getRenderTarget(); - object = new AmbientLight( data.color, data.intensity ); + 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 ); - break; + if ( attributes.xrCompatible !== true ) { - case 'DirectionalLight': + await gl.makeXRCompatible(); - object = new DirectionalLight( data.color, data.intensity ); + } - break; + currentPixelRatio = renderer.getPixelRatio(); + renderer.getSize( currentSize ); - case 'PointLight': + if ( session.renderState.layers === undefined ) { - object = new PointLight( data.color, data.intensity, data.distance, data.decay ); + const layerInit = { + antialias: attributes.antialias, + alpha: true, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor: framebufferScaleFactor + }; - break; + glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); - case 'RectAreaLight': + session.updateRenderState( { baseLayer: glBaseLayer } ); - object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); + renderer.setPixelRatio( 1 ); + renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); - break; + newRenderTarget = new WebGLRenderTarget( + glBaseLayer.framebufferWidth, + glBaseLayer.framebufferHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + colorSpace: renderer.outputColorSpace, + stencilBuffer: attributes.stencil + } + ); - case 'SpotLight': + } else { - object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); + let depthFormat = null; + let depthType = null; + let glDepthFormat = null; - break; + if ( attributes.depth ) { - case 'HemisphereLight': + glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; + depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; + depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; - object = new HemisphereLight( data.color, data.groundColor, data.intensity ); + } - break; + const projectionlayerInit = { + colorFormat: gl.RGBA8, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; - case 'SkinnedMesh': + glBinding = new XRWebGLBinding( session, gl ); - console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' ); + glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); - case 'Mesh': + session.updateRenderState( { layers: [ glProjLayer ] } ); - var geometry = getGeometry( data.geometry ); - var material = getMaterial( data.material ); + renderer.setPixelRatio( 1 ); + renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false ); - if ( geometry.bones && geometry.bones.length > 0 ) { + newRenderTarget = new WebGLRenderTarget( + glProjLayer.textureWidth, + glProjLayer.textureHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), + stencilBuffer: attributes.stencil, + colorSpace: renderer.outputColorSpace, + samples: attributes.antialias ? 4 : 0, + resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false ) + } ); - object = new SkinnedMesh( geometry, material ); + } - } else { + newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 - object = new Mesh( geometry, material ); + this.setFoveation( foveation ); - } + customReferenceSpace = null; + referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); - break; + animation.setContext( session ); + animation.start(); - case 'LOD': + scope.isPresenting = true; - object = new LOD(); + scope.dispatchEvent( { type: 'sessionstart' } ); - break; + } - case 'Line': + }; - object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); + this.getEnvironmentBlendMode = function () { - break; + if ( session !== null ) { - case 'LineLoop': + return session.environmentBlendMode; - object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); + } - break; + }; - case 'LineSegments': + this.getDepthTexture = function () { - object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); + return depthSensing.getDepthTexture(); - break; + }; - case 'PointCloud': - case 'Points': + function onInputSourcesChange( event ) { - object = new Points$1( getGeometry( data.geometry ), getMaterial( data.material ) ); + // Notify disconnected - break; + for ( let i = 0; i < event.removed.length; i ++ ) { - case 'Sprite': + const inputSource = event.removed[ i ]; + const index = controllerInputSources.indexOf( inputSource ); - object = new Sprite( getMaterial( data.material ) ); + if ( index >= 0 ) { - break; + controllerInputSources[ index ] = null; + controllers[ index ].disconnect( inputSource ); - case 'Group': + } - object = new Group(); + } - break; + // Notify connected - default: + for ( let i = 0; i < event.added.length; i ++ ) { - object = new Object3D(); + const inputSource = event.added[ i ]; - } + let controllerIndex = controllerInputSources.indexOf( inputSource ); - object.uuid = data.uuid; + if ( controllerIndex === - 1 ) { - if ( data.name !== undefined ) { object.name = data.name; } - if ( data.matrix !== undefined ) { + // Assign input source a controller that currently has no input source - matrix.fromArray( data.matrix ); - matrix.decompose( object.position, object.quaternion, object.scale ); + for ( let i = 0; i < controllers.length; i ++ ) { - } else { + if ( i >= controllerInputSources.length ) { - if ( data.position !== undefined ) { object.position.fromArray( data.position ); } - if ( data.rotation !== undefined ) { object.rotation.fromArray( data.rotation ); } - if ( data.quaternion !== undefined ) { object.quaternion.fromArray( data.quaternion ); } - if ( data.scale !== undefined ) { object.scale.fromArray( data.scale ); } + controllerInputSources.push( inputSource ); + controllerIndex = i; + break; - } + } else if ( controllerInputSources[ i ] === null ) { - if ( data.castShadow !== undefined ) { object.castShadow = data.castShadow; } - if ( data.receiveShadow !== undefined ) { object.receiveShadow = data.receiveShadow; } + controllerInputSources[ i ] = inputSource; + controllerIndex = i; + break; - if ( data.shadow ) { + } - if ( data.shadow.bias !== undefined ) { object.shadow.bias = data.shadow.bias; } - if ( data.shadow.radius !== undefined ) { object.shadow.radius = data.shadow.radius; } - if ( data.shadow.mapSize !== undefined ) { object.shadow.mapSize.fromArray( data.shadow.mapSize ); } - if ( data.shadow.camera !== undefined ) { object.shadow.camera = this.parseObject( data.shadow.camera ); } + } - } + // If all controllers do currently receive input we ignore new ones - if ( data.visible !== undefined ) { object.visible = data.visible; } - if ( data.userData !== undefined ) { object.userData = data.userData; } + if ( controllerIndex === - 1 ) break; - if ( data.children !== undefined ) { + } - var children = data.children; + const controller = controllers[ controllerIndex ]; - for ( var i = 0; i < children.length; i ++ ) { + if ( controller ) { - object.add( this.parseObject( children[ i ], geometries, materials ) ); + controller.connect( inputSource ); } } - if ( data.type === 'LOD' ) { + } + + // - var levels = data.levels; + const cameraLPos = new Vector3(); + const cameraRPos = new Vector3(); - for ( var l = 0; l < levels.length; l ++ ) { + /** + * Assumes 2 cameras that are parallel and share an X-axis, and that + * the cameras' projection and world matrices have already been set. + * And that near and far planes are identical for both cameras. + * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 + */ + function setProjectionFromUnion( camera, cameraL, cameraR ) { - var level = levels[ l ]; - var child = object.getObjectByProperty( 'uuid', level.object ); + cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); + cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); - if ( child !== undefined ) { + const ipd = cameraLPos.distanceTo( cameraRPos ); - object.addLevel( child, level.distance ); + const projL = cameraL.projectionMatrix.elements; + const projR = cameraR.projectionMatrix.elements; - } + // VR systems will have identical far and near planes, and + // most likely identical top and bottom frustum extents. + // Use the left camera for these values. + 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; - } + // Calculate the new camera's position offset from the + // left camera. xOffset should be roughly half `ipd`. + const zOffset = ipd / ( - leftFov + rightFov ); + const xOffset = zOffset * - leftFov; - return object; + // TODO: Better way to apply this offset? + cameraL.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(); - }; + // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // although must now be relative to the new union camera. + 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 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); -} ); + } -var TEXTURE_MAPPING = { - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping -}; + function updateCamera( camera, parent ) { -var TEXTURE_WRAPPING = { - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping -}; + if ( parent === null ) { -var TEXTURE_FILTER = { - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter -}; + camera.matrixWorld.copy( camera.matrix ); -/** - * @author thespite / http://clicktorelease.com/ - */ + } else { + + camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); + + } -function ImageBitmapLoader( manager ) { + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); - if ( typeof createImageBitmap === 'undefined' ) { + } - console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); + this.updateCamera = function ( camera ) { - } + if ( session === null ) return; - if ( typeof fetch === 'undefined' ) { + if ( depthSensing.texture !== null ) { - console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); + camera.near = depthSensing.depthNear; + camera.far = depthSensing.depthFar; - } + } - this.manager = manager !== undefined ? manager : DefaultLoadingManager; - this.options = undefined; + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; -} + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { -ImageBitmapLoader.prototype = { + // Note that the new renderState won't apply until the next frame. See #18320 - constructor: ImageBitmapLoader, + session.updateRenderState( { + depthNear: cameraXR.near, + depthFar: cameraXR.far + } ); - setOptions: function setOptions( options ) { + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; - this.options = options; + cameraL.near = _currentDepthNear; + cameraL.far = _currentDepthFar; + cameraR.near = _currentDepthNear; + cameraR.far = _currentDepthFar; - return this; + cameraL.updateProjectionMatrix(); + cameraR.updateProjectionMatrix(); + camera.updateProjectionMatrix(); - }, + } - load: function load( url, onLoad, onProgress, onError ) { + const parent = camera.parent; + const cameras = cameraXR.cameras; - if ( url === undefined ) { url = ''; } + updateCamera( cameraXR, parent ); - if ( this.path !== undefined ) { url = this.path + url; } + for ( let i = 0; i < cameras.length; i ++ ) { - var scope = this; + updateCamera( cameras[ i ], parent ); - var cached = Cache.get( url ); + } - if ( cached !== undefined ) { + // update projection matrix for proper view frustum culling - scope.manager.itemStart( url ); + if ( cameras.length === 2 ) { - setTimeout( function () { + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - if ( onLoad ) { onLoad( cached ); } + } else { - scope.manager.itemEnd( url ); + // assume single camera setup (AR) - }, 0 ); + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); - return cached; + } - } + // update user camera and its children - fetch( url ).then( function ( res ) { + updateUserCamera( camera, cameraXR, parent ); - return res.blob(); + }; - } ).then( function ( blob ) { + function updateUserCamera( camera, cameraXR, parent ) { - return createImageBitmap( blob, scope.options ); + if ( parent === null ) { - } ).then( function ( imageBitmap ) { + camera.matrix.copy( cameraXR.matrixWorld ); - Cache.add( url, imageBitmap ); + } else { - if ( onLoad ) { onLoad( imageBitmap ); } + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); - scope.manager.itemEnd( url ); + } - } ).catch( function ( e ) { + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); - if ( onError ) { onError( e ); } + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + if ( camera.isPerspectiveCamera ) { - } ); + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - }, + } - setCrossOrigin: function ( /* value */ ) { + } - return this; + this.getCamera = function () { - }, + return cameraXR; - setPath: function ( value ) { + }; - this.path = value; - return this; + this.getFoveation = function () { - } + if ( glProjLayer === null && glBaseLayer === null ) { -}; + return undefined; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * minimal class for proxing functions to Path. Replaces old "extractSubpaths()" - **/ + } -function ShapePath() { + return foveation; - this.type = 'ShapePath'; + }; - this.subPaths = []; - this.currentPath = null; + this.setFoveation = function ( value ) { -} + // 0 = no foveation = full resolution + // 1 = maximum foveation = the edges render at lower resolution -Object.assign( ShapePath.prototype, { + foveation = value; - moveTo: function ( x, y ) { + if ( glProjLayer !== null ) { - this.currentPath = new Path$1(); - this.subPaths.push( this.currentPath ); - this.currentPath.moveTo( x, y ); + glProjLayer.fixedFoveation = value; - }, + } - lineTo: function ( x, y ) { + if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { - this.currentPath.lineTo( x, y ); + glBaseLayer.fixedFoveation = value; - }, + } - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { + }; - this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); + this.hasDepthSensing = function () { - }, + return depthSensing.texture !== null; - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + }; - this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); + this.getDepthSensingMesh = function () { - }, + return depthSensing.getMesh( cameraXR ); - splineThru: function ( pts ) { + }; - this.currentPath.splineThru( pts ); + // Animation Loop - }, + let onAnimationFrameCallback = null; - toShapes: function ( isCCW, noHoles ) { + function onAnimationFrame( time, frame ) { - function toShapesNoHoles( inSubpaths ) { + pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); + xrFrame = frame; - var shapes = []; + if ( pose !== null ) { - for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) { + const views = pose.views; - var tmpPath = inSubpaths[ i ]; + if ( glBaseLayer !== null ) { - var tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; + renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); + renderer.setRenderTarget( newRenderTarget ); - shapes.push( tmpShape ); + } - } + let cameraXRNeedsUpdate = false; - return shapes; + // check if it's necessary to rebuild cameraXR's camera list - } + if ( views.length !== cameraXR.cameras.length ) { - function isPointInsidePolygon( inPt, inPolygon ) { + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; - var polyLen = inPolygon.length; + } - // inPt on polygon contour => immediate success or - // toggling of inside/outside at every single! intersection point of an edge - // with the horizontal line through inPt, left of inPt - // not counting lowerY endpoints of edges and whole edges on that line - var inside = false; - for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { + for ( let i = 0; i < views.length; i ++ ) { - var edgeLowPt = inPolygon[ p ]; - var edgeHighPt = inPolygon[ q ]; + const view = views[ i ]; - var edgeDx = edgeHighPt.x - edgeLowPt.x; - var edgeDy = edgeHighPt.y - edgeLowPt.y; + let viewport = null; - if ( Math.abs( edgeDy ) > Number.EPSILON ) { + if ( glBaseLayer !== null ) { - // not parallel - if ( edgeDy < 0 ) { + viewport = glBaseLayer.getViewport( view ); - edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; - edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; + } else { - } - if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) { continue; } + const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); + viewport = glSubImage.viewport; - if ( inPt.y === edgeLowPt.y ) { + // For side-by-side projection, we only produce a single texture for both eyes. + if ( i === 0 ) { - if ( inPt.x === edgeLowPt.x ) { return true; } // inPt is on contour ? - // continue; // no intersection or edgeLowPt => doesn't count !!! + renderer.setRenderTargetTextures( + newRenderTarget, + glSubImage.colorTexture, + glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); - } else { + renderer.setRenderTarget( newRenderTarget ); - var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); - if ( perpEdge === 0 ) { return true; } // inPt is on contour ? - if ( perpEdge < 0 ) { continue; } - inside = ! inside; // true intersection left of inPt + } } - } else { - - // parallel or collinear - if ( inPt.y !== edgeLowPt.y ) { continue; } // parallel - // edge lies on the same horizontal line as inPt - if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || - ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) { return true; } // inPt: Point on contour ! - // continue; + let camera = cameras[ i ]; - } + if ( camera === undefined ) { - } + camera = new PerspectiveCamera(); + camera.layers.enable( i ); + camera.viewport = new Vector4(); + cameras[ i ] = camera; - return inside; + } - } + camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); + camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); - var isClockWise = ShapeUtils.isClockWise; + if ( i === 0 ) { - var subPaths = this.subPaths; - if ( subPaths.length === 0 ) { return []; } + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); - if ( noHoles === true ) { return toShapesNoHoles( subPaths ); } + } + if ( cameraXRNeedsUpdate === true ) { - var solid, tmpPath, tmpShape, shapes = []; + cameraXR.cameras.push( camera ); - if ( subPaths.length === 1 ) { + } - tmpPath = subPaths[ 0 ]; - tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; - shapes.push( tmpShape ); - return shapes; + } - } + // - var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); - holesFirst = isCCW ? ! holesFirst : holesFirst; + const enabledFeatures = session.enabledFeatures; - // console.log("Holes first", holesFirst); + if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { - var betterShapeHoles = []; - var newShapes = []; - var newShapeHoles = []; - var mainIdx = 0; - var tmpPoints; + const depthData = glBinding.getDepthInformation( views[ 0 ] ); - newShapes[ mainIdx ] = undefined; - newShapeHoles[ mainIdx ] = []; + if ( depthData && depthData.isValid && depthData.texture ) { - for ( var i = 0, l = subPaths.length; i < l; i ++ ) { + depthSensing.init( renderer, depthData, session.renderState ); - 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 ] = []; + for ( let i = 0; i < controllers.length; i ++ ) { - //console.log('cw', i); + const inputSource = controllerInputSources[ i ]; + const controller = controllers[ i ]; - } else { + if ( inputSource !== null && controller !== undefined ) { - newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); + controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); - //console.log('ccw', i); + } } - } - - // only Holes? -> probably all Shapes with wrong orientation - if ( ! newShapes[ 0 ] ) { return toShapesNoHoles( subPaths ); } + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); + if ( frame.detectedPlanes ) { - if ( newShapes.length > 1 ) { + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); - var ambiguous = false; - var toChange = []; - - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + } - betterShapeHoles[ sIdx ] = []; + xrFrame = null; - } + } - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + const animation = new WebGLAnimation(); - var sho = newShapeHoles[ sIdx ]; + animation.setAnimationLoop( onAnimationFrame ); - for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) { + this.setAnimationLoop = function ( callback ) { - var ho = sho[ hIdx ]; - var hole_unassigned = true; + onAnimationFrameCallback = callback; - for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { + }; - if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { + this.dispose = function () {}; - if ( sIdx !== s2Idx ) { toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); } - if ( hole_unassigned ) { + } - hole_unassigned = false; - betterShapeHoles[ s2Idx ].push( ho ); +} - } else { +const _e1 = /*@__PURE__*/ new Euler(); +const _m1 = /*@__PURE__*/ new Matrix4(); - ambiguous = true; +function WebGLMaterials( renderer, properties ) { - } + function refreshTransformUniform( map, uniform ) { - } + if ( map.matrixAutoUpdate === true ) { - } - if ( hole_unassigned ) { + map.updateMatrix(); - betterShapeHoles[ sIdx ].push( ho ); + } - } + uniform.value.copy( map.matrix ); - } + } - } - // console.log("ambiguous: ", ambiguous); - if ( toChange.length > 0 ) { + function refreshFogUniforms( uniforms, fog ) { - // console.log("to change: ", toChange); - if ( ! ambiguous ) { newShapeHoles = betterShapeHoles; } + fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); - } + if ( fog.isFog ) { - } + uniforms.fogNear.value = fog.near; + uniforms.fogFar.value = fog.far; - var tmpHoles; + } else if ( fog.isFogExp2 ) { - for ( var i = 0, il = newShapes.length; i < il; i ++ ) { + uniforms.fogDensity.value = fog.density; - tmpShape = newShapes[ i ].s; - shapes.push( tmpShape ); - tmpHoles = newShapeHoles[ i ]; + } - for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) { + } - tmpShape.holes.push( tmpHoles[ j ].h ); + function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { - } + if ( material.isMeshBasicMaterial ) { - } + refreshUniformsCommon( uniforms, material ); - //console.log("shape", shapes); + } else if ( material.isMeshLambertMaterial ) { - return shapes; + refreshUniformsCommon( uniforms, material ); - } + } else if ( material.isMeshToonMaterial ) { -} ); + refreshUniformsCommon( uniforms, material ); + refreshUniformsToon( uniforms, material ); -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author mrdoob / http://mrdoob.com/ - */ + } else if ( material.isMeshPhongMaterial ) { -function Font( data ) { + refreshUniformsCommon( uniforms, material ); + refreshUniformsPhong( uniforms, material ); - this.type = 'Font'; + } else if ( material.isMeshStandardMaterial ) { - this.data = data; + refreshUniformsCommon( uniforms, material ); + refreshUniformsStandard( uniforms, material ); -} + if ( material.isMeshPhysicalMaterial ) { -Object.assign( Font.prototype, { + refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); - isFont: true, + } - generateShapes: function ( text, size, divisions ) { + } else if ( material.isMeshMatcapMaterial ) { - function createPaths( text ) { + refreshUniformsCommon( uniforms, material ); + refreshUniformsMatcap( uniforms, material ); - var chars = String( text ).split( '' ); - var scale = size / data.resolution; - var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale; + } else if ( material.isMeshDepthMaterial ) { - var offsetX = 0, offsetY = 0; + refreshUniformsCommon( uniforms, material ); - var paths = []; + } else if ( material.isMeshDistanceMaterial ) { - for ( var i = 0; i < chars.length; i ++ ) { + refreshUniformsCommon( uniforms, material ); + refreshUniformsDistance( uniforms, material ); - var char = chars[ i ]; + } else if ( material.isMeshNormalMaterial ) { - if ( char === '\n' ) { + refreshUniformsCommon( uniforms, material ); - offsetX = 0; - offsetY -= line_height; + } else if ( material.isLineBasicMaterial ) { - } else { + refreshUniformsLine( uniforms, material ); - var ret = createPath( char, scale, offsetX, offsetY ); - offsetX += ret.offsetX; - paths.push( ret.path ); + if ( material.isLineDashedMaterial ) { - } + refreshUniformsDash( uniforms, material ); } - return paths; + } else if ( material.isPointsMaterial ) { - } + refreshUniformsPoints( uniforms, material, pixelRatio, height ); - function createPath( c, scale, offsetX, offsetY ) { + } else if ( material.isSpriteMaterial ) { - var glyph = data.glyphs[ c ] || data.glyphs[ '?' ]; + refreshUniformsSprites( uniforms, material ); - if ( ! glyph ) { return; } + } else if ( material.isShadowMaterial ) { - var path = new ShapePath(); + uniforms.color.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - var pts = []; - var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2, laste; + } else if ( material.isShaderMaterial ) { - if ( glyph.o ) { + material.uniformsNeedUpdate = false; // #15581 - var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); + } - for ( var i = 0, l = outline.length; i < l; ) { + } - var action = outline[ i ++ ]; + function refreshUniformsCommon( uniforms, material ) { - switch ( action ) { + uniforms.opacity.value = material.opacity; - case 'm': // moveTo + if ( material.color ) { - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; + uniforms.diffuse.value.copy( material.color ); - path.moveTo( x, y ); + } - break; + if ( material.emissive ) { - case 'l': // lineTo + uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; + } - path.lineTo( x, y ); + if ( material.map ) { - break; + uniforms.map.value = material.map; - case 'q': // quadraticCurveTo + refreshTransformUniform( material.map, uniforms.mapTransform ); - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; + } - path.quadraticCurveTo( cpx1, cpy1, cpx, cpy ); + if ( material.alphaMap ) { - laste = pts[ pts.length - 1 ]; + uniforms.alphaMap.value = material.alphaMap; - if ( laste ) { + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - laste.x; - laste.y; + } - + if ( material.bumpMap ) { - } + uniforms.bumpMap.value = material.bumpMap; - break; + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); - case 'b': // bezierCurveTo + uniforms.bumpScale.value = material.bumpScale; - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; - cpx2 = outline[ i ++ ] * scale + offsetX; - cpy2 = outline[ i ++ ] * scale + offsetY; + if ( material.side === BackSide ) { - path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy ); + uniforms.bumpScale.value *= - 1; - laste = pts[ pts.length - 1 ]; + } - if ( laste ) { + } - laste.x; - laste.y; + if ( material.normalMap ) { - + uniforms.normalMap.value = material.normalMap; - } + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); - break; + uniforms.normalScale.value.copy( material.normalScale ); - } + if ( material.side === BackSide ) { - } + uniforms.normalScale.value.negate(); } - return { offsetX: glyph.ha * scale, path: path }; - } - // + if ( material.displacementMap ) { - if ( size === undefined ) { size = 100; } + uniforms.displacementMap.value = material.displacementMap; - var data = this.data; + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); - var paths = createPaths( text ); - var shapes = []; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; - for ( var p = 0, pl = paths.length; p < pl; p ++ ) { + } - Array.prototype.push.apply( shapes, paths[ p ].toShapes() ); + if ( material.emissiveMap ) { - } + uniforms.emissiveMap.value = material.emissiveMap; - return shapes; + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); - } + } -} ); + if ( material.specularMap ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + uniforms.specularMap.value = material.specularMap; -function FontLoader( manager ) { + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + } -} + if ( material.alphaTest > 0 ) { -Object.assign( FontLoader.prototype, { + uniforms.alphaTest.value = material.alphaTest; - load: function ( url, onLoad, onProgress, onError ) { + } - var scope = this; + const materialProperties = properties.get( material ); - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { + const envMap = materialProperties.envMap; + const envMapRotation = materialProperties.envMapRotation; - var json; + if ( envMap ) { - try { + uniforms.envMap.value = envMap; - json = JSON.parse( text ); + _e1.copy( envMapRotation ); - } catch ( e ) { + // accommodate left-handed frame + _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1; + + if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) { - console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' ); - json = JSON.parse( text.substring( 65, text.length - 2 ) ); + // environment maps which are not cube render targets or PMREMs follow a different convention + _e1.y *= - 1; + _e1.z *= - 1; } - var font = scope.parse( json ); + uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) ); - if ( onLoad ) { onLoad( font ); } + uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - }, onProgress, onError ); + uniforms.reflectivity.value = material.reflectivity; + uniforms.ior.value = material.ior; + uniforms.refractionRatio.value = material.refractionRatio; - }, + } + + if ( material.lightMap ) { - parse: function ( json ) { + uniforms.lightMap.value = material.lightMap; + uniforms.lightMapIntensity.value = material.lightMapIntensity; - return new Font( json ); + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); - }, + } - setPath: function ( value ) { + if ( material.aoMap ) { - this.path = value; - return this; + uniforms.aoMap.value = material.aoMap; + uniforms.aoMapIntensity.value = material.aoMapIntensity; - } + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -var context; + function refreshUniformsLine( uniforms, material ) { -var AudioContext = { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - getContext: function () { + if ( material.map ) { - if ( context === undefined ) { + uniforms.map.value = material.map; - context = new ( window.AudioContext || window.webkitAudioContext )(); + refreshTransformUniform( material.map, uniforms.mapTransform ); } - return context; - - }, + } - setContext: function ( value ) { + function refreshUniformsDash( uniforms, material ) { - context = value; + uniforms.dashSize.value = material.dashSize; + uniforms.totalSize.value = material.dashSize + material.gapSize; + uniforms.scale.value = material.scale; } -}; + function refreshUniformsPoints( uniforms, material, pixelRatio, height ) { -/** - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; + uniforms.size.value = material.size * pixelRatio; + uniforms.scale.value = height * 0.5; -function AudioLoader( manager ) { + if ( material.map ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + uniforms.map.value = material.map; -} + refreshTransformUniform( material.map, uniforms.uvTransform ); -Object.assign( AudioLoader.prototype, { + } - load: function ( url, onLoad, onProgress, onError ) { + if ( material.alphaMap ) { - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - loader.load( url, function ( buffer ) { + uniforms.alphaMap.value = material.alphaMap; - var context = AudioContext.getContext(); + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - context.decodeAudioData( buffer, function ( audioBuffer ) { + } - onLoad( audioBuffer ); + if ( material.alphaTest > 0 ) { - } ); + uniforms.alphaTest.value = material.alphaTest; - }, onProgress, onError ); + } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function StereoCamera() { + function refreshUniformsSprites( uniforms, material ) { - this.type = 'StereoCamera'; + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; + uniforms.rotation.value = material.rotation; - this.aspect = 1; + if ( material.map ) { - this.eyeSep = 0.064; + uniforms.map.value = material.map; - this.cameraL = new PerspectiveCamera(); - this.cameraL.layers.enable( 1 ); - this.cameraL.matrixAutoUpdate = false; + refreshTransformUniform( material.map, uniforms.mapTransform ); - this.cameraR = new PerspectiveCamera(); - this.cameraR.layers.enable( 2 ); - this.cameraR.matrixAutoUpdate = false; + } -} + if ( material.alphaMap ) { -Object.assign( StereoCamera.prototype, { + uniforms.alphaMap.value = material.alphaMap; - update: ( function () { + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - var instance, focus, fov, aspect, near, far, zoom, eyeSep; + } - var eyeRight = new Matrix4(); - var eyeLeft = new Matrix4(); + if ( material.alphaTest > 0 ) { - return function update( camera ) { + uniforms.alphaTest.value = material.alphaTest; - var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov || - aspect !== camera.aspect * this.aspect || near !== camera.near || - far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep; + } - if ( needsUpdate ) { + } - instance = this; - focus = camera.focus; - fov = camera.fov; - aspect = camera.aspect * this.aspect; - near = camera.near; - far = camera.far; - zoom = camera.zoom; + function refreshUniformsPhong( uniforms, material ) { - // Off-axis stereoscopic effect based on - // http://paulbourke.net/stereographics/stereorender/ + uniforms.specular.value.copy( material.specular ); + uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) - var projectionMatrix = camera.projectionMatrix.clone(); - eyeSep = this.eyeSep / 2; - var eyeSepOnProjection = eyeSep * near / focus; - var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom; - var xmin, xmax; + } - // translate xOffset + function refreshUniformsToon( uniforms, material ) { - eyeLeft.elements[ 12 ] = - eyeSep; - eyeRight.elements[ 12 ] = eyeSep; + if ( material.gradientMap ) { - // for left eye + uniforms.gradientMap.value = material.gradientMap; - xmin = - ymax * aspect + eyeSepOnProjection; - xmax = ymax * aspect + eyeSepOnProjection; + } - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + } - this.cameraL.projectionMatrix.copy( projectionMatrix ); + function refreshUniformsStandard( uniforms, material ) { - // for right eye + uniforms.metalness.value = material.metalness; - xmin = - ymax * aspect - eyeSepOnProjection; - xmax = ymax * aspect - eyeSepOnProjection; + if ( material.metalnessMap ) { - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + uniforms.metalnessMap.value = material.metalnessMap; - this.cameraR.projectionMatrix.copy( projectionMatrix ); + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); - } + } - this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft ); - this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight ); + uniforms.roughness.value = material.roughness; - }; + if ( material.roughnessMap ) { - } )() + uniforms.roughnessMap.value = material.roughnessMap; -} ); + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); -/** - * Camera for rendering cube maps - * - renders scene into axis-aligned cube - * - * @author alteredq / http://alteredqualia.com/ - */ + } -function CubeCamera( near, far, cubeResolution ) { + if ( material.envMap ) { - Object3D.call( this ); + //uniforms.envMap.value = material.envMap; // part of uniforms common - this.type = 'CubeCamera'; + uniforms.envMapIntensity.value = material.envMapIntensity; - var fov = 90, aspect = 1; + } - var cameraPX = new PerspectiveCamera( fov, aspect, near, far ); - cameraPX.up.set( 0, - 1, 0 ); - cameraPX.lookAt( new Vector3( 1, 0, 0 ) ); - this.add( cameraPX ); + } - var cameraNX = new PerspectiveCamera( fov, aspect, near, far ); - cameraNX.up.set( 0, - 1, 0 ); - cameraNX.lookAt( new Vector3( - 1, 0, 0 ) ); - this.add( cameraNX ); + function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { - var cameraPY = new PerspectiveCamera( fov, aspect, near, far ); - cameraPY.up.set( 0, 0, 1 ); - cameraPY.lookAt( new Vector3( 0, 1, 0 ) ); - this.add( cameraPY ); + uniforms.ior.value = material.ior; // also part of uniforms common - var cameraNY = new PerspectiveCamera( fov, aspect, near, far ); - cameraNY.up.set( 0, 0, - 1 ); - cameraNY.lookAt( new Vector3( 0, - 1, 0 ) ); - this.add( cameraNY ); + if ( material.sheen > 0 ) { - var cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraPZ.up.set( 0, - 1, 0 ); - cameraPZ.lookAt( new Vector3( 0, 0, 1 ) ); - this.add( cameraPZ ); + uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); - var cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraNZ.up.set( 0, - 1, 0 ); - cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) ); - this.add( cameraNZ ); + uniforms.sheenRoughness.value = material.sheenRoughness; - var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter }; + if ( material.sheenColorMap ) { - this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options ); - this.renderTarget.texture.name = "CubeCamera"; + uniforms.sheenColorMap.value = material.sheenColorMap; - this.update = function ( renderer, scene ) { + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); - if ( this.parent === null ) { this.updateMatrixWorld(); } + } - var renderTarget = this.renderTarget; - var generateMipmaps = renderTarget.texture.generateMipmaps; + if ( material.sheenRoughnessMap ) { - renderTarget.texture.generateMipmaps = false; + uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; - renderTarget.activeCubeFace = 0; - renderer.render( scene, cameraPX, renderTarget ); + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); - renderTarget.activeCubeFace = 1; - renderer.render( scene, cameraNX, renderTarget ); + } - renderTarget.activeCubeFace = 2; - renderer.render( scene, cameraPY, renderTarget ); + } - renderTarget.activeCubeFace = 3; - renderer.render( scene, cameraNY, renderTarget ); + if ( material.clearcoat > 0 ) { - renderTarget.activeCubeFace = 4; - renderer.render( scene, cameraPZ, renderTarget ); + uniforms.clearcoat.value = material.clearcoat; + uniforms.clearcoatRoughness.value = material.clearcoatRoughness; - renderTarget.texture.generateMipmaps = generateMipmaps; + if ( material.clearcoatMap ) { - renderTarget.activeCubeFace = 5; - renderer.render( scene, cameraNZ, renderTarget ); + uniforms.clearcoatMap.value = material.clearcoatMap; - renderer.setRenderTarget( null ); + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); - }; + } - this.clear = function ( renderer, color, depth, stencil ) { + if ( material.clearcoatRoughnessMap ) { - var renderTarget = this.renderTarget; + uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; - for ( var i = 0; i < 6; i ++ ) { + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); - renderTarget.activeCubeFace = i; - renderer.setRenderTarget( renderTarget ); + } - renderer.clear( color, depth, stencil ); + if ( material.clearcoatNormalMap ) { - } + uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; - renderer.setRenderTarget( null ); + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); - }; + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); -} + if ( material.side === BackSide ) { -CubeCamera.prototype = Object.create( Object3D.prototype ); -CubeCamera.prototype.constructor = CubeCamera; + uniforms.clearcoatNormalScale.value.negate(); -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function AudioListener() { + } - Object3D.call( this ); + } - this.type = 'AudioListener'; + if ( material.dispersion > 0 ) { - this.context = AudioContext.getContext(); + uniforms.dispersion.value = material.dispersion; - this.gain = this.context.createGain(); - this.gain.connect( this.context.destination ); + } - this.filter = null; + 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 ]; -AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), { + if ( material.iridescenceMap ) { - constructor: AudioListener, + uniforms.iridescenceMap.value = material.iridescenceMap; - getInput: function () { + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); - return this.gain; + } - }, + if ( material.iridescenceThicknessMap ) { - removeFilter: function ( ) { + uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; - if ( this.filter !== null ) { + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); - this.gain.connect( this.context.destination ); - this.filter = null; + } } - }, + if ( material.transmission > 0 ) { - getFilter: function () { + uniforms.transmission.value = material.transmission; + uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; + uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); - return this.filter; + if ( material.transmissionMap ) { - }, + uniforms.transmissionMap.value = material.transmissionMap; - setFilter: function ( value ) { + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); - if ( this.filter !== null ) { + } - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); + uniforms.thickness.value = material.thickness; - } else { + if ( material.thicknessMap ) { - this.gain.disconnect( this.context.destination ); + uniforms.thicknessMap.value = material.thicknessMap; - } + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); - this.filter = value; - this.gain.connect( this.filter ); - this.filter.connect( this.context.destination ); + } - }, + uniforms.attenuationDistance.value = material.attenuationDistance; + uniforms.attenuationColor.value.copy( material.attenuationColor ); - getMasterVolume: function () { + } - return this.gain.gain.value; + if ( material.anisotropy > 0 ) { - }, + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - setMasterVolume: function ( value ) { + if ( material.anisotropyMap ) { - this.gain.gain.value = value; + uniforms.anisotropyMap.value = material.anisotropyMap; - }, + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); - updateMatrixWorld: ( function () { + } - var position = new Vector3(); - var quaternion = new Quaternion(); - var scale = new Vector3(); + } - var orientation = new Vector3(); + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); - return function updateMatrixWorld( force ) { + if ( material.specularColorMap ) { - Object3D.prototype.updateMatrixWorld.call( this, force ); + uniforms.specularColorMap.value = material.specularColorMap; - var listener = this.context.listener; - var up = this.up; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); - this.matrixWorld.decompose( position, quaternion, scale ); + } - orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion ); + if ( material.specularIntensityMap ) { - if ( listener.positionX ) { + uniforms.specularIntensityMap.value = material.specularIntensityMap; - listener.positionX.setValueAtTime( position.x, this.context.currentTime ); - listener.positionY.setValueAtTime( position.y, this.context.currentTime ); - listener.positionZ.setValueAtTime( position.z, this.context.currentTime ); - listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime ); - listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime ); - listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime ); - listener.upX.setValueAtTime( up.x, this.context.currentTime ); - listener.upY.setValueAtTime( up.y, this.context.currentTime ); - listener.upZ.setValueAtTime( up.z, this.context.currentTime ); + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); - } else { + } - listener.setPosition( position.x, position.y, position.z ); - listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z ); + } - } + function refreshUniformsMatcap( uniforms, material ) { - }; + if ( material.matcap ) { - } )() + uniforms.matcap.value = material.matcap; -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ + } -function Audio( listener ) { + function refreshUniformsDistance( uniforms, material ) { - Object3D.call( this ); + const light = properties.get( material ).light; - this.type = 'Audio'; + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; - this.context = listener.context; + } - this.gain = this.context.createGain(); - this.gain.connect( listener.getInput() ); + return { + refreshFogUniforms: refreshFogUniforms, + refreshMaterialUniforms: refreshMaterialUniforms + }; - this.autoplay = false; +} - this.buffer = null; - this.loop = false; - this.startTime = 0; - this.offset = 0; - this.playbackRate = 1; - this.isPlaying = false; - this.hasPlaybackControl = true; - this.sourceType = 'empty'; +function WebGLUniformsGroups( gl, info, capabilities, state ) { - this.filters = []; + let buffers = {}; + let updateList = {}; + let allocatedBindingPoints = []; -} + const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program -Audio.prototype = Object.assign( Object.create( Object3D.prototype ), { + function bind( uniformsGroup, program ) { - constructor: Audio, + const webglProgram = program.program; + state.uniformBlockBinding( uniformsGroup, webglProgram ); - getOutput: function () { + } - return this.gain; + function update( uniformsGroup, program ) { - }, + let buffer = buffers[ uniformsGroup.id ]; - setNodeSource: function ( audioNode ) { + if ( buffer === undefined ) { - this.hasPlaybackControl = false; - this.sourceType = 'audioNode'; - this.source = audioNode; - this.connect(); + prepareUniformsGroup( uniformsGroup ); - return this; + buffer = createBuffer( uniformsGroup ); + buffers[ uniformsGroup.id ] = buffer; - }, + uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); - setBuffer: function ( audioBuffer ) { + } - this.buffer = audioBuffer; - this.sourceType = 'buffer'; + // ensure to update the binding points/block indices mapping for this program - if ( this.autoplay ) { this.play(); } + const webglProgram = program.program; + state.updateUBOMapping( uniformsGroup, webglProgram ); - return this; + // update UBO once per frame - }, + const frame = info.render.frame; - play: function () { + if ( updateList[ uniformsGroup.id ] !== frame ) { - if ( this.isPlaying === true ) { + updateBufferData( uniformsGroup ); - console.warn( 'THREE.Audio: Audio is already playing.' ); - return; + updateList[ uniformsGroup.id ] = frame; } - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + function createBuffer( uniformsGroup ) { - } + // the setup of an UBO is independent of a particular shader program but global + + const bindingPointIndex = allocateBindingPointIndex(); + uniformsGroup.__bindingPointIndex = bindingPointIndex; - var source = this.context.createBufferSource(); + const buffer = gl.createBuffer(); + const size = uniformsGroup.__size; + const usage = uniformsGroup.usage; - source.buffer = this.buffer; - source.loop = this.loop; - source.onended = this.onEnded.bind( this ); - source.playbackRate.setValueAtTime( this.playbackRate, this.startTime ); - this.startTime = this.context.currentTime; - source.start( this.startTime, this.offset ); + 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 ); - this.isPlaying = true; + return buffer; - this.source = source; + } - return this.connect(); + function allocateBindingPointIndex() { - }, + for ( let i = 0; i < maxBindingPoints; i ++ ) { - pause: function () { + if ( allocatedBindingPoints.indexOf( i ) === - 1 ) { - if ( this.hasPlaybackControl === false ) { + allocatedBindingPoints.push( i ); + return i; - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + } } - if ( this.isPlaying === true ) { + console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); - this.source.stop(); - this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate; - this.isPlaying = false; + return 0; - } + } - return this; + function updateBufferData( uniformsGroup ) { - }, + const buffer = buffers[ uniformsGroup.id ]; + const uniforms = uniformsGroup.uniforms; + const cache = uniformsGroup.__cache; - stop: function () { + gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); - if ( this.hasPlaybackControl === false ) { + for ( let i = 0, il = uniforms.length; i < il; i ++ ) { - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; - } + for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { - this.source.stop(); - this.offset = 0; - this.isPlaying = false; + const uniform = uniformArray[ j ]; - return this; + if ( hasUniformChanged( uniform, i, j, cache ) === true ) { - }, + const offset = uniform.__offset; - connect: function () { + const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; - if ( this.filters.length > 0 ) { + let arrayOffset = 0; - this.source.connect( this.filters[ 0 ] ); + for ( let k = 0; k < values.length; k ++ ) { - for ( var i = 1, l = this.filters.length; i < l; i ++ ) { + const value = values[ k ]; - this.filters[ i - 1 ].connect( this.filters[ i ] ); + const info = getUniformSize( value ); - } + // TODO add integer and struct support + if ( typeof value === 'number' || typeof value === 'boolean' ) { - this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); + uniform.__data[ 0 ] = value; + gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); - } else { + } else if ( value.isMatrix3 ) { - this.source.connect( this.getOutput() ); + // manually converting 3x3 to 3x4 - } + uniform.__data[ 0 ] = value.elements[ 0 ]; + uniform.__data[ 1 ] = value.elements[ 1 ]; + uniform.__data[ 2 ] = value.elements[ 2 ]; + uniform.__data[ 3 ] = 0; + uniform.__data[ 4 ] = value.elements[ 3 ]; + uniform.__data[ 5 ] = value.elements[ 4 ]; + uniform.__data[ 6 ] = value.elements[ 5 ]; + uniform.__data[ 7 ] = 0; + uniform.__data[ 8 ] = value.elements[ 6 ]; + uniform.__data[ 9 ] = value.elements[ 7 ]; + uniform.__data[ 10 ] = value.elements[ 8 ]; + uniform.__data[ 11 ] = 0; - return this; + } else { - }, + value.toArray( uniform.__data, arrayOffset ); - disconnect: function () { + arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; - if ( this.filters.length > 0 ) { + } - this.source.disconnect( this.filters[ 0 ] ); + } - for ( var i = 1, l = this.filters.length; i < l; i ++ ) { + gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); - this.filters[ i - 1 ].disconnect( this.filters[ i ] ); + } } - this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); + } - } else { + gl.bindBuffer( gl.UNIFORM_BUFFER, null ); - this.source.disconnect( this.getOutput() ); + } - } + function hasUniformChanged( uniform, index, indexArray, cache ) { - return this; + const value = uniform.value; + const indexString = index + '_' + indexArray; - }, + if ( cache[ indexString ] === undefined ) { - getFilters: function () { + // cache entry does not exist so far - return this.filters; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - }, + cache[ indexString ] = value; - setFilters: function ( value ) { + } else { - if ( ! value ) { value = []; } + cache[ indexString ] = value.clone(); - if ( this.isPlaying === true ) { + } - this.disconnect(); - this.filters = value; - this.connect(); + return true; } else { - this.filters = value; + const cachedObject = cache[ indexString ]; - } + // compare current value with cached entry - return this; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - }, + if ( cachedObject !== value ) { - getFilter: function () { + cache[ indexString ] = value; + return true; - return this.getFilters()[ 0 ]; + } - }, + } else { - setFilter: function ( filter ) { + if ( cachedObject.equals( value ) === false ) { - return this.setFilters( filter ? [ filter ] : [] ); + cachedObject.copy( value ); + return true; - }, + } - setPlaybackRate: function ( value ) { + } - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + return false; - } + } - this.playbackRate = value; + function prepareUniformsGroup( uniformsGroup ) { - if ( this.isPlaying === true ) { + // determine total buffer size according to the STD140 layout + // Hint: STD140 is the only supported layout in WebGL 2 - this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime ); + const uniforms = uniformsGroup.uniforms; - } + let offset = 0; // global buffer offset in bytes + const chunkSize = 16; // size of a chunk in bytes - return this; + for ( let i = 0, l = uniforms.length; i < l; i ++ ) { - }, + const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; - getPlaybackRate: function () { + for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { - return this.playbackRate; + const uniform = uniformArray[ j ]; - }, + const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; - onEnded: function () { + for ( let k = 0, kl = values.length; k < kl; k ++ ) { - this.isPlaying = false; + const value = values[ k ]; - }, + const info = getUniformSize( value ); - getLoop: function () { + const chunkOffset = offset % chunkSize; // offset in the current chunk + const chunkPadding = chunkOffset % info.boundary; // required padding to match boundary + const chunkStart = chunkOffset + chunkPadding; // the start position in the current chunk for the data - if ( this.hasPlaybackControl === false ) { + offset += chunkPadding; - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return false; + // Check for chunk overflow + if ( chunkStart !== 0 && ( chunkSize - chunkStart ) < info.storage ) { - } + // Add padding and adjust offset + offset += ( chunkSize - chunkStart ); - return this.loop; + } - }, + // the following two properties will be used for partial buffer updates + uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT ); + uniform.__offset = offset; - setLoop: function ( value ) { + // Update the global offset + offset += info.storage; - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + } } - this.loop = value; + // ensure correct final padding - if ( this.isPlaying === true ) { + const chunkOffset = offset % chunkSize; - this.source.loop = this.loop; - - } + if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); - return this; + // - }, + uniformsGroup.__size = offset; + uniformsGroup.__cache = {}; - getVolume: function () { + return this; - return this.gain.gain.value; + } - }, + function getUniformSize( value ) { - setVolume: function ( value ) { + const info = { + boundary: 0, // bytes + storage: 0 // bytes + }; - this.gain.gain.value = value; + // determine sizes according to STD140 - return this; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - } + // float/int/bool -} ); + info.boundary = 4; + info.storage = 4; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } else if ( value.isVector2 ) { -function PositionalAudio( listener ) { + // vec2 - Audio.call( this, listener ); + info.boundary = 8; + info.storage = 8; - this.panner = this.context.createPanner(); - this.panner.connect( this.gain ); + } else if ( value.isVector3 || value.isColor ) { -} + // vec3 -PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), { + info.boundary = 16; + info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes - constructor: PositionalAudio, + } else if ( value.isVector4 ) { - getOutput: function () { + // vec4 - return this.panner; + info.boundary = 16; + info.storage = 16; - }, + } else if ( value.isMatrix3 ) { - getRefDistance: function () { + // mat3 (in STD140 a 3x3 matrix is represented as 3x4) - return this.panner.refDistance; + info.boundary = 48; + info.storage = 48; - }, + } else if ( value.isMatrix4 ) { - setRefDistance: function ( value ) { + // mat4 - this.panner.refDistance = value; + info.boundary = 64; + info.storage = 64; - }, + } else if ( value.isTexture ) { - getRolloffFactor: function () { + console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); - return this.panner.rolloffFactor; + } else { - }, + console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); - setRolloffFactor: function ( value ) { + } - this.panner.rolloffFactor = value; + return info; - }, + } - getDistanceModel: function () { + function onUniformsGroupsDispose( event ) { - return this.panner.distanceModel; + const uniformsGroup = event.target; - }, + uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); - setDistanceModel: function ( value ) { + const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); + allocatedBindingPoints.splice( index, 1 ); - this.panner.distanceModel = value; + gl.deleteBuffer( buffers[ uniformsGroup.id ] ); - }, + delete buffers[ uniformsGroup.id ]; + delete updateList[ uniformsGroup.id ]; - getMaxDistance: function () { + } - return this.panner.maxDistance; + function dispose() { - }, + for ( const id in buffers ) { - setMaxDistance: function ( value ) { + gl.deleteBuffer( buffers[ id ] ); - this.panner.maxDistance = value; + } - }, + allocatedBindingPoints = []; + buffers = {}; + updateList = {}; - updateMatrixWorld: ( function () { + } - var position = new Vector3(); + return { - return function updateMatrixWorld( force ) { + bind: bind, + update: update, - Object3D.prototype.updateMatrixWorld.call( this, force ); + dispose: dispose - position.setFromMatrixPosition( this.matrixWorld ); + }; - this.panner.setPosition( position.x, position.y, position.z ); +} - }; +class WebGLRenderer { - } )() + constructor( parameters = {} ) { + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = false, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; -} ); + this.isWebGLRenderer = true; -/** - * @author mrdoob / http://mrdoob.com/ - */ + let _alpha; -function AudioAnalyser( audio, fftSize ) { + if ( context !== null ) { - this.analyser = audio.context.createAnalyser(); - this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048; + if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) { - this.data = new Uint8Array( this.analyser.frequencyBinCount ); + throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' ); - audio.getOutput().connect( this.analyser ); + } -} + _alpha = context.getContextAttributes().alpha; -Object.assign( AudioAnalyser.prototype, { + } else { - getFrequencyData: function () { + _alpha = alpha; - this.analyser.getByteFrequencyData( this.data ); + } - return this.data; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - }, + let currentRenderList = null; + let currentRenderState = null; - getAverageFrequency: function () { + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - var value = 0, data = this.getFrequencyData(); + const renderListStack = []; + const renderStateStack = []; - for ( var i = 0; i < data.length; i ++ ) { + // public properties - value += data[ i ]; + this.domElement = canvas; - } + // Debug configuration container + this.debug = { - return value / data.length; + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - } + // clearing -} ); + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; -/** - * - * Buffered scene graph property that allows weighted accumulation. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + // scene graph -function PropertyMixer( binding, typeName, valueSize ) { + this.sortObjects = true; - this.binding = binding; - this.valueSize = valueSize; + // user-defined clipping - var bufferType = Float64Array, - mixFunction; + this.clippingPlanes = []; + this.localClippingEnabled = false; - switch ( typeName ) { + // physically based shading - case 'quaternion': - mixFunction = this._slerp; - break; + this._outputColorSpace = SRGBColorSpace; - case 'string': - case 'bool': - bufferType = Array; - mixFunction = this._select; - break; + // tone mapping - default: - mixFunction = this._lerp; + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - } + // internal properties - this.buffer = new bufferType( valueSize * 4 ); - // layout: [ incoming | accu0 | accu1 | orig ] - // - // interpolators can use .buffer as their .result - // the data then goes to 'incoming' - // - // 'accu0' and 'accu1' are used frame-interleaved for - // the cumulative result and are compared to detect - // changes - // - // 'orig' stores the original state of the property + const _this = this; - this._mixBufferRegion = mixFunction; + let _isContextLost = false; - this.cumulativeWeight = 0; + // internal state cache - this.useCount = 0; - this.referenceCount = 0; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; -} + let _currentCamera = null; -Object.assign( PropertyMixer.prototype, { + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - // accumulate data in the 'incoming' region into 'accu' - accumulate: function ( accuIndex, weight ) { + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - // note: happily accumulating nothing when weight = 0, the caller knows - // the weight and shouldn't have made the call in the first place + // - var buffer = this.buffer, - stride = this.valueSize, - offset = accuIndex * stride + stride, + let _width = canvas.width; + let _height = canvas.height; - currentWeight = this.cumulativeWeight; + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - if ( currentWeight === 0 ) { + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - // accuN := incoming * weight + // frustum - for ( var i = 0; i !== stride; ++ i ) { + const _frustum = new Frustum(); - buffer[ offset + i ] = buffer[ i ]; + // clipping - } + let _clippingEnabled = false; + let _localClippingEnabled = false; - currentWeight = weight; + // camera matrices cache - } else { + const _projScreenMatrix = new Matrix4(); - // accuN := accuN + incoming * weight + const _vector3 = new Vector3(); - currentWeight += weight; - var mix = weight / currentWeight; - this._mixBufferRegion( buffer, offset, 0, mix, stride ); + const _vector4 = new Vector4(); - } + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - this.cumulativeWeight = currentWeight; + let _renderBackground = false; - }, + function getTargetPixelRatio() { - // apply the state of 'accu' to the binding when accus differ - apply: function ( accuIndex ) { + return _currentRenderTarget === null ? _pixelRatio : 1; - var stride = this.valueSize, - buffer = this.buffer, - offset = accuIndex * stride + stride, + } - weight = this.cumulativeWeight, + // initialize - binding = this.binding; + let _gl = context; - this.cumulativeWeight = 0; + function getContext( contextName, contextAttributes ) { - if ( weight < 1 ) { + return canvas.getContext( contextName, contextAttributes ); - // accuN := accuN + original * ( 1 - cumulativeWeight ) + } - var originalValueOffset = stride * 3; + try { - this._mixBufferRegion( - buffer, offset, originalValueOffset, 1 - weight, stride ); + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - } + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - for ( var i = stride, e = stride + stride; i !== e; ++ i ) { + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - if ( buffer[ i ] !== buffer[ i + stride ] ) { + if ( _gl === null ) { - // value has changed -> update scene graph + const contextName = 'webgl2'; - binding.setValue( buffer, offset ); - break; + _gl = getContext( contextName, contextAttributes ); - } + if ( _gl === null ) { - } + if ( getContext( contextName ) ) { - }, + throw new Error( 'Error creating WebGL context with your selected attributes.' ); - // remember the state of the bound property and copy it to both accus - saveOriginalState: function () { + } else { - var binding = this.binding; + throw new Error( 'Error creating WebGL context.' ); - var buffer = this.buffer, - stride = this.valueSize, + } - originalValueOffset = stride * 3; + } - binding.getValue( buffer, originalValueOffset ); + } - // accu[0..1] := orig -- initially detect changes against the original - for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) { + } catch ( error ) { - buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; } - this.cumulativeWeight = 0; + 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; - // apply the state previously taken via 'saveOriginalState' to the binding - restoreOriginalState: function () { + let utils, bindingStates, uniformsGroups; - var originalValueOffset = this.valueSize * 3; - this.binding.setValue( this.buffer, originalValueOffset ); + function initGLContext() { - }, + extensions = new WebGLExtensions( _gl ); + extensions.init(); + utils = new WebGLUtils( _gl, extensions ); - // mix functions + capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils ); - _select: function ( buffer, dstOffset, srcOffset, t, stride ) { + state = new WebGLState( _gl ); - if ( t >= 0.5 ) { + info = new WebGLInfo( _gl ); + 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 ); + bindingStates = new WebGLBindingStates( _gl, attributes ); + 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 ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); - for ( var i = 0; i !== stride; ++ i ) { + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info ); - buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; + 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; } - }, - - _slerp: function ( buffer, dstOffset, srcOffset, t ) { + initGLContext(); - Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); + // xr - }, + const xr = new WebXRManager( _this, _gl ); - _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) { + this.xr = xr; - var s = 1 - t; + // API - for ( var i = 0; i !== stride; ++ i ) { + this.getContext = function () { - var j = dstOffset + i; + return _gl; - buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; + }; - } + this.getContextAttributes = function () { - } + return _gl.getContextAttributes(); -} ); + }; -/** - * - * A reference to a real property in the scene graph. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + this.forceContextLoss = function () { -function Composite( targetGroup, path, optionalParsedPath ) { + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); - var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); + }; - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_( path, parsedPath ); + this.forceContextRestore = function () { -} + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); -Object.assign( Composite.prototype, { + }; - getValue: function ( array, offset ) { + this.getPixelRatio = function () { - this.bind(); // bind all binding + return _pixelRatio; - var firstValidIndex = this._targetGroup.nCachedObjects_, - binding = this._bindings[ firstValidIndex ]; + }; - // and only call .getValue on the first - if ( binding !== undefined ) { binding.getValue( array, offset ); } + this.setPixelRatio = function ( value ) { - }, + if ( value === undefined ) return; - setValue: function ( array, offset ) { + _pixelRatio = value; - var bindings = this._bindings; + this.setSize( _width, _height, false ); - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { + }; - bindings[ i ].setValue( array, offset ); + this.getSize = function ( target ) { - } + return target.set( _width, _height ); - }, + }; - bind: function () { + this.setSize = function ( width, height, updateStyle = true ) { - var bindings = this._bindings; + if ( xr.isPresenting ) { - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; - bindings[ i ].bind(); + } - } + _width = width; + _height = height; - }, + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); - unbind: function () { + if ( updateStyle === true ) { - var bindings = this._bindings; + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { + } - bindings[ i ].unbind(); + this.setViewport( 0, 0, width, height ); - } + }; - } + this.getDrawingBufferSize = function ( target ) { -} ); + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + }; -function PropertyBinding( rootNode, path, parsedPath ) { + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); + _width = width; + _height = height; - this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; + _pixelRatio = pixelRatio; - this.rootNode = rootNode; + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); -} + this.setViewport( 0, 0, width, height ); -Object.assign( PropertyBinding, { + }; - Composite: Composite, + this.getCurrentViewport = function ( target ) { - create: function ( root, path, parsedPath ) { + return target.copy( _currentViewport ); - if ( ! ( root && root.isAnimationObjectGroup ) ) { + }; - return new PropertyBinding( root, path, parsedPath ); + this.getViewport = function ( target ) { - } else { + return target.copy( _viewport ); - return new PropertyBinding.Composite( root, path, parsedPath ); + }; - } + this.setViewport = function ( x, y, width, height ) { - }, + if ( x.isVector4 ) { - /** - * Replaces spaces with underscores and removes unsupported characters from - * node names, to ensure compatibility with parseTrackName(). - * - * @param {string} name Node name to be sanitized. - * @return {string} - */ - sanitizeNodeName: function ( name ) { + _viewport.set( x.x, x.y, x.z, x.w ); - return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' ); + } else { - }, + _viewport.set( x, y, width, height ); - parseTrackName: function () { + } - // Parent directories, delimited by '/' or ':'. Currently unused, but must - // be matched to parse the rest of the track name. - var directoryRe = /((?:[\w-]+[\/:])*)/; + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() ); - // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. - var nodeRe = /([\w-\.]+)?/; + }; - // Object on target node, and accessor. Name may contain only word - // characters. Accessor may contain any character except closing bracket. - var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/; + this.getScissor = function ( target ) { - // Property and accessor. May contain only word characters. Accessor may - // contain any non-bracket characters. - var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/; + return target.copy( _scissor ); - var trackRe = new RegExp( '' - + '^' - + directoryRe.source - + nodeRe.source - + objectRe.source - + propertyRe.source - + '$' - ); + }; - var supportedObjectNames = [ 'material', 'materials', 'bones' ]; + this.setScissor = function ( x, y, width, height ) { - return function ( trackName ) { + if ( x.isVector4 ) { - var matches = trackRe.exec( trackName ); + _scissor.set( x.x, x.y, x.z, x.w ); - if ( ! matches ) { + } else { - throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); + _scissor.set( x, y, width, height ); } - var results = { - // directoryName: matches[ 1 ], // (tschw) currently unused - nodeName: matches[ 2 ], - objectName: matches[ 3 ], - objectIndex: matches[ 4 ], - propertyName: matches[ 5 ], // required - propertyIndex: matches[ 6 ] - }; + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() ); + + }; - var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); + this.getScissorTest = function () { - if ( lastDot !== undefined && lastDot !== - 1 ) { + return _scissorTest; - var objectName = results.nodeName.substring( lastDot + 1 ); + }; - // Object names must be checked against a whitelist. Otherwise, there - // is no way to parse 'foo.bar.baz': 'baz' must be a property, but - // 'bar' could be the objectName, or part of a nodeName (which can - // include '.' characters). - if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) { + this.setScissorTest = function ( boolean ) { - results.nodeName = results.nodeName.substring( 0, lastDot ); - results.objectName = objectName; + state.setScissorTest( _scissorTest = boolean ); - } + }; - } + this.setOpaqueSort = function ( method ) { - if ( results.propertyName === null || results.propertyName.length === 0 ) { + _opaqueSort = method; - throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); + }; - } + this.setTransparentSort = function ( method ) { - return results; + _transparentSort = method; }; - }(), + // Clearing - findNode: function ( root, nodeName ) { + this.getClearColor = function ( target ) { - if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { + return target.copy( background.getClearColor() ); - return root; + }; - } + this.setClearColor = function () { - // search into skeleton bones. - if ( root.skeleton ) { + background.setClearColor.apply( background, arguments ); - var searchSkeleton = function ( skeleton ) { + }; - for ( var i = 0; i < skeleton.bones.length; i ++ ) { + this.getClearAlpha = function () { - var bone = skeleton.bones[ i ]; + return background.getClearAlpha(); - if ( bone.name === nodeName ) { + }; - return bone; + this.setClearAlpha = function () { - } + background.setClearAlpha.apply( background, arguments ); - } + }; - return null; + this.clear = function ( color = true, depth = true, stencil = true ) { - }; + let bits = 0; - var bone = searchSkeleton( root.skeleton ); + if ( color ) { - if ( bone ) { + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - return bone; + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - } + } - } + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - // search into node subtree. - if ( root.children ) { + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - var searchNodeSubtree = function ( children ) { + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - for ( var i = 0; i < children.length; i ++ ) { + if ( isUnsignedType ) { - var childNode = children[ i ]; + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor ); - if ( childNode.name === nodeName || childNode.uuid === nodeName ) { + } else { - return childNode; + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, 0, intClearColor ); } - var result = searchNodeSubtree( childNode.children ); + } else { - if ( result ) { return result; } + bits |= _gl.COLOR_BUFFER_BIT; } - return null; - - }; - - var subTreeNode = searchNodeSubtree( root.children ); + } - if ( subTreeNode ) { + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) { - return subTreeNode; + bits |= _gl.STENCIL_BUFFER_BIT; + this.state.buffers.stencil.setMask( 0xffffffff ); } - } + _gl.clear( bits ); - return null; + }; - } + this.clearColor = function () { -} ); + this.clear( true, false, false ); -Object.assign( PropertyBinding.prototype, { // prototype, continued + }; - // these are used to "bind" a nonexistent property - _getValue_unavailable: function () {}, - _setValue_unavailable: function () {}, + this.clearDepth = function () { - BindingType: { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 - }, + this.clear( false, true, false ); - Versioning: { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 - }, + }; - GetterByBindingType: [ + this.clearStencil = function () { - function getValue_direct( buffer, offset ) { + this.clear( false, false, true ); - buffer[ offset ] = this.node[ this.propertyName ]; + }; - }, + // - function getValue_array( buffer, offset ) { + this.dispose = function () { - var source = this.resolvedProperty; + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - for ( var i = 0, n = source.length; i !== n; ++ i ) { + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - buffer[ offset ++ ] = source[ i ]; + xr.dispose(); - } + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - }, + animation.stop(); - function getValue_arrayElement( buffer, offset ) { + }; - buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; + // Events - }, + function onContextLost( event ) { - function getValue_toArray( buffer, offset ) { + event.preventDefault(); - this.resolvedProperty.toArray( buffer, offset ); + console.log( 'THREE.WebGLRenderer: Context Lost.' ); + + _isContextLost = true; } - ], + function onContextRestore( /* event */ ) { - SetterByBindingTypeAndVersioning: [ + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - [ - // Direct + _isContextLost = false; - function setValue_direct( buffer, offset ) { + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - this.targetObject[ this.propertyName ] = buffer[ offset ]; + initGLContext(); - }, + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - function setValue_direct_setNeedsUpdate( buffer, offset ) { + } - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + function onContextCreationError( event ) { - }, + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); - function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { + } - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + function onMaterialDispose( event ) { - } + const material = event.target; - ], [ + material.removeEventListener( 'dispose', onMaterialDispose ); - // EntireArray + deallocateMaterial( material ); - function setValue_array( buffer, offset ) { + } - var dest = this.resolvedProperty; + // Buffer deallocation - for ( var i = 0, n = dest.length; i !== n; ++ i ) { + function deallocateMaterial( material ) { - dest[ i ] = buffer[ offset ++ ]; + releaseMaterialProgramReferences( material ); - } + properties.remove( material ); - }, + } - function setValue_array_setNeedsUpdate( buffer, offset ) { - var dest = this.resolvedProperty; + function releaseMaterialProgramReferences( material ) { - for ( var i = 0, n = dest.length; i !== n; ++ i ) { + const programs = properties.get( material ).programs; - dest[ i ] = buffer[ offset ++ ]; + if ( programs !== undefined ) { - } + programs.forEach( function ( program ) { - this.targetObject.needsUpdate = true; + programCache.releaseProgram( program ); - }, + } ); - function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { + if ( material.isShaderMaterial ) { - var dest = this.resolvedProperty; + programCache.releaseShaderCache( material ); - for ( var i = 0, n = dest.length; i !== n; ++ i ) { + } - dest[ i ] = buffer[ offset ++ ]; + } - } + } - this.targetObject.matrixWorldNeedsUpdate = true; + // Buffer rendering - } + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - ], [ + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - // ArrayElement + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - function setValue_arrayElement( buffer, offset ) { + const program = setProgram( camera, scene, geometry, material, object ); - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + state.setMaterial( material, frontFaceCW ); - }, + // - function setValue_arrayElement_setNeedsUpdate( buffer, offset ) { + let index = geometry.index; + let rangeFactor = 1; - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + if ( material.wireframe === true ) { - }, + index = geometries.getWireframeAttribute( geometry ); - function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { + if ( index === undefined ) return; - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + rangeFactor = 2; } - ], [ + // - // HasToFromArray + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - function setValue_fromArray( buffer, offset ) { + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - this.resolvedProperty.fromArray( buffer, offset ); + if ( group !== null ) { - }, + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - function setValue_fromArray_setNeedsUpdate( buffer, offset ) { + } - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.needsUpdate = true; + if ( index !== null ) { - }, + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { + } else if ( position !== undefined && position !== null ) { - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.matrixWorldNeedsUpdate = true; + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); } - ] + const drawCount = drawEnd - drawStart; - ], + if ( drawCount < 0 || drawCount === Infinity ) return; - getValue: function getValue_unbound( targetArray, offset ) { + // - this.bind(); - this.getValue( targetArray, offset ); + bindingStates.setup( object, material, program, geometry, index ); - // Note: This class uses a State pattern on a per-method basis: - // 'bind' sets 'this.getValue' / 'setValue' and shadows the - // prototype version of these methods with one that represents - // the bound state. When the property is not found, the methods - // become no-ops. + let attribute; + let renderer = bufferRenderer; - }, + if ( index !== null ) { - setValue: function getValue_unbound( sourceArray, offset ) { + attribute = attributes.get( index ); - this.bind(); - this.setValue( sourceArray, offset ); + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - }, + } - // create getter / setter pair for a property in the scene graph - bind: function () { + // - var targetObject = this.node, - parsedPath = this.parsedPath, + if ( object.isMesh ) { - objectName = parsedPath.objectName, - propertyName = parsedPath.propertyName, - propertyIndex = parsedPath.propertyIndex; + if ( material.wireframe === true ) { - if ( ! targetObject ) { + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode; + } else { - this.node = targetObject; + renderer.setMode( _gl.TRIANGLES ); - } + } - // set fail state so we can just 'return' on error - this.getValue = this._getValue_unavailable; - this.setValue = this._setValue_unavailable; + } else if ( object.isLine ) { - // ensure there is a value node - if ( ! targetObject ) { + let lineWidth = material.linewidth; - console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' ); - return; + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - } + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - if ( objectName ) { + if ( object.isLineSegments ) { - var objectIndex = parsedPath.objectIndex; + renderer.setMode( _gl.LINES ); - // special cases were we need to reach deeper into the hierarchy to get the face materials.... - switch ( objectName ) { + } else if ( object.isLineLoop ) { - case 'materials': + renderer.setMode( _gl.LINE_LOOP ); - if ( ! targetObject.material ) { + } else { - console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); - return; + renderer.setMode( _gl.LINE_STRIP ); - } + } - if ( ! targetObject.material.materials ) { + } else if ( object.isPoints ) { - console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); - return; + renderer.setMode( _gl.POINTS ); - } + } else if ( object.isSprite ) { - targetObject = targetObject.material.materials; + renderer.setMode( _gl.TRIANGLES ); - break; + } - case 'bones': + if ( object.isBatchedMesh ) { - if ( ! targetObject.skeleton ) { + if ( object._multiDrawInstances !== null ) { - console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); - return; + renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); - } + } else { - // potential future optimization: skip this if propertyIndex is already an integer - // and convert the integer string to a true integer. + if ( ! extensions.get( 'WEBGL_multi_draw' ) ) { - targetObject = targetObject.skeleton.bones; + const starts = object._multiDrawStarts; + const counts = object._multiDrawCounts; + const drawCount = object._multiDrawCount; + const bytesPerElement = index ? attributes.get( index ).bytesPerElement : 1; + const uniforms = properties.get( material ).currentProgram.getUniforms(); + for ( let i = 0; i < drawCount; i ++ ) { - // support resolving morphTarget names into indices. - for ( var i = 0; i < targetObject.length; i ++ ) { + uniforms.setValue( _gl, '_gl_DrawID', i ); + renderer.render( starts[ i ] / bytesPerElement, counts[ i ] ); - if ( targetObject[ i ].name === objectIndex ) { + } - objectIndex = i; - break; + } else { - } + renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); } - break; + } - default: + } else if ( object.isInstancedMesh ) { - if ( targetObject[ objectName ] === undefined ) { + renderer.renderInstances( drawStart, drawCount, object.count ); - console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); - return; + } else if ( geometry.isInstancedBufferGeometry ) { - } + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); - targetObject = targetObject[ objectName ]; + renderer.renderInstances( drawStart, drawCount, instanceCount ); - } + } else { + renderer.render( drawStart, drawCount ); - if ( objectIndex !== undefined ) { + } - if ( targetObject[ objectIndex ] === undefined ) { + }; - console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); - return; + // Compile - } + function prepareMaterial( material, scene, object ) { - targetObject = targetObject[ objectIndex ]; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - } + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - } + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - // resolve property - var nodeProperty = targetObject[ propertyName ]; + material.side = DoubleSide; - if ( nodeProperty === undefined ) { + } else { - var nodeName = parsedPath.nodeName; + getProgram( material, scene, object ); - console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + - '.' + propertyName + ' but it wasn\'t found.', targetObject ); - return; + } } - // determine versioning scheme - var versioning = this.Versioning.None; - - if ( targetObject.needsUpdate !== undefined ) { // material + this.compile = function ( scene, camera, targetScene = null ) { - versioning = this.Versioning.NeedsUpdate; - this.targetObject = targetObject; + if ( targetScene === null ) targetScene = scene; - } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform + currentRenderState = renderStates.get( targetScene ); + currentRenderState.init( camera ); - versioning = this.Versioning.MatrixWorldNeedsUpdate; - this.targetObject = targetObject; + renderStateStack.push( currentRenderState ); - } - - // determine how the property gets bound - var bindingType = this.BindingType.Direct; + // gather lights from both the target scene and the new object that will be added to the scene. - if ( propertyIndex !== undefined ) { + targetScene.traverseVisible( function ( object ) { - // access a sub element of the property array (only primitives are supported right now) + if ( object.isLight && object.layers.test( camera.layers ) ) { - if ( propertyName === "morphTargetInfluences" ) { + currentRenderState.pushLight( object ); - // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. + if ( object.castShadow ) { - // support resolving morphTarget names into indices. - if ( ! targetObject.geometry ) { + currentRenderState.pushShadow( object ); - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); - return; + } } - if ( targetObject.geometry.isBufferGeometry ) { + } ); - if ( ! targetObject.geometry.morphAttributes ) { + if ( scene !== targetScene ) { - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); - return; + scene.traverseVisible( function ( object ) { - } + if ( object.isLight && object.layers.test( camera.layers ) ) { - for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) { + currentRenderState.pushLight( object ); - if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) { + if ( object.castShadow ) { - propertyIndex = i; - break; + currentRenderState.pushShadow( object ); } } + } ); - } else { + } - if ( ! targetObject.geometry.morphTargets ) { + currentRenderState.setupLights(); - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this ); - return; + // Only initialize materials in the new scene, not the targetScene. - } + const materials = new Set(); - for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) { + scene.traverse( function ( object ) { - if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) { + const material = object.material; - propertyIndex = i; - break; + if ( material ) { + + if ( Array.isArray( material ) ) { + + for ( let i = 0; i < material.length; i ++ ) { + + const material2 = material[ i ]; + + prepareMaterial( material2, targetScene, object ); + materials.add( material2 ); } + } else { + + prepareMaterial( material, targetScene, object ); + materials.add( material ); + } } - } + } ); - bindingType = this.BindingType.ArrayElement; + renderStateStack.pop(); + currentRenderState = null; - this.resolvedProperty = nodeProperty; - this.propertyIndex = propertyIndex; + return materials; - } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { + }; - // must use copy for Object3D.Euler/Quaternion + // compileAsync - bindingType = this.BindingType.HasFromToArray; + this.compileAsync = function ( scene, camera, targetScene = null ) { - this.resolvedProperty = nodeProperty; + const materials = this.compile( scene, camera, targetScene ); - } else if ( Array.isArray( nodeProperty ) ) { + // Wait for all the materials in the new object to indicate that they're + // ready to be used before resolving the promise. - bindingType = this.BindingType.EntireArray; + return new Promise( ( resolve ) => { - this.resolvedProperty = nodeProperty; + function checkMaterialsReady() { - } else { + materials.forEach( function ( material ) { - this.propertyName = propertyName; + const materialProperties = properties.get( material ); + const program = materialProperties.currentProgram; - } + if ( program.isReady() ) { - // select getter / setter - this.getValue = this.GetterByBindingType[ bindingType ]; - this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; + // remove any programs that report they're ready to use from the list + materials.delete( material ); - }, + } - unbind: function () { + } ); - this.node = null; + // once the list of compiling materials is empty, call the callback - // back to the prototype version of getValue / setValue - // note: avoiding to mutate the shape of 'this' via 'delete' - this.getValue = this._getValue_unbound; - this.setValue = this._setValue_unbound; + if ( materials.size === 0 ) { - } + resolve( scene ); + return; -} ); + } -//!\ DECLARE ALIAS AFTER assign prototype ! -Object.assign( PropertyBinding.prototype, { + // if some materials are still not ready, wait a bit and check again - // initial state of these methods that calls 'bind' - _getValue_unbound: PropertyBinding.prototype.getValue, - _setValue_unbound: PropertyBinding.prototype.setValue, + setTimeout( checkMaterialsReady, 10 ); -} ); + } -/** - * - * A group of objects that receives a shared animation state. - * - * Usage: - * - * - Add objects you would otherwise pass as 'root' to the - * constructor or the .clipAction method of AnimationMixer. - * - * - Instead pass this object as 'root'. - * - * - You can also add and remove objects later when the mixer - * is running. - * - * Note: - * - * Objects of this class appear as one object to the mixer, - * so cache control of the individual objects must be done - * on the group. - * - * Limitation: - * - * - The animated properties must be compatible among the - * all objects in the group. - * - * - A single property can either be controlled through a - * target group or directly, but not both. - * - * @author tschw - */ + if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) { -function AnimationObjectGroup() { - var arguments$1 = arguments; + // If we can check the compilation status of the materials without + // blocking then do so right away. + checkMaterialsReady(); - this.uuid = _Math.generateUUID(); + } else { - // cached objects followed by the active ones - this._objects = Array.prototype.slice.call( arguments ); + // Otherwise start by waiting a bit to give the materials we just + // initialized a chance to finish. - this.nCachedObjects_ = 0; // threshold - // note: read by PropertyBinding.Composite + setTimeout( checkMaterialsReady, 10 ); - var indices = {}; - this._indicesByUUID = indices; // for bookkeeping + } - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + } ); - indices[ arguments$1[ i ].uuid ] = i; + }; - } + // Animation Loop - this._paths = []; // inside: string - this._parsedPaths = []; // inside: { we don't care, here } - this._bindings = []; // inside: Array< PropertyBinding > - this._bindingsIndicesByPath = {}; // inside: indices in these arrays + let onAnimationFrameCallback = null; - var scope = this; + function onAnimationFrame( time ) { - this.stats = { + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - objects: { - get total() { + } - return scope._objects.length; + function onXRSessionStart() { - }, - get inUse() { + animation.stop(); - return this.total - scope.nCachedObjects_; + } - } - }, - get bindingsPerObject() { + function onXRSessionEnd() { - return scope._bindings.length; + animation.start(); } - }; + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); -} + if ( typeof self !== 'undefined' ) animation.setContext( self ); -Object.assign( AnimationObjectGroup.prototype, { + this.setAnimationLoop = function ( callback ) { - isAnimationObjectGroup: true, + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - add: function () { - var arguments$1 = arguments; + ( callback === null ) ? animation.stop() : animation.start(); + }; - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - nBindings = bindings.length; + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + // Rendering - var object = arguments$1[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ], - knownObject = undefined; + this.render = function ( scene, camera ) { - if ( index === undefined ) { + if ( camera !== undefined && camera.isCamera !== true ) { - // unknown object -> add it to the ACTIVE region + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; - index = nObjects ++; - indicesByUUID[ uuid ] = index; - objects.push( object ); + } - // accounting is done, now do the same for all bindings + if ( _isContextLost === true ) return; - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // update scene graph - bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - } + // update camera matrices and frustum - } else if ( index < nCachedObjects ) { + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - knownObject = objects[ index ]; + if ( xr.enabled === true && xr.isPresenting === true ) { - // move existing object to the ACTIVE region + if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ]; + camera = xr.getCamera(); // use XR camera for rendering - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; + } + + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - indicesByUUID[ uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = object; + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init( camera ); - // accounting is done, now do the same for all bindings + renderStateStack.push( currentRenderState ); - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - binding = bindingsForPath[ index ]; + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - bindingsForPath[ index ] = lastCached; + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - if ( binding === undefined ) { + renderListStack.push( currentRenderList ); - // since we do not bother to create new bindings - // for objects that are cached, the binding may - // or may not exist + if ( xr.enabled === true && xr.isPresenting === true ) { - binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); + const depthSensingMesh = _this.xr.getDepthSensingMesh(); - } + if ( depthSensingMesh !== null ) { - bindingsForPath[ firstActiveIndex ] = binding; + projectObject( depthSensingMesh, camera, - Infinity, _this.sortObjects ); } - } else if ( objects[ index ] !== knownObject ) { + } - console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + - 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); + projectObject( scene, camera, 0, _this.sortObjects ); - } // else the object is already where we want it to be + currentRenderList.finish(); - } // for arguments + if ( _this.sortObjects === true ) { - this.nCachedObjects_ = nCachedObjects; + currentRenderList.sort( _opaqueSort, _transparentSort ); - }, + } - remove: function () { - var arguments$1 = arguments; + _renderBackground = xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false; + if ( _renderBackground ) { + background.addToRenderList( currentRenderList, scene ); - var objects = this._objects, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; + } - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + // - var object = arguments$1[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; + this.info.render.frame ++; - if ( index !== undefined && index >= nCachedObjects ) { + if ( _clippingEnabled === true ) clipping.beginShadows(); - // move existing object into the CACHED region + const shadowsArray = currentRenderState.state.shadowsArray; - var lastCachedIndex = nCachedObjects ++, - firstActiveObject = objects[ lastCachedIndex ]; + shadowMap.render( shadowsArray, scene, camera ); - indicesByUUID[ firstActiveObject.uuid ] = index; - objects[ index ] = firstActiveObject; + if ( _clippingEnabled === true ) clipping.endShadows(); - indicesByUUID[ uuid ] = lastCachedIndex; - objects[ lastCachedIndex ] = object; + // - // accounting is done, now do the same for all bindings + if ( this.info.autoReset === true ) this.info.reset(); - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // render scene - var bindingsForPath = bindings[ j ], - firstActive = bindingsForPath[ lastCachedIndex ], - binding = bindingsForPath[ index ]; + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; - bindingsForPath[ index ] = firstActive; - bindingsForPath[ lastCachedIndex ] = binding; + currentRenderState.setupLights(); - } + if ( camera.isArrayCamera ) { - } + const cameras = camera.cameras; - } // for arguments + if ( transmissiveObjects.length > 0 ) { - this.nCachedObjects_ = nCachedObjects; + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - }, + const camera2 = cameras[ i ]; - // remove & forget - uncache: function () { - var arguments$1 = arguments; + renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 ); + } - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; + } - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + if ( _renderBackground ) background.render( scene ); - var object = arguments$1[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - if ( index !== undefined ) { + const camera2 = cameras[ i ]; - delete indicesByUUID[ uuid ]; + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - if ( index < nCachedObjects ) { + } - // object is cached, shrink the CACHED region + } else { - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ], - lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - // last cached object takes this object's place - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; + if ( _renderBackground ) background.render( scene ); - // last object goes to the activated slot and pop - indicesByUUID[ lastObject.uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = lastObject; - objects.pop(); + renderScene( currentRenderList, scene, camera ); - // accounting is done, now do the same for all bindings + } - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - last = bindingsForPath[ lastIndex ]; + if ( _currentRenderTarget !== null ) { - bindingsForPath[ index ] = lastCached; - bindingsForPath[ firstActiveIndex ] = last; - bindingsForPath.pop(); + // resolve multisample renderbuffers to a single-sample texture if necessary - } + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - } else { + // Generate mipmap if we're using any kind of mipmap filtering - // object is active, just swap with the last and pop + textures.updateRenderTargetMipmap( _currentRenderTarget ); - var lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; + } - indicesByUUID[ lastObject.uuid ] = index; - objects[ index ] = lastObject; - objects.pop(); + // - // accounting is done, now do the same for all bindings + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // _gl.finish(); - var bindingsForPath = bindings[ j ]; + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; - bindingsForPath.pop(); + renderStateStack.pop(); - } + if ( renderStateStack.length > 0 ) { - } // cached or active + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - } // if object is known + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, currentRenderState.state.camera ); - } // for arguments + } else { - this.nCachedObjects_ = nCachedObjects; + currentRenderState = null; - }, + } - // Internal interface used by befriended PropertyBinding.Composite: + renderListStack.pop(); - subscribe_: function ( path, parsedPath ) { + if ( renderListStack.length > 0 ) { - // returns an array of bindings for the given path that is changed - // according to the contained objects in the group + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ], - bindings = this._bindings; + } else { - if ( index !== undefined ) { return bindings[ index ]; } + currentRenderList = null; - var paths = this._paths, - parsedPaths = this._parsedPaths, - objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - bindingsForPath = new Array( nObjects ); + } - index = bindings.length; + }; - indicesByPath[ path ] = index; + function projectObject( object, camera, groupOrder, sortObjects ) { - paths.push( path ); - parsedPaths.push( parsedPath ); - bindings.push( bindingsForPath ); + if ( object.visible === false ) return; - for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) { + const visible = object.layers.test( camera.layers ); - var object = objects[ i ]; - bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); + if ( visible ) { - } + if ( object.isGroup ) { - return bindingsForPath; + groupOrder = object.renderOrder; - }, + } else if ( object.isLOD ) { - unsubscribe_: function ( path ) { + if ( object.autoUpdate === true ) object.update( camera ); - // tells the group to forget about a property path and no longer - // update the array previously obtained with 'subscribe_' + } else if ( object.isLight ) { - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ]; + currentRenderState.pushLight( object ); - if ( index !== undefined ) { + if ( object.castShadow ) { - var paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - lastBindingsIndex = bindings.length - 1, - lastBindings = bindings[ lastBindingsIndex ], - lastBindingsPath = path[ lastBindingsIndex ]; + currentRenderState.pushShadow( object ); - indicesByPath[ lastBindingsPath ] = index; + } - bindings[ index ] = lastBindings; - bindings.pop(); + } else if ( object.isSprite ) { - parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; - parsedPaths.pop(); + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - paths[ index ] = paths[ lastBindingsIndex ]; - paths.pop(); + if ( sortObjects ) { - } + _vector4.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - } + } -} ); + const geometry = objects.update( object ); + const material = object.material; -/** - * - * Action provided by AnimationMixer for scheduling clip playback on specific - * objects. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - * - */ + if ( material.visible ) { -function AnimationAction( mixer, clip, localRoot ) { + currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null ); - this._mixer = mixer; - this._clip = clip; - this._localRoot = localRoot || null; + } - var tracks = clip.tracks, - nTracks = tracks.length, - interpolants = new Array( nTracks ); + } - var interpolantSettings = { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - }; + } else if ( object.isMesh || object.isLine || object.isPoints ) { - for ( var i = 0; i !== nTracks; ++ i ) { + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - var interpolant = tracks[ i ].createInterpolant( null ); - interpolants[ i ] = interpolant; - interpolant.settings = interpolantSettings; + const geometry = objects.update( object ); + const material = object.material; - } + if ( sortObjects ) { - this._interpolantSettings = interpolantSettings; + if ( object.boundingSphere !== undefined ) { - this._interpolants = interpolants; // bound by the mixer + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector4.copy( object.boundingSphere.center ); - // inside: PropertyMixer (managed by the mixer) - this._propertyBindings = new Array( nTracks ); + } else { - this._cacheIndex = null; // for the memory manager - this._byClipCacheIndex = null; // for the memory manager + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector4.copy( geometry.boundingSphere.center ); - this._timeScaleInterpolant = null; - this._weightInterpolant = null; + } - this.loop = LoopRepeat; - this._loopCount = - 1; + _vector4 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - // global mixer time when the action is to be started - // it's set back to 'null' upon start of the action - this._startTime = null; + } - // scaled local time of the action - // gets clamped or wrapped to 0..clip.duration according to loop - this.time = 0; + if ( Array.isArray( material ) ) { - this.timeScale = 1; - this._effectiveTimeScale = 1; + const groups = geometry.groups; - this.weight = 1; - this._effectiveWeight = 1; + for ( let i = 0, l = groups.length; i < l; i ++ ) { - this.repetitions = Infinity; // no. of repetitions when looping + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - this.paused = false; // true -> zero effective time scale - this.enabled = true; // false -> zero effective weight + if ( groupMaterial && groupMaterial.visible ) { - this.clampWhenFinished = false; // keep feeding the last frame? + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group ); - this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate - this.zeroSlopeAtEnd = true; // clips for start, loop and end + } -} + } -Object.assign( AnimationAction.prototype, { + } else if ( material.visible ) { - // State & Scheduling + currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null ); - play: function () { + } - this._mixer._activateAction( this ); + } - return this; + } - }, + } - stop: function () { + const children = object.children; - this._mixer._deactivateAction( this ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - return this.reset(); + projectObject( children[ i ], camera, groupOrder, sortObjects ); - }, + } - reset: function () { + } - this.paused = false; - this.enabled = true; + function renderScene( currentRenderList, scene, camera, viewport ) { - this.time = 0; // restart clip - this._loopCount = - 1; // forget previous loops - this._startTime = null; // forget scheduling + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - return this.stopFading().stopWarping(); + currentRenderState.setupLightsView( camera ); - }, + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, 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 ); + + // Ensure depth buffer writing is enabled so it can be cleared on next render + + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); + + state.setPolygonOffset( false ); + + } - isRunning: function () { + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - return this.enabled && ! this.paused && this.timeScale !== 0 && - this._startTime === null && this._mixer._isActiveAction( this ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - }, + if ( overrideMaterial !== null ) { - // return true when play has been called - isScheduled: function () { + return; - return this._mixer._isActiveAction( this ); + } - }, + if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) { - startAt: function ( time ) { + currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: 4, + stencilBuffer: stencil, + resolveDepthBuffer: false, + resolveStencilBuffer: false, + colorSpace: ColorManagement.workingColorSpace, + } ); - this._startTime = time; + // debug - return this; + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - }, + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - setLoop: function ( mode, repetitions ) { + } - this.loop = mode; - this.repetitions = repetitions; + const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget[ camera.id ]; - return this; + const activeViewport = camera.viewport || _currentViewport; + transmissionRenderTarget.setSize( activeViewport.z, activeViewport.w ); - }, + // - // Weight + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( transmissionRenderTarget ); - // set the weight stopping any scheduled fading - // although .enabled = false yields an effective weight of zero, this - // method does *not* change .enabled, because it would be confusing - setEffectiveWeight: function ( weight ) { + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - this.weight = weight; + _this.clear(); - // note: same logic as when updated at runtime - this._effectiveWeight = this.enabled ? weight : 0; + if ( _renderBackground ) background.render( scene ); - return this.stopFading(); + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - }, + // Remove viewport from camera to avoid nested render calls resetting viewport to it (e.g Reflector). + // Transmission render pass requires viewport to match the transmissionRenderTarget. + const currentCameraViewport = camera.viewport; + if ( camera.viewport !== undefined ) camera.viewport = undefined; - // return the weight considering fading and .enabled - getEffectiveWeight: function () { + currentRenderState.setupLightsView( camera ); - return this._effectiveWeight; + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - }, + renderObjects( opaqueObjects, scene, camera ); - fadeIn: function ( duration ) { + textures.updateMultisampleRenderTarget( transmissionRenderTarget ); + textures.updateRenderTargetMipmap( transmissionRenderTarget ); - return this._scheduleFading( duration, 0, 1 ); + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === false ) { // see #28131 - }, + let renderTargetNeedsUpdate = false; - fadeOut: function ( duration ) { + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - return this._scheduleFading( duration, 1, 0 ); + const renderItem = transmissiveObjects[ i ]; - }, + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - crossFadeFrom: function ( fadeOutAction, duration, warp ) { + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - fadeOutAction.fadeOut( duration ); - this.fadeIn( duration ); + const currentSide = material.side; - if ( warp ) { + material.side = BackSide; + material.needsUpdate = true; - var fadeInDuration = this._clip.duration, - fadeOutDuration = fadeOutAction._clip.duration, + renderObject( object, scene, camera, geometry, material, group ); - startEndRatio = fadeOutDuration / fadeInDuration, - endStartRatio = fadeInDuration / fadeOutDuration; + material.side = currentSide; + material.needsUpdate = true; - fadeOutAction.warp( 1.0, startEndRatio, duration ); - this.warp( endStartRatio, 1.0, duration ); + renderTargetNeedsUpdate = true; - } + } - return this; + } - }, + if ( renderTargetNeedsUpdate === true ) { - crossFadeTo: function ( fadeInAction, duration, warp ) { + textures.updateMultisampleRenderTarget( transmissionRenderTarget ); + textures.updateRenderTargetMipmap( transmissionRenderTarget ); - return fadeInAction.crossFadeFrom( this, duration, warp ); + } - }, + } - stopFading: function () { + _this.setRenderTarget( currentRenderTarget ); - var weightInterpolant = this._weightInterpolant; + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - if ( weightInterpolant !== null ) { + if ( currentCameraViewport !== undefined ) camera.viewport = currentCameraViewport; - this._weightInterpolant = null; - this._mixer._takeBackControlInterpolant( weightInterpolant ); + _this.toneMapping = currentToneMapping; } - return this; - - }, + function renderObjects( renderList, scene, camera ) { - // Time Scale Control + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - // set the time scale stopping any scheduled warping - // although .paused = true yields an effective time scale of zero, this - // method does *not* change .paused, because it would be confusing - setEffectiveTimeScale: function ( timeScale ) { + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - this.timeScale = timeScale; - this._effectiveTimeScale = this.paused ? 0 : timeScale; + const renderItem = renderList[ i ]; - return this.stopWarping(); + 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 ) ) { - // return the time scale considering warping and .paused - getEffectiveTimeScale: function () { + renderObject( object, scene, camera, geometry, material, group ); - return this._effectiveTimeScale; + } - }, + } - setDuration: function ( duration ) { + } - this.timeScale = this._clip.duration / duration; + function renderObject( object, scene, camera, geometry, material, group ) { - return this.stopWarping(); + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - }, + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - syncWith: function ( action ) { + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - this.time = action.time; - this.timeScale = action.timeScale; + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - return this.stopWarping(); + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - }, + material.side = DoubleSide; - halt: function ( duration ) { + } else { - return this.warp( this._effectiveTimeScale, 0, duration ); + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - }, + } - warp: function ( startTimeScale, endTimeScale, duration ) { + object.onAfterRender( _this, scene, camera, geometry, material, group ); - var mixer = this._mixer, now = mixer.time, - interpolant = this._timeScaleInterpolant, + } - timeScale = this.timeScale; + function getProgram( material, scene, object ) { - if ( interpolant === null ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - interpolant = mixer._lendControlInterpolant(); - this._timeScaleInterpolant = interpolant; + const materialProperties = properties.get( material ); - } + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; + const lightsStateVersion = lights.state.version; - times[ 0 ] = now; - times[ 1 ] = now + duration; + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - values[ 0 ] = startTimeScale / timeScale; - values[ 1 ] = endTimeScale / timeScale; + let programs = materialProperties.programs; - return this; + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - }, + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; - stopWarping: function () { + if ( programs === undefined ) { - var timeScaleInterpolant = this._timeScaleInterpolant; + // new material - if ( timeScaleInterpolant !== null ) { + material.addEventListener( 'dispose', onMaterialDispose ); - this._timeScaleInterpolant = null; - this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); + programs = new Map(); + materialProperties.programs = programs; - } + } - return this; + let program = programs.get( programCacheKey ); - }, + if ( program !== undefined ) { - // Object Accessors + // early out if program and light state is identical - getMixer: function () { + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { - return this._mixer; + updateCommonMaterialProperties( material, parameters ); - }, + return program; - getClip: function () { + } - return this._clip; + } else { - }, + parameters.uniforms = programCache.getUniforms( material ); - getRoot: function () { + material.onBeforeCompile( parameters, _this ); - return this._localRoot || this._mixer._root; + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - }, + materialProperties.uniforms = parameters.uniforms; - // Interna + } - _update: function ( time, deltaTime, timeDirection, accuIndex ) { + const uniforms = materialProperties.uniforms; - // called by the mixer + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - if ( ! this.enabled ) { + uniforms.clippingPlanes = clipping.uniform; - // call ._updateWeight() to update ._effectiveWeight + } - this._updateWeight( time ); - return; + updateCommonMaterialProperties( material, parameters ); - } + // store the light setup it was created for - var startTime = this._startTime; + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - if ( startTime !== null ) { + if ( materialProperties.needsLights ) { - // check for scheduled start of action + // wire up the material to this renderer's lighting state - var timeRunning = ( time - startTime ) * timeDirection; - if ( timeRunning < 0 || timeDirection === 0 ) { + 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; - return; // yet to come / don't decide when delta = 0 + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms } - // start + materialProperties.currentProgram = program; + materialProperties.uniformsList = null; - this._startTime = null; // unschedule - deltaTime = timeDirection * timeRunning; + return program; } - // apply time scale and advance time + function getUniformList( materialProperties ) { - deltaTime *= this._updateTimeScale( time ); - var clipTime = this._updateTime( deltaTime ); + if ( materialProperties.uniformsList === null ) { - // note: _updateTime may disable the action resulting in - // an effective weight of 0 + const progUniforms = materialProperties.currentProgram.getUniforms(); + materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms ); - var weight = this._updateWeight( time ); + } - if ( weight > 0 ) { + return materialProperties.uniformsList; - var interpolants = this._interpolants; - var propertyMixers = this._propertyBindings; + } - for ( var j = 0, m = interpolants.length; j !== m; ++ j ) { + function updateCommonMaterialProperties( material, parameters ) { - interpolants[ j ].evaluate( clipTime ); - propertyMixers[ j ].accumulate( accuIndex, weight ); + const materialProperties = properties.get( material ); - } + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.batching = parameters.batching; + materialProperties.batchingColor = parameters.batchingColor; + materialProperties.instancing = parameters.instancing; + materialProperties.instancingColor = parameters.instancingColor; + materialProperties.instancingMorph = parameters.instancingMorph; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } - }, + function setProgram( camera, scene, geometry, material, object ) { - _updateWeight: function ( time ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - var weight = 0; + textures.resetTextureUnits(); - if ( this.enabled ) { + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + 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 = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; - weight = this.weight; - var interpolant = this._weightInterpolant; + let toneMapping = NoToneMapping; - if ( interpolant !== null ) { + if ( material.toneMapped ) { - var interpolantValue = interpolant.evaluate( time )[ 0 ]; + if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) { - weight *= interpolantValue; + toneMapping = _this.toneMapping; - if ( time > interpolant.parameterPositions[ 1 ] ) { + } - this.stopFading(); + } - if ( interpolantValue === 0 ) { + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - // faded out, disable - this.enabled = false; + 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; + + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); } } - } - - this._effectiveWeight = weight; - return weight; + // - }, + let needsProgramChange = false; - _updateTimeScale: function ( time ) { + if ( material.version === materialProperties.__version ) { - var timeScale = 0; + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - if ( ! this.paused ) { + needsProgramChange = true; - timeScale = this.timeScale; + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - var interpolant = this._timeScaleInterpolant; + needsProgramChange = true; - if ( interpolant !== null ) { + } else if ( object.isBatchedMesh && materialProperties.batching === false ) { - var interpolantValue = interpolant.evaluate( time )[ 0 ]; + needsProgramChange = true; - timeScale *= interpolantValue; + } else if ( ! object.isBatchedMesh && materialProperties.batching === true ) { - if ( time > interpolant.parameterPositions[ 1 ] ) { + needsProgramChange = true; - this.stopWarping(); + } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { - if ( timeScale === 0 ) { + needsProgramChange = true; - // motion has halted, pause - this.paused = true; + } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { - } else { + needsProgramChange = true; - // warp done - apply final time scale - this.timeScale = timeScale; + } 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 ) { - this._effectiveTimeScale = timeScale; - return timeScale; + needsProgramChange = true; - }, + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - _updateTime: function ( deltaTime ) { + needsProgramChange = true; - var time = this.time + deltaTime; + } else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) { - if ( deltaTime === 0 ) { return time; } + needsProgramChange = true; - var duration = this._clip.duration, + } else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) { - loop = this.loop, - loopCount = this._loopCount; + needsProgramChange = true; - if ( loop === LoopOnce ) { + } else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) { - if ( loopCount === - 1 ) { + needsProgramChange = true; - // just started + } else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) { - this._loopCount = 0; - this._setEndings( true, true, false ); + needsProgramChange = true; - } + } else if ( materialProperties.envMap !== envMap ) { - handle_stop: { + needsProgramChange = true; - if ( time >= duration ) { + } else if ( material.fog === true && materialProperties.fog !== fog ) { - time = duration; + needsProgramChange = true; - } else if ( time < 0 ) { + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - time = 0; + needsProgramChange = true; - } else { break handle_stop; } + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - if ( this.clampWhenFinished ) { this.paused = true; } - else { this.enabled = false; } + needsProgramChange = true; - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime < 0 ? - 1 : 1 - } ); + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - } + needsProgramChange = true; - } else { // repetitive Repeat or PingPong + } else if ( materialProperties.morphTargets !== morphTargets ) { - var pingPong = ( loop === LoopPingPong ); + needsProgramChange = true; - if ( loopCount === - 1 ) { + } else if ( materialProperties.morphNormals !== morphNormals ) { - // just started + needsProgramChange = true; - if ( deltaTime >= 0 ) { + } else if ( materialProperties.morphColors !== morphColors ) { - loopCount = 0; + needsProgramChange = true; - this._setEndings( true, this.repetitions === 0, pingPong ); + } else if ( materialProperties.toneMapping !== toneMapping ) { - } else { + needsProgramChange = true; - // when looping in reverse direction, the initial - // transition through zero counts as a repetition, - // so leave loopCount at -1 + } else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) { - this._setEndings( this.repetitions === 0, true, pingPong ); + needsProgramChange = true; } - } + } else { - if ( time >= duration || time < 0 ) { + needsProgramChange = true; + materialProperties.__version = material.version; - // wrap around + } - var loopDelta = Math.floor( time / duration ); // signed - time -= duration * loopDelta; + // - loopCount += Math.abs( loopDelta ); + let program = materialProperties.currentProgram; - var pending = this.repetitions - loopCount; + if ( needsProgramChange === true ) { - if ( pending < 0 ) { + program = getProgram( material, scene, object ); - // have to stop (switch state, clamp time, fire event) + } - if ( this.clampWhenFinished ) { this.paused = true; } - else { this.enabled = false; } + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - time = deltaTime > 0 ? duration : 0; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime > 0 ? 1 : - 1 - } ); + if ( state.useProgram( program.program ) ) { - } else { + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - // keep running + } - if ( pending === 0 ) { + if ( material.id !== _currentMaterialId ) { - // entering the last round + _currentMaterialId = material.id; - var atStart = deltaTime < 0; - this._setEndings( atStart, ! atStart, pingPong ); + refreshMaterial = true; - } else { + } - this._setEndings( false, false, pingPong ); + if ( refreshProgram || _currentCamera !== camera ) { - } + // common camera uniforms - this._loopCount = loopCount; + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - this._mixer.dispatchEvent( { - type: 'loop', action: this, loopDelta: loopDelta - } ); + const uCamPos = p_uniforms.map.cameraPosition; - } + if ( uCamPos !== undefined ) { - } + uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) ); - if ( pingPong && ( loopCount & 1 ) === 1 ) { + } - // invert time for the "pong round" + if ( capabilities.logarithmicDepthBuffer ) { - this.time = time; - return duration - time; + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); - } + } - } + // consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067 - this.time = time; - return time; + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - }, + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - _setEndings: function ( atStart, atEnd, pingPong ) { + } - var settings = this._interpolantSettings; + if ( _currentCamera !== camera ) { - if ( pingPong ) { + _currentCamera = camera; - settings.endingStart = ZeroSlopeEnding; - settings.endingEnd = ZeroSlopeEnding; + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - } else { + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - // assuming for LoopOnce atStart == atEnd == true + } - if ( atStart ) { + } - settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - } else { + if ( object.isSkinnedMesh ) { - settings.endingStart = WrapAroundEnding; + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - } + const skeleton = object.skeleton; - if ( atEnd ) { + if ( skeleton ) { - settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - } else { + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - settings.endingEnd = WrapAroundEnding; + } } - } - - }, + if ( object.isBatchedMesh ) { - _scheduleFading: function ( duration, weightNow, weightThen ) { + p_uniforms.setOptional( _gl, object, 'batchingTexture' ); + p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); - var mixer = this._mixer, now = mixer.time, - interpolant = this._weightInterpolant; + p_uniforms.setOptional( _gl, object, 'batchingIdTexture' ); + p_uniforms.setValue( _gl, 'batchingIdTexture', object._indirectTexture, textures ); - if ( interpolant === null ) { + p_uniforms.setOptional( _gl, object, 'batchingColorTexture' ); + if ( object._colorsTexture !== null ) { - interpolant = mixer._lendControlInterpolant(); - this._weightInterpolant = interpolant; + p_uniforms.setValue( _gl, 'batchingColorTexture', object._colorsTexture, textures ); - } + } - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; + } - times[ 0 ] = now; values[ 0 ] = weightNow; - times[ 1 ] = now + duration; values[ 1 ] = weightThen; + const morphAttributes = geometry.morphAttributes; - return this; + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) { - } + morphtargets.update( object, geometry, program ); -} ); + } -/** - * - * Player for AnimationClips. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { -function AnimationMixer( root ) { + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); - this._root = root; - this._initMemoryManager(); - this._accuIndex = 0; + } - this.time = 0; + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - this.timeScale = 1.0; + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { -} + m_uniforms.envMap.value = envMap; -AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - constructor: AnimationMixer, + } - _bindAction: function ( action, prototypeAction ) { + if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) { - var root = action._localRoot || this._root, - tracks = action._clip.tracks, - nTracks = tracks.length, - bindings = action._propertyBindings, - interpolants = action._interpolants, - rootUuid = root.uuid, - bindingsByRoot = this._bindingsByRootAndName, - bindingsByName = bindingsByRoot[ rootUuid ]; + m_uniforms.envMapIntensity.value = scene.environmentIntensity; - if ( bindingsByName === undefined ) { + } - bindingsByName = {}; - bindingsByRoot[ rootUuid ] = bindingsByName; + if ( refreshMaterial ) { - } + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - for ( var i = 0; i !== nTracks; ++ i ) { + if ( materialProperties.needsLights ) { - var track = tracks[ i ], - trackName = track.name, - binding = bindingsByName[ trackName ]; + // the current material requires lighting info - if ( binding !== undefined ) { + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - bindings[ i ] = binding; + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); - } else { + } - binding = bindings[ i ]; + // refresh uniforms common to several materials - if ( binding !== undefined ) { + if ( fog && material.fog === true ) { - // existing binding, make sure the cache knows + materials.refreshFogUniforms( m_uniforms, fog ); - if ( binding._cacheIndex === null ) { + } - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget[ camera.id ] ); - } + WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); - continue; + } - } + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - var path = prototypeAction && prototypeAction. - _propertyBindings[ i ].binding.parsedPath; + WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); + material.uniformsNeedUpdate = false; - binding = new PropertyMixer( - PropertyBinding.create( root, trackName, path ), - track.ValueTypeName, track.getValueSize() ); + } - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); + if ( material.isSpriteMaterial ) { - bindings[ i ] = binding; + p_uniforms.setValue( _gl, 'center', object.center ); } - interpolants[ i ].resultBuffer = binding.buffer; + // common matrices - } - - }, + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - _activateAction: function ( action ) { + // UBOs - if ( ! this._isActiveAction( action ) ) { + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - if ( action._cacheIndex === null ) { + const groups = material.uniformsGroups; - // this action has been forgotten by the cache, but the user - // appears to be still using it -> rebind + for ( let i = 0, l = groups.length; i < l; i ++ ) { - var rootUuid = ( action._localRoot || this._root ).uuid, - clipUuid = action._clip.uuid, - actionsForClip = this._actionsByClip[ clipUuid ]; + const group = groups[ i ]; - this._bindAction( action, - actionsForClip && actionsForClip.knownActions[ 0 ] ); + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - this._addInactiveAction( action, clipUuid, rootUuid ); + } } - var bindings = action._propertyBindings; + return program; - // increment reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( binding.useCount ++ === 0 ) { + } - this._lendBinding( binding ); - binding.saveOriginalState(); + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - } + function markUniformsLightsNeedsUpdate( uniforms, value ) { - } + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - this._lendAction( action ); + 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 ) { - _deactivateAction: function ( action ) { + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - if ( this._isActiveAction( action ) ) { + } - var bindings = action._propertyBindings; + this.getActiveCubeFace = function () { - // decrement reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { + return _currentActiveCubeFace; - var binding = bindings[ i ]; + }; - if ( -- binding.useCount === 0 ) { + this.getActiveMipmapLevel = function () { - binding.restoreOriginalState(); - this._takeBackBinding( binding ); + return _currentActiveMipmapLevel; - } + }; - } + this.getRenderTarget = function () { - this._takeBackAction( action ); + return _currentRenderTarget; - } + }; - }, + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - // Memory manager + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - _initMemoryManager: function () { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - this._actions = []; // 'nActiveActions' followed by inactive ones - this._nActiveActions = 0; + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - this._actionsByClip = {}; - // inside: - // { - // knownActions: Array< AnimationAction > - used as prototypes - // actionByRoot: AnimationAction - lookup - // } + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - this._bindings = []; // 'nActiveBindings' followed by inactive ones - this._nActiveBindings = 0; + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > + } + } - this._controlInterpolants = []; // same game as above - this._nActiveControlInterpolants = 0; + }; - var scope = this; + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - this.stats = { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - actions: { - get total() { + }; - return scope._actions.length; + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - }, - get inUse() { + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - return scope._nActiveActions; + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - } - }, - bindings: { - get total() { + if ( renderTarget ) { - return scope._bindings.length; + const renderTargetProperties = properties.get( renderTarget ); - }, - get inUse() { + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - return scope._nActiveBindings; + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - } - }, - controlInterpolants: { - get total() { + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - return scope._controlInterpolants.length; + textures.setupRenderTarget( renderTarget ); - }, - get inUse() { + } else if ( renderTargetProperties.__hasExternalTextures ) { - return scope._nActiveControlInterpolants; + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); } - } - }; + const texture = renderTarget.texture; - }, + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - // Memory management for AnimationAction objects + isRenderTarget3D = true; - _isActiveAction: function ( action ) { + } - var index = action._cacheIndex; - return index !== null && index < this._nActiveActions; + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - }, + if ( renderTarget.isWebGLCubeRenderTarget ) { - _addInactiveAction: function ( action, clipUuid, rootUuid ) { + if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) { - var actions = this._actions, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; + framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ]; - if ( actionsForClip === undefined ) { + } else { - actionsForClip = { + framebuffer = __webglFramebuffer[ activeCubeFace ]; - knownActions: [ action ], - actionByRoot: {} + } - }; + isCube = true; - action._byClipCacheIndex = 0; + } else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - actionsByClip[ clipUuid ] = actionsForClip; + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - } else { + } else { - var knownActions = actionsForClip.knownActions; + if ( Array.isArray( __webglFramebuffer ) ) { - action._byClipCacheIndex = knownActions.length; - knownActions.push( action ); + framebuffer = __webglFramebuffer[ activeMipmapLevel ]; - } + } else { - action._cacheIndex = actions.length; - actions.push( action ); + framebuffer = __webglFramebuffer; - actionsForClip.actionByRoot[ rootUuid ] = action; + } - }, + } - _removeInactiveAction: function ( action ) { + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; - var actions = this._actions, - lastInactiveAction = actions[ actions.length - 1 ], - cacheIndex = action._cacheIndex; + } else { - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; - action._cacheIndex = null; + } + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - var clipUuid = action._clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ], - knownActionsForClip = actionsForClip.knownActions, + if ( framebufferBound && useDefaultFramebuffer ) { - lastKnownAction = - knownActionsForClip[ knownActionsForClip.length - 1 ], + state.drawBuffers( renderTarget, framebuffer ); - byClipCacheIndex = action._byClipCacheIndex; + } - lastKnownAction._byClipCacheIndex = byClipCacheIndex; - knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; - knownActionsForClip.pop(); + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - action._byClipCacheIndex = null; + 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 ); - var actionByRoot = actionsForClip.actionByRoot, - rootUuid = ( action._localRoot || this._root ).uuid; + } else if ( isRenderTarget3D ) { - delete actionByRoot[ rootUuid ]; + const textureProperties = properties.get( renderTarget.texture ); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); - if ( knownActionsForClip.length === 0 ) { + } - delete actionsByClip[ clipUuid ]; + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - } + }; - this._removeInactiveBindingsForAction( action ); + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - }, + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - _removeInactiveBindingsForAction: function ( action ) { + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - var bindings = action._propertyBindings; - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { + } - var binding = bindings[ i ]; + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( -- binding.referenceCount === 0 ) { + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - this._removeInactiveBinding( binding ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; } - } - - }, + if ( framebuffer ) { - _lendAction: function ( action ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - // [ active actions | inactive actions ] - // [ active actions >| inactive actions ] - // s a - // <-swap-> - // a s + try { - var actions = this._actions, - prevIndex = action._cacheIndex, + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - lastActiveIndex = this._nActiveActions ++, + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - firstInactiveAction = actions[ lastActiveIndex ]; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - action._cacheIndex = lastActiveIndex; - actions[ lastActiveIndex ] = action; + } - firstInactiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = firstInactiveAction; + if ( ! capabilities.textureTypeReadable( textureType ) ) { - }, + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - _takeBackAction: function ( action ) { + } - // [ active actions | inactive actions ] - // [ active actions |< inactive actions ] - // a s - // <-swap-> - // s a + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - var actions = this._actions, - prevIndex = action._cacheIndex, + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - firstInactiveIndex = -- this._nActiveActions, + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - lastActiveAction = actions[ firstInactiveIndex ]; + } - action._cacheIndex = firstInactiveIndex; - actions[ firstInactiveIndex ] = action; + } finally { - lastActiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = lastActiveAction; + // restore framebuffer of current render target if necessary - }, + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - // Memory management for PropertyMixer objects + } - _addInactiveBinding: function ( binding, rootUuid, trackName ) { + } - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], + }; - bindings = this._bindings; + this.readRenderTargetPixelsAsync = async function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - if ( bindingByName === undefined ) { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - bindingByName = {}; - bindingsByRoot[ rootUuid ] = bindingByName; + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - } + } - bindingByName[ trackName ] = binding; + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - binding._cacheIndex = bindings.length; - bindings.push( binding ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; - }, + } - _removeInactiveBinding: function ( binding ) { + if ( framebuffer ) { - var bindings = this._bindings, - propBinding = binding.binding, - rootUuid = propBinding.rootNode.uuid, - trackName = propBinding.path, - bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - lastInactiveBinding = bindings[ bindings.length - 1 ], - cacheIndex = binding._cacheIndex; + try { - lastInactiveBinding._cacheIndex = cacheIndex; - bindings[ cacheIndex ] = lastInactiveBinding; - bindings.pop(); + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - delete bindingByName[ trackName ]; + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - remove_empty_map: { + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); - for ( var _ in bindingByName ) { break remove_empty_map; } // eslint-disable-line no-unused-vars + } - delete bindingsByRoot[ rootUuid ]; + if ( ! capabilities.textureTypeReadable( textureType ) ) { - } + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); - }, + } - _lendBinding: function ( binding ) { + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - var bindings = this._bindings, - prevIndex = binding._cacheIndex, + const glBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); + _gl.flush(); - lastActiveIndex = this._nActiveBindings ++, + // check if the commands have finished every 8 ms + const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); + await probeAsync( _gl, sync, 4 ); - firstInactiveBinding = bindings[ lastActiveIndex ]; + try { - binding._cacheIndex = lastActiveIndex; - bindings[ lastActiveIndex ] = binding; + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); - firstInactiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = firstInactiveBinding; + } finally { - }, + _gl.deleteBuffer( glBuffer ); + _gl.deleteSync( sync ); - _takeBackBinding: function ( binding ) { + } - var bindings = this._bindings, - prevIndex = binding._cacheIndex, + return buffer; - firstInactiveIndex = -- this._nActiveBindings, + } - lastActiveBinding = bindings[ firstInactiveIndex ]; + } finally { - binding._cacheIndex = firstInactiveIndex; - bindings[ firstInactiveIndex ] = binding; + // restore framebuffer of current render target if necessary - lastActiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = lastActiveBinding; + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - }, + } + } - // Memory management of Interpolants for weight and time scale + }; - _lendControlInterpolant: function () { + this.copyFramebufferToTexture = function ( texture, position = null, level = 0 ) { - var interpolants = this._controlInterpolants, - lastActiveIndex = this._nActiveControlInterpolants ++, - interpolant = interpolants[ lastActiveIndex ]; + // support previous signature with position first + if ( texture.isTexture !== true ) { - if ( interpolant === undefined ) { + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyFramebufferToTexture function signature has changed.' ); - interpolant = new LinearInterpolant( - new Float32Array( 2 ), new Float32Array( 2 ), - 1, this._controlInterpolantsResultBuffer ); + position = arguments[ 0 ] || null; + texture = arguments[ 1 ]; - interpolant.__cacheIndex = lastActiveIndex; - interpolants[ lastActiveIndex ] = interpolant; + } - } + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - return interpolant; + const x = position !== null ? position.x : 0; + const y = position !== null ? position.y : 0; - }, + textures.setTexture2D( texture, 0 ); - _takeBackControlInterpolant: function ( interpolant ) { + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, x, y, width, height ); - var interpolants = this._controlInterpolants, - prevIndex = interpolant.__cacheIndex, + state.unbindTexture(); - firstInactiveIndex = -- this._nActiveControlInterpolants, + }; - lastActiveInterpolant = interpolants[ firstInactiveIndex ]; + this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { - interpolant.__cacheIndex = firstInactiveIndex; - interpolants[ firstInactiveIndex ] = interpolant; + // support previous signature with dstPosition first + if ( srcTexture.isTexture !== true ) { - lastActiveInterpolant.__cacheIndex = prevIndex; - interpolants[ prevIndex ] = lastActiveInterpolant; + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyTextureToTexture function signature has changed.' ); - }, + dstPosition = arguments[ 0 ] || null; + srcTexture = arguments[ 1 ]; + dstTexture = arguments[ 2 ]; + level = arguments[ 3 ] || 0; + srcRegion = null; - _controlInterpolantsResultBuffer: new Float32Array( 1 ), + } - // return an action for a clip optionally using a custom root target - // object (this method allocates a lot of dynamic memory in case a - // previously unknown clip/root combination is specified) - clipAction: function ( clip, optionalRoot ) { + let width, height, minX, minY; + let dstX, dstY; + if ( srcRegion !== null ) { - var root = optionalRoot || this._root, - rootUuid = root.uuid, + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + minX = srcRegion.min.x; + minY = srcRegion.min.y; - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, + } else { - clipUuid = clipObject !== null ? clipObject.uuid : clip, + width = srcTexture.image.width; + height = srcTexture.image.height; + minX = 0; + minY = 0; - actionsForClip = this._actionsByClip[ clipUuid ], - prototypeAction = null; + } - if ( actionsForClip !== undefined ) { + if ( dstPosition !== null ) { - var existingAction = - actionsForClip.actionByRoot[ rootUuid ]; + dstX = dstPosition.x; + dstY = dstPosition.y; - if ( existingAction !== undefined ) { + } else { - return existingAction; + dstX = 0; + dstY = 0; } - // we know the clip, so we don't have to parse all - // the bindings again but can just copy - prototypeAction = actionsForClip.knownActions[ 0 ]; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - // also, take the clip from the prototype action - if ( clipObject === null ) - { clipObject = prototypeAction._clip; } + textures.setTexture2D( dstTexture, 0 ); - } - - // clip must be known when specified via string - if ( clipObject === null ) { return null; } + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _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 ); - // allocate all resources required to run it - var newAction = new AnimationAction( this, clipObject, optionalRoot ); + const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - this._bindAction( newAction, prototypeAction ); + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; - // and make the action known to the memory manager - this._addInactiveAction( newAction, clipUuid, rootUuid ); + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); - return newAction; + if ( srcTexture.isDataTexture ) { - }, + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); - // get an existing action - existingAction: function ( clip, optionalRoot ) { + } else { - var root = optionalRoot || this._root, - rootUuid = root.uuid, + if ( srcTexture.isCompressedTexture ) { - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); - clipUuid = clipObject ? clipObject.uuid : clip, + } else { - actionsForClip = this._actionsByClip[ clipUuid ]; + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image ); - if ( actionsForClip !== undefined ) { + } - return actionsForClip.actionByRoot[ rootUuid ] || null; + } - } + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); - return null; + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - }, + state.unbindTexture(); - // deactivates all previously scheduled actions - stopAllAction: function () { + }; - var actions = this._actions, - nActions = this._nActiveActions, - bindings = this._bindings, - nBindings = this._nActiveBindings; + this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { - this._nActiveActions = 0; - this._nActiveBindings = 0; + // support previous signature with source box first + if ( srcTexture.isTexture !== true ) { - for ( var i = 0; i !== nActions; ++ i ) { + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' ); - actions[ i ].reset(); + srcRegion = arguments[ 0 ] || null; + dstPosition = arguments[ 1 ] || null; + srcTexture = arguments[ 2 ]; + dstTexture = arguments[ 3 ]; + level = arguments[ 4 ] || 0; - } + } - for ( var i = 0; i !== nBindings; ++ i ) { + let width, height, depth, minX, minY, minZ; + let dstX, dstY, dstZ; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; + if ( srcRegion !== null ) { - bindings[ i ].useCount = 0; + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + depth = srcRegion.max.z - srcRegion.min.z; + minX = srcRegion.min.x; + minY = srcRegion.min.y; + minZ = srcRegion.min.z; - } + } else { - return this; + width = image.width; + height = image.height; + depth = image.depth; + minX = 0; + minY = 0; + minZ = 0; - }, + } - // advance the time and update apply the animation - update: function ( deltaTime ) { + if ( dstPosition !== null ) { - deltaTime *= this.timeScale; + dstX = dstPosition.x; + dstY = dstPosition.y; + dstZ = dstPosition.z; - var actions = this._actions, - nActions = this._nActiveActions, + } else { - time = this.time += deltaTime, - timeDirection = Math.sign( deltaTime ), + dstX = 0; + dstY = 0; + dstZ = 0; - accuIndex = this._accuIndex ^= 1; + } - // run active actions + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - for ( var i = 0; i !== nActions; ++ i ) { + if ( dstTexture.isData3DTexture ) { - var action = actions[ i ]; + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - action._update( time, deltaTime, timeDirection, accuIndex ); + } else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) { - } + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; - // update scene graph + } else { - var bindings = this._bindings, - nBindings = this._nActiveBindings; + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; - for ( var i = 0; i !== nBindings; ++ i ) { + } - bindings[ i ].apply( accuIndex ); + _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 currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - return this; + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ ); - }, + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - // return this mixer's root target object - getRoot: function () { + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data ); - return this._root; + } else { - }, + if ( dstTexture.isCompressedArrayTexture ) { - // free all resources specific to a particular clip - uncacheClip: function ( clip ) { + _gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data ); - var actions = this._actions, - clipUuid = clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; + } else { - if ( actionsForClip !== undefined ) { + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image ); - // note: just calling _removeInactiveAction would mess up the - // iteration state and also require updating the state we can - // just throw away + } - var actionsToRemove = actionsForClip.knownActions; + } - for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); - var action = actionsToRemove[ i ]; + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - this._deactivateAction( action ); + state.unbindTexture(); - var cacheIndex = action._cacheIndex, - lastInactiveAction = actions[ actions.length - 1 ]; + }; - action._cacheIndex = null; - action._byClipCacheIndex = null; + this.initRenderTarget = function ( target ) { - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); + if ( properties.get( target ).__webglFramebuffer === undefined ) { - this._removeInactiveBindingsForAction( action ); + textures.setupRenderTarget( target ); } - delete actionsByClip[ clipUuid ]; + }; - } + this.initTexture = function ( texture ) { - }, + if ( texture.isCubeTexture ) { - // free all resources specific to a particular root target object - uncacheRoot: function ( root ) { + textures.setTextureCube( texture, 0 ); - var rootUuid = root.uuid, - actionsByClip = this._actionsByClip; + } else if ( texture.isData3DTexture ) { - for ( var clipUuid in actionsByClip ) { + textures.setTexture3D( texture, 0 ); - var actionByRoot = actionsByClip[ clipUuid ].actionByRoot, - action = actionByRoot[ rootUuid ]; + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - if ( action !== undefined ) { + textures.setTexture2DArray( texture, 0 ); - this._deactivateAction( action ); - this._removeInactiveAction( action ); + } else { + + textures.setTexture2D( texture, 0 ); } - } + state.unbindTexture(); + + }; + + this.resetState = function () { - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ]; + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - if ( bindingByName !== undefined ) { + state.reset(); + bindingStates.reset(); - for ( var trackName in bindingByName ) { + }; - var binding = bindingByName[ trackName ]; - binding.restoreOriginalState(); - this._removeInactiveBinding( binding ); + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - } + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); } - }, + } - // remove a targeted clip from the cache - uncacheAction: function ( clip, optionalRoot ) { + get coordinateSystem() { - var action = this.existingAction( clip, optionalRoot ); + return WebGLCoordinateSystem; - if ( action !== null ) { + } - this._deactivateAction( action ); - this._removeInactiveAction( action ); + get outputColorSpace() { - } + return this._outputColorSpace; } -} ); + set outputColorSpace( colorSpace ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + this._outputColorSpace = colorSpace; -function Uniform( value ) { + const gl = this.getContext(); + gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb'; + gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb'; - if ( typeof value === 'string' ) { + } - console.warn( 'THREE.Uniform: Type parameter is no longer needed.' ); - value = arguments[ 1 ]; +} - } +class Scene extends Object3D { - this.value = value; + constructor() { -} + super(); -Uniform.prototype.clone = function () { + this.isScene = true; - return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); + this.type = 'Scene'; -}; + this.background = null; + this.environment = null; + this.fog = null; -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + this.backgroundBlurriness = 0; + this.backgroundIntensity = 1; + this.backgroundRotation = new Euler(); -function InstancedBufferGeometry() { + this.environmentIntensity = 1; + this.environmentRotation = new Euler(); - BufferGeometry.call( this ); + this.overrideMaterial = null; - this.type = 'InstancedBufferGeometry'; - this.maxInstancedCount = undefined; + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { -} + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); -InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), { + } - constructor: InstancedBufferGeometry, + } - isInstancedBufferGeometry: true, + copy( source, recursive ) { - copy: function ( source ) { + super.copy( source, recursive ); - BufferGeometry.prototype.copy.call( this, source ); + 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(); - this.maxInstancedCount = source.maxInstancedCount; + this.backgroundBlurriness = source.backgroundBlurriness; + this.backgroundIntensity = source.backgroundIntensity; + this.backgroundRotation.copy( source.backgroundRotation ); - return this; + this.environmentIntensity = source.environmentIntensity; + this.environmentRotation.copy( source.environmentRotation ); - }, + if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); - clone: function () { + this.matrixAutoUpdate = source.matrixAutoUpdate; - return new this.constructor().copy( this ); + return this; } -} ); + toJSON( meta ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + const data = super.toJSON( meta ); + + if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); -function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) { + if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; + if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; + data.object.backgroundRotation = this.backgroundRotation.toArray(); - this.uuid = _Math.generateUUID(); + if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity; + data.object.environmentRotation = this.environmentRotation.toArray(); - this.data = interleavedBuffer; - this.itemSize = itemSize; - this.offset = offset; + return data; - this.normalized = normalized === true; + } } -Object.defineProperties( InterleavedBufferAttribute.prototype, { +class InterleavedBuffer { - count: { + constructor( array, stride ) { - get: function () { + this.isInterleavedBuffer = true; - return this.data.count; + this.array = array; + this.stride = stride; + this.count = array !== undefined ? array.length / stride : 0; - } + this.usage = StaticDrawUsage; + this._updateRange = { offset: 0, count: - 1 }; + this.updateRanges = []; - }, + this.version = 0; + + this.uuid = generateUUID(); - array: { + } - get: function () { + onUploadCallback() {} - return this.data.array; + set needsUpdate( value ) { - } + if ( value === true ) this.version ++; } -} ); + get updateRange() { -Object.assign( InterleavedBufferAttribute.prototype, { + warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 + return this._updateRange; - isInterleavedBufferAttribute: true, + } - setX: function ( index, x ) { + setUsage( value ) { - this.data.array[ index * this.data.stride + this.offset ] = x; + this.usage = value; return this; - }, + } - setY: function ( index, y ) { + addUpdateRange( start, count ) { - this.data.array[ index * this.data.stride + this.offset + 1 ] = y; + this.updateRanges.push( { start, count } ); - return this; + } - }, + clearUpdateRanges() { - setZ: function ( index, z ) { + this.updateRanges.length = 0; - this.data.array[ index * this.data.stride + this.offset + 2 ] = z; + } - return this; + copy( source ) { - }, + this.array = new source.array.constructor( source.array ); + this.count = source.count; + this.stride = source.stride; + this.usage = source.usage; - setW: function ( index, w ) { + return this; - this.data.array[ index * this.data.stride + this.offset + 3 ] = w; + } - return this; + copyAt( index1, attribute, index2 ) { - }, + index1 *= this.stride; + index2 *= attribute.stride; - getX: function ( index ) { + for ( let i = 0, l = this.stride; i < l; i ++ ) { - return this.data.array[ index * this.data.stride + this.offset ]; + this.array[ index1 + i ] = attribute.array[ index2 + i ]; - }, + } - getY: function ( index ) { + return this; - return this.data.array[ index * this.data.stride + this.offset + 1 ]; + } - }, + set( value, offset = 0 ) { - getZ: function ( index ) { + this.array.set( value, offset ); - return this.data.array[ index * this.data.stride + this.offset + 2 ]; + return this; - }, + } - getW: function ( index ) { + clone( data ) { - return this.data.array[ index * this.data.stride + this.offset + 3 ]; + if ( data.arrayBuffers === undefined ) { - }, + data.arrayBuffers = {}; - setXY: function ( index, x, y ) { + } - index = index * this.data.stride + this.offset; + if ( this.array.buffer._uuid === undefined ) { - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; + this.array.buffer._uuid = generateUUID(); - return this; + } - }, + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { - setXYZ: function ( index, x, y, z ) { + data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; - index = index * this.data.stride + this.offset; + } - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; + const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); - return this; + const ib = new this.constructor( array, this.stride ); + ib.setUsage( this.usage ); - }, + return ib; - setXYZW: function ( index, x, y, z, w ) { + } - index = index * this.data.stride + this.offset; + onUpload( callback ) { - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; - this.data.array[ index + 3 ] = w; + this.onUploadCallback = callback; return this; } -} ); - -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ - -function InterleavedBuffer( array, stride ) { + toJSON( data ) { - this.uuid = _Math.generateUUID(); + if ( data.arrayBuffers === undefined ) { - this.array = array; - this.stride = stride; - this.count = array !== undefined ? array.length / stride : 0; + data.arrayBuffers = {}; - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; + } - this.onUploadCallback = function () {}; + // generate UUID for array buffer if necessary - this.version = 0; + if ( this.array.buffer._uuid === undefined ) { -} + this.array.buffer._uuid = generateUUID(); -Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', { + } - set: function ( value ) { + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { - if ( value === true ) { this.version ++; } + data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); - } + } -} ); + // -Object.assign( InterleavedBuffer.prototype, { + return { + uuid: this.uuid, + buffer: this.array.buffer._uuid, + type: this.array.constructor.name, + stride: this.stride + }; - isInterleavedBuffer: true, + } - setArray: function ( array ) { +} - if ( Array.isArray( array ) ) { +const _vector$6 = /*@__PURE__*/ new Vector3(); - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); +class InterleavedBufferAttribute { - } + constructor( interleavedBuffer, itemSize, offset, normalized = false ) { - this.count = array !== undefined ? array.length / this.stride : 0; - this.array = array; + this.isInterleavedBufferAttribute = true; - }, + this.name = ''; - setDynamic: function ( value ) { + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; - this.dynamic = value; + this.normalized = normalized; - return this; + } - }, + get count() { - copy: function ( source ) { + return this.data.count; - this.array = new source.array.constructor( source.array ); - this.count = source.count; - this.stride = source.stride; - this.dynamic = source.dynamic; + } - return this; + get array() { - }, + return this.data.array; - copyAt: function ( index1, attribute, index2 ) { + } - index1 *= this.stride; - index2 *= attribute.stride; + set needsUpdate( value ) { - for ( var i = 0, l = this.stride; i < l; i ++ ) { + this.data.needsUpdate = value; - this.array[ index1 + i ] = attribute.array[ index2 + i ]; + } - } + applyMatrix4( m ) { - return this; + for ( let i = 0, l = this.data.count; i < l; i ++ ) { - }, + _vector$6.fromBufferAttribute( this, i ); - set: function ( value, offset ) { + _vector$6.applyMatrix4( m ); - if ( offset === undefined ) { offset = 0; } + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); - this.array.set( value, offset ); + } return this; - }, + } - clone: function () { + applyNormalMatrix( m ) { - return new this.constructor().copy( this ); + for ( let i = 0, l = this.count; i < l; i ++ ) { - }, + _vector$6.fromBufferAttribute( this, i ); - onUpload: function ( callback ) { + _vector$6.applyNormalMatrix( m ); - this.onUploadCallback = callback; + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + + } return this; } -} ); + transformDirection( m ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + for ( let i = 0, l = this.count; i < l; i ++ ) { -function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) { + _vector$6.fromBufferAttribute( this, i ); - InterleavedBuffer.call( this, array, stride ); + _vector$6.transformDirection( m ); - this.meshPerAttribute = meshPerAttribute || 1; - -} + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); -InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), { + } - constructor: InstancedInterleavedBuffer, + return this; - isInstancedInterleavedBuffer: true, + } - copy: function ( source ) { + getComponent( index, component ) { - InterleavedBuffer.prototype.copy.call( this, source ); + let value = this.array[ index * this.data.stride + this.offset + component ]; - this.meshPerAttribute = source.meshPerAttribute; + if ( this.normalized ) value = denormalize( value, this.array ); - return this; + return value; } -} ); + setComponent( index, component, value ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + if ( this.normalized ) value = normalize( value, this.array ); -function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) { + this.data.array[ index * this.data.stride + this.offset + component ] = value; + + return this; - BufferAttribute.call( this, array, itemSize ); + } - this.meshPerAttribute = meshPerAttribute || 1; + setX( index, x ) { -} + if ( this.normalized ) x = normalize( x, this.array ); -InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), { + this.data.array[ index * this.data.stride + this.offset ] = x; - constructor: InstancedBufferAttribute, + return this; - isInstancedBufferAttribute: true, + } - copy: function ( source ) { + setY( index, y ) { - BufferAttribute.prototype.copy.call( this, source ); + if ( this.normalized ) y = normalize( y, this.array ); - this.meshPerAttribute = source.meshPerAttribute; + this.data.array[ index * this.data.stride + this.offset + 1 ] = y; return this; } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author bhouston / http://clara.io/ - * @author stephomi / http://stephaneginier.com/ - */ - -function Raycaster( origin, direction, near, far ) { + setZ( index, z ) { - this.ray = new Ray( origin, direction ); - // direction is assumed to be normalized (for accurate distance calculations) + if ( this.normalized ) z = normalize( z, this.array ); - this.near = near || 0; - this.far = far || Infinity; + this.data.array[ index * this.data.stride + this.offset + 2 ] = z; - this.params = { - Mesh: {}, - Line: {}, - LOD: {}, - Points: { threshold: 1 }, - Sprite: {} - }; + return this; - Object.defineProperties( this.params, { - PointCloud: { - get: function () { + } - console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); - return this.Points; + setW( index, w ) { - } - } - } ); + if ( this.normalized ) w = normalize( w, this.array ); -} + this.data.array[ index * this.data.stride + this.offset + 3 ] = w; -function ascSort( a, b ) { + return this; - return a.distance - b.distance; + } -} + getX( index ) { -function intersectObject( object, raycaster, intersects, recursive ) { + let x = this.data.array[ index * this.data.stride + this.offset ]; - if ( object.visible === false ) { return; } + if ( this.normalized ) x = denormalize( x, this.array ); - object.raycast( raycaster, intersects ); + return x; - if ( recursive === true ) { + } - var children = object.children; + getY( index ) { - for ( var i = 0, l = children.length; i < l; i ++ ) { + let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; - intersectObject( children[ i ], raycaster, intersects, true ); + if ( this.normalized ) y = denormalize( y, this.array ); - } + return y; } -} + getZ( index ) { -Object.assign( Raycaster.prototype, { + let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; - linePrecision: 1, + if ( this.normalized ) z = denormalize( z, this.array ); - set: function ( origin, direction ) { + return z; - // direction is assumed to be normalized (for accurate distance calculations) + } - this.ray.set( origin, direction ); + getW( index ) { - }, + let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; - setFromCamera: function ( coords, camera ) { + if ( this.normalized ) w = denormalize( w, this.array ); - if ( ( camera && camera.isPerspectiveCamera ) ) { + return w; - this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); - this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); + } - } else if ( ( camera && camera.isOrthographicCamera ) ) { + setXY( index, x, y ) { - this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera - this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + index = index * this.data.stride + this.offset; - } else { + if ( this.normalized ) { - console.error( 'THREE.Raycaster: Unsupported camera type.' ); + x = normalize( x, this.array ); + y = normalize( y, this.array ); } - }, + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; - intersectObject: function ( object, recursive ) { + return this; - var intersects = []; + } - intersectObject( object, this, intersects, recursive ); + setXYZ( index, x, y, z ) { - intersects.sort( ascSort ); + index = index * this.data.stride + this.offset; - return intersects; + if ( this.normalized ) { - }, + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } - intersectObjects: function ( objects, recursive ) { + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; - var intersects = []; + return this; - if ( Array.isArray( objects ) === false ) { + } - console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); - return intersects; + setXYZW( index, x, y, z, w ) { - } + index = index * this.data.stride + this.offset; - for ( var i = 0, l = objects.length; i < l; i ++ ) { + if ( this.normalized ) { - intersectObject( objects[ i ], this, intersects, recursive ); + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); } - intersects.sort( ascSort ); + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; + this.data.array[ index + 3 ] = w; - return intersects; + return this; } -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - */ - -function Clock( autoStart ) { - - this.autoStart = ( autoStart !== undefined ) ? autoStart : true; + clone( data ) { - this.startTime = 0; - this.oldTime = 0; - this.elapsedTime = 0; + if ( data === undefined ) { - this.running = false; + console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); -} + const array = []; -Object.assign( Clock.prototype, { + for ( let i = 0; i < this.count; i ++ ) { - start: function () { + const index = i * this.data.stride + this.offset; - this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 + for ( let j = 0; j < this.itemSize; j ++ ) { - this.oldTime = this.startTime; - this.elapsedTime = 0; - this.running = true; + array.push( this.data.array[ index + j ] ); - }, + } - stop: function () { + } - this.getElapsedTime(); - this.running = false; - this.autoStart = false; + return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); - }, + } else { - getElapsedTime: function () { + if ( data.interleavedBuffers === undefined ) { - this.getDelta(); - return this.elapsedTime; + data.interleavedBuffers = {}; - }, + } - getDelta: function () { + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { - var diff = 0; + data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); - if ( this.autoStart && ! this.running ) { + } - this.start(); - return 0; + return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); } - if ( this.running ) { + } - var newTime = ( typeof performance === 'undefined' ? Date : performance ).now(); + toJSON( data ) { - diff = ( newTime - this.oldTime ) / 1000; - this.oldTime = newTime; + if ( data === undefined ) { - this.elapsedTime += diff; + console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); - } + const array = []; - return diff; + for ( let i = 0; i < this.count; i ++ ) { - } + const index = i * this.data.stride + this.offset; -} ); + for ( let j = 0; j < this.itemSize; j ++ ) { -/** - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - * - * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system - * - * The poles (phi) are at the positive and negative y axis. - * The equator starts at positive z. - */ + array.push( this.data.array[ index + j ] ); + + } -function Spherical( radius, phi, theta ) { + } - this.radius = ( radius !== undefined ) ? radius : 1.0; - this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole - this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere + // de-interleave data and save it as an ordinary buffer attribute for now - return this; + return { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: array, + normalized: this.normalized + }; -} + } else { -Object.assign( Spherical.prototype, { + // save as true interleaved attribute - set: function ( radius, phi, theta ) { + if ( data.interleavedBuffers === undefined ) { - this.radius = radius; - this.phi = phi; - this.theta = theta; + data.interleavedBuffers = {}; - return this; + } - }, + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { - clone: function () { + data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); - return new this.constructor().copy( this ); + } - }, + return { + isInterleavedBufferAttribute: true, + itemSize: this.itemSize, + data: this.data.uuid, + offset: this.offset, + normalized: this.normalized + }; - copy: function ( other ) { + } - this.radius = other.radius; - this.phi = other.phi; - this.theta = other.theta; + } - return this; +} - }, +class SpriteMaterial extends Material { - // restrict phi to be betwee EPS and PI-EPS - makeSafe: function () { + constructor( parameters ) { - var EPS = 0.000001; - this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); + super(); - return this; + this.isSpriteMaterial = true; - }, + this.type = 'SpriteMaterial'; - setFromVector3: function ( vec3 ) { + this.color = new Color( 0xffffff ); - this.radius = vec3.length(); + this.map = null; - if ( this.radius === 0 ) { + this.alphaMap = null; - this.theta = 0; - this.phi = 0; + this.rotation = 0; - } else { + this.sizeAttenuation = true; - this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis - this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle + this.transparent = true; - } + this.fog = true; - return this; + this.setValues( parameters ); } -} ); - -/** - * @author Mugen87 / https://github.com/Mugen87 - * - * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system - * - */ + copy( source ) { -function Cylindrical( radius, theta, y ) { + super.copy( source ); - this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane - this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis - this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane + this.color.copy( source.color ); - return this; + this.map = source.map; -} + this.alphaMap = source.alphaMap; -Object.assign( Cylindrical.prototype, { + this.rotation = source.rotation; - set: function ( radius, theta, y ) { + this.sizeAttenuation = source.sizeAttenuation; - this.radius = radius; - this.theta = theta; - this.y = y; + this.fog = source.fog; return this; - }, + } - clone: function () { +} - return new this.constructor().copy( this ); +let _geometry; - }, +const _intersectPoint = /*@__PURE__*/ new Vector3(); +const _worldScale = /*@__PURE__*/ new Vector3(); +const _mvPosition = /*@__PURE__*/ new Vector3(); - copy: function ( other ) { +const _alignedPosition = /*@__PURE__*/ new Vector2(); +const _rotatedPosition = /*@__PURE__*/ new Vector2(); +const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); - this.radius = other.radius; - this.theta = other.theta; - this.y = other.y; +const _vA$2 = /*@__PURE__*/ new Vector3(); +const _vB$2 = /*@__PURE__*/ new Vector3(); +const _vC$2 = /*@__PURE__*/ new Vector3(); - return this; +const _uvA = /*@__PURE__*/ new Vector2(); +const _uvB = /*@__PURE__*/ new Vector2(); +const _uvC = /*@__PURE__*/ new Vector2(); - }, +class Sprite extends Object3D { - setFromVector3: function ( vec3 ) { + constructor( material = new SpriteMaterial() ) { - this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z ); - this.theta = Math.atan2( vec3.x, vec3.z ); - this.y = vec3.y; + super(); - return this; + this.isSprite = true; - } + this.type = 'Sprite'; -} ); + if ( _geometry === undefined ) { -/** - * @author alteredq / http://alteredqualia.com/ - */ + _geometry = new BufferGeometry(); -function ImmediateRenderObject( material ) { + 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 + ] ); - Object3D.call( this ); + const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); - this.material = material; - this.render = function ( /* renderCallback */ ) {}; + _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 ) ); -} + } -ImmediateRenderObject.prototype = Object.create( Object3D.prototype ); -ImmediateRenderObject.prototype.constructor = ImmediateRenderObject; + this.geometry = _geometry; + this.material = material; -ImmediateRenderObject.prototype.isImmediateRenderObject = true; + this.center = new Vector2( 0.5, 0.5 ); -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + } -function VertexNormalsHelper( object, size, hex, linewidth ) { + raycast( raycaster, intersects ) { - this.object = object; + if ( raycaster.camera === null ) { - this.size = ( size !== undefined ) ? size : 1; + console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); - var color = ( hex !== undefined ) ? hex : 0xff0000; + } - var width = ( linewidth !== undefined ) ? linewidth : 1; + _worldScale.setFromMatrixScale( this.matrixWorld ); - // + _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); + this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); - var nNormals = 0; + _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); - var objGeometry = this.object.geometry; + if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { - if ( objGeometry && objGeometry.isGeometry ) { + _worldScale.multiplyScalar( - _mvPosition.z ); - nNormals = objGeometry.faces.length * 3; + } - } else if ( objGeometry && objGeometry.isBufferGeometry ) { + const rotation = this.material.rotation; + let sin, cos; - nNormals = objGeometry.attributes.normal.count; + if ( rotation !== 0 ) { - } + cos = Math.cos( rotation ); + sin = Math.sin( rotation ); - // + } - var geometry = new BufferGeometry(); + const center = this.center; - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); + transformVertex( _vA$2.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vB$2.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vC$2.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); - geometry.addAttribute( 'position', positions ); + _uvA.set( 0, 0 ); + _uvB.set( 1, 0 ); + _uvC.set( 1, 1 ); - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); + // check first triangle + let intersect = raycaster.ray.intersectTriangle( _vA$2, _vB$2, _vC$2, false, _intersectPoint ); - // + if ( intersect === null ) { - this.matrixAutoUpdate = false; + // check second triangle + transformVertex( _vB$2.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + _uvB.set( 0, 1 ); - this.update(); + intersect = raycaster.ray.intersectTriangle( _vA$2, _vC$2, _vB$2, false, _intersectPoint ); + if ( intersect === null ) { -} + return; -VertexNormalsHelper.prototype = Object.create( LineSegments.prototype ); -VertexNormalsHelper.prototype.constructor = VertexNormalsHelper; + } -VertexNormalsHelper.prototype.update = ( function () { + } - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); + const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); - return function update() { + if ( distance < raycaster.near || distance > raycaster.far ) return; - var keys = [ 'a', 'b', 'c' ]; + intersects.push( { - this.object.updateMatrixWorld( true ); + distance: distance, + point: _intersectPoint.clone(), + uv: Triangle.getInterpolation( _intersectPoint, _vA$2, _vB$2, _vC$2, _uvA, _uvB, _uvC, new Vector2() ), + face: null, + object: this - normalMatrix.getNormalMatrix( this.object.matrixWorld ); + } ); - var matrixWorld = this.object.matrixWorld; + } - var position = this.geometry.attributes.position; + copy( source, recursive ) { - // + super.copy( source, recursive ); - var objGeometry = this.object.geometry; + if ( source.center !== undefined ) this.center.copy( source.center ); - if ( objGeometry && objGeometry.isGeometry ) { + this.material = source.material; - var vertices = objGeometry.vertices; + return this; - var faces = objGeometry.faces; + } - var idx = 0; +} - for ( var i = 0, l = faces.length; i < l; i ++ ) { +function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { - var face = faces[ i ]; + // compute position in camera space + _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { + // to check if rotation is not zero + if ( sin !== undefined ) { - var vertex = vertices[ face[ keys[ j ] ] ]; + _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); + _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); - var normal = face.vertexNormals[ j ]; + } else { - v1.copy( vertex ).applyMatrix4( matrixWorld ); + _rotatedPosition.copy( _alignedPosition ); - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); + } - position.setXYZ( idx, v1.x, v1.y, v1.z ); - idx = idx + 1; + vertexPosition.copy( mvPosition ); + vertexPosition.x += _rotatedPosition.x; + vertexPosition.y += _rotatedPosition.y; - position.setXYZ( idx, v2.x, v2.y, v2.z ); + // transform to world space + vertexPosition.applyMatrix4( _viewWorldMatrix ); - idx = idx + 1; +} - } +const _basePosition = /*@__PURE__*/ new Vector3(); - } +const _skinIndex = /*@__PURE__*/ new Vector4(); +const _skinWeight = /*@__PURE__*/ new Vector4(); - } else if ( objGeometry && objGeometry.isBufferGeometry ) { +const _vector3 = /*@__PURE__*/ new Vector3(); +const _matrix4 = /*@__PURE__*/ new Matrix4(); +const _vertex = /*@__PURE__*/ new Vector3(); - var objPos = objGeometry.attributes.position; +const _sphere$4 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _ray$2 = /*@__PURE__*/ new Ray(); - var objNorm = objGeometry.attributes.normal; +class SkinnedMesh extends Mesh { - var idx = 0; + constructor( geometry, material ) { - // for simplicity, ignore index and drawcalls, and render every normal + super( geometry, material ); - for ( var j = 0, jl = objPos.count; j < jl; j ++ ) { + this.isSkinnedMesh = true; - v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); + this.type = 'SkinnedMesh'; - v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) ); + this.bindMode = AttachedBindMode; + this.bindMatrix = new Matrix4(); + this.bindMatrixInverse = new Matrix4(); - v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); + this.boundingBox = null; + this.boundingSphere = null; - position.setXYZ( idx, v1.x, v1.y, v1.z ); + } - idx = idx + 1; + computeBoundingBox() { - position.setXYZ( idx, v2.x, v2.y, v2.z ); + const geometry = this.geometry; - idx = idx + 1; + if ( this.boundingBox === null ) { - } + this.boundingBox = new Box3(); } - position.needsUpdate = true; + this.boundingBox.makeEmpty(); - }; + const positionAttribute = geometry.getAttribute( 'position' ); -}() ); + for ( let i = 0; i < positionAttribute.count; i ++ ) { -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + this.getVertexPosition( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); -function SpotLightHelper( light, color ) { + } - Object3D.call( this ); + } - this.light = light; - this.light.updateMatrixWorld(); + computeBoundingSphere() { - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + const geometry = this.geometry; - this.color = color; + if ( this.boundingSphere === null ) { - var geometry = new BufferGeometry(); + this.boundingSphere = new Sphere(); - var 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 ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { + this.boundingSphere.makeEmpty(); - var p1 = ( i / l ) * Math.PI * 2; - var p2 = ( j / l ) * Math.PI * 2; + const positionAttribute = geometry.getAttribute( 'position' ); - positions.push( - Math.cos( p1 ), Math.sin( p1 ), 1, - Math.cos( p2 ), Math.sin( p2 ), 1 - ); + for ( let i = 0; i < positionAttribute.count; i ++ ) { - } + this.getVertexPosition( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + } - var material = new LineBasicMaterial( { fog: false } ); + } - this.cone = new LineSegments( geometry, material ); - this.add( this.cone ); + copy( source, recursive ) { - this.update(); + super.copy( source, recursive ); -} + this.bindMode = source.bindMode; + this.bindMatrix.copy( source.bindMatrix ); + this.bindMatrixInverse.copy( source.bindMatrixInverse ); -SpotLightHelper.prototype = Object.create( Object3D.prototype ); -SpotLightHelper.prototype.constructor = SpotLightHelper; + this.skeleton = source.skeleton; -SpotLightHelper.prototype.dispose = function () { + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); - this.cone.geometry.dispose(); - this.cone.material.dispose(); + return this; -}; + } -SpotLightHelper.prototype.update = function () { + raycast( raycaster, intersects ) { - var vector = new Vector3(); - var vector2 = new Vector3(); + const material = this.material; + const matrixWorld = this.matrixWorld; - return function update() { + if ( material === undefined ) return; - this.light.updateMatrixWorld(); + // test with bounding sphere in world space - var coneLength = this.light.distance ? this.light.distance : 1000; - var coneWidth = coneLength * Math.tan( this.light.angle ); + if ( this.boundingSphere === null ) this.computeBoundingSphere(); - this.cone.scale.set( coneWidth, coneWidth, coneLength ); + _sphere$4.copy( this.boundingSphere ); + _sphere$4.applyMatrix4( matrixWorld ); - vector.setFromMatrixPosition( this.light.matrixWorld ); - vector2.setFromMatrixPosition( this.light.target.matrixWorld ); + if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; - this.cone.lookAt( vector2.sub( vector ) ); + // convert ray to local space of skinned mesh - if ( this.color !== undefined ) { + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); - this.cone.material.color.set( this.color ); + // test with bounding box in local space - } else { + if ( this.boundingBox !== null ) { - this.cone.material.color.copy( this.light.color ); + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; } - }; + // test for intersections with geometry -}(); + this._computeIntersections( raycaster, intersects, _ray$2 ); -/** - * @author Sean Griffin / http://twitter.com/sgrif - * @author Michael Guerrero / http://realitymeltdown.com - * @author mrdoob / http://mrdoob.com/ - * @author ikerr / http://verold.com - * @author Mugen87 / https://github.com/Mugen87 - */ + } -function getBoneList( object ) { + getVertexPosition( index, target ) { - var boneList = []; + super.getVertexPosition( index, target ); - if ( object && object.isBone ) { + this.applyBoneTransform( index, target ); - boneList.push( object ); + return target; } - for ( var i = 0; i < object.children.length; i ++ ) { - - boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); + bind( skeleton, bindMatrix ) { - } + this.skeleton = skeleton; - return boneList; + if ( bindMatrix === undefined ) { -} + this.updateMatrixWorld( true ); -function SkeletonHelper( object ) { + this.skeleton.calculateInverses(); - var bones = getBoneList( object ); + bindMatrix = this.matrixWorld; - var geometry = new BufferGeometry(); + } - var vertices = []; - var colors = []; + this.bindMatrix.copy( bindMatrix ); + this.bindMatrixInverse.copy( bindMatrix ).invert(); - var color1 = new Color( 0, 0, 1 ); - var color2 = new Color( 0, 1, 0 ); + } - for ( var i = 0; i < bones.length; i ++ ) { + pose() { - var bone = bones[ i ]; + this.skeleton.pose(); - 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 ); + normalizeSkinWeights() { - } + const vector = new Vector4(); - } + const skinWeight = this.geometry.attributes.skinWeight; - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { - var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } ); + vector.fromBufferAttribute( skinWeight, i ); - LineSegments.call( this, geometry, material ); + const scale = 1.0 / vector.manhattanLength(); - this.root = object; - this.bones = bones; + if ( scale !== Infinity ) { - this.matrix = object.matrixWorld; - this.matrixAutoUpdate = false; + vector.multiplyScalar( scale ); -} + } else { -SkeletonHelper.prototype = Object.create( LineSegments.prototype ); -SkeletonHelper.prototype.constructor = SkeletonHelper; + vector.set( 1, 0, 0, 0 ); // do something reasonable -SkeletonHelper.prototype.updateMatrixWorld = function () { + } - var vector = new Vector3(); + skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); - var boneMatrix = new Matrix4(); - var matrixWorldInv = new Matrix4(); + } - return function updateMatrixWorld( force ) { + } - var bones = this.bones; + updateMatrixWorld( force ) { - var geometry = this.geometry; - var position = geometry.getAttribute( 'position' ); + super.updateMatrixWorld( force ); - matrixWorldInv.getInverse( this.root.matrixWorld ); + if ( this.bindMode === AttachedBindMode ) { - for ( var i = 0, j = 0; i < bones.length; i ++ ) { + this.bindMatrixInverse.copy( this.matrixWorld ).invert(); - var bone = bones[ i ]; + } else if ( this.bindMode === DetachedBindMode ) { - if ( bone.parent && bone.parent.isBone ) { + this.bindMatrixInverse.copy( this.bindMatrix ).invert(); - boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j, vector.x, vector.y, vector.z ); + } else { - boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j + 1, vector.x, vector.y, vector.z ); + console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); - j += 2; + } - } + } - } + applyBoneTransform( index, vector ) { - geometry.getAttribute( 'position' ).needsUpdate = true; + const skeleton = this.skeleton; + const geometry = this.geometry; - Object3D.prototype.updateMatrixWorld.call( this, force ); + _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); + _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - }; + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); -}(); + vector.set( 0, 0, 0 ); -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + for ( let i = 0; i < 4; i ++ ) { -function PointLightHelper( light, sphereSize, color ) { + const weight = _skinWeight.getComponent( i ); - this.light = light; - this.light.updateMatrixWorld(); + if ( weight !== 0 ) { - this.color = color; + const boneIndex = _skinIndex.getComponent( i ); - var geometry = new SphereBufferGeometry( sphereSize, 4, 2 ); - var material = new MeshBasicMaterial( { wireframe: true, fog: false } ); + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - Mesh.call( this, geometry, material ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); - this.matrix = this.light.matrixWorld; - this.matrixAutoUpdate = false; + } - this.update(); + } + return vector.applyMatrix4( this.bindMatrixInverse ); - /* - var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); - var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); + } - this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); - this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); +} - var d = light.distance; +class Bone extends Object3D { - if ( d === 0.0 ) { + constructor() { - this.lightDistance.visible = false; + super(); - } else { + this.isBone = true; - this.lightDistance.scale.set( d, d, d ); + this.type = 'Bone'; } - this.add( this.lightDistance ); - */ - } -PointLightHelper.prototype = Object.create( Mesh.prototype ); -PointLightHelper.prototype.constructor = PointLightHelper; - -PointLightHelper.prototype.dispose = function () { +class DataTexture extends Texture { - this.geometry.dispose(); - this.material.dispose(); + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { -}; - -PointLightHelper.prototype.update = function () { + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); - if ( this.color !== undefined ) { + this.isDataTexture = true; - this.material.color.set( this.color ); - - } else { + this.image = { data: data, width: width, height: height }; - this.material.color.copy( this.light.color ); + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; } - /* - var d = this.light.distance; +} - if ( d === 0.0 ) { +const _offsetMatrix = /*@__PURE__*/ new Matrix4(); +const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); - this.lightDistance.visible = false; +class Skeleton { - } else { + constructor( bones = [], boneInverses = [] ) { - this.lightDistance.visible = true; - this.lightDistance.scale.set( d, d, d ); + this.uuid = generateUUID(); - } - */ + this.bones = bones.slice( 0 ); + this.boneInverses = boneInverses; + this.boneMatrices = null; -}; + this.boneTexture = null; -/** - * @author abelnation / http://github.com/abelnation - * @author Mugen87 / http://github.com/Mugen87 - * @author WestLangley / http://github.com/WestLangley - */ + this.init(); -function RectAreaLightHelper( light, color ) { + } - Object3D.call( this ); + init() { - this.light = light; - this.light.updateMatrixWorld(); + const bones = this.bones; + const boneInverses = this.boneInverses; - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + this.boneMatrices = new Float32Array( bones.length * 16 ); - this.color = color; + // calculate inverse bone matrices if necessary - var material = new LineBasicMaterial( { fog: false } ); + if ( boneInverses.length === 0 ) { - var geometry = new BufferGeometry(); + this.calculateInverses(); - geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) ); + } else { - this.line = new Line( geometry, material ); - this.add( this.line ); + // handle special case + if ( bones.length !== boneInverses.length ) { - this.update(); + console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); -} + this.boneInverses = []; -RectAreaLightHelper.prototype = Object.create( Object3D.prototype ); -RectAreaLightHelper.prototype.constructor = RectAreaLightHelper; + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { -RectAreaLightHelper.prototype.dispose = function () { + this.boneInverses.push( new Matrix4() ); - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); + } -}; + } -RectAreaLightHelper.prototype.update = function () { + } - // calculate new dimensions of the helper + } - var hx = this.light.width * 0.5; - var hy = this.light.height * 0.5; + calculateInverses() { - var position = this.line.geometry.attributes.position; - var array = position.array; + this.boneInverses.length = 0; - // update vertices + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0; - array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0; - array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0; - array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0; - array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0; + const inverse = new Matrix4(); - position.needsUpdate = true; + if ( this.bones[ i ] ) { - if ( this.color !== undefined ) { + inverse.copy( this.bones[ i ].matrixWorld ).invert(); - this.line.material.color.set( this.color ); + } - } else { + this.boneInverses.push( inverse ); - this.line.material.color.copy( this.light.color ); + } } -}; + pose() { -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + // recover the bind-time world matrices -function HemisphereLightHelper( light, size, color ) { + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - Object3D.call( this ); + const bone = this.bones[ i ]; - this.light = light; - this.light.updateMatrixWorld(); + if ( bone ) { - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); - this.color = color; + } - var geometry = new OctahedronBufferGeometry( size ); - geometry.rotateY( Math.PI * 0.5 ); + } - this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - if ( this.color === undefined ) { this.material.vertexColors = VertexColors; } + // compute the local matrices, positions, rotations and scales - var position = geometry.getAttribute( 'position' ); - var colors = new Float32Array( position.count * 3 ); + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); + const bone = this.bones[ i ]; - this.add( new Mesh( geometry, this.material ) ); + if ( bone ) { - this.update(); + if ( bone.parent && bone.parent.isBone ) { -} + bone.matrix.copy( bone.parent.matrixWorld ).invert(); + bone.matrix.multiply( bone.matrixWorld ); -HemisphereLightHelper.prototype = Object.create( Object3D.prototype ); -HemisphereLightHelper.prototype.constructor = HemisphereLightHelper; + } else { -HemisphereLightHelper.prototype.dispose = function () { + bone.matrix.copy( bone.matrixWorld ); - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); + } -}; + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); -HemisphereLightHelper.prototype.update = function () { + } - var vector = new Vector3(); + } - var color1 = new Color(); - var color2 = new Color(); + } - return function update() { + update() { - var mesh = this.children[ 0 ]; + const bones = this.bones; + const boneInverses = this.boneInverses; + const boneMatrices = this.boneMatrices; + const boneTexture = this.boneTexture; - if ( this.color !== undefined ) { + // flatten bone matrices to array - this.material.color.set( this.color ); + for ( let i = 0, il = bones.length; i < il; i ++ ) { - } else { + // compute the offset between the current and the original transform - var colors = mesh.geometry.getAttribute( 'color' ); + const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; - color1.copy( this.light.color ); - color2.copy( this.light.groundColor ); + _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); + _offsetMatrix.toArray( boneMatrices, i * 16 ); - for ( var i = 0, l = colors.count; i < l; i ++ ) { + } - var color = ( i < ( l / 2 ) ) ? color1 : color2; + if ( boneTexture !== null ) { - colors.setXYZ( i, color.r, color.g, color.b ); + boneTexture.needsUpdate = true; - } + } - colors.needsUpdate = true; + } - } + clone() { - mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); + return new Skeleton( this.bones, this.boneInverses ); - }; + } -}(); + computeBoneTexture() { -/** - * @author mrdoob / http://mrdoob.com/ - */ + // layout (1 matrix = 4 pixels) + // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) + // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) + // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) + // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) + // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) -function GridHelper( size, divisions, color1, color2 ) { + let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix + size = Math.ceil( size / 4 ) * 4; + size = Math.max( size, 4 ); - size = size || 10; - divisions = divisions || 10; - color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); - color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); + const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel + boneMatrices.set( this.boneMatrices ); // copy current values - var center = divisions / 2; - var step = size / divisions; - var halfSize = size / 2; + const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + boneTexture.needsUpdate = true; - var vertices = [], colors = []; + this.boneMatrices = boneMatrices; + this.boneTexture = boneTexture; - for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { + return this; - vertices.push( - halfSize, 0, k, halfSize, 0, k ); - vertices.push( k, 0, - halfSize, k, 0, halfSize ); + } - var color = i === center ? color1 : color2; + getBoneByName( name ) { - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - } + const bone = this.bones[ i ]; - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + if ( bone.name === name ) { - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); + return bone; - LineSegments.call( this, geometry, material ); + } -} + } -GridHelper.prototype = Object.create( LineSegments.prototype ); -GridHelper.prototype.constructor = GridHelper; + return undefined; -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - * @author Hectate / http://www.github.com/Hectate - */ + } -function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) { + dispose( ) { - radius = radius || 10; - radials = radials || 16; - circles = circles || 8; - divisions = divisions || 64; - color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); - color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); + if ( this.boneTexture !== null ) { - var vertices = []; - var colors = []; + this.boneTexture.dispose(); - var x, z; - var v, i, j, r, color; + this.boneTexture = null; - // create the radials + } - for ( i = 0; i <= radials; i ++ ) { + } - v = ( i / radials ) * ( Math.PI * 2 ); + fromJSON( json, bones ) { - x = Math.sin( v ) * radius; - z = Math.cos( v ) * radius; + this.uuid = json.uuid; - vertices.push( 0, 0, 0 ); - vertices.push( x, 0, z ); + for ( let i = 0, l = json.bones.length; i < l; i ++ ) { - color = ( i & 1 ) ? color1 : color2; + const uuid = json.bones[ i ]; + let bone = bones[ uuid ]; - colors.push( color.r, color.g, color.b ); - colors.push( color.r, color.g, color.b ); + if ( bone === undefined ) { - } + console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); + bone = new Bone(); - // create the circles + } - for ( i = 0; i <= circles; i ++ ) { + this.bones.push( bone ); + this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); - color = ( i & 1 ) ? color1 : color2; + } - r = radius - ( radius / circles * i ); + this.init(); - for ( j = 0; j < divisions; j ++ ) { + return this; - // first vertex + } - v = ( j / divisions ) * ( Math.PI * 2 ); + toJSON() { - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; + const data = { + metadata: { + version: 4.6, + type: 'Skeleton', + generator: 'Skeleton.toJSON' + }, + bones: [], + boneInverses: [] + }; - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); + data.uuid = this.uuid; - // second vertex + const bones = this.bones; + const boneInverses = this.boneInverses; - v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); + for ( let i = 0, l = bones.length; i < l; i ++ ) { - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; + const bone = bones[ i ]; + data.bones.push( bone.uuid ); - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); + const boneInverse = boneInverses[ i ]; + data.boneInverses.push( boneInverse.toArray() ); } + return data; + } - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); +} - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); +class LineBasicMaterial extends Material { - LineSegments.call( this, geometry, material ); + constructor( parameters ) { -} + super(); -PolarGridHelper.prototype = Object.create( LineSegments.prototype ); -PolarGridHelper.prototype.constructor = PolarGridHelper; + this.isLineBasicMaterial = true; -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + this.type = 'LineBasicMaterial'; -function FaceNormalsHelper( object, size, hex, linewidth ) { + this.color = new Color( 0xffffff ); - // FaceNormalsHelper only supports THREE.Geometry + this.map = null; - this.object = object; + this.linewidth = 1; + this.linecap = 'round'; + this.linejoin = 'round'; - this.size = ( size !== undefined ) ? size : 1; + this.fog = true; - var color = ( hex !== undefined ) ? hex : 0xffff00; + this.setValues( parameters ); - var width = ( linewidth !== undefined ) ? linewidth : 1; + } - // - var nNormals = 0; + copy( source ) { - var objGeometry = this.object.geometry; + super.copy( source ); - if ( objGeometry && objGeometry.isGeometry ) { + this.color.copy( source.color ); - nNormals = objGeometry.faces.length; + this.map = source.map; - } else { + this.linewidth = source.linewidth; + this.linecap = source.linecap; + this.linejoin = source.linejoin; - console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' ); + this.fog = source.fog; - } + return this; - // + } - var geometry = new BufferGeometry(); +} - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); +const _vStart = /*@__PURE__*/ new Vector3(); +const _vEnd = /*@__PURE__*/ new Vector3(); - geometry.addAttribute( 'position', positions ); +const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _ray$1 = /*@__PURE__*/ new Ray(); +const _sphere$1 = /*@__PURE__*/ new Sphere(); - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); +const _intersectPointOnRay = /*@__PURE__*/ new Vector3(); +const _intersectPointOnSegment = /*@__PURE__*/ new Vector3(); - // +class Line extends Object3D { - this.matrixAutoUpdate = false; - this.update(); + constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { -} + super(); -FaceNormalsHelper.prototype = Object.create( LineSegments.prototype ); -FaceNormalsHelper.prototype.constructor = FaceNormalsHelper; + this.isLine = true; -FaceNormalsHelper.prototype.update = ( function () { + this.type = 'Line'; - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); + this.geometry = geometry; + this.material = material; - return function update() { + this.updateMorphTargets(); - this.object.updateMatrixWorld( true ); + } - normalMatrix.getNormalMatrix( this.object.matrixWorld ); + copy( source, recursive ) { - var matrixWorld = this.object.matrixWorld; + super.copy( source, recursive ); - var position = this.geometry.attributes.position; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - // + return this; - var objGeometry = this.object.geometry; + } - var vertices = objGeometry.vertices; + computeLineDistances() { - var faces = objGeometry.faces; + const geometry = this.geometry; - var idx = 0; + // we assume non-indexed geometry - for ( var i = 0, l = faces.length; i < l; i ++ ) { + if ( geometry.index === null ) { - var face = faces[ i ]; + const positionAttribute = geometry.attributes.position; + const lineDistances = [ 0 ]; - var normal = face.normal; + for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { - v1.copy( vertices[ face.a ] ) - .add( vertices[ face.b ] ) - .add( vertices[ face.c ] ) - .divideScalar( 3 ) - .applyMatrix4( matrixWorld ); + _vStart.fromBufferAttribute( positionAttribute, i - 1 ); + _vEnd.fromBufferAttribute( positionAttribute, i ); - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); + lineDistances[ i ] = lineDistances[ i - 1 ]; + lineDistances[ i ] += _vStart.distanceTo( _vEnd ); - position.setXYZ( idx, v1.x, v1.y, v1.z ); + } - idx = idx + 1; + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); - position.setXYZ( idx, v2.x, v2.y, v2.z ); + } else { - idx = idx + 1; + console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); } - position.needsUpdate = true; + return this; - }; + } -}() ); + raycast( raycaster, intersects ) { -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Line.threshold; + const drawRange = geometry.drawRange; -function DirectionalLightHelper( light, size, color ) { + // Checking boundingSphere distance to ray - Object3D.call( this ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - this.light = light; - this.light.updateMatrixWorld(); + _sphere$1.copy( geometry.boundingSphere ); + _sphere$1.applyMatrix4( matrixWorld ); + _sphere$1.radius += threshold; - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; - this.color = color; + // - if ( size === undefined ) { size = 1; } + _inverseMatrix$1.copy( matrixWorld ).invert(); + _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( [ - - size, size, 0, - size, size, 0, - size, - size, 0, - - size, - size, 0, - - size, size, 0 - ], 3 ) ); + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; - var material = new LineBasicMaterial( { fog: false } ); + const step = this.isLineSegments ? 2 : 1; - this.lightPlane = new Line( geometry, material ); - this.add( this.lightPlane ); + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; - geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); + if ( index !== null ) { - this.targetLine = new Line( geometry, material ); - this.add( this.targetLine ); + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - this.update(); + for ( let i = start, l = end - 1; i < l; i += step ) { -} + const a = index.getX( i ); + const b = index.getX( i + 1 ); -DirectionalLightHelper.prototype = Object.create( Object3D.prototype ); -DirectionalLightHelper.prototype.constructor = DirectionalLightHelper; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); -DirectionalLightHelper.prototype.dispose = function () { + if ( intersect ) { - this.lightPlane.geometry.dispose(); - this.lightPlane.material.dispose(); - this.targetLine.geometry.dispose(); - this.targetLine.material.dispose(); + intersects.push( intersect ); -}; + } + + } -DirectionalLightHelper.prototype.update = function () { + if ( this.isLineLoop ) { - var v1 = new Vector3(); - var v2 = new Vector3(); - var v3 = new Vector3(); + const a = index.getX( end - 1 ); + const b = index.getX( start ); - return function update() { + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); - v1.setFromMatrixPosition( this.light.matrixWorld ); - v2.setFromMatrixPosition( this.light.target.matrixWorld ); - v3.subVectors( v2, v1 ); + if ( intersect ) { - this.lightPlane.lookAt( v3 ); + intersects.push( intersect ); - if ( this.color !== undefined ) { + } - 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 ); - - } + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); - this.targetLine.lookAt( v3 ); - this.targetLine.scale.z = v3.length(); + for ( let i = start, l = end - 1; i < l; i += step ) { - }; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1 ); -}(); + if ( intersect ) { -/** - * @author alteredq / http://alteredqualia.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - shows frustum, line of sight and up of the camera - * - suitable for fast updates - * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html - */ + intersects.push( intersect ); -function CameraHelper( camera ) { + } - var geometry = new BufferGeometry(); - var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } ); + } - var vertices = []; - var colors = []; + if ( this.isLineLoop ) { - var pointMap = {}; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start ); - // colors + if ( intersect ) { - var colorFrustum = new Color( 0xffaa00 ); - var colorCone = new Color( 0xff0000 ); - var colorUp = new Color( 0x00aaff ); - var colorTarget = new Color( 0xffffff ); - var colorCross = new Color( 0x333333 ); + intersects.push( intersect ); - // near + } - addLine( 'n1', 'n2', colorFrustum ); - addLine( 'n2', 'n4', colorFrustum ); - addLine( 'n4', 'n3', colorFrustum ); - addLine( 'n3', 'n1', colorFrustum ); + } - // far + } - addLine( 'f1', 'f2', colorFrustum ); - addLine( 'f2', 'f4', colorFrustum ); - addLine( 'f4', 'f3', colorFrustum ); - addLine( 'f3', 'f1', colorFrustum ); + } - // sides + updateMorphTargets() { - addLine( 'n1', 'f1', colorFrustum ); - addLine( 'n2', 'f2', colorFrustum ); - addLine( 'n3', 'f3', colorFrustum ); - addLine( 'n4', 'f4', colorFrustum ); + const geometry = this.geometry; - // cone + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - addLine( 'p', 'n1', colorCone ); - addLine( 'p', 'n2', colorCone ); - addLine( 'p', 'n3', colorCone ); - addLine( 'p', 'n4', colorCone ); + if ( keys.length > 0 ) { - // up + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - addLine( 'u1', 'u2', colorUp ); - addLine( 'u2', 'u3', colorUp ); - addLine( 'u3', 'u1', colorUp ); + if ( morphAttribute !== undefined ) { - // target + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - addLine( 'c', 't', colorTarget ); - addLine( 'p', 'c', colorCross ); + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - // cross + const name = morphAttribute[ m ].name || String( m ); - addLine( 'cn1', 'cn2', colorCross ); - addLine( 'cn3', 'cn4', colorCross ); + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - addLine( 'cf1', 'cf2', colorCross ); - addLine( 'cf3', 'cf4', colorCross ); + } - function addLine( a, b, color ) { + } - addPoint( a, color ); - addPoint( b, color ); + } } - function addPoint( id, color ) { - - vertices.push( 0, 0, 0 ); - colors.push( color.r, color.g, color.b ); +} - if ( pointMap[ id ] === undefined ) { +function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { - pointMap[ id ] = []; + const positionAttribute = object.geometry.attributes.position; - } + _vStart.fromBufferAttribute( positionAttribute, a ); + _vEnd.fromBufferAttribute( positionAttribute, b ); - pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); + const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment ); - } + if ( distSq > thresholdSq ) return; - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + _intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation - LineSegments.call( this, geometry, material ); + const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay ); - this.camera = camera; - if ( this.camera.updateProjectionMatrix ) { this.camera.updateProjectionMatrix(); } + if ( distance < raycaster.near || distance > raycaster.far ) return; - this.matrix = camera.matrixWorld; - this.matrixAutoUpdate = false; + return { - this.pointMap = pointMap; + distance: distance, + // What do we want? intersection point on the ray or on the segment?? + // point: raycaster.ray.at( distance ), + point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ), + index: a, + face: null, + faceIndex: null, + object: object - this.update(); + }; } -CameraHelper.prototype = Object.create( LineSegments.prototype ); -CameraHelper.prototype.constructor = CameraHelper; +const _start = /*@__PURE__*/ new Vector3(); +const _end = /*@__PURE__*/ new Vector3(); -CameraHelper.prototype.update = function () { +class LineSegments extends Line { - var geometry, pointMap; + constructor( geometry, material ) { - var vector = new Vector3(); - var camera = new Camera(); + super( geometry, material ); - function setPoint( point, x, y, z ) { + this.isLineSegments = true; - vector.set( x, y, z ).unproject( camera ); + this.type = 'LineSegments'; - var points = pointMap[ point ]; + } - if ( points !== undefined ) { + computeLineDistances() { - var position = geometry.getAttribute( 'position' ); + const geometry = this.geometry; - for ( var i = 0, l = points.length; i < l; i ++ ) { + // we assume non-indexed geometry - position.setXYZ( points[ i ], vector.x, vector.y, vector.z ); + 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 ); - return function update() { + lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; + lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); - geometry = this.geometry; - pointMap = this.pointMap; + } - var w = 1, h = 1; + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); - // we need just camera projection matrix - // world matrix must be identity + } else { - camera.projectionMatrix.copy( this.camera.projectionMatrix ); + console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); - // center / target + } - setPoint( 'c', 0, 0, - 1 ); - setPoint( 't', 0, 0, 1 ); + return this; - // near + } - setPoint( 'n1', - w, - h, - 1 ); - setPoint( 'n2', w, - h, - 1 ); - setPoint( 'n3', - w, h, - 1 ); - setPoint( 'n4', w, h, - 1 ); +} - // far +class PointsMaterial extends Material { - setPoint( 'f1', - w, - h, 1 ); - setPoint( 'f2', w, - h, 1 ); - setPoint( 'f3', - w, h, 1 ); - setPoint( 'f4', w, h, 1 ); + constructor( parameters ) { - // up + super(); - setPoint( 'u1', w * 0.7, h * 1.1, - 1 ); - setPoint( 'u2', - w * 0.7, h * 1.1, - 1 ); - setPoint( 'u3', 0, h * 2, - 1 ); + this.isPointsMaterial = true; - // cross + this.type = 'PointsMaterial'; - setPoint( 'cf1', - w, 0, 1 ); - setPoint( 'cf2', w, 0, 1 ); - setPoint( 'cf3', 0, - h, 1 ); - setPoint( 'cf4', 0, h, 1 ); + this.color = new Color( 0xffffff ); - setPoint( 'cn1', - w, 0, - 1 ); - setPoint( 'cn2', w, 0, - 1 ); - setPoint( 'cn3', 0, - h, - 1 ); - setPoint( 'cn4', 0, h, - 1 ); + this.map = null; - geometry.getAttribute( 'position' ).needsUpdate = true; + this.alphaMap = null; - }; + this.size = 1; + this.sizeAttenuation = true; -}(); + this.fog = true; -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - */ + this.setValues( parameters ); + + } + + copy( source ) { -function BoxHelper( object, color ) { + super.copy( source ); - this.object = object; + this.color.copy( source.color ); - if ( color === undefined ) { color = 0xffff00; } + this.map = source.map; - var 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 ] ); - var positions = new Float32Array( 8 * 3 ); + this.alphaMap = source.alphaMap; - var geometry = new BufferGeometry(); - geometry.setIndex( new BufferAttribute( indices, 1 ) ); - geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) ); + this.size = source.size; + this.sizeAttenuation = source.sizeAttenuation; - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + this.fog = source.fog; - this.matrixAutoUpdate = false; + return this; - this.update(); + } } -BoxHelper.prototype = Object.create( LineSegments.prototype ); -BoxHelper.prototype.constructor = BoxHelper; +const _inverseMatrix = /*@__PURE__*/ new Matrix4(); +const _ray = /*@__PURE__*/ new Ray(); +const _sphere = /*@__PURE__*/ new Sphere(); +const _position$2 = /*@__PURE__*/ new Vector3(); -BoxHelper.prototype.update = ( function () { +class Points$1 extends Object3D { - var box = new Box3(); + constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { - return function update( object ) { + super(); - if ( object !== undefined ) { + this.isPoints = true; - console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); + this.type = 'Points'; - } + this.geometry = geometry; + this.material = material; - if ( this.object !== undefined ) { + this.updateMorphTargets(); - box.setFromObject( this.object ); + } - } + copy( source, recursive ) { - if ( box.isEmpty() ) { return; } + super.copy( source, recursive ); - var min = box.min; - var max = box.max; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - /* - 5____4 - 1/___0/| - | 6__|_7 - 2/___3/ + return this; - 0: max.x, max.y, max.z - 1: min.x, max.y, max.z - 2: min.x, min.y, max.z - 3: max.x, min.y, max.z - 4: max.x, max.y, min.z - 5: min.x, max.y, min.z - 6: min.x, min.y, min.z - 7: max.x, min.y, min.z - */ + } - var position = this.geometry.attributes.position; - var array = position.array; + raycast( raycaster, intersects ) { - array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; - array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; - array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; - array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; - array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; - array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; - array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; - array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Points.threshold; + const drawRange = geometry.drawRange; - position.needsUpdate = true; + // Checking boundingSphere distance to ray - this.geometry.computeBoundingSphere(); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - }; + _sphere.copy( geometry.boundingSphere ); + _sphere.applyMatrix4( matrixWorld ); + _sphere.radius += threshold; -} )(); + if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; -BoxHelper.prototype.setFromObject = function ( object ) { + // - this.object = object; - this.update(); + _inverseMatrix.copy( matrixWorld ).invert(); + _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); - return this; + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; -}; + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; -/** - * @author WestLangley / http://github.com/WestLangley - */ + if ( index !== null ) { -function Box3Helper( box, hex ) { + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - this.type = 'Box3Helper'; + for ( let i = start, il = end; i < il; i ++ ) { - this.box = box; + const a = index.getX( i ); - var color = ( hex !== undefined ) ? hex : 0xffff00; + _position$2.fromBufferAttribute( positionAttribute, a ); - var 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 ] ); + testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); - var 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 ]; + } - var geometry = new BufferGeometry(); + } else { - geometry.setIndex( new BufferAttribute( indices, 1 ) ); + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + for ( let i = start, l = end; i < l; i ++ ) { - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + _position$2.fromBufferAttribute( positionAttribute, i ); - this.geometry.computeBoundingSphere(); + testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); -} + } -Box3Helper.prototype = Object.create( LineSegments.prototype ); -Box3Helper.prototype.constructor = Box3Helper; + } -Box3Helper.prototype.updateMatrixWorld = function ( force ) { + } - var box = this.box; + updateMorphTargets() { - if ( box.isEmpty() ) { return; } + const geometry = this.geometry; - box.getCenter( this.position ); + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - box.getSize( this.scale ); + if ( keys.length > 0 ) { - this.scale.multiplyScalar( 0.5 ); + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - Object3D.prototype.updateMatrixWorld.call( this, force ); + if ( morphAttribute !== undefined ) { -}; + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; -/** - * @author WestLangley / http://github.com/WestLangley - */ + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { -function PlaneHelper( plane, size, hex ) { + const name = morphAttribute[ m ].name || String( m ); - this.type = 'PlaneHelper'; + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - this.plane = plane; + } - this.size = ( size === undefined ) ? 1 : size; + } - var color = ( hex !== undefined ) ? hex : 0xffff00; + } - var 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, 0, 0, 1, 0, 0, 0 ]; + } - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - geometry.computeBoundingSphere(); +} - Line.call( this, geometry, new LineBasicMaterial( { color: color } ) ); +function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { - // + const rayPointDistanceSq = _ray.distanceSqToPoint( point ); - var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ]; + if ( rayPointDistanceSq < localThresholdSq ) { - var geometry2 = new BufferGeometry(); - geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); - geometry2.computeBoundingSphere(); + const intersectPoint = new Vector3(); - this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) ); + _ray.closestPointToPoint( point, intersectPoint ); + intersectPoint.applyMatrix4( matrixWorld ); -} + const distance = raycaster.ray.origin.distanceTo( intersectPoint ); -PlaneHelper.prototype = Object.create( Line.prototype ); -PlaneHelper.prototype.constructor = PlaneHelper; + if ( distance < raycaster.near || distance > raycaster.far ) return; -PlaneHelper.prototype.updateMatrixWorld = function ( force ) { + intersects.push( { - var scale = - this.plane.constant; + distance: distance, + distanceToRay: Math.sqrt( rayPointDistanceSq ), + point: intersectPoint, + index: index, + face: null, + object: object - if ( Math.abs( scale ) < 1e-8 ) { scale = 1e-8; } // sign does not matter + } ); - this.scale.set( 0.5 * this.size, 0.5 * this.size, scale ); + } - this.lookAt( this.plane.normal ); +} - Object3D.prototype.updateMatrixWorld.call( this, force ); +class CylinderGeometry extends BufferGeometry { -}; + constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { -/** - * @author WestLangley / http://github.com/WestLangley - * @author zz85 / http://github.com/zz85 - * @author bhouston / http://clara.io - * - * Creates an arrow for visualizing directions - * - * Parameters: - * dir - Vector3 - * origin - Vector3 - * length - Number - * color - color in hex value - * headLength - Number - * headWidth - Number - */ + super(); -var lineGeometry; -var coneGeometry; + this.type = 'CylinderGeometry'; -function ArrowHelper( dir, origin, length, color, headLength, headWidth ) { + this.parameters = { + radiusTop: radiusTop, + radiusBottom: radiusBottom, + height: height, + radialSegments: radialSegments, + heightSegments: heightSegments, + openEnded: openEnded, + thetaStart: thetaStart, + thetaLength: thetaLength + }; - // dir is assumed to be normalized + const scope = this; - Object3D.call( this ); + radialSegments = Math.floor( radialSegments ); + heightSegments = Math.floor( heightSegments ); - if ( color === undefined ) { color = 0xffff00; } - if ( length === undefined ) { length = 1; } - if ( headLength === undefined ) { headLength = 0.2 * length; } - if ( headWidth === undefined ) { headWidth = 0.2 * headLength; } + // buffers - if ( lineGeometry === undefined ) { + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - lineGeometry = new BufferGeometry(); - lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); + // helper variables - coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 ); - coneGeometry.translate( 0, - 0.5, 0 ); + let index = 0; + const indexArray = []; + const halfHeight = height / 2; + let groupStart = 0; - } + // generate geometry - this.position.copy( origin ); + generateTorso(); - this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) ); - this.line.matrixAutoUpdate = false; - this.add( this.line ); + if ( openEnded === false ) { - this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) ); - this.cone.matrixAutoUpdate = false; - this.add( this.cone ); + if ( radiusTop > 0 ) generateCap( true ); + if ( radiusBottom > 0 ) generateCap( false ); - this.setDirection( dir ); - this.setLength( length, headLength, headWidth ); + } -} + // build geometry -ArrowHelper.prototype = Object.create( Object3D.prototype ); -ArrowHelper.prototype.constructor = ArrowHelper; + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); -ArrowHelper.prototype.setDirection = ( function () { + function generateTorso() { - var axis = new Vector3(); - var radians; + const normal = new Vector3(); + const vertex = new Vector3(); - return function setDirection( dir ) { + let groupCount = 0; - // dir is assumed to be normalized + // this will be used to calculate the normal + const slope = ( radiusBottom - radiusTop ) / height; - if ( dir.y > 0.99999 ) { + // generate vertices, normals and uvs - this.quaternion.set( 0, 0, 0, 1 ); + for ( let y = 0; y <= heightSegments; y ++ ) { - } else if ( dir.y < - 0.99999 ) { + const indexRow = []; - this.quaternion.set( 1, 0, 0, 0 ); + const v = y / heightSegments; - } else { + // calculate the radius of the current row - axis.set( dir.z, 0, - dir.x ).normalize(); + const radius = v * ( radiusBottom - radiusTop ) + radiusTop; - radians = Math.acos( dir.y ); + for ( let x = 0; x <= radialSegments; x ++ ) { - this.quaternion.setFromAxisAngle( axis, radians ); + const u = x / radialSegments; - } + const theta = u * thetaLength + thetaStart; - }; + const sinTheta = Math.sin( theta ); + const cosTheta = Math.cos( theta ); -}() ); + // vertex -ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) { + vertex.x = radius * sinTheta; + vertex.y = - v * height + halfHeight; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); - if ( headLength === undefined ) { headLength = 0.2 * length; } - if ( headWidth === undefined ) { headWidth = 0.2 * headLength; } + // normal - this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 ); - this.line.updateMatrix(); + normal.set( sinTheta, slope, cosTheta ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - this.cone.scale.set( headWidth, headLength, headWidth ); - this.cone.position.y = length; - this.cone.updateMatrix(); + // uv -}; + uvs.push( u, 1 - v ); -ArrowHelper.prototype.setColor = function ( color ) { + // save index of vertex in respective row - this.line.material.color.copy( color ); - this.cone.material.color.copy( color ); + indexRow.push( index ++ ); -}; + } -/** - * @author sroucheray / http://sroucheray.org/ - * @author mrdoob / http://mrdoob.com/ - */ + // now save vertices of the row in our index array -function AxesHelper( size ) { + indexArray.push( indexRow ); - size = size || 1; + } - var vertices = [ - 0, 0, 0, size, 0, 0, - 0, 0, 0, 0, size, 0, - 0, 0, 0, 0, 0, size - ]; + // generate indices - var colors = [ - 1, 0, 0, 1, 0.6, 0, - 0, 1, 0, 0.6, 1, 0, - 0, 0, 1, 0, 0.6, 1 - ]; + for ( let x = 0; x < radialSegments; x ++ ) { - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + for ( let y = 0; y < heightSegments; y ++ ) { - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); + // we use the index array to access the correct indices - LineSegments.call( this, geometry, material ); + const a = indexArray[ y ][ x ]; + const b = indexArray[ y + 1 ][ x ]; + const c = indexArray[ y + 1 ][ x + 1 ]; + const d = indexArray[ y ][ x + 1 ]; -} + // faces -AxesHelper.prototype = Object.create( LineSegments.prototype ); -AxesHelper.prototype.constructor = AxesHelper; + indices.push( a, b, d ); + indices.push( b, c, d ); -/** - * @author alteredq / http://alteredqualia.com/ - */ + // update group counter -var SceneUtils = { + groupCount += 6; - createMultiMaterialObject: function ( geometry, materials ) { + } - var group = new Group(); + } - for ( var i = 0, l = materials.length; i < l; i ++ ) { + // add a group to the geometry. this will ensure multi material support - group.add( new Mesh( geometry, materials[ i ] ) ); + scope.addGroup( groupStart, groupCount, 0 ); - } + // calculate new start value for groups - return group; + groupStart += groupCount; - }, + } - detach: function ( child, parent, scene ) { + function generateCap( top ) { - child.applyMatrix( parent.matrixWorld ); - parent.remove( child ); - scene.add( child ); + // save the index of the first center vertex + const centerIndexStart = index; - }, + const uv = new Vector2(); + const vertex = new Vector3(); - attach: function ( child, scene, parent ) { + let groupCount = 0; - child.applyMatrix( new Matrix4().getInverse( parent.matrixWorld ) ); + const radius = ( top === true ) ? radiusTop : radiusBottom; + const sign = ( top === true ) ? 1 : - 1; - scene.remove( child ); - parent.add( child ); + // first we generate the center vertex data of the cap. + // because the geometry needs one set of uvs per face, + // we must generate a center vertex per face/segment - } + for ( let x = 1; x <= radialSegments; x ++ ) { -}; + // vertex -/** - * @author mrdoob / http://mrdoob.com/ - */ + vertices.push( 0, halfHeight * sign, 0 ); -function Face4( a, b, c, d, normal, color, materialIndex ) { + // normal - console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' ); - return new Face3( a, b, c, normal, color, materialIndex ); + normals.push( 0, sign, 0 ); -} + // uv -var LineStrip = 0; + uvs.push( 0.5, 0.5 ); -var LinePieces = 1; + // increase index -function MeshFaceMaterial( materials ) { + index ++; - console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' ); - return materials; + } -} + // save the index of the last center vertex + const centerIndexEnd = index; -function MultiMaterial( materials ) { + // now we generate the surrounding vertices, normals and uvs - if ( materials === undefined ) { materials = []; } + for ( let x = 0; x <= radialSegments; x ++ ) { - console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' ); - materials.isMultiMaterial = true; - materials.materials = materials; - materials.clone = function () { + const u = x / radialSegments; + const theta = u * thetaLength + thetaStart; - return materials.slice(); + const cosTheta = Math.cos( theta ); + const sinTheta = Math.sin( theta ); - }; - return materials; + // vertex -} + vertex.x = radius * sinTheta; + vertex.y = halfHeight * sign; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); -function PointCloud( geometry, material ) { + // normal - console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' ); - return new Points$1( geometry, material ); + normals.push( 0, sign, 0 ); -} + // uv -function Particle( material ) { + uv.x = ( cosTheta * 0.5 ) + 0.5; + uv.y = ( sinTheta * 0.5 * sign ) + 0.5; + uvs.push( uv.x, uv.y ); - console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' ); - return new Sprite( material ); + // increase index -} + index ++; -function ParticleSystem( geometry, material ) { + } - console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' ); - return new Points$1( geometry, material ); + // generate indices -} + for ( let x = 0; x < radialSegments; x ++ ) { -function PointCloudMaterial( parameters ) { + const c = centerIndexStart + x; + const i = centerIndexEnd + x; - console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); + if ( top === true ) { -} + // face top -function ParticleBasicMaterial( parameters ) { + indices.push( i, i + 1, c ); - console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); + } else { -} + // face bottom -function ParticleSystemMaterial( parameters ) { + indices.push( i + 1, i, c ); - console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); + } -} + groupCount += 3; -function Vertex( x, y, z ) { + } - console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' ); - return new Vector3( x, y, z ); + // add a group to the geometry. this will ensure multi material support -} + scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); -// + // calculate new start value for groups -function DynamicBufferAttribute( array, itemSize ) { + groupStart += groupCount; - console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' ); - return new BufferAttribute( array, itemSize ).setDynamic( true ); + } -} + } -function Int8Attribute( array, itemSize ) { + copy( source ) { - console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' ); - return new Int8BufferAttribute( array, itemSize ); + super.copy( source ); -} + this.parameters = Object.assign( {}, source.parameters ); -function Uint8Attribute( array, itemSize ) { + return this; - console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' ); - return new Uint8BufferAttribute( array, itemSize ); + } -} + static fromJSON( data ) { -function Uint8ClampedAttribute( array, itemSize ) { + return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); - console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' ); - return new Uint8ClampedBufferAttribute( array, itemSize ); + } } -function Int16Attribute( array, itemSize ) { +class SphereGeometry extends BufferGeometry { - console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' ); - return new Int16BufferAttribute( array, itemSize ); + constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { -} + super(); -function Uint16Attribute( array, itemSize ) { + this.type = 'SphereGeometry'; - console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' ); - return new Uint16BufferAttribute( array, itemSize ); + this.parameters = { + radius: radius, + widthSegments: widthSegments, + heightSegments: heightSegments, + phiStart: phiStart, + phiLength: phiLength, + thetaStart: thetaStart, + thetaLength: thetaLength + }; -} + widthSegments = Math.max( 3, Math.floor( widthSegments ) ); + heightSegments = Math.max( 2, Math.floor( heightSegments ) ); -function Int32Attribute( array, itemSize ) { + const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); - console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' ); - return new Int32BufferAttribute( array, itemSize ); + let index = 0; + const grid = []; -} + const vertex = new Vector3(); + const normal = new Vector3(); -function Uint32Attribute( array, itemSize ) { + // buffers - console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' ); - return new Uint32BufferAttribute( array, itemSize ); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; -} + // generate vertices, normals and uvs -function Float32Attribute( array, itemSize ) { + for ( let iy = 0; iy <= heightSegments; iy ++ ) { - console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' ); - return new Float32BufferAttribute( array, itemSize ); + const verticesRow = []; -} + const v = iy / heightSegments; -function Float64Attribute( array, itemSize ) { + // special case for the poles - console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' ); - return new Float64BufferAttribute( array, itemSize ); + let uOffset = 0; -} + if ( iy === 0 && thetaStart === 0 ) { -// + uOffset = 0.5 / widthSegments; -Curve.create = function ( construct, getPoint ) { + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { - console.log( 'THREE.Curve.create() has been deprecated' ); + uOffset = - 0.5 / widthSegments; - construct.prototype = Object.create( Curve.prototype ); - construct.prototype.constructor = construct; - construct.prototype.getPoint = getPoint; + } - return construct; + for ( let ix = 0; ix <= widthSegments; ix ++ ) { -}; + const u = ix / widthSegments; -// + // vertex -Object.assign( CurvePath.prototype, { + vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); + vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); + vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - createPointsGeometry: function ( divisions ) { + vertices.push( vertex.x, vertex.y, vertex.z ); - console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); + // normal - // generate geometry from path points (for Line or Points objects) + normal.copy( vertex ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - var pts = this.getPoints( divisions ); - return this.createGeometry( pts ); + // uv - }, + uvs.push( u + uOffset, 1 - v ); - createSpacedPointsGeometry: function ( divisions ) { + verticesRow.push( index ++ ); - console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); + } - // generate geometry from equidistant sampling along the path + grid.push( verticesRow ); - var pts = this.getSpacedPoints( divisions ); - return this.createGeometry( pts ); + } - }, + // indices - createGeometry: function ( points ) { + for ( let iy = 0; iy < heightSegments; iy ++ ) { - console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); + for ( let ix = 0; ix < widthSegments; ix ++ ) { - var geometry = new Geometry(); + const a = grid[ iy ][ ix + 1 ]; + const b = grid[ iy ][ ix ]; + const c = grid[ iy + 1 ][ ix ]; + const d = grid[ iy + 1 ][ ix + 1 ]; - for ( var i = 0, l = points.length; i < l; i ++ ) { + if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); + if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); - var point = points[ i ]; - geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); + } } - return geometry; + // build geometry - } + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); -} ); + } -// + copy( source ) { -Object.assign( Path$1.prototype, { + super.copy( source ); - fromPoints: function ( points ) { + this.parameters = Object.assign( {}, source.parameters ); - console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' ); - this.setFromPoints( points ); + return this; } -} ); + static fromJSON( data ) { -// - -function ClosedSplineCurve3( points ) { + return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); - console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' ); - - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; - this.closed = true; + } } -ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype ); +class MeshPhongMaterial extends Material { -// + constructor( parameters ) { -function SplineCurve3( points ) { + super(); - console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' ); + this.isMeshPhongMaterial = true; - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; + this.type = 'MeshPhongMaterial'; -} + this.color = new Color( 0xffffff ); // diffuse + this.specular = new Color( 0x111111 ); + this.shininess = 30; -SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype ); + this.map = null; -// + this.lightMap = null; + this.lightMapIntensity = 1.0; -function Spline( points ) { + this.aoMap = null; + this.aoMapIntensity = 1.0; - console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' ); + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; + this.bumpMap = null; + this.bumpScale = 1; -} + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); -Spline.prototype = Object.create( CatmullRomCurve3.prototype ); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; -Object.assign( Spline.prototype, { + this.specularMap = null; - initFromArray: function ( /* a */ ) { + this.alphaMap = null; - console.error( 'THREE.Spline: .initFromArray() has been removed.' ); + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - }, - getControlPointsArray: function ( /* optionalTarget */ ) { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' ); + this.flatShading = false; - }, - reparametrizeByArcLength: function ( /* samplingCoef */ ) { + this.fog = true; - console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' ); + this.setValues( parameters ); } -} ); - -// + copy( source ) { -function AxisHelper( size ) { + super.copy( source ); - console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' ); - return new AxesHelper( size ); + this.color.copy( source.color ); + this.specular.copy( source.specular ); + this.shininess = source.shininess; -} + this.map = source.map; -function BoundingBoxHelper( object, color ) { + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' ); - return new BoxHelper( object, color ); + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; -} + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; -function EdgesHelper( object, hex ) { + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' ); - return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) ); + 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; -GridHelper.prototype.setColors = function () { + this.specularMap = source.specularMap; - console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' ); + this.alphaMap = source.alphaMap; -}; + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; -SkeletonHelper.prototype.update = function () { + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' ); + this.flatShading = source.flatShading; -}; + this.fog = source.fog; -function WireframeHelper( object, hex ) { + return this; - console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' ); - return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) ); + } } -// +class MeshLambertMaterial extends Material { -Object.assign( Loader.prototype, { + constructor( parameters ) { - extractUrlBase: function ( url ) { + super(); - console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' ); - return LoaderUtils.extractUrlBase( url ); + this.isMeshLambertMaterial = true; - } + this.type = 'MeshLambertMaterial'; -} ); + this.color = new Color( 0xffffff ); // diffuse -function XHRLoader( manager ) { + this.map = null; - console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' ); - return new FileLoader( manager ); + this.lightMap = null; + this.lightMapIntensity = 1.0; -} + this.aoMap = null; + this.aoMapIntensity = 1.0; -function BinaryTextureLoader( manager ) { + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' ); - return new DataTextureLoader( manager ); + this.bumpMap = null; + this.bumpScale = 1; -} + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); -// + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; -Object.assign( Box2.prototype, { + this.specularMap = null; - center: function ( optionalTarget ) { + this.alphaMap = null; - console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - }, - empty: function () { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' ); - return this.isEmpty(); + this.flatShading = false; - }, - isIntersectionBox: function ( box ) { + this.fog = true; - console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); + this.setValues( parameters ); - }, - size: function ( optionalTarget ) { + } - console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' ); - return this.getSize( optionalTarget ); + copy( source ) { - } -} ); + super.copy( source ); -Object.assign( Box3.prototype, { + this.color.copy( source.color ); - center: function ( optionalTarget ) { + this.map = source.map; - console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - }, - empty: function () { + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' ); - return this.isEmpty(); + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; - }, - isIntersectionBox: function ( box ) { + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); - }, - isIntersectionSphere: function ( sphere ) { + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); - return this.intersectsSphere( sphere ); + this.specularMap = source.specularMap; - }, - size: function ( optionalTarget ) { + this.alphaMap = source.alphaMap; - console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' ); - return this.getSize( optionalTarget ); + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + 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; -Line3.prototype.center = function ( optionalTarget ) { + this.flatShading = source.flatShading; - console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); + this.fog = source.fog; -}; + return this; -Object.assign( _Math, { + } - random16: function () { +} - console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' ); - return Math.random(); +// converts an array to a specific type +function convertArray( array, type, forceClone ) { - }, + if ( ! array || // let 'undefined' and 'null' pass + ! forceClone && array.constructor === type ) return array; - nearestPowerOfTwo: function ( value ) { + if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { - console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' ); - return _Math.floorPowerOfTwo( value ); + return new type( array ); // create typed array - }, + } - nextPowerOfTwo: function ( value ) { + return Array.prototype.slice.call( array ); // create Array - console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' ); - return _Math.ceilPowerOfTwo( value ); +} - } +function isTypedArray( object ) { -} ); + return ArrayBuffer.isView( object ) && + ! ( object instanceof DataView ); -Object.assign( Matrix3.prototype, { +} - flattenToArrayOffset: function ( array, offset ) { +// returns an array by which times and values can be sorted +function getKeyframeOrder( times ) { - console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); - return this.toArray( array, offset ); + function compareTime( i, j ) { - }, - multiplyVector3: function ( vector ) { + return times[ i ] - times[ j ]; - console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' ); - return vector.applyMatrix3( this ); + } - }, - multiplyVector3Array: function ( /* a */ ) { + const n = times.length; + const result = new Array( n ); + for ( let i = 0; i !== n; ++ i ) result[ i ] = i; - console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' ); + result.sort( compareTime ); - }, - applyToBuffer: function ( buffer /*, offset, length */ ) { + return result; - console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); - return this.applyToBufferAttribute( buffer ); +} - }, - applyToVector3Array: function ( /* array, offset, length */ ) { +// uses the array previously returned by 'getKeyframeOrder' to sort data +function sortedArray( values, stride, order ) { - console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' ); + 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 ) { -Object.assign( Matrix4.prototype, { + result[ dstOffset ++ ] = values[ srcOffset + j ]; + + } + + } - extractPosition: function ( m ) { + return result; - console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' ); - return this.copyPosition( m ); +} - }, - flattenToArrayOffset: function ( array, offset ) { +// function for parsing AOS keyframe formats +function flattenJSON( jsonKeys, times, values, valuePropertyName ) { - console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); - return this.toArray( array, offset ); + let i = 1, key = jsonKeys[ 0 ]; - }, - getPosition: function () { + while ( key !== undefined && key[ valuePropertyName ] === undefined ) { - var v1; + key = jsonKeys[ i ++ ]; - return function getPosition() { + } - if ( v1 === undefined ) { v1 = new Vector3(); } - console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); - return v1.setFromMatrixColumn( this, 3 ); + if ( key === undefined ) return; // no data - }; + let value = key[ valuePropertyName ]; + if ( value === undefined ) return; // no data - }(), - setRotationFromQuaternion: function ( q ) { + if ( Array.isArray( value ) ) { - console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); - return this.makeRotationFromQuaternion( q ); + do { - }, - multiplyToArray: function () { + value = key[ valuePropertyName ]; - console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' ); + if ( value !== undefined ) { - }, - multiplyVector3: function ( vector ) { + times.push( key.time ); + values.push.apply( values, value ); // push all elements - console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); + } - }, - multiplyVector4: function ( vector ) { + key = jsonKeys[ i ++ ]; - console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); + } while ( key !== undefined ); - }, - multiplyVector3Array: function ( /* a */ ) { + } else if ( value.toArray !== undefined ) { - console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' ); + // ...assume THREE.Math-ish - }, - rotateAxis: function ( v ) { + do { - console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); - v.transformDirection( this ); + value = key[ valuePropertyName ]; - }, - crossVector: function ( vector ) { + if ( value !== undefined ) { - console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); + times.push( key.time ); + value.toArray( values, values.length ); - }, - translate: function () { + } - console.error( 'THREE.Matrix4: .translate() has been removed.' ); + key = jsonKeys[ i ++ ]; - }, - rotateX: function () { + } while ( key !== undefined ); - console.error( 'THREE.Matrix4: .rotateX() has been removed.' ); + } else { - }, - rotateY: function () { + // otherwise push as-is - console.error( 'THREE.Matrix4: .rotateY() has been removed.' ); + do { - }, - rotateZ: function () { + value = key[ valuePropertyName ]; - console.error( 'THREE.Matrix4: .rotateZ() has been removed.' ); + if ( value !== undefined ) { - }, - rotateByAxis: function () { + times.push( key.time ); + values.push( value ); - console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); + } - }, - applyToBuffer: function ( buffer /*, offset, length */ ) { + key = jsonKeys[ i ++ ]; - console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); - return this.applyToBufferAttribute( buffer ); + } while ( key !== undefined ); - }, - applyToVector3Array: function ( /* array, offset, length */ ) { + } - console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' ); +} - }, - makeFrustum: function ( left, right, bottom, top, near, far ) { +/** + * Abstract base class of interpolants over parametric samples. + * + * The parameter domain is one dimensional, typically the time or a path + * along a curve defined by the data. + * + * The sample values can have any dimensionality and derived classes may + * apply special interpretations to the data. + * + * This class provides the interval seek in a Template Method, deferring + * the actual interpolation to derived classes. + * + * Time complexity is O(1) for linear access crossing at most two points + * and O(log N) for random access, where N is the number of positions. + * + * References: + * + * http://www.oodesign.com/template-method-pattern.html + * + */ - console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' ); - return this.makePerspective( left, right, top, bottom, near, far ); +class Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { -} ); + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; -Plane.prototype.isIntersectionLine = function ( line ) { + this.resultBuffer = resultBuffer !== undefined ? + resultBuffer : new sampleValues.constructor( sampleSize ); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; - console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' ); - return this.intersectsLine( line ); + this.settings = null; + this.DefaultSettings_ = {}; -}; + } -Quaternion.prototype.multiplyVector3 = function ( vector ) { + evaluate( t ) { - console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' ); - return vector.applyQuaternion( this ); + const pp = this.parameterPositions; + let i1 = this._cachedIndex, + t1 = pp[ i1 ], + t0 = pp[ i1 - 1 ]; -}; + validate_interval: { -Object.assign( Ray.prototype, { + seek: { - isIntersectionBox: function ( box ) { + let right; - console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); + linear_scan: { - }, - isIntersectionPlane: function ( plane ) { + //- See http://jsperf.com/comparison-to-undefined/3 + //- slower code: + //- + //- if ( t >= t1 || t1 === undefined ) { + forward_scan: if ( ! ( t < t1 ) ) { - console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' ); - return this.intersectsPlane( plane ); + for ( let giveUpAt = i1 + 2; ; ) { - }, - isIntersectionSphere: function ( sphere ) { + if ( t1 === undefined ) { - console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); - return this.intersectsSphere( sphere ); + if ( t < t0 ) break forward_scan; - } + // after end -} ); + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); -Object.assign( Shape.prototype, { + } - extractAllPoints: function ( divisions ) { + if ( i1 === giveUpAt ) break; // this loop - console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' ); - return this.extractPoints( divisions ); + t0 = t1; + t1 = pp[ ++ i1 ]; - }, - extrude: function ( options ) { + if ( t < t1 ) { - console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' ); - return new ExtrudeGeometry( this, options ); + // we have arrived at the sought interval + break seek; - }, - makeGeometry: function ( options ) { + } - console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' ); - return new ShapeGeometry( this, options ); + } - } + // prepare binary search on the right side of the index + right = pp.length; + break linear_scan; -} ); + } -Object.assign( Vector2.prototype, { + //- slower code: + //- if ( t < t0 || t0 === undefined ) { + if ( ! ( t >= t0 ) ) { - fromAttribute: function ( attribute, index, offset ) { + // looping? - console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); + const t1global = pp[ 1 ]; - }, - distanceToManhattan: function ( v ) { + if ( t < t1global ) { - console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); - return this.manhattanDistanceTo( v ); + i1 = 2; // + 1, using the scan for the details + t0 = t1global; - }, - lengthManhattan: function () { + } - console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); + // linear reverse scan - } + for ( let giveUpAt = i1 - 2; ; ) { -} ); + if ( t0 === undefined ) { -Object.assign( Vector3.prototype, { + // before start - setEulerFromRotationMatrix: function () { + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); - console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' ); + } - }, - setEulerFromQuaternion: function () { + if ( i1 === giveUpAt ) break; // this loop - console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' ); + t1 = t0; + t0 = pp[ -- i1 - 1 ]; - }, - getPositionFromMatrix: function ( m ) { + if ( t >= t0 ) { - console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' ); - return this.setFromMatrixPosition( m ); + // we have arrived at the sought interval + break seek; - }, - getScaleFromMatrix: function ( m ) { + } - console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' ); - return this.setFromMatrixScale( m ); + } - }, - getColumnFromMatrix: function ( index, matrix ) { + // prepare binary search on the left side of the index + right = i1; + i1 = 0; + break linear_scan; - console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' ); - return this.setFromMatrixColumn( matrix, index ); + } - }, - applyProjection: function ( m ) { + // the interval is valid - console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' ); - return this.applyMatrix4( m ); + break validate_interval; - }, - fromAttribute: function ( attribute, index, offset ) { + } // linear scan - console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); + // binary search - }, - distanceToManhattan: function ( v ) { + while ( i1 < right ) { - console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); - return this.manhattanDistanceTo( v ); + const mid = ( i1 + right ) >>> 1; - }, - lengthManhattan: function () { + if ( t < pp[ mid ] ) { - console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); + right = mid; - } + } else { -} ); + i1 = mid + 1; -Object.assign( Vector4.prototype, { + } - fromAttribute: function ( attribute, index, offset ) { + } - console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); + t1 = pp[ i1 ]; + t0 = pp[ i1 - 1 ]; - }, - lengthManhattan: function () { + // check boundary cases, again - console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); + if ( t0 === undefined ) { - } + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); -} ); + } -// + if ( t1 === undefined ) { -Geometry.prototype.computeTangents = function () { + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); - console.warn( 'THREE.Geometry: .computeTangents() has been removed.' ); + } -}; + } // seek -Object.assign( Object3D.prototype, { + this._cachedIndex = i1; - getChildByName: function ( name ) { + this.intervalChanged_( i1, t0, t1 ); - console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' ); - return this.getObjectByName( name ); + } // validate_interval - }, - renderDepth: function () { + return this.interpolate_( i1, t0, t, t1 ); - console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' ); + } - }, - translate: function ( distance, axis ) { + getSettings_() { - console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' ); - return this.translateOnAxis( axis, distance ); + return this.settings || this.DefaultSettings_; } -} ); + copySampleValue_( index ) { -Object.defineProperties( Object3D.prototype, { - - eulerOrder: { - get: function () { + // copies a sample value to the result buffer - console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); - return this.rotation.order; + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + offset = index * stride; - }, - set: function ( value ) { + for ( let i = 0; i !== stride; ++ i ) { - console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); - this.rotation.order = value; + result[ i ] = values[ offset + i ]; } - }, - useQuaternion: { - get: function () { - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); + return result; - }, - set: function () { + } - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); + // Template methods for derived classes: - } - } + interpolate_( /* i1, t0, t, t1 */ ) { -} ); + throw new Error( 'call to abstract method' ); + // implementations shall return this.resultBuffer -Object.defineProperties( LOD.prototype, { + } - objects: { - get: function () { + intervalChanged_( /* i1, t0, t1 */ ) { - console.warn( 'THREE.LOD: .objects has been renamed to .levels.' ); - return this.levels; + // empty - } } -} ); +} + +/** + * Fast and simple cubic spline interpolant. + * + * It was derived from a Hermitian construction setting the first derivative + * at each sample position to the linear slope between neighboring positions + * over their parameter interval. + */ -Object.defineProperty( Skeleton.prototype, 'useVertexTexture', { +class CubicInterpolant extends Interpolant { - get: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - }, - set: function () { + this._weightPrev = - 0; + this._offsetPrev = - 0; + this._weightNext = - 0; + this._offsetNext = - 0; - console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); + this.DefaultSettings_ = { - } + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding -} ); + }; -Object.defineProperty( Curve.prototype, '__arcLengthDivisions', { + } - get: function () { + intervalChanged_( i1, t0, t1 ) { - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - return this.arcLengthDivisions; + const pp = this.parameterPositions; + let iPrev = i1 - 2, + iNext = i1 + 1, - }, - set: function ( value ) { + tPrev = pp[ iPrev ], + tNext = pp[ iNext ]; - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - this.arcLengthDivisions = value; + if ( tPrev === undefined ) { - } + switch ( this.getSettings_().endingStart ) { -} ); + case ZeroSlopeEnding: -// + // f'(t0) = 0 + iPrev = i1; + tPrev = 2 * t0 - t1; -PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) { + break; - console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " + - "Use .setFocalLength and .filmGauge for a photographic setup." ); + case WrapAroundEnding: - if ( filmGauge !== undefined ) { this.filmGauge = filmGauge; } - this.setFocalLength( focalLength ); + // use the other end of the curve + iPrev = pp.length - 2; + tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; -}; + break; -// + default: // ZeroCurvatureEnding -Object.defineProperties( Light.prototype, { - onlyShadow: { - set: function () { + // f''(t0) = 0 a.k.a. Natural Spline + iPrev = i1; + tPrev = t1; - console.warn( 'THREE.Light: .onlyShadow has been removed.' ); + } } - }, - shadowCameraFov: { - set: function ( value ) { - console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' ); - this.shadow.camera.fov = value; + if ( tNext === undefined ) { - } - }, - shadowCameraLeft: { - set: function ( value ) { + switch ( this.getSettings_().endingEnd ) { - console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' ); - this.shadow.camera.left = value; + case ZeroSlopeEnding: - } - }, - shadowCameraRight: { - set: function ( value ) { + // f'(tN) = 0 + iNext = i1; + tNext = 2 * t1 - t0; - console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' ); - this.shadow.camera.right = value; + break; - } - }, - shadowCameraTop: { - set: function ( value ) { + case WrapAroundEnding: - console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' ); - this.shadow.camera.top = value; + // use the other end of the curve + iNext = 1; + tNext = t1 + pp[ 1 ] - pp[ 0 ]; - } - }, - shadowCameraBottom: { - set: function ( value ) { + break; - console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' ); - this.shadow.camera.bottom = value; + default: // ZeroCurvatureEnding - } - }, - shadowCameraNear: { - set: function ( value ) { + // f''(tN) = 0, a.k.a. Natural Spline + iNext = i1 - 1; + tNext = t0; - console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' ); - this.shadow.camera.near = value; + } } - }, - shadowCameraFar: { - set: function ( value ) { - console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' ); - this.shadow.camera.far = value; + const halfDt = ( t1 - t0 ) * 0.5, + stride = this.valueSize; - } - }, - shadowCameraVisible: { - set: function () { + 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, - console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' ); + o1 = i1 * stride, o0 = o1 - stride, + oP = this._offsetPrev, oN = this._offsetNext, + wP = this._weightPrev, wN = this._weightNext, - } - }, - shadowBias: { - set: function ( value ) { + p = ( t - t0 ) / ( t1 - t0 ), + pp = p * p, + ppp = pp * p; - console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' ); - this.shadow.bias = value; + // evaluate polynomials - } - }, - shadowDarkness: { - set: function () { + 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; - console.warn( 'THREE.Light: .shadowDarkness has been removed.' ); + // combine data linearly - } - }, - shadowMapWidth: { - set: function ( value ) { + for ( let i = 0; i !== stride; ++ i ) { - console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' ); - this.shadow.mapSize.width = value; + result[ i ] = + sP * values[ oP + i ] + + s0 * values[ o0 + i ] + + s1 * values[ o1 + i ] + + sN * values[ oN + i ]; } - }, - shadowMapHeight: { - set: function ( value ) { - console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' ); - this.shadow.mapSize.height = value; + return result; - } } -} ); -// +} -Object.defineProperties( BufferAttribute.prototype, { +class LinearInterpolant extends Interpolant { - length: { - get: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' ); - return this.array.length; + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - } } -} ); + interpolate_( i1, t0, t, t1 ) { -Object.assign( BufferGeometry.prototype, { - - addIndex: function ( index ) { + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, - console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' ); - this.setIndex( index ); + offset1 = i1 * stride, + offset0 = offset1 - stride, - }, - addDrawCall: function ( start, count, indexOffset ) { + weight1 = ( t - t0 ) / ( t1 - t0 ), + weight0 = 1 - weight1; - if ( indexOffset !== undefined ) { + for ( let i = 0; i !== stride; ++ i ) { - console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' ); + result[ i ] = + values[ offset0 + i ] * weight0 + + values[ offset1 + i ] * weight1; } - console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' ); - this.addGroup( start, count ); - }, - clearDrawCalls: function () { + return result; + + } - console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' ); - this.clearGroups(); +} - }, - computeTangents: function () { +/** + * + * Interpolant that evaluates to the sample value at the position preceding + * the parameter. + */ - console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' ); +class DiscreteInterpolant extends Interpolant { - }, - computeOffsets: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' ); + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); } -} ); + interpolate_( i1 /*, t0, t, t1 */ ) { -Object.defineProperties( BufferGeometry.prototype, { + return this.copySampleValue_( i1 - 1 ); - drawcalls: { - get: function () { + } - console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' ); - return this.groups; +} - } - }, - offsets: { - get: function () { +class KeyframeTrack { - console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' ); - return this.groups; + constructor( name, times, values, interpolation ) { - } - } + if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); + if ( times === undefined || 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 ); -Object.defineProperties( Uniform.prototype, { + this.setInterpolation( interpolation || this.DefaultInterpolation ); - dynamic: { - set: function () { + } - console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' ); + // Serialization (in static context, because of constructor invocation + // and automatic invocation of .toJSON): - } - }, - onUpdate: { - value: function () { + static toJSON( track ) { - console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' ); - return this; + const trackType = track.constructor; - } - } + let json; -} ); + // derived classes can define a static toJSON method + if ( trackType.toJSON !== this.toJSON ) { -// + json = trackType.toJSON( track ); -Object.defineProperties( Material.prototype, { + } else { - wrapAround: { - get: function () { + // by default, we assume the data can be serialized as-is + json = { - console.warn( 'THREE.Material: .wrapAround has been removed.' ); + 'name': track.name, + 'times': convertArray( track.times, Array ), + 'values': convertArray( track.values, Array ) - }, - set: function () { + }; - console.warn( 'THREE.Material: .wrapAround has been removed.' ); + const interpolation = track.getInterpolation(); - } - }, - wrapRGB: { - get: function () { + if ( interpolation !== track.DefaultInterpolation ) { - console.warn( 'THREE.Material: .wrapRGB has been removed.' ); - return new Color(); + json.interpolation = interpolation; + + } } - }, - shading: { - get: function () { + json.type = track.ValueTypeName; // mandatory - console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + return json; - }, - set: function ( value ) { + } - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( value === FlatShading ); + InterpolantFactoryMethodDiscrete( result ) { - } - } + return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); -} ); + } -Object.defineProperties( MeshPhongMaterial.prototype, { + InterpolantFactoryMethodLinear( result ) { - metal: { - get: function () { + return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); - console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' ); - return false; + } - }, - set: function () { + InterpolantFactoryMethodSmooth( result ) { - console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' ); + return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); - } } -} ); + setInterpolation( interpolation ) { -Object.defineProperties( ShaderMaterial.prototype, { + let factoryMethod; - derivatives: { - get: function () { + switch ( interpolation ) { - console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); - return this.extensions.derivatives; + case InterpolateDiscrete: - }, - set: function ( value ) { + factoryMethod = this.InterpolantFactoryMethodDiscrete; - console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); - this.extensions.derivatives = value; + break; - } - } + case InterpolateLinear: -} ); + factoryMethod = this.InterpolantFactoryMethodLinear; -// + break; -Object.assign( WebGLRenderer.prototype, { + case InterpolateSmooth: - getCurrentRenderTarget: function () { + factoryMethod = this.InterpolantFactoryMethodSmooth; - console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' ); - return this.getRenderTarget(); + break; - }, + } - getMaxAnisotropy: function () { + if ( factoryMethod === undefined ) { - console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' ); - return this.capabilities.getMaxAnisotropy(); + const message = 'unsupported interpolation for ' + + this.ValueTypeName + ' keyframe track named ' + this.name; - }, + if ( this.createInterpolant === undefined ) { - getPrecision: function () { + // fall back to default, unless the default itself is messed up + if ( interpolation !== this.DefaultInterpolation ) { - console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' ); - return this.capabilities.precision; + this.setInterpolation( this.DefaultInterpolation ); - }, + } else { - resetGLState: function () { + throw new Error( message ); // fatal, in this case - console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' ); - return this.state.reset(); + } - }, + } - supportsFloatTextures: function () { + console.warn( 'THREE.KeyframeTrack:', message ); + return this; - console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' ); - return this.extensions.get( 'OES_texture_float' ); + } - }, - supportsHalfFloatTextures: function () { + this.createInterpolant = factoryMethod; - console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' ); - return this.extensions.get( 'OES_texture_half_float' ); + return this; - }, - supportsStandardDerivatives: function () { + } - console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' ); - return this.extensions.get( 'OES_standard_derivatives' ); + getInterpolation() { - }, - supportsCompressedTextureS3TC: function () { + switch ( this.createInterpolant ) { - console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' ); - return this.extensions.get( 'WEBGL_compressed_texture_s3tc' ); + case this.InterpolantFactoryMethodDiscrete: - }, - supportsCompressedTexturePVRTC: function () { + return InterpolateDiscrete; - console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' ); - return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + case this.InterpolantFactoryMethodLinear: - }, - supportsBlendMinMax: function () { + return InterpolateLinear; - console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' ); - return this.extensions.get( 'EXT_blend_minmax' ); + case this.InterpolantFactoryMethodSmooth: - }, - supportsVertexTextures: function () { + return InterpolateSmooth; - console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' ); - return this.capabilities.vertexTextures; + } - }, - supportsInstancedArrays: function () { + } - console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' ); - return this.extensions.get( 'ANGLE_instanced_arrays' ); + getValueSize() { - }, - enableScissorTest: function ( boolean ) { + return this.values.length / this.times.length; - console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' ); - this.setScissorTest( boolean ); + } - }, - initMaterial: function () { + // move all keyframes either forwards or backwards in time + shift( timeOffset ) { - console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' ); + if ( timeOffset !== 0.0 ) { - }, - addPrePlugin: function () { + const times = this.times; - console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' ); + for ( let i = 0, n = times.length; i !== n; ++ i ) { - }, - addPostPlugin: function () { + times[ i ] += timeOffset; - console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' ); + } - }, - updateShadowMap: function () { + } - console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' ); + return this; } -} ); + // scale all keyframe times by a factor (useful for frame <-> seconds conversions) + scale( timeScale ) { -Object.defineProperties( WebGLRenderer.prototype, { + if ( timeScale !== 1.0 ) { - shadowMapEnabled: { - get: function () { + const times = this.times; - return this.shadowMap.enabled; + for ( let i = 0, n = times.length; i !== n; ++ i ) { - }, - set: function ( value ) { + times[ i ] *= timeScale; - console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' ); - this.shadowMap.enabled = value; + } } - }, - shadowMapType: { - get: function () { - return this.shadowMap.type; + return this; - }, - set: function ( value ) { + } - console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' ); - this.shadowMap.type = value; + // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. + // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values + trim( startTime, endTime ) { - } - }, - shadowMapCullFace: { - get: function () { + const times = this.times, + nKeys = times.length; - return this.shadowMap.cullFace; + let from = 0, + to = nKeys - 1; - }, - set: function ( value ) { + while ( from !== nKeys && times[ from ] < startTime ) { - console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' ); - this.shadowMap.cullFace = value; + ++ from; } - } -} ); -Object.defineProperties( WebGLShadowMap.prototype, { - - cullFace: { - get: function () { + while ( to !== - 1 && times[ to ] > endTime ) { - return this.renderReverseSided ? CullFaceFront : CullFaceBack; + -- to; - }, - set: function ( cullFace ) { + } - var value = ( cullFace !== CullFaceBack ); - console.warn( "WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to " + value + "." ); - this.renderReverseSided = value; + ++ to; // inclusive -> exclusive bound - } - } + if ( from !== 0 || to !== nKeys ) { -} ); + // empty tracks are forbidden, so keep at least one keyframe + if ( from >= to ) { -// + to = Math.max( to, 1 ); + from = to - 1; -Object.defineProperties( WebGLRenderTarget.prototype, { + } - wrapS: { - get: function () { + const stride = this.getValueSize(); + this.times = times.slice( from, to ); + this.values = this.values.slice( from * stride, to * stride ); - console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); - return this.texture.wrapS; + } - }, - set: function ( value ) { + return this; - console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); - this.texture.wrapS = value; + } - } - }, - wrapT: { - get: function () { + // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable + validate() { - console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); - return this.texture.wrapT; + let valid = true; - }, - set: function ( value ) { + const valueSize = this.getValueSize(); + if ( valueSize - Math.floor( valueSize ) !== 0 ) { - console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); - this.texture.wrapT = value; + console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); + valid = false; } - }, - magFilter: { - get: function () { - console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); - return this.texture.magFilter; + const times = this.times, + values = this.values, - }, - set: function ( value ) { + nKeys = times.length; - console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); - this.texture.magFilter = value; + if ( nKeys === 0 ) { - } - }, - minFilter: { - get: function () { + console.error( 'THREE.KeyframeTrack: Track is empty.', this ); + valid = false; - console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); - return this.texture.minFilter; + } - }, - set: function ( value ) { + let prevTime = null; - console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); - this.texture.minFilter = value; + for ( let i = 0; i !== nKeys; i ++ ) { - } - }, - anisotropy: { - get: function () { + const currTime = times[ i ]; - console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); - return this.texture.anisotropy; + if ( typeof currTime === 'number' && isNaN( currTime ) ) { - }, - set: function ( value ) { + console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); + valid = false; + break; - console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); - this.texture.anisotropy = value; + } - } - }, - offset: { - get: function () { + if ( prevTime !== null && prevTime > currTime ) { - console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); - return this.texture.offset; + console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); + valid = false; + break; - }, - set: function ( value ) { + } - console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); - this.texture.offset = value; + prevTime = currTime; } - }, - repeat: { - get: function () { - console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); - return this.texture.repeat; + if ( values !== undefined ) { - }, - set: function ( value ) { + if ( isTypedArray( values ) ) { - console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); - this.texture.repeat = value; + for ( let i = 0, n = values.length; i !== n; ++ i ) { - } - }, - format: { - get: function () { + const value = values[ i ]; - console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); - return this.texture.format; + if ( isNaN( value ) ) { - }, - set: function ( value ) { + console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); + valid = false; + break; + + } + + } - console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); - this.texture.format = value; + } } - }, - type: { - get: function () { - console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); - return this.texture.type; + return valid; + + } - }, - set: function ( value ) { + // removes equivalent sequential keys as common in morph target sequences + // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) + optimize() { - console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); - this.texture.type = value; + // times or values may be shared with other tracks, so overwriting is unsafe + const times = this.times.slice(), + values = this.values.slice(), + stride = this.getValueSize(), - } - }, - generateMipmaps: { - get: function () { + smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + + lastIndex = times.length - 1; + + let writeIndex = 1; - console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); - return this.texture.generateMipmaps; + for ( let i = 1; i < lastIndex; ++ i ) { - }, - set: function ( value ) { + let keep = false; - console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); - this.texture.generateMipmaps = value; + const time = times[ i ]; + const timeNext = times[ i + 1 ]; - } - } + // remove adjacent keyframes scheduled at the same time -} ); + if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { -// + if ( ! smoothInterpolation ) { -Object.assign( WebVRManager.prototype, { + // remove unnecessary keyframes same as their neighbors - getStandingMatrix: function () { + const offset = i * stride, + offsetP = offset - stride, + offsetN = offset + stride; - console.warn( 'THREE.WebVRManager: .getStandingMatrix() has been removed.' ); + for ( let j = 0; j !== stride; ++ j ) { - } + const value = values[ offset + j ]; -} ); + if ( value !== values[ offsetP + j ] || + value !== values[ offsetN + j ] ) { -Object.defineProperties( WebVRManager.prototype, { + keep = true; + break; - standing: { - set: function ( /* value */ ) { + } - console.warn( 'THREE.WebVRManager: .standing has been removed.' ); + } - } - } + } else { -} ); + keep = true; -// + } -Audio.prototype.load = function ( file ) { + } - console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' ); - var scope = this; - var audioLoader = new AudioLoader(); - audioLoader.load( file, function ( buffer ) { + // in-place compaction - scope.setBuffer( buffer ); + if ( keep ) { - } ); - return this; + if ( i !== writeIndex ) { -}; + times[ writeIndex ] = times[ i ]; -AudioAnalyser.prototype.getData = function () { + const readOffset = i * stride, + writeOffset = writeIndex * stride; - console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' ); - return this.getFrequencyData(); + for ( let j = 0; j !== stride; ++ j ) { -}; + values[ writeOffset + j ] = values[ readOffset + j ]; -// + } -CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) { + } - console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' ); - return this.update( renderer, scene ); + ++ writeIndex; -}; + } -// + } + + // flush last keyframe (compaction looks ahead) -var GeometryUtils = { + if ( lastIndex > 0 ) { - merge: function ( geometry1, geometry2, materialIndexOffset ) { + times[ writeIndex ] = times[ lastIndex ]; - console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); - var matrix; + for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { - if ( geometry2.isMesh ) { + values[ writeOffset + j ] = values[ readOffset + j ]; - geometry2.matrixAutoUpdate && geometry2.updateMatrix(); + } - matrix = geometry2.matrix; - geometry2 = geometry2.geometry; + ++ writeIndex; } - geometry1.merge( geometry2, matrix, materialIndexOffset ); + if ( writeIndex !== times.length ) { - }, + this.times = times.slice( 0, writeIndex ); + this.values = values.slice( 0, writeIndex * stride ); + + } else { - center: function ( geometry ) { + this.times = times; + this.values = values; - console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); - return geometry.center(); + } + + return this; } -}; + clone() { -var ImageUtils = { + const times = this.times.slice(); + const values = this.values.slice(); - crossOrigin: undefined, + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack( this.name, times, values ); - loadTexture: function ( url, mapping, onLoad, onError ) { + // Interpolant argument to constructor is not saved, so copy the factory method directly. + track.createInterpolant = this.createInterpolant; - console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' ); + return track; - var loader = new TextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); + } - var texture = loader.load( url, onLoad, undefined, onError ); +} - if ( mapping ) { texture.mapping = mapping; } +KeyframeTrack.prototype.TimeBufferType = Float32Array; +KeyframeTrack.prototype.ValueBufferType = Float32Array; +KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; - return texture; +/** + * A Track of Boolean keyframe values. + */ +class BooleanKeyframeTrack extends KeyframeTrack { - }, + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { - loadTextureCube: function ( urls, mapping, onLoad, onError ) { + super( name, times, values ); - console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' ); + } - var loader = new CubeTextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); +} - var texture = loader.load( urls, onLoad, undefined, onError ); +BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; +BooleanKeyframeTrack.prototype.ValueBufferType = Array; +BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - if ( mapping ) { texture.mapping = mapping; } +/** + * A Track of keyframe values that represent color. + */ +class ColorKeyframeTrack extends KeyframeTrack {} - return texture; +ColorKeyframeTrack.prototype.ValueTypeName = 'color'; - }, +/** + * A Track of numeric keyframe values. + */ +class NumberKeyframeTrack extends KeyframeTrack {} - loadCompressedTexture: function () { +NumberKeyframeTrack.prototype.ValueTypeName = 'number'; - console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ); +/** + * Spherical linear unit quaternion interpolant. + */ - }, +class QuaternionLinearInterpolant extends Interpolant { - loadCompressedTextureCube: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ); + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); } -}; + interpolate_( i1, t0, t, t1 ) { -// + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, -function Projector() { + alpha = ( t - t0 ) / ( t1 - t0 ); - console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' ); + let offset = i1 * stride; - this.projectVector = function ( vector, camera ) { + for ( let end = offset + stride; offset !== end; offset += 4 ) { - console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); - vector.project( camera ); + Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); - }; + } - this.unprojectVector = function ( vector, camera ) { + return result; - console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); - vector.unproject( camera ); + } - }; +} - this.pickingRay = function () { +/** + * A Track of quaternion keyframe values. + */ +class QuaternionKeyframeTrack extends KeyframeTrack { - console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' ); + InterpolantFactoryMethodLinear( result ) { - }; + return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); + + } } -// +QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; +// ValueBufferType is inherited +// DefaultInterpolation is inherited; +QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; -function CanvasRenderer() { - - console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' ); - - this.domElement = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - this.clear = function () {}; - this.render = function () {}; - this.setClearColor = function () {}; - this.setSize = function () {}; - -} - -var THREE$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - WebGLRenderTargetCube: WebGLRenderTargetCube, - WebGLRenderTarget: WebGLRenderTarget, - WebGLRenderer: WebGLRenderer, - ShaderLib: ShaderLib, - UniformsLib: UniformsLib, - UniformsUtils: UniformsUtils, - ShaderChunk: ShaderChunk, - FogExp2: FogExp2, - Fog: Fog, - Scene: Scene, - LensFlare: LensFlare, - Sprite: Sprite, - LOD: LOD, - SkinnedMesh: SkinnedMesh, - Skeleton: Skeleton, - Bone: Bone, - Mesh: Mesh, - LineSegments: LineSegments, - LineLoop: LineLoop, - Line: Line, - Points: Points$1, - Group: Group, - VideoTexture: VideoTexture, - DataTexture: DataTexture, - CompressedTexture: CompressedTexture, - CubeTexture: CubeTexture, - CanvasTexture: CanvasTexture, - DepthTexture: DepthTexture, - Texture: Texture, - CompressedTextureLoader: CompressedTextureLoader, - DataTextureLoader: DataTextureLoader, - CubeTextureLoader: CubeTextureLoader, - TextureLoader: TextureLoader, - ObjectLoader: ObjectLoader, - MaterialLoader: MaterialLoader, - BufferGeometryLoader: BufferGeometryLoader, - DefaultLoadingManager: DefaultLoadingManager, - LoadingManager: LoadingManager, - JSONLoader: JSONLoader, - ImageLoader: ImageLoader, - ImageBitmapLoader: ImageBitmapLoader, - FontLoader: FontLoader, - FileLoader: FileLoader, - Loader: Loader, - LoaderUtils: LoaderUtils, - Cache: Cache, - AudioLoader: AudioLoader, - SpotLightShadow: SpotLightShadow, - SpotLight: SpotLight, - PointLight: PointLight, - RectAreaLight: RectAreaLight, - HemisphereLight: HemisphereLight, - DirectionalLightShadow: DirectionalLightShadow, - DirectionalLight: DirectionalLight, - AmbientLight: AmbientLight, - LightShadow: LightShadow, - Light: Light, - StereoCamera: StereoCamera, - PerspectiveCamera: PerspectiveCamera, - OrthographicCamera: OrthographicCamera, - CubeCamera: CubeCamera, - ArrayCamera: ArrayCamera, - Camera: Camera, - AudioListener: AudioListener, - PositionalAudio: PositionalAudio, - AudioContext: AudioContext, - AudioAnalyser: AudioAnalyser, - Audio: Audio, - VectorKeyframeTrack: VectorKeyframeTrack, - StringKeyframeTrack: StringKeyframeTrack, - QuaternionKeyframeTrack: QuaternionKeyframeTrack, - NumberKeyframeTrack: NumberKeyframeTrack, - ColorKeyframeTrack: ColorKeyframeTrack, - BooleanKeyframeTrack: BooleanKeyframeTrack, - PropertyMixer: PropertyMixer, - PropertyBinding: PropertyBinding, - KeyframeTrack: KeyframeTrack, - AnimationUtils: AnimationUtils, - AnimationObjectGroup: AnimationObjectGroup, - AnimationMixer: AnimationMixer, - AnimationClip: AnimationClip, - Uniform: Uniform, - InstancedBufferGeometry: InstancedBufferGeometry, - BufferGeometry: BufferGeometry, - Geometry: Geometry, - InterleavedBufferAttribute: InterleavedBufferAttribute, - InstancedInterleavedBuffer: InstancedInterleavedBuffer, - InterleavedBuffer: InterleavedBuffer, - InstancedBufferAttribute: InstancedBufferAttribute, - Face3: Face3, - Object3D: Object3D, - Raycaster: Raycaster, - Layers: Layers, - EventDispatcher: EventDispatcher, - Clock: Clock, - QuaternionLinearInterpolant: QuaternionLinearInterpolant, - LinearInterpolant: LinearInterpolant, - DiscreteInterpolant: DiscreteInterpolant, - CubicInterpolant: CubicInterpolant, - Interpolant: Interpolant, - Triangle: Triangle, - Math: _Math, - Spherical: Spherical, - Cylindrical: Cylindrical, - Plane: Plane, - Frustum: Frustum, - Sphere: Sphere, - Ray: Ray, - Matrix4: Matrix4, - Matrix3: Matrix3, - Box3: Box3, - Box2: Box2, - Line3: Line3, - Euler: Euler, - Vector4: Vector4, - Vector3: Vector3, - Vector2: Vector2, - Quaternion: Quaternion, - Color: Color, - ImmediateRenderObject: ImmediateRenderObject, - VertexNormalsHelper: VertexNormalsHelper, - SpotLightHelper: SpotLightHelper, - SkeletonHelper: SkeletonHelper, - PointLightHelper: PointLightHelper, - RectAreaLightHelper: RectAreaLightHelper, - HemisphereLightHelper: HemisphereLightHelper, - GridHelper: GridHelper, - PolarGridHelper: PolarGridHelper, - FaceNormalsHelper: FaceNormalsHelper, - DirectionalLightHelper: DirectionalLightHelper, - CameraHelper: CameraHelper, - BoxHelper: BoxHelper, - Box3Helper: Box3Helper, - PlaneHelper: PlaneHelper, - ArrowHelper: ArrowHelper, - AxesHelper: AxesHelper, - Shape: Shape, - Path: Path$1, - ShapePath: ShapePath, - Font: Font, - CurvePath: CurvePath, - Curve: Curve, - ShapeUtils: ShapeUtils, - SceneUtils: SceneUtils, - WebGLUtils: WebGLUtils, - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry, - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material, - Float64BufferAttribute: Float64BufferAttribute, - Float32BufferAttribute: Float32BufferAttribute, - Uint32BufferAttribute: Uint32BufferAttribute, - Int32BufferAttribute: Int32BufferAttribute, - Uint16BufferAttribute: Uint16BufferAttribute, - Int16BufferAttribute: Int16BufferAttribute, - Uint8ClampedBufferAttribute: Uint8ClampedBufferAttribute, - Uint8BufferAttribute: Uint8BufferAttribute, - Int8BufferAttribute: Int8BufferAttribute, - BufferAttribute: BufferAttribute, - ArcCurve: ArcCurve, - CatmullRomCurve3: CatmullRomCurve3, - CubicBezierCurve: CubicBezierCurve, - CubicBezierCurve3: CubicBezierCurve3, - EllipseCurve: EllipseCurve, - LineCurve: LineCurve, - LineCurve3: LineCurve3, - QuadraticBezierCurve: QuadraticBezierCurve, - QuadraticBezierCurve3: QuadraticBezierCurve3, - SplineCurve: SplineCurve, - REVISION: REVISION, - MOUSE: MOUSE, - CullFaceNone: CullFaceNone, - CullFaceBack: CullFaceBack, - CullFaceFront: CullFaceFront, - CullFaceFrontBack: CullFaceFrontBack, - FrontFaceDirectionCW: FrontFaceDirectionCW, - FrontFaceDirectionCCW: FrontFaceDirectionCCW, - BasicShadowMap: BasicShadowMap, - PCFShadowMap: PCFShadowMap, - PCFSoftShadowMap: PCFSoftShadowMap, - FrontSide: FrontSide, - BackSide: BackSide, - DoubleSide: DoubleSide, - FlatShading: FlatShading, - SmoothShading: SmoothShading, - NoColors: NoColors, - FaceColors: FaceColors, - VertexColors: VertexColors, - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending, - AddEquation: AddEquation, - SubtractEquation: SubtractEquation, - ReverseSubtractEquation: ReverseSubtractEquation, - MinEquation: MinEquation, - MaxEquation: MaxEquation, - ZeroFactor: ZeroFactor, - OneFactor: OneFactor, - SrcColorFactor: SrcColorFactor, - OneMinusSrcColorFactor: OneMinusSrcColorFactor, - SrcAlphaFactor: SrcAlphaFactor, - OneMinusSrcAlphaFactor: OneMinusSrcAlphaFactor, - DstAlphaFactor: DstAlphaFactor, - OneMinusDstAlphaFactor: OneMinusDstAlphaFactor, - DstColorFactor: DstColorFactor, - OneMinusDstColorFactor: OneMinusDstColorFactor, - SrcAlphaSaturateFactor: SrcAlphaSaturateFactor, - NeverDepth: NeverDepth, - AlwaysDepth: AlwaysDepth, - LessDepth: LessDepth, - LessEqualDepth: LessEqualDepth, - EqualDepth: EqualDepth, - GreaterEqualDepth: GreaterEqualDepth, - GreaterDepth: GreaterDepth, - NotEqualDepth: NotEqualDepth, - MultiplyOperation: MultiplyOperation, - MixOperation: MixOperation, - AddOperation: AddOperation, - NoToneMapping: NoToneMapping, - LinearToneMapping: LinearToneMapping, - ReinhardToneMapping: ReinhardToneMapping, - Uncharted2ToneMapping: Uncharted2ToneMapping, - CineonToneMapping: CineonToneMapping, - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping, - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping, - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter, - UnsignedByteType: UnsignedByteType, - ByteType: ByteType, - ShortType: ShortType, - UnsignedShortType: UnsignedShortType, - IntType: IntType, - UnsignedIntType: UnsignedIntType, - FloatType: FloatType, - HalfFloatType: HalfFloatType, - UnsignedShort4444Type: UnsignedShort4444Type, - UnsignedShort5551Type: UnsignedShort5551Type, - UnsignedShort565Type: UnsignedShort565Type, - UnsignedInt248Type: UnsignedInt248Type, - AlphaFormat: AlphaFormat, - RGBFormat: RGBFormat, - RGBAFormat: RGBAFormat, - LuminanceFormat: LuminanceFormat, - LuminanceAlphaFormat: LuminanceAlphaFormat, - RGBEFormat: RGBEFormat, - DepthFormat: DepthFormat, - DepthStencilFormat: DepthStencilFormat, - RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format, - RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format, - RGBA_S3TC_DXT3_Format: RGBA_S3TC_DXT3_Format, - RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format, - RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format, - RGB_PVRTC_2BPPV1_Format: RGB_PVRTC_2BPPV1_Format, - RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format, - RGBA_PVRTC_2BPPV1_Format: RGBA_PVRTC_2BPPV1_Format, - RGB_ETC1_Format: RGB_ETC1_Format, - LoopOnce: LoopOnce, - LoopRepeat: LoopRepeat, - LoopPingPong: LoopPingPong, - InterpolateDiscrete: InterpolateDiscrete, - InterpolateLinear: InterpolateLinear, - InterpolateSmooth: InterpolateSmooth, - ZeroCurvatureEnding: ZeroCurvatureEnding, - ZeroSlopeEnding: ZeroSlopeEnding, - WrapAroundEnding: WrapAroundEnding, - TrianglesDrawMode: TrianglesDrawMode, - TriangleStripDrawMode: TriangleStripDrawMode, - TriangleFanDrawMode: TriangleFanDrawMode, - LinearEncoding: LinearEncoding, - sRGBEncoding: sRGBEncoding, - GammaEncoding: GammaEncoding, - RGBEEncoding: RGBEEncoding, - LogLuvEncoding: LogLuvEncoding, - RGBM7Encoding: RGBM7Encoding, - RGBM16Encoding: RGBM16Encoding, - RGBDEncoding: RGBDEncoding, - BasicDepthPacking: BasicDepthPacking, - RGBADepthPacking: RGBADepthPacking, - CubeGeometry: BoxGeometry, - Face4: Face4, - LineStrip: LineStrip, - LinePieces: LinePieces, - MeshFaceMaterial: MeshFaceMaterial, - MultiMaterial: MultiMaterial, - PointCloud: PointCloud, - Particle: Particle, - ParticleSystem: ParticleSystem, - PointCloudMaterial: PointCloudMaterial, - ParticleBasicMaterial: ParticleBasicMaterial, - ParticleSystemMaterial: ParticleSystemMaterial, - Vertex: Vertex, - DynamicBufferAttribute: DynamicBufferAttribute, - Int8Attribute: Int8Attribute, - Uint8Attribute: Uint8Attribute, - Uint8ClampedAttribute: Uint8ClampedAttribute, - Int16Attribute: Int16Attribute, - Uint16Attribute: Uint16Attribute, - Int32Attribute: Int32Attribute, - Uint32Attribute: Uint32Attribute, - Float32Attribute: Float32Attribute, - Float64Attribute: Float64Attribute, - ClosedSplineCurve3: ClosedSplineCurve3, - SplineCurve3: SplineCurve3, - Spline: Spline, - AxisHelper: AxisHelper, - BoundingBoxHelper: BoundingBoxHelper, - EdgesHelper: EdgesHelper, - WireframeHelper: WireframeHelper, - XHRLoader: XHRLoader, - BinaryTextureLoader: BinaryTextureLoader, - GeometryUtils: GeometryUtils, - ImageUtils: ImageUtils, - Projector: Projector, - CanvasRenderer: CanvasRenderer -}); +/** + * A Track that interpolates Strings + */ +class StringKeyframeTrack extends KeyframeTrack { -var THREE = Object.assign({}, THREE$1); + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { -// Marker types -var MARKER_ARROW = 0; -var MARKER_CUBE = 1; -var MARKER_SPHERE = 2; -var MARKER_CYLINDER = 3; -var MARKER_LINE_STRIP = 4; -var MARKER_LINE_LIST = 5; -var MARKER_CUBE_LIST = 6; -var MARKER_SPHERE_LIST = 7; -var MARKER_POINTS = 8; -var MARKER_TEXT_VIEW_FACING = 9; -var MARKER_MESH_RESOURCE = 10; -var MARKER_TRIANGLE_LIST = 11; + super( name, times, values ); -// Interactive marker feedback types -var INTERACTIVE_MARKER_KEEP_ALIVE = 0; -var INTERACTIVE_MARKER_POSE_UPDATE = 1; -var INTERACTIVE_MARKER_MENU_SELECT = 2; -var INTERACTIVE_MARKER_BUTTON_CLICK = 3; -var INTERACTIVE_MARKER_MOUSE_DOWN = 4; -var INTERACTIVE_MARKER_MOUSE_UP = 5; + } -// Interactive marker control types -var INTERACTIVE_MARKER_NONE = 0; -var INTERACTIVE_MARKER_MENU = 1; -var INTERACTIVE_MARKER_BUTTON = 2; -var INTERACTIVE_MARKER_MOVE_AXIS = 3; -var INTERACTIVE_MARKER_MOVE_PLANE = 4; -var INTERACTIVE_MARKER_ROTATE_AXIS = 5; -var INTERACTIVE_MARKER_MOVE_ROTATE = 6; -var INTERACTIVE_MARKER_MOVE_3D = 7; -var INTERACTIVE_MARKER_ROTATE_3D = 8; -var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; +} -// Interactive marker rotation behavior -var INTERACTIVE_MARKER_INHERIT = 0; -var INTERACTIVE_MARKER_FIXED = 1; -var INTERACTIVE_MARKER_VIEW_FACING = 2; +StringKeyframeTrack.prototype.ValueTypeName = 'string'; +StringKeyframeTrack.prototype.ValueBufferType = Array; +StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; /** - * @function makeColorMaterial - * @description Create a THREE material based on the given RGBA values. - * - * @param r - the red value - * @param g - the green value - * @param b - the blue value - * @param a - the alpha value - * @returns the THREE material + * A Track of vectored keyframe values. */ -var makeColorMaterial = function(r, g, b, a) { - var color = new THREE.Color(); - color.setRGB(r, g, b); - if (a <= 0.99) { - return new THREE.MeshBasicMaterial({ - color : color.getHex(), - opacity : a + 0.1, - transparent : true, - depthWrite : true, - blendSrc : THREE.SrcAlphaFactor, - blendDst : THREE.OneMinusSrcAlphaFactor, - blendEquation : THREE.ReverseSubtractEquation, - blending : THREE.NormalBlending - }); - } else { - return new THREE.MeshPhongMaterial({ - color : color.getHex(), - opacity : a, - blending : THREE.NormalBlending - }); - } -}; +class VectorKeyframeTrack extends KeyframeTrack {} -/** - * @function intersectPlane - * @description Return the intersection between the mouseray and the plane. - * - * @param mouseRay - the mouse ray - * @param planeOrigin - the origin of the plane - * @param planeNormal - the normal of the plane - * @returns the intersection point - */ -var intersectPlane = function(mouseRay, planeOrigin, planeNormal) { - var vector = new THREE.Vector3(); - var intersectPoint = new THREE.Vector3(); - vector.subVectors(planeOrigin, mouseRay.origin); - var dot = mouseRay.direction.dot(planeNormal); +VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; - // bail if ray and plane are parallel - if (Math.abs(dot) < mouseRay.precision) { - return undefined; - } +class AnimationClip { - // calc distance to plane - var scalar = planeNormal.dot(vector) / dot; + constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { - intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); - return intersectPoint; -}; + this.name = name; + this.tracks = tracks; + this.duration = duration; + this.blendMode = blendMode; -/** - * @function findClosestPoint - * @description Find the closest point on targetRay to any point on mouseRay. Math taken from - * http://paulbourke.net/geometry/lineline3d/ - * - * @param targetRay - the target ray to use - * @param mouseRay - the mouse ray - * @param the closest point between the two rays - */ -var findClosestPoint = function(targetRay, mouseRay) { - var v13 = new THREE.Vector3(); - v13.subVectors(targetRay.origin, mouseRay.origin); - var v43 = mouseRay.direction.clone(); - var v21 = targetRay.direction.clone(); - var d1343 = v13.dot(v43); - var d4321 = v43.dot(v21); - var d1321 = v13.dot(v21); - var d4343 = v43.dot(v43); - var d2121 = v21.dot(v21); + this.uuid = generateUUID(); - var denom = d2121 * d4343 - d4321 * d4321; - // check within a delta - if (Math.abs(denom) <= 0.0001) { - return undefined; - } - var numer = d1343 * d4321 - d1321 * d4343; + // this means it should figure out its duration by scanning the tracks + if ( this.duration < 0 ) { - var mua = numer / denom; - return mua; -}; + this.resetDuration(); -/** - * @function closestAxisPoint - * @description Find the closest point between the axis and the mouse. - * - * @param axisRay - the ray from the axis - * @param camera - the camera to project from - * @param mousePos - the mouse position - * @returns the closest axis point - */ -var closestAxisPoint = function(axisRay, camera, mousePos) { - // project axis onto screen - var o = axisRay.origin.clone(); - o.project(camera); - var o2 = axisRay.direction.clone().add(axisRay.origin); - o2.project(camera); + } - // d is the axis vector in screen space (d = o2-o) - var d = o2.clone().sub(o); + } - // t is the 2d ray param of perpendicular projection of mousePos onto o - var tmp = new THREE.Vector2(); - // (t = (mousePos - o) * d / (d*d)) - var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); - // mp is the final 2d-projected mouse pos (mp = o + d*t) - var mp = new THREE.Vector2(); - mp.addVectors(o, d.clone().multiplyScalar(t)); + static parse( json ) { - // go back to 3d by shooting a ray - var vector = new THREE.Vector3(mp.x, mp.y, 0.5); - vector.unproject(camera); - var mpRay = new THREE.Ray(camera.position, vector.sub(camera.position).normalize()); + const tracks = [], + jsonTracks = json.tracks, + frameTime = 1.0 / ( json.fps || 1.0 ); - return findClosestPoint(axisRay, mpRay); -}; + for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { -/** - * @fileOverview - * @author Julius Kammerl - jkammerl@willowgarage.com - */ + tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); -var DepthCloud = /*@__PURE__*/(function (superclass) { - function DepthCloud(options) { - superclass.call(this); - options = options || {}; + } - this.url = options.url; - this.streamType = options.streamType || 'vp8'; - this.f = options.f || 526; - this.maxDepthPerTile = options.maxDepthPerTile || 1.0; - this.pointSize = options.pointSize || 3; - this.width = options.width || 1024; - this.height = options.height || 1024; - this.resolutionFactor = Math.max(this.width, this.height) / 1024; - this.whiteness = options.whiteness || 0; - this.varianceThreshold = options.varianceThreshold || 0.000016667; - - this.isMjpeg = this.streamType.toLowerCase() === 'mjpeg'; - - this.video = document.createElement(this.isMjpeg ? 'img' : 'video'); - this.video.crossOrigin = 'Anonymous'; - this.video.addEventListener(this.isMjpeg ? 'load' : 'loadedmetadata', this.metaLoaded.bind(this), false); - - if (!this.isMjpeg) { - this.video.loop = true; - } + const clip = new this( json.name, json.duration, tracks, json.blendMode ); + clip.uuid = json.uuid; - this.video.src = this.url; - this.video.setAttribute('crossorigin', 'Anonymous'); + return clip; - // define custom shaders - this.vertex_shader = [ - 'uniform sampler2D map;', - '', - 'uniform float width;', - 'uniform float height;', - 'uniform float nearClipping, farClipping;', - '', - 'uniform float pointSize;', - 'uniform float zOffset;', - '', - 'uniform float focallength;', - 'uniform float maxDepthPerTile;', - 'uniform float resolutionFactor;', - '', - 'varying vec2 vUvP;', - 'varying vec2 colorP;', - '', - 'varying float depthVariance;', - 'varying float maskVal;', - '', - 'float sampleDepth(vec2 pos)', - ' {', - ' float depth;', - ' ', - ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', - ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', - ' ', - ' vec4 depthColor = texture2D( map, vUv );', - ' ', - ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', - ' ', - ' if (depth>0.99)', - ' {', - ' vec4 depthColor2 = texture2D( map, vUv2 );', - ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', - ' depth = 0.99+depth2;', - ' }', - ' ', - ' return depth;', - ' }', - '', - 'float median(float a, float b, float c)', - ' {', - ' float r=a;', - ' ', - ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', - ' {', - ' vec2 smp = decodeDepth(vec2(position.x, position.y));', - ' float depth = smp.x;', - ' depthVariance = smp.y;', - ' ', - ' float z = -depth;', - ' ', - ' pos = vec4(', - ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', - ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', - ' (- z + zOffset / 1000.0) * maxDepthPerTile,', - ' 1.0);', - ' ', - ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', - ' vec4 maskColor = texture2D( map, maskP );', - ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', - ' }', - ' ', - ' gl_PointSize = pointSize;', - ' gl_Position = projectionMatrix * modelViewMatrix * pos;', - ' ', - '}' - ].join('\n'); - - this.fragment_shader = [ - 'uniform sampler2D map;', - 'uniform float varianceThreshold;', - 'uniform float whiteness;', - '', - 'varying vec2 vUvP;', - 'varying vec2 colorP;', - '', - 'varying float depthVariance;', - 'varying float maskVal;', - '', - '', - 'void main() {', - ' ', - ' vec4 color;', - ' ', - ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', - ' { ', - ' discard;', - ' }', - ' else ', - ' {', - ' color = texture2D( map, colorP );', - ' ', - ' float fader = whiteness /100.0;', - ' ', - ' color.r = color.r * (1.0-fader)+ fader;', - ' ', - ' color.g = color.g * (1.0-fader)+ fader;', - ' ', - ' color.b = color.b * (1.0-fader)+ fader;', - ' ', - ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', - ' }', - ' ', - ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', - ' ', - '}' - ].join('\n'); - } + } - if ( superclass ) DepthCloud.__proto__ = superclass; - DepthCloud.prototype = Object.create( superclass && superclass.prototype ); - DepthCloud.prototype.constructor = DepthCloud; - /** - * Callback called when video metadata is ready - */ - DepthCloud.prototype.metaLoaded = function metaLoaded () { - this.metaLoaded = true; - this.initStreamer(); - }; - /** - * Callback called when video metadata is ready - */ - DepthCloud.prototype.initStreamer = function initStreamer () { - var this$1$1 = this; + 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 ) { - if (this.metaLoaded) { - this.texture = new THREE.Texture(this.video); - this.geometry = new THREE.Geometry(); + tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); - for (var i = 0, l = this.width * this.height; i < l; i++) { + } - var vertex = new THREE.Vector3(); - vertex.x = (i % this.width); - vertex.y = Math.floor(i / this.width); + return json; - this.geometry.vertices.push(vertex); - } + } - this.material = new THREE.ShaderMaterial({ - uniforms : { - 'map' : { - type : 't', - value : this.texture - }, - 'width' : { - type : 'f', - value : this.width - }, - 'height' : { - type : 'f', - value : this.height - }, - 'focallength' : { - type : 'f', - value : this.f - }, - 'pointSize' : { - type : 'f', - value : this.pointSize - }, - 'zOffset' : { - type : 'f', - value : 0 - }, - 'whiteness' : { - type : 'f', - value : this.whiteness - }, - 'varianceThreshold' : { - type : 'f', - value : this.varianceThreshold - }, - 'maxDepthPerTile': { - type : 'f', - value : this.maxDepthPerTile - }, - 'resolutionFactor': { - type : 'f', - value : this.resolutionFactor - }, - }, - vertexShader : this.vertex_shader, - fragmentShader : this.fragment_shader - }); + static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { - this.mesh = new THREE.ParticleSystem(this.geometry, this.material); - this.mesh.position.x = 0; - this.mesh.position.y = 0; - this.add(this.mesh); + const numMorphTargets = morphTargetSequence.length; + const tracks = []; - setInterval(function () { - if (this$1$1.isMjpeg || this$1$1.video.readyState === this$1$1.video.HAVE_ENOUGH_DATA) { - this$1$1.texture.needsUpdate = true; - } - }, 1000 / 30); - } - }; - /** - * Start video playback - */ - DepthCloud.prototype.startStream = function startStream () { - if (!this.isMjpeg) { - this.video.play(); - } - }; - /** - * Stop video playback - */ - DepthCloud.prototype.stopStream = function stopStream () { - if (!this.isMjpeg) { - this.video.pause(); - } - }; + for ( let i = 0; i < numMorphTargets; i ++ ) { - return DepthCloud; -}(THREE.Object3D)); + let times = []; + let values = []; -/** - * @fileOverview - * @author David Gossow - dgossow@willowgarage.com - */ + times.push( + ( i + numMorphTargets - 1 ) % numMorphTargets, + i, + ( i + 1 ) % numMorphTargets ); -var Arrow = /*@__PURE__*/(function (superclass) { - function Arrow(options) { - options = options || {}; - var origin = options.origin || new THREE.Vector3(0, 0, 0); - var direction = options.direction || new THREE.Vector3(1, 0, 0); - var length = options.length || 1; - var headLength = options.headLength || 0.2; - var shaftDiameter = options.shaftDiameter || 0.05; - var headDiameter = options.headDiameter || 0.1; - var material = options.material || new THREE.MeshBasicMaterial(); + values.push( 0, 1, 0 ); - var shaftLength = length - headLength; + const order = getKeyframeOrder( times ); + times = sortedArray( times, 1, order ); + values = sortedArray( values, 1, order ); - // create and merge geometry - var geometry = new THREE.CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, - 12, 1); - var m = new THREE.Matrix4(); - m.setPosition(new THREE.Vector3(0, shaftLength * 0.5, 0)); - geometry.applyMatrix(m); + // if there is a key at the first frame, duplicate it as the + // last frame as well for perfect loop. + if ( ! noLoop && times[ 0 ] === 0 ) { - // create the head - var coneGeometry = new THREE.CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); - m.setPosition(new THREE.Vector3(0, shaftLength + (headLength * 0.5), 0)); - coneGeometry.applyMatrix(m); + times.push( numMorphTargets ); + values.push( values[ 0 ] ); - // put the arrow together - geometry.merge(coneGeometry); + } - superclass.call(this, geometry, material); + tracks.push( + new NumberKeyframeTrack( + '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', + times, values + ).scale( 1.0 / fps ) ); - this.position.copy(origin); - this.setDirection(direction); - } + } - if ( superclass ) Arrow.__proto__ = superclass; - Arrow.prototype = Object.create( superclass && superclass.prototype ); - Arrow.prototype.constructor = Arrow; - /** - * Set the direction of this arrow to that of the given vector. - * - * @param direction - the direction to set this arrow - */ - Arrow.prototype.setDirection = function setDirection (direction) { - var axis = new THREE.Vector3(); - if(direction.x === 0 && direction.z === 0){ - axis.set(1, 0, 0); - } else { - axis.set(0, 1, 0).cross(direction); - } - var radians = Math.acos(new THREE.Vector3(0, 1, 0).dot(direction.clone().normalize())); - this.matrix = new THREE.Matrix4().makeRotationAxis(axis.normalize(), radians); - this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); - }; - /** - * Set this arrow to be the given length. - * - * @param length - the new length of the arrow - */ - Arrow.prototype.setLength = function setLength (length) { - this.scale.set(length, length, length); - }; - /** - * Set the color of this arrow to the given hex value. - * - * @param hex - the hex value of the color to use - */ - Arrow.prototype.setColor = function setColor (hex) { - this.material.color.setHex(hex); - }; - /* - * Free memory of elements in this marker. - */ - Arrow.prototype.dispose = function dispose () { - if (this.geometry !== undefined) { - this.geometry.dispose(); - } - if (this.material !== undefined) { - this.material.dispose(); - } - }; + return new this( name, - 1, tracks ); - return Arrow; -}(THREE.Mesh)); + } -/** - * @fileOverview - * @author aleeper / http://adamleeper.com/ - * @author mrdoob / http://mrdoob.com/ - * @author gero3 / https://github.com/gero3 - * @author Mugen87 / https://github.com/Mugen87 - * - * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. - * - * Supports both binary and ASCII encoded files, with automatic detection of type. - * - * The loader returns a non-indexed buffer geometry. - * - * Limitations: - * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). - * There is perhaps some question as to how valid it is to always assume little-endian-ness. - * ASCII decoding assumes file is UTF-8. - * - * Usage: - * var loader = new THREE.STLLoader(); - * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { - * scene.add( new THREE.Mesh( geometry ) ); - * }); - * - * For binary STLs geometry might contain colors for vertices. To use it: - * // use the same code to load STL as above - * if (geometry.hasColors) { - * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors }); - * } else { .... } - * var mesh = new THREE.Mesh( geometry, material ); - */ + static findByName( objectOrClipArray, name ) { -THREE.STLLoader = function (manager) { + let clipArray = objectOrClipArray; - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; + if ( ! Array.isArray( objectOrClipArray ) ) { -}; + const o = objectOrClipArray; + clipArray = o.geometry && o.geometry.animations || o.animations; -THREE.STLLoader.prototype = { + } - constructor: THREE.STLLoader, + for ( let i = 0; i < clipArray.length; i ++ ) { - load: function (url, onLoad, onProgress, onError) { + if ( clipArray[ i ].name === name ) { - var scope = this; + return clipArray[ i ]; - var loader = new THREE.FileLoader(scope.manager); - loader.setResponseType('arraybuffer'); - loader.load(url, function (text) { + } - onLoad(scope.parse(text)); + } - }, onProgress, onError); + return null; - }, + } - parse: function (data) { + static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { - function isBinary(data) { + const animationToMorphTargets = {}; - var expect, face_size, n_faces, reader; - reader = new DataView(data); - face_size = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8); - n_faces = reader.getUint32(80, true); - expect = 80 + (32 / 8) + (n_faces * face_size); + // tested with https://regex101.com/ on trick sequences + // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 + const pattern = /^([\w-]*?)([\d]+)$/; + + // sort morph target names into animation groups based + // patterns like Walk_001, Walk_002, Run_001, Run_002 + for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { - if (expect === reader.byteLength) { + const morphTarget = morphTargets[ i ]; + const parts = morphTarget.name.match( pattern ); - return true; + if ( parts && parts.length > 1 ) { - } + const name = parts[ 1 ]; - // An ASCII STL data must begin with 'solid ' as the first six bytes. - // However, ASCII STLs lacking the SPACE after the 'd' are known to be - // plentiful. So, check the first 5 bytes for 'solid'. + let animationMorphTargets = animationToMorphTargets[ name ]; - // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' + if ( ! animationMorphTargets ) { - var solid = [115, 111, 108, 105, 100]; + animationToMorphTargets[ name ] = animationMorphTargets = []; - for (var i = 0; i < 5; i++) { + } - // If solid[ i ] does not match the i-th byte, then it is not an - // ASCII STL; hence, it is binary and return true. + animationMorphTargets.push( morphTarget ); - if (solid[i] != reader.getUint8(i, false)) { return true; } + } - } + } - // First 5 bytes read "solid"; declare it to be an ASCII STL + const clips = []; - return false; + for ( const name in animationToMorphTargets ) { - } + clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); - function parseBinary(data) { + } - var reader = new DataView(data); - var faces = reader.getUint32(80, true); + return clips; - var r, g, b, hasColors = false, colors; - var defaultR, defaultG, defaultB, alpha; + } - // process STL header - // check for default color in header ("COLOR=rgba" sequence). + // parse the animation.hierarchy format + static parseAnimation( animation, bones ) { - for (var index = 0; index < 80 - 10; index++) { + if ( ! animation ) { - if ((reader.getUint32(index, false) == 0x434F4C4F /*COLO*/) && - (reader.getUint8(index + 4) == 0x52 /*'R'*/) && - (reader.getUint8(index + 5) == 0x3D /*'='*/)) { + console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); + return null; - hasColors = true; - colors = []; + } - defaultR = reader.getUint8(index + 6) / 255; - defaultG = reader.getUint8(index + 7) / 255; - defaultB = reader.getUint8(index + 8) / 255; - alpha = reader.getUint8(index + 9) / 255; + const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { - } + // only return track if there are actually keys. + if ( animationKeys.length !== 0 ) { - } + const times = []; + const values = []; - var dataOffset = 84; - var faceLength = 12 * 4 + 2; + flattenJSON( animationKeys, times, values, propertyName ); - var geometry = new THREE.BufferGeometry(); + // empty keys are filtered out, so check again + if ( times.length !== 0 ) { - var vertices = []; - var normals = []; + destTracks.push( new trackType( trackName, times, values ) ); - for (var face = 0; face < faces; face++) { + } - var start = dataOffset + face * faceLength; - var normalX = reader.getFloat32(start, true); - var normalY = reader.getFloat32(start + 4, true); - var normalZ = reader.getFloat32(start + 8, true); + } - if (hasColors) { + }; - var packedColor = reader.getUint16(start + 48, true); + const tracks = []; - if ((packedColor & 0x8000) === 0) { + const clipName = animation.name || 'default'; + const fps = animation.fps || 30; + const blendMode = animation.blendMode; - // facet has its own unique color + // automatic length determination in AnimationClip. + let duration = animation.length || - 1; - r = (packedColor & 0x1F) / 31; - g = ((packedColor >> 5) & 0x1F) / 31; - b = ((packedColor >> 10) & 0x1F) / 31; + const hierarchyTracks = animation.hierarchy || []; - } else { + for ( let h = 0; h < hierarchyTracks.length; h ++ ) { - r = defaultR; - g = defaultG; - b = defaultB; + const animationKeys = hierarchyTracks[ h ].keys; - } + // skip empty tracks + if ( ! animationKeys || animationKeys.length === 0 ) continue; - } + // process morph targets + if ( animationKeys[ 0 ].morphTargets ) { - for (var i = 1; i <= 3; i++) { + // figure out all morph targets used in this track + const morphTargetNames = {}; - var vertexstart = start + i * 12; + let k; - vertices.push(reader.getFloat32(vertexstart, true)); - vertices.push(reader.getFloat32(vertexstart + 4, true)); - vertices.push(reader.getFloat32(vertexstart + 8, true)); + for ( k = 0; k < animationKeys.length; k ++ ) { - normals.push(normalX, normalY, normalZ); + if ( animationKeys[ k ].morphTargets ) { - if (hasColors) { + for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { - colors.push(r, g, b); + morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; - } + } - } + } - } + } + + // create a track for each morph target with all zero + // morphTargetInfluences except for the keys in which + // the morphTarget is named. + for ( const morphTargetName in morphTargetNames ) { - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); + const times = []; + const values = []; - if (hasColors) { + for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); - geometry.hasColors = true; - geometry.alpha = alpha; + const animationKey = animationKeys[ k ]; - } + times.push( animationKey.time ); + values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); - return geometry; + } - } + tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); - function parseASCII(data) { + } - var geometry = new THREE.BufferGeometry(); - var patternFace = /facet([\s\S]*?)endfacet/g; - var faceCounter = 0; + duration = morphTargetNames.length * fps; - var patternFloat = /[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source; - var patternVertex = new RegExp('vertex' + patternFloat + patternFloat + patternFloat, 'g'); - var patternNormal = new RegExp('normal' + patternFloat + patternFloat + patternFloat, 'g'); + } else { - var vertices = []; - var normals = []; + // ...assume skeletal animation - var normal = new THREE.Vector3(); + const boneName = '.bones[' + bones[ h ].name + ']'; - var result; + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.position', + animationKeys, 'pos', tracks ); - while ((result = patternFace.exec(data)) !== null) { + addNonemptyTrack( + QuaternionKeyframeTrack, boneName + '.quaternion', + animationKeys, 'rot', tracks ); - var vertexCountPerFace = 0; - var normalCountPerFace = 0; + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.scale', + animationKeys, 'scl', tracks ); - var text = result[0]; + } - while ((result = patternNormal.exec(text)) !== null) { + } - normal.x = parseFloat(result[1]); - normal.y = parseFloat(result[2]); - normal.z = parseFloat(result[3]); - normalCountPerFace++; + if ( tracks.length === 0 ) { - } + return null; - while ((result = patternVertex.exec(text)) !== null) { + } - vertices.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])); - normals.push(normal.x, normal.y, normal.z); - vertexCountPerFace++; + const clip = new this( clipName, duration, tracks, blendMode ); - } + return clip; - // every face have to own ONE valid normal + } - if (normalCountPerFace !== 1) { + resetDuration() { - console.error('THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter); + const tracks = this.tracks; + let duration = 0; - } + for ( let i = 0, n = tracks.length; i !== n; ++ i ) { - // each face have to own THREE valid vertices + const track = this.tracks[ i ]; - if (vertexCountPerFace !== 3) { + duration = Math.max( duration, track.times[ track.times.length - 1 ] ); - console.error('THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter); + } - } + this.duration = duration; - faceCounter++; + return this; - } + } - geometry.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); - geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normals, 3)); + trim() { - return geometry; + for ( let i = 0; i < this.tracks.length; i ++ ) { - } + this.tracks[ i ].trim( 0, this.duration ); - function ensureString(buffer) { + } - if (typeof buffer !== 'string') { + return this; - var array_buffer = new Uint8Array(buffer); + } - if (window.TextDecoder !== undefined) { + validate() { - return new TextDecoder().decode(array_buffer); + let valid = true; - } + for ( let i = 0; i < this.tracks.length; i ++ ) { - var str = ''; + valid = valid && this.tracks[ i ].validate(); - for (var i = 0, il = buffer.byteLength; i < il; i++) { + } - str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian + return valid; - } + } - return str; + optimize() { - } else { + for ( let i = 0; i < this.tracks.length; i ++ ) { - return buffer; + this.tracks[ i ].optimize(); - } + } - } + return this; - function ensureBinary(buffer) { + } - if (typeof buffer === 'string') { + clone() { - var array_buffer = new Uint8Array(buffer.length); - for (var i = 0; i < buffer.length; i++) { + const tracks = []; - array_buffer[i] = buffer.charCodeAt(i) & 0xff; // implicitly assumes little-endian + for ( let i = 0; i < this.tracks.length; i ++ ) { - } - return array_buffer.buffer || array_buffer; + tracks.push( this.tracks[ i ].clone() ); - } else { + } - return buffer; + return new this.constructor( this.name, this.duration, tracks, this.blendMode ); - } + } - } + toJSON() { - // start + return this.constructor.toJSON( this ); - var binData = ensureBinary(data); + } - return isBinary(binData) ? parseBinary(binData) : parseASCII(ensureString(data)); +} - } +function getTrackTypeForValueTypeName( typeName ) { -}; + switch ( typeName.toLowerCase() ) { -/** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * - * @Modified by Jose Rojas from OBJLoader.js@r106 - * - */ + case 'scalar': + case 'double': + case 'float': + case 'number': + case 'integer': -// o object_name | g group_name -var object_pattern = /^[og]\s*(.+)?/; -// mtllib file_reference -var material_library_pattern = /^mtllib /; -// usemtl material_name -var material_use_pattern = /^usemtl /; + return NumberKeyframeTrack; -function ParserState() { + case 'vector': + case 'vector2': + case 'vector3': + case 'vector4': - var state = { - objects: [], - object: {}, + return VectorKeyframeTrack; - vertices: [], - normals: [], - colors: [], - uvs: [], + case 'color': - materialLibraries: [], + return ColorKeyframeTrack; - startObject: function ( name, fromDeclaration ) { + case 'quaternion': - // If the current object (initial from reset) is not from a g/o declaration in the parsed - // file. We need to use it for the first parsed g/o to keep things in sync. - if ( this.object && this.object.fromDeclaration === false ) { + return QuaternionKeyframeTrack; - this.object.name = name; - this.object.fromDeclaration = ( fromDeclaration !== false ); - return; + case 'bool': + case 'boolean': - } + return BooleanKeyframeTrack; - var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); + case 'string': - if ( this.object && typeof this.object._finalize === 'function' ) { + return StringKeyframeTrack; - this.object._finalize( true ); + } - } + throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); - this.object = { - name: name || '', - fromDeclaration: ( fromDeclaration !== false ), +} - geometry: { - vertices: [], - normals: [], - colors: [], - uvs: [] - }, - materials: [], - smooth: true, +function parseKeyframeTrack( json ) { - startMaterial: function ( name, libraries ) { + if ( json.type === undefined ) { - var previous = this._finalize( false ); + throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); - // New usemtl declaration overwrites an inherited material, except if faces were declared - // after the material, then it must be preserved for proper MultiMaterial continuation. - if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { + } - this.materials.splice( previous.index, 1 ); + const trackType = getTrackTypeForValueTypeName( json.type ); - } + if ( json.times === undefined ) { - var material = { - index: this.materials.length, - name: name || '', - mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), - smooth: ( previous !== undefined ? previous.smooth : this.smooth ), - groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), - groupEnd: - 1, - groupCount: - 1, - inherited: false, - - clone: function ( index ) { - - var cloned = { - index: ( typeof index === 'number' ? index : this.index ), - name: this.name, - mtllib: this.mtllib, - smooth: this.smooth, - groupStart: 0, - groupEnd: - 1, - groupCount: - 1, - inherited: false - }; - cloned.clone = this.clone.bind( cloned ); - return cloned; + const times = [], values = []; - } - }; + flattenJSON( json.keys, times, values, 'value' ); - this.materials.push( material ); + json.times = times; + json.values = values; - return material; + } - }, + // derived classes can define a static parse method + if ( trackType.parse !== undefined ) { - currentMaterial: function () { + return trackType.parse( json ); - if ( this.materials.length > 0 ) { + } else { - return this.materials[ this.materials.length - 1 ]; + // by default, we assume a constructor compatible with the base + return new trackType( json.name, json.times, json.values, json.interpolation ); - } + } - return undefined; +} - }, +const Cache = { - _finalize: function ( end ) { + enabled: false, - var lastMultiMaterial = this.currentMaterial(); - if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { + files: {}, - lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; - lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; - lastMultiMaterial.inherited = false; + add: function ( key, file ) { - } + if ( this.enabled === false ) return; - // Ignore objects tail materials if no face declarations followed them before a new o/g started. - if ( end && this.materials.length > 1 ) { + // console.log( 'THREE.Cache', 'Adding key:', key ); - for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { + this.files[ key ] = file; - if ( this.materials[ mi ].groupCount <= 0 ) { + }, - this.materials.splice( mi, 1 ); + get: function ( key ) { - } + if ( this.enabled === false ) return; - } + // console.log( 'THREE.Cache', 'Checking key:', key ); - } + return this.files[ key ]; - // Guarantee at least one empty material, this makes the creation later more straight forward. - if ( end && this.materials.length === 0 ) { + }, - this.materials.push( { - name: '', - smooth: this.smooth - } ); + remove: function ( key ) { - } + delete this.files[ key ]; - return lastMultiMaterial; + }, - } - }; + clear: function () { - // Inherit previous objects material. - // Spec tells us that a declared material must be set to all objects until a new material is declared. - // If a usemtl declaration is encountered while this new object is being parsed, it will - // overwrite the inherited material. Exception being that there was already face declarations - // to the inherited material, then it will be preserved for proper MultiMaterial continuation. + this.files = {}; - if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { + } - var declared = previousMaterial.clone( 0 ); - declared.inherited = true; - this.object.materials.push( declared ); +}; - } +class LoadingManager { - this.objects.push( this.object ); + constructor( onLoad, onProgress, onError ) { - }, + const scope = this; - finalize: function () { + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; - if ( this.object && typeof this.object._finalize === 'function' ) { + // Refer to #5689 for the reason why we don't set .onStart + // in the constructor - this.object._finalize( true ); + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; - } + this.itemStart = function ( url ) { - }, + itemsTotal ++; - parseVertexIndex: function ( value, len ) { + if ( isLoading === false ) { - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + if ( scope.onStart !== undefined ) { - }, + scope.onStart( url, itemsLoaded, itemsTotal ); - parseNormalIndex: function ( value, len ) { + } - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + } - }, + isLoading = true; - parseUVIndex: function ( value, len ) { + }; - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; + this.itemEnd = function ( url ) { - }, + itemsLoaded ++; - addVertex: function ( a, b, c ) { + if ( scope.onProgress !== undefined ) { - var src = this.vertices; - var dst = this.object.geometry.vertices; + scope.onProgress( url, itemsLoaded, itemsTotal ); - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + } - }, + if ( itemsLoaded === itemsTotal ) { - addVertexPoint: function ( a ) { + isLoading = false; - var src = this.vertices; - var dst = this.object.geometry.vertices; + if ( scope.onLoad !== undefined ) { - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + scope.onLoad(); - }, + } - addVertexLine: function ( a ) { + } - var src = this.vertices; - var dst = this.object.geometry.vertices; + }; - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + this.itemError = function ( url ) { - }, + if ( scope.onError !== undefined ) { - addNormal: function ( a, b, c ) { + scope.onError( url ); - var src = this.normals; - var dst = this.object.geometry.normals; + } - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + }; - }, + this.resolveURL = function ( url ) { - addColor: function ( a, b, c ) { + if ( urlModifier ) { - var src = this.colors; - var dst = this.object.geometry.colors; + return urlModifier( url ); - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + } - }, + return url; - addUV: function ( a, b, c ) { + }; - var src = this.uvs; - var dst = this.object.geometry.uvs; + this.setURLModifier = function ( transform ) { - dst.push( src[ a + 0 ], src[ a + 1 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ] ); + urlModifier = transform; - }, + return this; - addUVLine: function ( a ) { + }; - var src = this.uvs; - var dst = this.object.geometry.uvs; + this.addHandler = function ( regex, loader ) { - dst.push( src[ a + 0 ], src[ a + 1 ] ); + handlers.push( regex, loader ); - }, + return this; - addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { + }; - var vLen = this.vertices.length; + this.removeHandler = function ( regex ) { - var ia = this.parseVertexIndex( a, vLen ); - var ib = this.parseVertexIndex( b, vLen ); - var ic = this.parseVertexIndex( c, vLen ); + const index = handlers.indexOf( regex ); - this.addVertex( ia, ib, ic ); + if ( index !== - 1 ) { - if ( ua !== undefined && ua !== '' ) { + handlers.splice( index, 2 ); - var uvLen = this.uvs.length; - ia = this.parseUVIndex( ua, uvLen ); - ib = this.parseUVIndex( ub, uvLen ); - ic = this.parseUVIndex( uc, uvLen ); - this.addUV( ia, ib, ic ); + } - } + return this; - if ( na !== undefined && na !== '' ) { + }; - // Normals are many times the same. If so, skip function call and parseInt. - var nLen = this.normals.length; - ia = this.parseNormalIndex( na, nLen ); + this.getHandler = function ( file ) { - ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); - ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); + for ( let i = 0, l = handlers.length; i < l; i += 2 ) { - this.addNormal( ia, ib, ic ); + const regex = handlers[ i ]; + const loader = handlers[ i + 1 ]; - } + if ( regex.global ) regex.lastIndex = 0; // see #17920 - if ( this.colors.length > 0 ) { + if ( regex.test( file ) ) { - this.addColor( ia, ib, ic ); + return loader; - } + } - }, + } - addPointGeometry: function ( vertices ) { + return null; - this.object.geometry.type = 'Points'; + }; - var vLen = this.vertices.length; + } - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { +} - this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); +const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); - } +class Loader { - }, + constructor( manager ) { - addLineGeometry: function ( vertices, uvs ) { + this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.object.geometry.type = 'Line'; + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; - var vLen = this.vertices.length; - var uvLen = this.uvs.length; + } - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { + load( /* url, onLoad, onProgress, onError */ ) {} - this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); + loadAsync( url, onProgress ) { - } + const scope = this; - for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { + return new Promise( function ( resolve, reject ) { - this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); + scope.load( url, resolve, onProgress, reject ); - } + } ); - } + } - }; + parse( /* data */ ) {} - state.startObject( '', false ); + setCrossOrigin( crossOrigin ) { - return state; + this.crossOrigin = crossOrigin; + return this; -} + } -THREE.OBJLoader = function( manager ) { + setWithCredentials( value ) { - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + this.withCredentials = value; + return this; - this.materials = null; + } -}; + setPath( path ) { -THREE.OBJLoader.prototype = { + this.path = path; + return this; - constructor: THREE.OBJLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + setResourcePath( resourcePath ) { - var scope = this; + this.resourcePath = resourcePath; + return this; - var loader = new THREE.FileLoader( scope.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { + } - onLoad( scope.parse( text ) ); + setRequestHeader( requestHeader ) { - }, onProgress, onError ); + this.requestHeader = requestHeader; + return this; - }, + } - setPath: function ( value ) { +} - this.path = value; +Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; - return this; +const loading = {}; - }, +class HttpError extends Error { - setMaterials: function ( materials ) { + constructor( message, response ) { - this.materials = materials; + super( message ); + this.response = response; - return this; + } - }, +} - parse: function ( text ) { +class FileLoader extends Loader { - console.time( 'OBJLoader' ); + constructor( manager ) { - var state = new ParserState(); + super( manager ); - if ( text.indexOf( '\r\n' ) !== - 1 ) { + } - // This is faster than String.split with regex that splits on both - text = text.replace( /\r\n/g, '\n' ); + load( url, onLoad, onProgress, onError ) { - } + if ( url === undefined ) url = ''; - if ( text.indexOf( '\\\n' ) !== - 1 ) { + if ( this.path !== undefined ) url = this.path + url; - // join lines separated by a line continuation character (\) - text = text.replace( /\\\n/g, '' ); + url = this.manager.resolveURL( url ); - } + const cached = Cache.get( url ); - var lines = text.split( '\n' ); - var line = '', lineFirstChar = ''; - var lineLength = 0; - var result = []; + if ( cached !== undefined ) { - // Faster to just trim left side of the line. Use if available. - var trimLeft = ( typeof ''.trimLeft === 'function' ); + this.manager.itemStart( url ); - for ( var i = 0, l = lines.length; i < l; i ++ ) { + setTimeout( () => { - line = lines[ i ]; + if ( onLoad ) onLoad( cached ); - line = trimLeft ? line.trimLeft() : line.trim(); + this.manager.itemEnd( url ); - lineLength = line.length; + }, 0 ); - if ( lineLength === 0 ) { continue; } + return cached; - lineFirstChar = line.charAt( 0 ); + } - // @todo invoke passed in handler if any - if ( lineFirstChar === '#' ) { continue; } + // Check if request is duplicate - if ( lineFirstChar === 'v' ) { + if ( loading[ url ] !== undefined ) { - var data = line.split( /\s+/ ); + loading[ url ].push( { - switch ( data[ 0 ] ) { + onLoad: onLoad, + onProgress: onProgress, + onError: onError - case 'v': - state.vertices.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - if ( data.length === 8 ) { + } ); - state.colors.push( - parseFloat( data[ 4 ] ), - parseFloat( data[ 5 ] ), - parseFloat( data[ 6 ] ) + return; - ); + } - } - break; - case 'vn': - state.normals.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - break; - case 'vt': - state.uvs.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ) - ); - break; + // Initialise array for duplicate requests + loading[ url ] = []; - } + loading[ url ].push( { + onLoad: onLoad, + onProgress: onProgress, + onError: onError, + } ); - } else if ( lineFirstChar === 'f' ) { + // create request + const req = new Request( url, { + headers: new Headers( this.requestHeader ), + credentials: this.withCredentials ? 'include' : 'same-origin', + // An abort controller could be added within a future PR + } ); - var lineData = line.substr( 1 ).trim(); - var vertexData = lineData.split( /\s+/ ); - var faceVertices = []; + // record states ( avoid data race ) + const mimeType = this.mimeType; + const responseType = this.responseType; - // Parse the face vertex data into an easy to work with format + // start the fetch + fetch( req ) + .then( response => { - for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { + if ( response.status === 200 || response.status === 0 ) { - var vertex = vertexData[ j ]; + // Some browsers return HTTP Status 0 when using non-http protocol + // e.g. 'file://' or 'data://'. Handle as success. - if ( vertex.length > 0 ) { + if ( response.status === 0 ) { - var vertexParts = vertex.split( '/' ); - faceVertices.push( vertexParts ); + console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); } - } + // Workaround: Checking if response.body === undefined for Alipay browser #23548 - // Draw an edge between the first vertex and all subsequent vertices to form an n-gon + if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { - var v1 = faceVertices[ 0 ]; + return response; - for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { + } - var v2 = faceVertices[ j ]; - var v3 = faceVertices[ j + 1 ]; + const callbacks = loading[ url ]; + const reader = response.body.getReader(); - state.addFace( - v1[ 0 ], v2[ 0 ], v3[ 0 ], - v1[ 1 ], v2[ 1 ], v3[ 1 ], - v1[ 2 ], v2[ 2 ], v3[ 2 ] - ); + // Nginx needs X-File-Size check + // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content + const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); + const total = contentLength ? parseInt( contentLength ) : 0; + const lengthComputable = total !== 0; + let loaded = 0; - } + // periodically read data into the new stream tracking while download progress + const stream = new ReadableStream( { + start( controller ) { - } else if ( lineFirstChar === 'l' ) { + readData(); - var lineParts = line.substring( 1 ).trim().split( " " ); - var lineVertices = [], lineUVs = []; + function readData() { - if ( line.indexOf( "/" ) === - 1 ) { + reader.read().then( ( { done, value } ) => { - lineVertices = lineParts; + if ( done ) { - } else { + controller.close(); - for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { + } else { - var parts = lineParts[ li ].split( "/" ); + loaded += value.byteLength; - if ( parts[ 0 ] !== "" ) { lineVertices.push( parts[ 0 ] ); } - if ( parts[ 1 ] !== "" ) { lineUVs.push( parts[ 1 ] ); } + 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 ); - } - state.addLineGeometry( lineVertices, lineUVs ); + } - } else if ( lineFirstChar === 'p' ) { + controller.enqueue( value ); + readData(); - var lineData = line.substr( 1 ).trim(); - var pointData = lineData.split( " " ); + } - state.addPointGeometry( pointData ); + }, ( e ) => { - } else if ( ( result = object_pattern.exec( line ) ) !== null ) { + controller.error( e ); - // o object_name - // or - // g group_name + } ); - // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 - // var name = result[ 0 ].substr( 1 ).trim(); - var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); + } - state.startObject( name ); + } - } else if ( material_use_pattern.test( line ) ) { + } ); - // material + return new Response( stream ); - state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); + } else { - } else if ( material_library_pattern.test( line ) ) { + throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); - // mtl file + } - state.materialLibraries.push( line.substring( 7 ).trim() ); + } ) + .then( response => { - } else if ( lineFirstChar === 's' ) { + switch ( responseType ) { - result = line.split( ' ' ); + case 'arraybuffer': - // smooth shading + return response.arrayBuffer(); - // @todo Handle files that have varying smooth values for a set of faces inside one geometry, - // but does not define a usemtl for each face set. - // This should be detected and a dummy material created (later MultiMaterial and geometry groups). - // This requires some care to not create extra material on each smooth value for "normal" obj files. - // where explicit usemtl defines geometry groups. - // Example asset: examples/models/obj/cerberus/Cerberus.obj + case 'blob': - /* - * http://paulbourke.net/dataformats/obj/ - * or - * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf - * - * From chapter "Grouping" Syntax explanation "s group_number": - * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. - * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form - * surfaces, smoothing groups are either turned on or off; there is no difference between values greater - * than 0." - */ - if ( result.length > 1 ) { + return response.blob(); - var value = result[ 1 ].trim().toLowerCase(); - state.object.smooth = ( value !== '0' && value !== 'off' ); + case 'document': - } else { + return response.text() + .then( text => { - // ZBrush can produce "s" lines #11707 - state.object.smooth = true; + const parser = new DOMParser(); + return parser.parseFromString( text, mimeType ); - } - var material = state.object.currentMaterial(); - if ( material ) { material.smooth = state.object.smooth; } + } ); - } else { + case 'json': - // Handle null terminated files without exception - if ( line === '\0' ) { continue; } + return response.json(); - throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); + default: - } + if ( mimeType === undefined ) { - } + return response.text(); - state.finalize(); + } else { - var container = new THREE.Object3D(); - container.materialLibraries = [].concat( state.materialLibraries ); + // sniff encoding + const re = /charset="?([^;"\s]*)"?/i; + const exec = re.exec( mimeType ); + const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; + const decoder = new TextDecoder( label ); + return response.arrayBuffer().then( ab => decoder.decode( ab ) ); + + } - for ( var i = 0, l = state.objects.length; i < l; i ++ ) { + } - var object = state.objects[ i ]; - var geometry = object.geometry; - var materials = object.materials; - var isLine = ( geometry.type === 'Line' ); - var isPoints = ( geometry.type === 'Points' ); - var hasVertexColors = false; + } ) + .then( data => { - // Skip o/g line declarations that did not follow with any faces - if ( geometry.vertices.length === 0 ) { continue; } + // Add to cache only on HTTP success, so that we do not cache + // error response bodies as proper responses to requests. + Cache.add( url, data ); - var buffergeometry = new THREE.BufferGeometry(); + const callbacks = loading[ url ]; + delete loading[ url ]; - buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - if ( geometry.normals.length > 0 ) { + const callback = callbacks[ i ]; + if ( callback.onLoad ) callback.onLoad( data ); - buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); + } - } else { + } ) + .catch( err => { - buffergeometry.computeVertexNormals(); + // Abort errors and other errors are handled the same - } + const callbacks = loading[ url ]; - if ( geometry.colors.length > 0 ) { + if ( callbacks === undefined ) { - hasVertexColors = true; - buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); + // When onLoad was called and url was deleted in `loading` + this.manager.itemError( url ); + throw err; - } + } - if ( geometry.uvs.length > 0 ) { + delete loading[ url ]; - buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - } + const callback = callbacks[ i ]; + if ( callback.onError ) callback.onError( err ); - // Create materials + } - var createdMaterials = []; + this.manager.itemError( url ); - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + } ) + .finally( () => { - var sourceMaterial = materials[ mi ]; - var material = undefined; + this.manager.itemEnd( url ); - if ( this.materials !== null ) { + } ); - material = this.materials.create( sourceMaterial.name ); + this.manager.itemStart( url ); - // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. - if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { + } - var materialLine = new THREE.LineBasicMaterial(); - THREE.Material.prototype.copy.call( materialLine, material ); - materialLine.color.copy( material.color ); - materialLine.lights = false; - material = materialLine; + setResponseType( value ) { - } else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { + this.responseType = value; + return this; - var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); - THREE.Material.prototype.copy.call( materialPoints, material ); - materialPoints.color.copy( material.color ); - materialPoints.map = material.map; - materialPoints.lights = false; - material = materialPoints; + } - } + setMimeType( value ) { - } + this.mimeType = value; + return this; - if ( ! material ) { + } - if ( isLine ) { +} - material = new THREE.LineBasicMaterial(); +class ImageLoader extends Loader { - } else if ( isPoints ) { + constructor( manager ) { - material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); + super( manager ); - } else { + } - material = new THREE.MeshPhongMaterial(); + load( url, onLoad, onProgress, onError ) { - } + if ( this.path !== undefined ) url = this.path + url; - material.name = sourceMaterial.name; + url = this.manager.resolveURL( url ); - } + const scope = this; - material.flatShading = sourceMaterial.smooth ? false : true; - material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; + const cached = Cache.get( url ); - createdMaterials.push( material ); + if ( cached !== undefined ) { - } + scope.manager.itemStart( url ); - // Create mesh + setTimeout( function () { - var mesh; + if ( onLoad ) onLoad( cached ); - if ( createdMaterials.length > 1 ) { + scope.manager.itemEnd( url ); - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + }, 0 ); - var sourceMaterial = materials[ mi ]; - buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); + return cached; - } + } - if ( isLine ) { + const image = createElementNS( 'img' ); - mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); + function onImageLoad() { - } else if ( isPoints ) { + removeEventListeners(); - mesh = new THREE.Points( buffergeometry, createdMaterials ); + Cache.add( url, this ); - } else { + if ( onLoad ) onLoad( this ); - mesh = new THREE.Mesh( buffergeometry, createdMaterials ); + scope.manager.itemEnd( url ); - } + } - } else { + function onImageError( event ) { - if ( isLine ) { + removeEventListeners(); - mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); + if ( onError ) onError( event ); - } else if ( isPoints ) { + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); + } - } else { + function removeEventListeners() { - mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); + image.removeEventListener( 'load', onImageLoad, false ); + image.removeEventListener( 'error', onImageError, false ); - } + } - } + image.addEventListener( 'load', onImageLoad, false ); + image.addEventListener( 'error', onImageError, false ); - mesh.name = object.name; + if ( url.slice( 0, 5 ) !== 'data:' ) { - container.add( mesh ); + if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; } - console.timeEnd( 'OBJLoader' ); + scope.manager.itemStart( url ); + + image.src = url; - return container; + return image; } -}; +} /** - * @fileOverview - * Loads a Wavefront .mtl file specifying materials + * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) * - * @author angelxuanchang + * Sub classes have to implement the parse() method which will be used in load(). */ -THREE.MTLLoader = function ( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - -}; +class DataTextureLoader extends Loader { -THREE.MTLLoader.prototype = { + constructor( manager ) { - constructor: THREE.MTLLoader, + super( manager ); - crossOrigin: 'anonymous', + } - /** - * Loads and parses a MTL asset from a URL. - * - * @param {String} url - URL to the MTL file. - * @param {Function} [onLoad] - Callback invoked with the loaded object. - * @param {Function} [onProgress] - Callback for download progress. - * @param {Function} [onError] - Callback for download errors. - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to load. - */ - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var path = ( this.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path; + const texture = new DataTexture(); - var loader = new THREE.FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); loader.setPath( this.path ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text, path ) ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( buffer ) { - }, onProgress, onError ); + let texData; - }, + try { - /** - * Set base path for resolving references. - * If set this path will be prepended to each loaded and found reference. - * - * @see setResourcePath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setPath: function ( path ) { + texData = scope.parse( buffer ); - this.path = path; - return this; + } catch ( error ) { - }, + if ( onError !== undefined ) { - /** - * Set base path for additional resources like textures. - * - * @see setPath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.setResourcePath( 'assets/textures/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setResourcePath: function ( path ) { + onError( error ); - this.resourcePath = path; - return this; + } else { - }, + console.error( error ); + return; - setTexturePath: function ( path ) { + } - console.warn( 'THREE.MTLLoader: .setTexturePath() has been renamed to .setResourcePath().' ); - return this.setResourcePath( path ); + } - }, + if ( texData.image !== undefined ) { - setCrossOrigin: function ( value ) { + texture.image = texData.image; - this.crossOrigin = value; - return this; + } else if ( texData.data !== undefined ) { - }, + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; - setMaterialOptions: function ( value ) { + } - this.materialOptions = value; - return this; + texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; + texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; - }, + texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; + texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; - /** - * Parses a MTL file. - * - * @param {String} text - Content of MTL file - * @return {THREE.MTLLoader.MaterialCreator} - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to parse. - */ - parse: function ( text, path ) { + texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - var lines = text.split( '\n' ); - var info = {}; - var delimiter_pattern = /\s+/; - var materialsInfo = {}; + if ( texData.colorSpace !== undefined ) { - for ( var i = 0; i < lines.length; i ++ ) { + texture.colorSpace = texData.colorSpace; - var line = lines[ i ]; - line = line.trim(); + } - if ( line.length === 0 || line.charAt( 0 ) === '#' ) { + if ( texData.flipY !== undefined ) { - // Blank line or comment ignore - continue; + texture.flipY = texData.flipY; } - var pos = line.indexOf( ' ' ); - - var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; - key = key.toLowerCase(); + if ( texData.format !== undefined ) { - var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; - value = value.trim(); + texture.format = texData.format; - if ( key === 'newmtl' ) { + } - // New material + if ( texData.type !== undefined ) { - info = { name: value }; - materialsInfo[ value ] = info; + texture.type = texData.type; - } else { + } - if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { + if ( texData.mipmaps !== undefined ) { - var ss = value.split( delimiter_pattern, 3 ); - info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; + texture.mipmaps = texData.mipmaps; + texture.minFilter = LinearMipmapLinearFilter; // presumably... - } else { + } - info[ key ] = value; + if ( texData.mipmapCount === 1 ) { - } + texture.minFilter = LinearFilter; } - } - - var materialCreator = new THREE.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions ); - materialCreator.setCrossOrigin( this.crossOrigin ); - materialCreator.setManager( this.manager ); - materialCreator.setMaterials( materialsInfo ); - return materialCreator; + if ( texData.generateMipmaps !== undefined ) { - } + texture.generateMipmaps = texData.generateMipmaps; -}; + } -/** - * Create a new THREE-MTLLoader.MaterialCreator - * @param baseUrl - Url relative to which textures are loaded - * @param options - Set of options on how to construct the materials - * side: Which side to apply the material - * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide - * wrap: What type of wrapping to apply for textures - * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping - * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 - * Default: false, assumed to be already normalized - * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's - * Default: false - * @constructor - */ + texture.needsUpdate = true; -THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) { + if ( onLoad ) onLoad( texture, texData ); - this.baseUrl = baseUrl || ''; - this.options = options; - this.materialsInfo = {}; - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; + }, onProgress, onError ); - this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide; - this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping; -}; + return texture; -THREE.MTLLoader.MaterialCreator.prototype = { + } - constructor: THREE.MTLLoader.MaterialCreator, +} - crossOrigin: 'anonymous', +class TextureLoader extends Loader { - setCrossOrigin: function ( value ) { + constructor( manager ) { - this.crossOrigin = value; - return this; + super( manager ); - }, + } - setManager: function ( value ) { + load( url, onLoad, onProgress, onError ) { - this.manager = value; + const texture = new Texture(); - }, + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); - setMaterials: function ( materialsInfo ) { + loader.load( url, function ( image ) { - this.materialsInfo = this.convert( materialsInfo ); - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; + texture.image = image; + texture.needsUpdate = true; - }, + if ( onLoad !== undefined ) { - convert: function ( materialsInfo ) { + onLoad( texture ); - if ( ! this.options ) { return materialsInfo; } + } - var converted = {}; + }, onProgress, onError ); - for ( var mn in materialsInfo ) { + return texture; - // Convert materials info into normalized form based on options + } - var mat = materialsInfo[ mn ]; +} - var covmat = {}; +class Light extends Object3D { - converted[ mn ] = covmat; + constructor( color, intensity = 1 ) { - for ( var prop in mat ) { + super(); - var save = true; - var value = mat[ prop ]; - var lprop = prop.toLowerCase(); + this.isLight = true; - switch ( lprop ) { + this.type = 'Light'; - case 'kd': - case 'ka': - case 'ks': + this.color = new Color( color ); + this.intensity = intensity; - // Diffuse color (color under white light) using RGB values + } - if ( this.options && this.options.normalizeRGB ) { + dispose() { - value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; + // Empty here in base class; some subclasses override. - } + } - if ( this.options && this.options.ignoreZeroRGBs ) { + copy( source, recursive ) { - if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { + super.copy( source, recursive ); - // ignore + this.color.copy( source.color ); + this.intensity = source.intensity; - save = false; + return this; - } + } - } + toJSON( meta ) { - break; + const data = super.toJSON( meta ); - } + data.object.color = this.color.getHex(); + data.object.intensity = this.intensity; - if ( save ) { + if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); - covmat[ lprop ] = value; + if ( this.distance !== undefined ) data.object.distance = this.distance; + if ( this.angle !== undefined ) data.object.angle = this.angle; + if ( this.decay !== undefined ) data.object.decay = this.decay; + if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - } + if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); + if ( this.target !== undefined ) data.object.target = this.target.uuid; - } + return data; - } + } - return converted; +} - }, +const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); +const _lookTarget$1 = /*@__PURE__*/ new Vector3(); - preload: function () { +class LightShadow { - for ( var mn in this.materialsInfo ) { + constructor( camera ) { - this.create( mn ); + this.camera = camera; - } + this.intensity = 1; - }, + this.bias = 0; + this.normalBias = 0; + this.radius = 1; + this.blurSamples = 8; - getIndex: function ( materialName ) { + this.mapSize = new Vector2( 512, 512 ); - return this.nameLookup[ materialName ]; + this.map = null; + this.mapPass = null; + this.matrix = new Matrix4(); - }, + this.autoUpdate = true; + this.needsUpdate = false; - getAsArray: function () { + this._frustum = new Frustum(); + this._frameExtents = new Vector2( 1, 1 ); - var index = 0; + this._viewportCount = 1; - for ( var mn in this.materialsInfo ) { + this._viewports = [ - this.materialsArray[ index ] = this.create( mn ); - this.nameLookup[ mn ] = index; - index ++; + new Vector4( 0, 0, 1, 1 ) - } + ]; - return this.materialsArray; + } - }, + getViewportCount() { - create: function ( materialName ) { + return this._viewportCount; - if ( this.materials[ materialName ] === undefined ) { + } - this.createMaterial_( materialName ); + getFrustum() { - } + return this._frustum; - return this.materials[ materialName ]; + } - }, + updateMatrices( light ) { - createMaterial_: function ( materialName ) { + const shadowCamera = this.camera; + const shadowMatrix = this.matrix; - // Create material + _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld$1 ); - var scope = this; - var mat = this.materialsInfo[ materialName ]; - var params = { + _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget$1 ); + shadowCamera.updateMatrixWorld(); - name: materialName, - side: this.side + _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); - }; + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - function resolveURL( baseUrl, url ) { + shadowMatrix.multiply( _projScreenMatrix$1 ); - if ( typeof url !== 'string' || url === '' ) - { return ''; } + } - // Absolute URL - if ( /^https?:\/\//i.test( url ) ) { return url; } + getViewport( viewportIndex ) { - return baseUrl + url; + return this._viewports[ viewportIndex ]; - } + } - function setMapForType( mapType, value ) { + getFrameExtents() { - if ( params[ mapType ] ) { return; } // Keep the first encountered texture + return this._frameExtents; - var texParams = scope.getTextureParams( value, params ); - var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); + } - map.repeat.copy( texParams.scale ); - map.offset.copy( texParams.offset ); + dispose() { - map.wrapS = scope.wrap; - map.wrapT = scope.wrap; + if ( this.map ) { - params[ mapType ] = map; + this.map.dispose(); } - for ( var prop in mat ) { - - var value = mat[ prop ]; - var n; - - if ( value === '' ) { continue; } - - switch ( prop.toLowerCase() ) { - - // Ns is material specular exponent - - case 'kd': - - // Diffuse color (color under white light) using RGB values - - params.color = new THREE.Color().fromArray( value ); + if ( this.mapPass ) { - break; + this.mapPass.dispose(); - case 'ks': + } - // Specular color (color when light is reflected from shiny surface) using RGB values - params.specular = new THREE.Color().fromArray( value ); + } - break; + copy( source ) { - case 'ke': + this.camera = source.camera.clone(); - // Emissive using RGB values - params.emissive = new THREE.Color().fromArray( value ); + this.intensity = source.intensity; - break; + this.bias = source.bias; + this.radius = source.radius; - case 'map_kd': + this.mapSize.copy( source.mapSize ); - // Diffuse texture map + return this; - setMapForType( "map", value ); + } - break; + clone() { - case 'map_ks': + return new this.constructor().copy( this ); - // Specular map + } - setMapForType( "specularMap", value ); + toJSON() { - break; + const object = {}; - case 'map_ke': + if ( this.intensity !== 1 ) object.intensity = this.intensity; + 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(); - // Emissive map + object.camera = this.camera.toJSON( false ).object; + delete object.camera.matrix; - setMapForType( "emissiveMap", value ); + return object; - break; + } - case 'norm': +} - setMapForType( "normalMap", value ); +class SpotLightShadow extends LightShadow { - break; + constructor() { - case 'map_bump': - case 'bump': + super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); - // Bump texture map + this.isSpotLightShadow = true; - setMapForType( "bumpMap", value ); + this.focus = 1; - break; + } - case 'map_d': + updateMatrices( light ) { - // Alpha map + const camera = this.camera; - setMapForType( "alphaMap", value ); - params.transparent = true; + const fov = RAD2DEG * 2 * light.angle * this.focus; + const aspect = this.mapSize.width / this.mapSize.height; + const far = light.distance || camera.far; - break; + if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { - case 'ns': + camera.fov = fov; + camera.aspect = aspect; + camera.far = far; + camera.updateProjectionMatrix(); - // The specular exponent (defines the focus of the specular highlight) - // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. + } - params.shininess = parseFloat( value ); + super.updateMatrices( light ); - break; + } - case 'd': - n = parseFloat( value ); + copy( source ) { - if ( n < 1 ) { + super.copy( source ); - params.opacity = n; - params.transparent = true; + this.focus = source.focus; - } + return this; - break; + } - case 'tr': - n = parseFloat( value ); +} - if ( this.options && this.options.invertTrProperty ) { n = 1 - n; } +class SpotLight extends Light { - if ( n > 0 ) { + constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { - params.opacity = 1 - n; - params.transparent = true; + super( color, intensity ); - } + this.isSpotLight = true; - break; + this.type = 'SpotLight'; - } + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - } + this.target = new Object3D(); - this.materials[ materialName ] = new THREE.MeshPhongMaterial( params ); - return this.materials[ materialName ]; + this.distance = distance; + this.angle = angle; + this.penumbra = penumbra; + this.decay = decay; - }, + this.map = null; - getTextureParams: function ( value, matParams ) { + this.shadow = new SpotLightShadow(); - var texParams = { + } - scale: new THREE.Vector2( 1, 1 ), - offset: new THREE.Vector2( 0, 0 ) + get power() { - }; + // compute the light's luminous power (in lumens) from its intensity (in candela) + // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd) + return this.intensity * Math.PI; - var items = value.split( /\s+/ ); - var pos; + } - pos = items.indexOf( '-bm' ); + set power( power ) { - if ( pos >= 0 ) { + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / Math.PI; - matParams.bumpScale = parseFloat( items[ pos + 1 ] ); - items.splice( pos, 2 ); + } - } + dispose() { - pos = items.indexOf( '-s' ); + this.shadow.dispose(); - if ( pos >= 0 ) { + } - texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! + copy( source, recursive ) { - } + super.copy( source, recursive ); - pos = items.indexOf( '-o' ); + this.distance = source.distance; + this.angle = source.angle; + this.penumbra = source.penumbra; + this.decay = source.decay; - if ( pos >= 0 ) { + this.target = source.target.clone(); - texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! + this.shadow = source.shadow.clone(); - } + return this; - texParams.url = items.join( ' ' ).trim(); - return texParams; + } - }, +} - loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { +const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld = /*@__PURE__*/ new Vector3(); +const _lookTarget = /*@__PURE__*/ new Vector3(); - var texture; - var loader = THREE.Loader.Handlers.get( url ); - var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager; +class PointLightShadow extends LightShadow { - if ( loader === null ) { + constructor() { - loader = new THREE.TextureLoader( manager ); + super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); - } + this.isPointLightShadow = true; - if ( loader.setCrossOrigin ) { loader.setCrossOrigin( this.crossOrigin ); } - texture = loader.load( url, onLoad, onProgress, onError ); + this._frameExtents = new Vector2( 4, 2 ); - if ( mapping !== undefined ) { texture.mapping = mapping; } + this._viewportCount = 6; - return texture; + this._viewports = [ + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction + + // positive X + new Vector4( 2, 1, 1, 1 ), + // negative X + new Vector4( 0, 1, 1, 1 ), + // positive Z + new Vector4( 3, 1, 1, 1 ), + // negative Z + new Vector4( 1, 1, 1, 1 ), + // positive Y + new Vector4( 3, 0, 1, 1 ), + // negative Y + new Vector4( 1, 0, 1, 1 ) + ]; - } + this._cubeDirections = [ + new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), + new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) + ]; -}; + this._cubeUps = [ + new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), + new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) + ]; -/** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - * @Modified by Jihoon Lee from ColladerLoader.js@r88 - * To support rviz compatible collada viewing. - * See: #202 why it is forked. - * - * It is a fork from ColladerLoader.js in three.js. It follows three.js license. - */ + } -THREE.ColladaLoader = function (manager) { + updateMatrices( light, viewportIndex = 0 ) { - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; + const camera = this.camera; + const shadowMatrix = this.matrix; -}; + const far = light.distance || camera.far; -THREE.ColladaLoader.prototype = { + if ( far !== camera.far ) { - constructor: THREE.ColladaLoader, + camera.far = far; + camera.updateProjectionMatrix(); - crossOrigin: 'Anonymous', + } - load: function (url, onLoad, onProgress, onError) { + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + camera.position.copy( _lightPositionWorld ); - var scope = this; + _lookTarget.copy( camera.position ); + _lookTarget.add( this._cubeDirections[ viewportIndex ] ); + camera.up.copy( this._cubeUps[ viewportIndex ] ); + camera.lookAt( _lookTarget ); + camera.updateMatrixWorld(); - var path = THREE.Loader.prototype.extractUrlBase(url); + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - var loader = new THREE.FileLoader(scope.manager); - loader.load(url, function (text) { + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix ); - onLoad(scope.parse(text, path)); + } - }, onProgress, onError); +} - }, +class PointLight extends Light { - options: { + constructor( color, intensity, distance = 0, decay = 2 ) { - set convertUpAxis(value) { + super( color, intensity ); - console.warn('THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.'); + this.isPointLight = true; - } + this.type = 'PointLight'; - }, + this.distance = distance; + this.decay = decay; - setCrossOrigin: function (value) { + this.shadow = new PointLightShadow(); - this.crossOrigin = value; + } - }, + get power() { - parse: function (text, path) { + // compute the light's luminous power (in lumens) from its intensity (in candela) + // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd) + return this.intensity * 4 * Math.PI; - function getElementsByTagName(xml, name) { + } - // Non recursive xml.getElementsByTagName() ... + set power( power ) { - var array = []; - var childNodes = xml.childNodes; + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / ( 4 * Math.PI ); - for (var i = 0, l = childNodes.length; i < l; i++) { + } - var child = childNodes[i]; + dispose() { - if (child.nodeName === name) { + this.shadow.dispose(); - array.push(child); + } - } + copy( source, recursive ) { - } + super.copy( source, recursive ); - return array; + this.distance = source.distance; + this.decay = source.decay; - } + this.shadow = source.shadow.clone(); - function parseStrings(text) { + return this; - if (text.length === 0) { return []; } + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); +} - for (var i = 0, l = parts.length; i < l; i++) { +class DirectionalLightShadow extends LightShadow { - array[i] = parts[i]; + constructor() { - } + super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); - return array; + this.isDirectionalLightShadow = true; - } + } - function parseFloats(text) { +} - if (text.length === 0) { return []; } +class DirectionalLight extends Light { - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + constructor( color, intensity ) { - for (var i = 0, l = parts.length; i < l; i++) { + super( color, intensity ); - array[i] = parseFloat(parts[i]); + this.isDirectionalLight = true; - } + this.type = 'DirectionalLight'; - return array; + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - } + this.target = new Object3D(); - function parseInts(text) { + this.shadow = new DirectionalLightShadow(); - if (text.length === 0) { return []; } + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + dispose() { - for (var i = 0, l = parts.length; i < l; i++) { + this.shadow.dispose(); - array[i] = parseInt(parts[i]); + } - } + copy( source ) { - return array; + super.copy( source ); - } + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); - function parseId(text) { + return this; - return text.substring(1); + } - } +} - function generateId() { +class AmbientLight extends Light { - return 'three_default_' + (count++); + constructor( color, intensity ) { - } + super( color, intensity ); - function isEmpty(object) { + this.isAmbientLight = true; - return Object.keys(object).length === 0; + this.type = 'AmbientLight'; - } + } - // asset +} - function parseAsset(xml) { +class LoaderUtils { - return { - unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), - upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) - }; + static decodeText( array ) { // @deprecated, r165 - } + console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); - function parseAssetUnit(xml) { + if ( typeof TextDecoder !== 'undefined' ) { - return xml !== undefined ? parseFloat(xml.getAttribute('meter')) : 1; + return new TextDecoder().decode( array ); - } + } - function parseAssetUpAxis(xml) { + // Avoid the String.fromCharCode.apply(null, array) shortcut, which + // throws a "maximum call stack size exceeded" error for large arrays. - return xml !== undefined ? xml.textContent : 'Y_UP'; + let s = ''; - } + for ( let i = 0, il = array.length; i < il; i ++ ) { - // library + // Implicitly assumes little-endian. + s += String.fromCharCode( array[ i ] ); - function parseLibrary(xml, libraryName, nodeName, parser) { + } - var library = getElementsByTagName(xml, libraryName)[0]; + try { - if (library !== undefined) { + // merges multi-byte utf-8 characters. - var elements = getElementsByTagName(library, nodeName); + return decodeURIComponent( escape( s ) ); - for (var i = 0; i < elements.length; i++) { + } catch ( e ) { // see #16358 - parser(elements[i]); + return s; - } + } - } + } - } + static extractUrlBase( url ) { - function buildLibrary(data, builder) { + const index = url.lastIndexOf( '/' ); - for (var name in data) { + if ( index === - 1 ) return './'; - var object = data[name]; - object.build = builder(data[name]); + return url.slice( 0, index + 1 ); - } + } - } + static resolveURL( url, path ) { - // get + // Invalid URL + if ( typeof url !== 'string' || url === '' ) return ''; - function getBuild(data, builder) { + // Host Relative URL + if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { - if (data.build !== undefined) { return data.build; } + path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); - data.build = builder(data); + } - return data.build; + // Absolute URL http://,https://,// + if ( /^(https?:)?\/\//i.test( url ) ) return url; - } + // Data URI + if ( /^data:.*,.*$/i.test( url ) ) return url; - // animation + // Blob URL + if ( /^blob:.*$/i.test( url ) ) return url; - function parseAnimation(xml) { + // Relative URL + return path + url; - var data = { - sources: {}, - samplers: {}, - channels: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { +} - var child = xml.childNodes[i]; +const _matrix = /*@__PURE__*/ new Matrix4(); - if (child.nodeType !== 1) { continue; } +class Raycaster { - var id; + constructor( origin, direction, near = 0, far = Infinity ) { - switch (child.nodeName) { + this.ray = new Ray( origin, direction ); + // direction is assumed to be normalized (for accurate distance calculations) - case 'source': - id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); + + this.params = { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + }; - case 'sampler': - id = child.getAttribute('id'); - data.samplers[id] = parseAnimationSampler(child); - break; + } - case 'channel': - id = child.getAttribute('target'); - data.channels[id] = parseAnimationChannel(child); - break; + set( origin, direction ) { - default: - console.log(child); + // direction is assumed to be normalized (for accurate distance calculations) - } + this.ray.set( origin, direction ); - } + } - library.animations[xml.getAttribute('id')] = data; + setFromCamera( coords, camera ) { - } + if ( camera.isPerspectiveCamera ) { - function parseAnimationSampler(xml) { + 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; - var data = { - inputs: {}, - }; + } else if ( camera.isOrthographicCamera ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera + this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + this.camera = camera; - var child = xml.childNodes[i]; + } else { - if (child.nodeType !== 1) { continue; } + console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); - switch (child.nodeName) { + } - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - data.inputs[semantic] = id; - break; + } - } + setFromXRController( controller ) { - } + _matrix.identity().extractRotation( controller.matrixWorld ); - return data; + this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); - } + return this; - function parseAnimationChannel(xml) { + } - var data = {}; + intersectObject( object, recursive = true, intersects = [] ) { - var target = xml.getAttribute('target'); + intersect( object, this, intersects, recursive ); - // parsing SID Addressing Syntax + intersects.sort( ascSort ); - var parts = target.split('/'); + return intersects; - var id = parts.shift(); - var sid = parts.shift(); + } - // check selection syntax + intersectObjects( objects, recursive = true, intersects = [] ) { - var arraySyntax = (sid.indexOf('(') !== - 1); - var memberSyntax = (sid.indexOf('.') !== - 1); + for ( let i = 0, l = objects.length; i < l; i ++ ) { - if (memberSyntax) { + intersect( objects[ i ], this, intersects, recursive ); - // member selection access + } - parts = sid.split('.'); - sid = parts.shift(); - data.member = parts.shift(); + intersects.sort( ascSort ); - } else if (arraySyntax) { + return intersects; - // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. + } - var indices = sid.split('('); - sid = indices.shift(); +} - for (var i = 0; i < indices.length; i++) { +function ascSort( a, b ) { - indices[i] = parseInt(indices[i].replace(/\)/, '')); + return a.distance - b.distance; - } +} - data.indices = indices; +function intersect( object, raycaster, intersects, recursive ) { - } + let propagate = true; - data.id = id; - data.sid = sid; + if ( object.layers.test( raycaster.layers ) ) { - data.arraySyntax = arraySyntax; - data.memberSyntax = memberSyntax; + const result = object.raycast( raycaster, intersects ); - data.sampler = parseId(xml.getAttribute('source')); + if ( result === false ) propagate = false; - return data; + } - } + if ( propagate === true && recursive === true ) { - function buildAnimation(data) { + const children = object.children; - var tracks = []; + for ( let i = 0, l = children.length; i < l; i ++ ) { - var channels = data.channels; - var samplers = data.samplers; - var sources = data.sources; + intersect( children[ i ], raycaster, intersects, true ); - for (var target in channels) { + } - if (channels.hasOwnProperty(target)) { + } - var channel = channels[target]; - var sampler = samplers[channel.sampler]; +} - var inputId = sampler.inputs.INPUT; - var outputId = sampler.inputs.OUTPUT; +const _axis = /*@__PURE__*/ new Vector3(); +let _lineGeometry, _coneGeometry; - var inputSource = sources[inputId]; - var outputSource = sources[outputId]; +class ArrowHelper extends Object3D { - var animation = buildAnimationChannel(channel, inputSource, outputSource); + // dir is assumed to be normalized - createKeyframeTracks(animation, tracks); + constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - } + super(); - } + this.type = 'ArrowHelper'; - return tracks; + if ( _lineGeometry === undefined ) { - } + _lineGeometry = new BufferGeometry(); + _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); - function getAnimation(id) { + _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); + _coneGeometry.translate( 0, - 0.5, 0 ); - return getBuild(library.animations[id], buildAnimation); + } - } + this.position.copy( origin ); - function buildAnimationChannel(channel, inputSource, outputSource) { + this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + this.line.matrixAutoUpdate = false; + this.add( this.line ); - var node = library.nodes[channel.id]; - var object3D = getNode(node.id); + this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); + this.cone.matrixAutoUpdate = false; + this.add( this.cone ); - var transform = node.transforms[channel.sid]; - var defaultMatrix = node.matrix.clone().transpose(); + this.setDirection( dir ); + this.setLength( length, headLength, headWidth ); - var time, stride; - var i, il, j, jl; + } - var data = {}; + setDirection( dir ) { - // the collada spec allows the animation of data in various ways. - // depending on the transform type (matrix, translate, rotate, scale), we execute different logic + // dir is assumed to be normalized - switch (transform) { + if ( dir.y > 0.99999 ) { - case 'matrix': + this.quaternion.set( 0, 0, 0, 1 ); - for (i = 0, il = inputSource.array.length; i < il; i++) { + } else if ( dir.y < - 0.99999 ) { - time = inputSource.array[i]; - stride = i * outputSource.stride; + this.quaternion.set( 1, 0, 0, 0 ); - if (data[time] === undefined) { data[time] = {}; } + } else { - if (channel.arraySyntax === true) { + _axis.set( dir.z, 0, - dir.x ).normalize(); - var value = outputSource.array[stride]; - var index = channel.indices[0] + 4 * channel.indices[1]; + const radians = Math.acos( dir.y ); - data[time][index] = value; + this.quaternion.setFromAxisAngle( _axis, radians ); - } else { + } - for (j = 0, jl = outputSource.stride; j < jl; j++) { + } - data[time][j] = outputSource.array[stride + j]; + setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - } + this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 + this.line.updateMatrix(); - } + this.cone.scale.set( headWidth, headLength, headWidth ); + this.cone.position.y = length; + this.cone.updateMatrix(); - } + } - break; + setColor( color ) { - case 'translate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + this.line.material.color.set( color ); + this.cone.material.color.set( color ); - case 'rotate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + } - case 'scale': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + copy( source ) { - } + super.copy( source, false ); - var keyframes = prepareAnimationData(data, defaultMatrix); + this.line.copy( source.line ); + this.cone.copy( source.cone ); - var animation = { - name: object3D.uuid, - keyframes: keyframes - }; + return this; - return animation; + } - } + dispose() { - function prepareAnimationData(data, defaultMatrix) { + this.line.geometry.dispose(); + this.line.material.dispose(); + this.cone.geometry.dispose(); + this.cone.material.dispose(); - var keyframes = []; + } - // transfer data into a sortable array +} - for (var time in data) { +if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - keyframes.push({ time: parseFloat(time), value: data[time] }); + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { + revision: REVISION, + } } ) ); - } +} - // ensure keyframes are sorted by time +if ( typeof window !== 'undefined' ) { - keyframes.sort(ascending); + if ( window.__THREE__ ) { - // now we clean up all animation data, so we can use them for keyframe tracks + console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); - for (var i = 0; i < 16; i++) { + } else { - transformAnimationData(keyframes, i, defaultMatrix.elements[i]); + window.__THREE__ = REVISION; - } + } - return keyframes; +} - // array sort function +// Marker types +var MARKER_ARROW = 0; +var MARKER_CUBE = 1; +var MARKER_SPHERE = 2; +var MARKER_CYLINDER = 3; +var MARKER_LINE_STRIP = 4; +var MARKER_LINE_LIST = 5; +var MARKER_CUBE_LIST = 6; +var MARKER_SPHERE_LIST = 7; +var MARKER_POINTS = 8; +var MARKER_TEXT_VIEW_FACING = 9; +var MARKER_MESH_RESOURCE = 10; +var MARKER_TRIANGLE_LIST = 11; - function ascending(a, b) { +// Interactive marker feedback types +var INTERACTIVE_MARKER_KEEP_ALIVE = 0; +var INTERACTIVE_MARKER_POSE_UPDATE = 1; +var INTERACTIVE_MARKER_MENU_SELECT = 2; +var INTERACTIVE_MARKER_BUTTON_CLICK = 3; +var INTERACTIVE_MARKER_MOUSE_DOWN = 4; +var INTERACTIVE_MARKER_MOUSE_UP = 5; - return a.time - b.time; +// Interactive marker control types +var INTERACTIVE_MARKER_NONE = 0; +var INTERACTIVE_MARKER_MENU = 1; +var INTERACTIVE_MARKER_BUTTON = 2; +var INTERACTIVE_MARKER_MOVE_AXIS = 3; +var INTERACTIVE_MARKER_MOVE_PLANE = 4; +var INTERACTIVE_MARKER_ROTATE_AXIS = 5; +var INTERACTIVE_MARKER_MOVE_ROTATE = 6; +var INTERACTIVE_MARKER_MOVE_3D = 7; +var INTERACTIVE_MARKER_ROTATE_3D = 8; +var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; - } +// Interactive marker rotation behavior +var INTERACTIVE_MARKER_INHERIT = 0; +var INTERACTIVE_MARKER_FIXED = 1; +var INTERACTIVE_MARKER_VIEW_FACING = 2; - } +/** + * @function makeColorMaterial + * @description Create a THREE material based on the given RGBA values. + * + * @param r - the red value + * @param g - the green value + * @param b - the blue value + * @param a - the alpha value + * @returns the THREE material + */ +var makeColorMaterial = function makeColorMaterial(r, g, b, a) { + var color = new Color(); + color.setRGB(r, g, b); + if (a <= 0.99) { + return new MeshBasicMaterial({ + color: color.getHex(), + opacity: a + 0.1, + transparent: true, + depthWrite: true, + blendSrc: SrcAlphaFactor, + blendDst: OneMinusSrcAlphaFactor, + blendEquation: ReverseSubtractEquation, + blending: NormalBlending + }); + } else { + return new MeshPhongMaterial({ + color: color.getHex(), + opacity: a, + blending: NormalBlending + }); + } +}; - var position = new THREE.Vector3(); - var scale = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); +/** + * @function intersectPlane + * @description Return the intersection between the mouseray and the plane. + * + * @param mouseRay - the mouse ray + * @param planeOrigin - the origin of the plane + * @param planeNormal - the normal of the plane + * @returns the intersection point + */ +var intersectPlane = function intersectPlane(mouseRay, planeOrigin, planeNormal) { + var vector = new Vector3(); + var intersectPoint = new Vector3(); + vector.subVectors(planeOrigin, mouseRay.origin); + var dot = mouseRay.direction.dot(planeNormal); - function createKeyframeTracks(animation, tracks) { + // bail if ray and plane are parallel + if (Math.abs(dot) < mouseRay.precision) { + return undefined; + } - var keyframes = animation.keyframes; - var name = animation.name; + // calc distance to plane + var scalar = planeNormal.dot(vector) / dot; + intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); + return intersectPoint; +}; - var times = []; - var positionData = []; - var quaternionData = []; - var scaleData = []; +/** + * @function findClosestPoint + * @description Find the closest point on targetRay to any point on mouseRay. Math taken from + * http://paulbourke.net/geometry/lineline3d/ + * + * @param targetRay - the target ray to use + * @param mouseRay - the mouse ray + * @param the closest point between the two rays + */ +var findClosestPoint = function findClosestPoint(targetRay, mouseRay) { + var v13 = new Vector3(); + v13.subVectors(targetRay.origin, mouseRay.origin); + var v43 = mouseRay.direction.clone(); + var v21 = targetRay.direction.clone(); + var d1343 = v13.dot(v43); + var d4321 = v43.dot(v21); + var d1321 = v13.dot(v21); + var d4343 = v43.dot(v43); + var d2121 = v21.dot(v21); + var denom = d2121 * d4343 - d4321 * d4321; + // check within a delta + if (Math.abs(denom) <= 0.0001) { + return undefined; + } + var numer = d1343 * d4321 - d1321 * d4343; + var mua = numer / denom; + return mua; +}; - for (var i = 0, l = keyframes.length; i < l; i++) { +/** + * @function closestAxisPoint + * @description Find the closest point between the axis and the mouse. + * + * @param axisRay - the ray from the axis + * @param camera - the camera to project from + * @param mousePos - the mouse position + * @returns the closest axis point + */ +var closestAxisPoint = function closestAxisPoint(axisRay, camera, mousePos) { + // project axis onto screen + var o = axisRay.origin.clone(); + o.project(camera); + var o2 = axisRay.direction.clone().add(axisRay.origin); + o2.project(camera); - var keyframe = keyframes[i]; + // d is the axis vector in screen space (d = o2-o) + var d = o2.clone().sub(o); - var time = keyframe.time; - var value = keyframe.value; + // t is the 2d ray param of perpendicular projection of mousePos onto o + var tmp = new Vector2(); + // (t = (mousePos - o) * d / (d*d)) + var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); - matrix.fromArray(value).transpose(); - matrix.decompose(position, quaternion, scale); + // mp is the final 2d-projected mouse pos (mp = o + d*t) + var mp = new Vector2(); + mp.addVectors(o, d.clone().multiplyScalar(t)); - times.push(time); - positionData.push(position.x, position.y, position.z); - quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); - scaleData.push(scale.x, scale.y, scale.z); + // go back to 3d by shooting a ray + var vector = new Vector3(mp.x, mp.y, 0.5); + vector.unproject(camera); + var mpRay = new Ray(camera.position, vector.sub(camera.position).normalize()); + return findClosestPoint(axisRay, mpRay); +}; - } +function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); +} - if (positionData.length > 0) { tracks.push(new THREE.VectorKeyframeTrack(name + '.position', times, positionData)); } - if (quaternionData.length > 0) { tracks.push(new THREE.QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); } - if (scaleData.length > 0) { tracks.push(new THREE.VectorKeyframeTrack(name + '.scale', times, scaleData)); } +function _typeof(o) { + "@babel/helpers - typeof"; - return tracks; + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); +} - } +function toPrimitive(t, r) { + if ("object" != _typeof(t) || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r || "default"); + if ("object" != _typeof(i)) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return ("string" === r ? String : Number)(t); +} - function transformAnimationData(keyframes, property, defaultValue) { +function toPropertyKey(t) { + var i = toPrimitive(t, "string"); + return "symbol" == _typeof(i) ? i : i + ""; +} - var keyframe; +function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, toPropertyKey(o.key), o); + } +} +function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { + writable: !1 + }), e; +} - var empty = true; - var i, l; +function _assertThisInitialized(e) { + if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return e; +} - // check, if values of a property are missing in our keyframes +function _possibleConstructorReturn(t, e) { + if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; + if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); + return _assertThisInitialized(t); +} - for (i = 0, l = keyframes.length; i < l; i++) { +function _getPrototypeOf(t) { + return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { + return t.__proto__ || Object.getPrototypeOf(t); + }, _getPrototypeOf(t); +} - keyframe = keyframes[i]; +function _setPrototypeOf(t, e) { + return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { + return t.__proto__ = e, t; + }, _setPrototypeOf(t, e); +} - if (keyframe.value[property] === undefined) { +function _inherits(t, e) { + if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); + t.prototype = Object.create(e && e.prototype, { + constructor: { + value: t, + writable: !0, + configurable: !0 + } + }), Object.defineProperty(t, "prototype", { + writable: !1 + }), e && _setPrototypeOf(t, e); +} - keyframe.value[property] = null; // mark as missing +function _callSuper$z(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$z() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$z() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$z = function _isNativeReflectConstruct() { return !!t; })(); } - } else { +/** + * @fileOverview + * @author Julius Kammerl - jkammerl@willowgarage.com + */ - empty = false; +var DepthCloud = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The DepthCloud object. + * + * @constructor + * @param options - object with following keys: + * + * * url - the URL of the stream + * * streamType (optional) - the stream type: mjpeg or vp8 video (defaults to vp8) + * * f (optional) - the camera's focal length (defaults to standard Kinect calibration) + * * maxDepthPerTile (optional) - the factor with which we control the desired depth range (defaults to 1.0) + * * pointSize (optional) - point size (pixels) for rendered point cloud + * * width (optional) - width of the video stream + * * height (optional) - height of the video stream + * * whiteness (optional) - blends rgb values to white (0..100) + * * varianceThreshold (optional) - threshold for variance filter, used for compression artifact removal + */ + function DepthCloud(options) { + var _this; + _classCallCheck(this, DepthCloud); + _this = _callSuper$z(this, DepthCloud); + options = options || {}; + _this.url = options.url; + _this.streamType = options.streamType || 'vp8'; + _this.f = options.f || 526; + _this.maxDepthPerTile = options.maxDepthPerTile || 1.0; + _this.pointSize = options.pointSize || 3; + _this.width = options.width || 1024; + _this.height = options.height || 1024; + _this.resolutionFactor = Math.max(_this.width, _this.height) / 1024; + _this.whiteness = options.whiteness || 0; + _this.varianceThreshold = options.varianceThreshold || 0.000016667; + _this.isMjpeg = _this.streamType.toLowerCase() === 'mjpeg'; + _this.video = document.createElement(_this.isMjpeg ? 'img' : 'video'); + _this.video.crossOrigin = 'Anonymous'; + _this.video.addEventListener(_this.isMjpeg ? 'load' : 'loadedmetadata', _this.metaLoaded.bind(_this), false); + if (!_this.isMjpeg) { + _this.video.loop = true; + } + _this.video.src = _this.url; + _this.video.setAttribute('crossorigin', 'Anonymous'); + // define custom shaders + _this.vertex_shader = ['uniform sampler2D map;', '', 'uniform float width;', 'uniform float height;', 'uniform float nearClipping, farClipping;', '', 'uniform float pointSize;', 'uniform float zOffset;', '', 'uniform float focallength;', 'uniform float maxDepthPerTile;', 'uniform float resolutionFactor;', '', 'varying vec2 vUvP;', 'varying vec2 colorP;', '', 'varying float depthVariance;', 'varying float maskVal;', '', 'float sampleDepth(vec2 pos)', ' {', ' float depth;', ' ', ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', ' ', ' vec4 depthColor = texture2D( map, vUv );', ' ', ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', ' ', ' if (depth>0.99)', ' {', ' vec4 depthColor2 = texture2D( map, vUv2 );', ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', ' depth = 0.99+depth2;', ' }', ' ', ' return depth;', ' }', '', 'float median(float a, float b, float c)', ' {', ' float r=a;', ' ', ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', ' {', ' vec2 smp = decodeDepth(vec2(position.x, position.y));', ' float depth = smp.x;', ' depthVariance = smp.y;', ' ', ' float z = -depth;', ' ', ' pos = vec4(', ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', ' (- z + zOffset / 1000.0) * maxDepthPerTile,', ' 1.0);', ' ', ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', ' vec4 maskColor = texture2D( map, maskP );', ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', ' }', ' ', ' gl_PointSize = pointSize;', ' gl_Position = projectionMatrix * modelViewMatrix * pos;', ' ', '}'].join('\n'); + _this.fragment_shader = ['uniform sampler2D map;', 'uniform float varianceThreshold;', 'uniform float whiteness;', '', 'varying vec2 vUvP;', 'varying vec2 colorP;', '', 'varying float depthVariance;', 'varying float maskVal;', '', '', 'void main() {', ' ', ' vec4 color;', ' ', ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', ' { ', ' discard;', ' }', ' else ', ' {', ' color = texture2D( map, colorP );', ' ', ' float fader = whiteness /100.0;', ' ', ' color.r = color.r * (1.0-fader)+ fader;', ' ', ' color.g = color.g * (1.0-fader)+ fader;', ' ', ' color.b = color.b * (1.0-fader)+ fader;', ' ', ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', ' }', ' ', ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', ' ', '}'].join('\n'); + return _this; + } + _inherits(DepthCloud, _THREE$Object3D); + return _createClass(DepthCloud, [{ + key: "metaLoaded", + value: + /** + * Callback called when video metadata is ready + */ + function metaLoaded() { + this.metaLoaded = true; + this.initStreamer(); + } + }, { + key: "initStreamer", + value: + /** + * Callback called when video metadata is ready + */ + function initStreamer() { + var _this2 = this; + if (this.metaLoaded) { + this.texture = new Texture(this.video); + this.geometry = new BufferGeometry(); + for (var i = 0, l = this.width * this.height; i < l; i++) { + var vertex = new Vector3(); + vertex.x = i % this.width; + vertex.y = Math.floor(i / this.width); + this.geometry.vertices.push(vertex); } - + this.material = new ShaderMaterial({ + uniforms: { + 'map': { + type: 't', + value: this.texture + }, + 'width': { + type: 'f', + value: this.width + }, + 'height': { + type: 'f', + value: this.height + }, + 'focallength': { + type: 'f', + value: this.f + }, + 'pointSize': { + type: 'f', + value: this.pointSize + }, + 'zOffset': { + type: 'f', + value: 0 + }, + 'whiteness': { + type: 'f', + value: this.whiteness + }, + 'varianceThreshold': { + type: 'f', + value: this.varianceThreshold + }, + 'maxDepthPerTile': { + type: 'f', + value: this.maxDepthPerTile + }, + 'resolutionFactor': { + type: 'f', + value: this.resolutionFactor + } + }, + vertexShader: this.vertex_shader, + fragmentShader: this.fragment_shader + }); + this.mesh = new Points$1(this.geometry, this.material); + this.mesh.position.x = 0; + this.mesh.position.y = 0; + this.add(this.mesh); + setInterval(function () { + if (_this2.isMjpeg || _this2.video.readyState === _this2.video.HAVE_ENOUGH_DATA) { + _this2.texture.needsUpdate = true; + } + }, 1000 / 30); + } + } + }, { + key: "startStream", + value: + /** + * Start video playback + */ + function startStream() { + if (!this.isMjpeg) { + this.video.play(); } + } + }, { + key: "stopStream", + value: + /** + * Stop video playback + */ + function stopStream() { + if (!this.isMjpeg) { + this.video.pause(); + } + } + }]); +}(Object3D); - if (empty === true) { +function _superPropBase(t, o) { + for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); + return t; +} - // no values at all, so we set a default value +function _get() { + return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { + var p = _superPropBase(e, t); + if (p) { + var n = Object.getOwnPropertyDescriptor(p, t); + return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; + } + }, _get.apply(null, arguments); +} - for (i = 0, l = keyframes.length; i < l; i++) { +function _callSuper$y(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$y() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$y() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$y = function _isNativeReflectConstruct() { return !!t; })(); } - keyframe = keyframes[i]; +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ - keyframe.value[property] = defaultValue; +var Arrow = /*#__PURE__*/function (_THREE$Mesh) { + /** + * A Arrow is a THREE object that can be used to display an arrow model. + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ + function Arrow(options) { + var _this; + _classCallCheck(this, Arrow); + options = options || {}; + var origin = options.origin || new Vector3(0, 0, 0); + var direction = options.direction || new Vector3(1, 0, 0); + var length = options.length || 1; + var headLength = options.headLength || 0.2; + var shaftDiameter = options.shaftDiameter || 0.05; + var headDiameter = options.headDiameter || 0.1; + var material = options.material || new MeshBasicMaterial(); + var shaftLength = length - headLength; - } + // create and merge geometry + var geometry = new CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, 12, 1); + var m = new Matrix4(); + m.setPosition(new Vector3(0, shaftLength * 0.5, 0)); + geometry.applyMatrix(m); - } else { + // create the head + var coneGeometry = new CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); + m.setPosition(new Vector3(0, shaftLength + headLength * 0.5, 0)); + coneGeometry.applyMatrix(m); - // filling gaps + // put the arrow together + geometry.merge(coneGeometry); + _this = _callSuper$y(this, Arrow, [geometry, material]); + _this.position.copy(origin); + _this.setDirection(direction); + return _this; + } + _inherits(Arrow, _THREE$Mesh); + return _createClass(Arrow, [{ + key: "setDirection", + value: + /** + * Set the direction of this arrow to that of the given vector. + * + * @param direction - the direction to set this arrow + */ + function setDirection(direction) { + var axis = new Vector3(); + if (direction.x === 0 && direction.z === 0) { + axis.set(1, 0, 0); + } else { + axis.set(0, 1, 0).cross(direction); + } + var radians = Math.acos(new Vector3(0, 1, 0).dot(direction.clone().normalize())); + this.matrix = new Matrix4().makeRotationAxis(axis.normalize(), radians); + this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); + } + }, { + key: "setLength", + value: + /** + * Set this arrow to be the given length. + * + * @param length - the new length of the arrow + */ + function setLength(length) { + this.scale.set(length, length, length); + } + }, { + key: "setColor", + value: + /** + * Set the color of this arrow to the given hex value. + * + * @param hex - the hex value of the color to use + */ + function setColor(hex) { + this.material.color.setHex(hex); + } + }, { + key: "dispose", + value: + /* + * Free memory of elements in this marker. + */ + function dispose() { + if (this.geometry !== undefined) { + this.geometry.dispose(); + } + if (this.material !== undefined) { + this.material.dispose(); + } + } + }]); +}(Mesh); - createMissingKeyframes(keyframes, property); +class TGALoader extends DataTextureLoader { - } + constructor( manager ) { - } + super( manager ); - function createMissingKeyframes(keyframes, property) { + } - var prev, next; + parse( buffer ) { - for (var i = 0, l = keyframes.length; i < l; i++) { + // reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js - var keyframe = keyframes[i]; + function tgaCheckHeader( header ) { - if (keyframe.value[property] === null) { + switch ( header.image_type ) { - prev = getPrev(keyframes, i, property); - next = getNext(keyframes, i, property); + // check indexed type - if (prev === null) { + case TGA_TYPE_INDEXED: + case TGA_TYPE_RLE_INDEXED: + if ( header.colormap_length > 256 || header.colormap_size !== 24 || header.colormap_type !== 1 ) { - keyframe.value[property] = next.value[property]; - continue; + throw new Error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' ); - } + } - if (next === null) { + break; - keyframe.value[property] = prev.value[property]; - continue; + // check colormap type - } + case TGA_TYPE_RGB: + case TGA_TYPE_GREY: + case TGA_TYPE_RLE_RGB: + case TGA_TYPE_RLE_GREY: + if ( header.colormap_type ) { - interpolate(keyframe, prev, next, property); + throw new Error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' ); - } + } - } + break; - } + // What the need of a file without data ? - function getPrev(keyframes, i, property) { + case TGA_TYPE_NO_DATA: + throw new Error( 'THREE.TGALoader: No data.' ); - while (i >= 0) { + // Invalid type ? - var keyframe = keyframes[i]; + default: + throw new Error( 'THREE.TGALoader: Invalid type ' + header.image_type ); - if (keyframe.value[property] !== null) { return keyframe; } + } - i--; + // check image width and height - } + if ( header.width <= 0 || header.height <= 0 ) { - return null; + throw new Error( 'THREE.TGALoader: Invalid image size.' ); - } + } - function getNext(keyframes, i, property) { + // check image pixel size - while (i < keyframes.length) { + if ( header.pixel_size !== 8 && header.pixel_size !== 16 && + header.pixel_size !== 24 && header.pixel_size !== 32 ) { - var keyframe = keyframes[i]; + throw new Error( 'THREE.TGALoader: Invalid pixel size ' + header.pixel_size ); - if (keyframe.value[property] !== null) { return keyframe; } + } - i++; + } - } + // parse tga image buffer - return null; + function tgaParse( use_rle, use_pal, header, offset, data ) { - } + let pixel_data, + palettes; - function interpolate(key, prev, next, property) { + const pixel_size = header.pixel_size >> 3; + const pixel_total = header.width * header.height * pixel_size; - if ((next.time - prev.time) === 0) { + // read palettes - key.value[property] = prev.value[property]; - return; + if ( use_pal ) { - } + palettes = data.subarray( offset, offset += header.colormap_length * ( header.colormap_size >> 3 ) ); - key.value[property] = ((key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time)) + prev.value[property]; + } - } + // read RLE - // animation clips + if ( use_rle ) { - function parseAnimationClip(xml) { + pixel_data = new Uint8Array( pixel_total ); - var data = { - name: xml.getAttribute('id') || 'default', - start: parseFloat(xml.getAttribute('start') || 0), - end: parseFloat(xml.getAttribute('end') || 0), - animations: [] - }; + let c, count, i; + let shift = 0; + const pixels = new Uint8Array( pixel_size ); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + while ( shift < pixel_total ) { - var child = xml.childNodes[i]; + c = data[ offset ++ ]; + count = ( c & 0x7f ) + 1; - if (child.nodeType !== 1) { continue; } + // RLE pixels - switch (child.nodeName) { + if ( c & 0x80 ) { - case 'instance_animation': - data.animations.push(parseId(child.getAttribute('url'))); - break; + // bind pixel tmp array - } + for ( i = 0; i < pixel_size; ++ i ) { - } + pixels[ i ] = data[ offset ++ ]; - library.clips[xml.getAttribute('id')] = data; + } - } + // copy pixel array - function buildAnimationClip(data) { + for ( i = 0; i < count; ++ i ) { - var tracks = []; + pixel_data.set( pixels, shift + i * pixel_size ); - var name = data.name; - var duration = (data.end - data.start) || - 1; - var animations = data.animations; + } - for (var i = 0, il = animations.length; i < il; i++) { + shift += pixel_size * count; - var animationTracks = getAnimation(animations[i]); + } else { - for (var j = 0, jl = animationTracks.length; j < jl; j++) { + // raw pixels - tracks.push(animationTracks[j]); + count *= pixel_size; - } + for ( i = 0; i < count; ++ i ) { - } + pixel_data[ shift + i ] = data[ offset ++ ]; - return new THREE.AnimationClip(name, duration, tracks); + } - } + shift += count; - function getAnimationClip(id) { + } - return getBuild(library.clips[id], buildAnimationClip); + } - } + } else { - // controller + // raw pixels - function parseController(xml) { + pixel_data = data.subarray( + offset, offset += ( use_pal ? header.width * header.height : pixel_total ) + ); - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + return { + pixel_data: pixel_data, + palettes: palettes + }; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) { continue; } + function tgaGetImageData8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes ) { - switch (child.nodeName) { + const colormap = palettes; + let color, i = 0, x, y; + const width = header.width; - case 'skin': - // there is exactly one skin per controller - data.id = parseId(child.getAttribute('source')); - data.skin = parseSkin(child); - break; + for ( y = y_start; y !== y_end; y += y_step ) { - case 'morph': - data.id = parseId(child.getAttribute('source')); - console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); - break; + for ( x = x_start; x !== x_end; x += x_step, i ++ ) { - } + color = image[ i ]; + imageData[ ( x + width * y ) * 4 + 3 ] = 255; + imageData[ ( x + width * y ) * 4 + 2 ] = colormap[ ( color * 3 ) + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = colormap[ ( color * 3 ) + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = colormap[ ( color * 3 ) + 2 ]; - } + } - library.controllers[xml.getAttribute('id')] = data; + } - } + return imageData; - function parseSkin(xml) { + } - var data = { - sources: {} - }; + function tgaGetImageData16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + let color, i = 0, x, y; + const width = header.width; - var child = xml.childNodes[i]; + for ( y = y_start; y !== y_end; y += y_step ) { - if (child.nodeType !== 1) { continue; } + for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { - switch (child.nodeName) { + color = image[ i + 0 ] + ( image[ i + 1 ] << 8 ); + imageData[ ( x + width * y ) * 4 + 0 ] = ( color & 0x7C00 ) >> 7; + imageData[ ( x + width * y ) * 4 + 1 ] = ( color & 0x03E0 ) >> 2; + imageData[ ( x + width * y ) * 4 + 2 ] = ( color & 0x001F ) << 3; + imageData[ ( x + width * y ) * 4 + 3 ] = ( color & 0x8000 ) ? 0 : 255; - case 'bind_shape_matrix': - data.bindShapeMatrix = parseFloats(child.textContent); - break; + } - case 'source': - var id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; + } - case 'joints': - data.joints = parseJoints(child); - break; + return imageData; - case 'vertex_weights': - data.vertexWeights = parseVertexWeights(child); - break; + } - } + function tgaGetImageData24bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - } + let i = 0, x, y; + const width = header.width; - return data; + for ( y = y_start; y !== y_end; y += y_step ) { - } + for ( x = x_start; x !== x_end; x += x_step, i += 3 ) { - function parseJoints(xml) { + imageData[ ( x + width * y ) * 4 + 3 ] = 255; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; - var data = { - inputs: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + return imageData; - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + function tgaGetImageData32bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - data.inputs[semantic] = id; - break; + let i = 0, x, y; + const width = header.width; - } + for ( y = y_start; y !== y_end; y += y_step ) { - } + for ( x = x_start; x !== x_end; x += x_step, i += 4 ) { - return data; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; + imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 3 ]; - } + } - function parseVertexWeights(xml) { + } - var data = { - inputs: {} - }; + return imageData; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + function tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - if (child.nodeType !== 1) { continue; } + let color, i = 0, x, y; + const width = header.width; - switch (child.nodeName) { + for ( y = y_start; y !== y_end; y += y_step ) { - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - var offset = parseInt(child.getAttribute('offset')); - data.inputs[semantic] = { id: id, offset: offset }; - break; + for ( x = x_start; x !== x_end; x += x_step, i ++ ) { - case 'vcount': - data.vcount = parseInts(child.textContent); - break; + color = image[ i ]; + imageData[ ( x + width * y ) * 4 + 0 ] = color; + imageData[ ( x + width * y ) * 4 + 1 ] = color; + imageData[ ( x + width * y ) * 4 + 2 ] = color; + imageData[ ( x + width * y ) * 4 + 3 ] = 255; - case 'v': - data.v = parseInts(child.textContent); - break; + } - } + } - } + return imageData; - return data; + } - } + function tgaGetImageDataGrey16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - function buildController(data) { + let i = 0, x, y; + const width = header.width; - var build = { - id: data.id - }; + for ( y = y_start; y !== y_end; y += y_step ) { - var geometry = library.geometries[build.id]; + for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { - if (data.skin !== undefined) { + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 1 ]; - build.skin = buildSkin(data.skin); + } - // we enhance the 'sources' property of the corresponding geometry with our skin data + } - geometry.sources.skinIndices = build.skin.indices; - geometry.sources.skinWeights = build.skin.weights; + return imageData; - } + } - return build; + function getTgaRGBA( data, width, height, image, palette ) { - } + let x_start, + y_start, + x_step, + y_step, + x_end, + y_end; - function buildSkin(data) { + switch ( ( header.flags & TGA_ORIGIN_MASK ) >> TGA_ORIGIN_SHIFT ) { - var BONE_LIMIT = 4; + default: + case TGA_ORIGIN_UL: + x_start = 0; + x_step = 1; + x_end = width; + y_start = 0; + y_step = 1; + y_end = height; + break; - var build = { - joints: [], // this must be an array to preserve the joint order - indices: { - array: [], - stride: BONE_LIMIT - }, - weights: { - array: [], - stride: BONE_LIMIT - } - }; + case TGA_ORIGIN_BL: + x_start = 0; + x_step = 1; + x_end = width; + y_start = height - 1; + y_step = - 1; + y_end = - 1; + break; - var sources = data.sources; - var vertexWeights = data.vertexWeights; + case TGA_ORIGIN_UR: + x_start = width - 1; + x_step = - 1; + x_end = - 1; + y_start = 0; + y_step = 1; + y_end = height; + break; - var vcount = vertexWeights.vcount; - var v = vertexWeights.v; - var jointOffset = vertexWeights.inputs.JOINT.offset; - var weightOffset = vertexWeights.inputs.WEIGHT.offset; + case TGA_ORIGIN_BR: + x_start = width - 1; + x_step = - 1; + x_end = - 1; + y_start = height - 1; + y_step = - 1; + y_end = - 1; + break; - var jointSource = data.sources[data.joints.inputs.JOINT]; - var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; + } - var weights = sources[vertexWeights.inputs.WEIGHT.id].array; - var stride = 0; + if ( use_grey ) { - var i, j, l; + switch ( header.pixel_size ) { - // procces skin data for each vertex + case 8: + tgaGetImageDataGrey8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - for (i = 0, l = vcount.length; i < l; i++) { + case 16: + tgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex - var vertexSkinData = []; + default: + throw new Error( 'THREE.TGALoader: Format not supported.' ); - for (j = 0; j < jointCount; j++) { + } - var skinIndex = v[stride + jointOffset]; - var weightId = v[stride + weightOffset]; - var skinWeight = weights[weightId]; + } else { - vertexSkinData.push({ index: skinIndex, weight: skinWeight }); + switch ( header.pixel_size ) { - stride += 2; + case 8: + tgaGetImageData8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image, palette ); + break; - } + case 16: + tgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - // we sort the joints in descending order based on the weights. - // this ensures, we only procced the most important joints of the vertex + case 24: + tgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - vertexSkinData.sort(descending); + case 32: + tgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - // now we provide for each vertex a set of four index and weight values. - // the order of the skin data matches the order of vertices + default: + throw new Error( 'THREE.TGALoader: Format not supported.' ); - for (j = 0; j < BONE_LIMIT; j++) { + } - var d = vertexSkinData[j]; + } - if (d !== undefined) { + // Load image data according to specific method + // let func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits'; + // func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette ); + return data; - build.indices.array.push(d.index); - build.weights.array.push(d.weight); + } - } else { + // TGA constants + + const TGA_TYPE_NO_DATA = 0, + TGA_TYPE_INDEXED = 1, + TGA_TYPE_RGB = 2, + TGA_TYPE_GREY = 3, + TGA_TYPE_RLE_INDEXED = 9, + TGA_TYPE_RLE_RGB = 10, + TGA_TYPE_RLE_GREY = 11, + + TGA_ORIGIN_MASK = 0x30, + TGA_ORIGIN_SHIFT = 0x04, + TGA_ORIGIN_BL = 0x00, + TGA_ORIGIN_BR = 0x01, + TGA_ORIGIN_UL = 0x02, + TGA_ORIGIN_UR = 0x03; + + if ( buffer.length < 19 ) throw new Error( 'THREE.TGALoader: Not enough data to contain header.' ); + + let offset = 0; + + const content = new Uint8Array( buffer ), + header = { + id_length: content[ offset ++ ], + colormap_type: content[ offset ++ ], + image_type: content[ offset ++ ], + colormap_index: content[ offset ++ ] | content[ offset ++ ] << 8, + colormap_length: content[ offset ++ ] | content[ offset ++ ] << 8, + colormap_size: content[ offset ++ ], + origin: [ + content[ offset ++ ] | content[ offset ++ ] << 8, + content[ offset ++ ] | content[ offset ++ ] << 8 + ], + width: content[ offset ++ ] | content[ offset ++ ] << 8, + height: content[ offset ++ ] | content[ offset ++ ] << 8, + pixel_size: content[ offset ++ ], + flags: content[ offset ++ ] + }; - build.indices.array.push(0); - build.weights.array.push(0); + // check tga if it is valid format - } + tgaCheckHeader( header ); - } + if ( header.id_length + offset > buffer.length ) { - } + throw new Error( 'THREE.TGALoader: No data.' ); - // setup bind matrix + } - build.bindMatrix = new THREE.Matrix4().fromArray(data.bindShapeMatrix).transpose(); + // skip the needn't data - // process bones and inverse bind matrix data + offset += header.id_length; - for (i = 0, l = jointSource.array.length; i < l; i++) { + // get targa information about RLE compression and palette - var name = jointSource.array[i]; - var boneInverse = new THREE.Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); + let use_rle = false, + use_pal = false, + use_grey = false; - build.joints.push({ name: name, boneInverse: boneInverse }); + switch ( header.image_type ) { - } + case TGA_TYPE_RLE_INDEXED: + use_rle = true; + use_pal = true; + break; - return build; + case TGA_TYPE_INDEXED: + use_pal = true; + break; - // array sort function + case TGA_TYPE_RLE_RGB: + use_rle = true; + break; - function descending(a, b) { + case TGA_TYPE_RGB: + break; - return b.weight - a.weight; + case TGA_TYPE_RLE_GREY: + use_rle = true; + use_grey = true; + break; - } + case TGA_TYPE_GREY: + use_grey = true; + break; - } + } - function getController(id) { + // - return getBuild(library.controllers[id], buildController); + const imageData = new Uint8Array( header.width * header.height * 4 ); + const result = tgaParse( use_rle, use_pal, header, offset, content ); + getTgaRGBA( imageData, header.width, header.height, result.pixel_data, result.palettes ); - } + return { - // image + data: imageData, + width: header.width, + height: header.height, + flipY: true, + generateMipmaps: true, + minFilter: LinearMipmapLinearFilter, - function parseImage(xml) { + }; - var data = { - init_from: getElementsByTagName(xml, 'init_from')[0].textContent - }; + } - library.images[xml.getAttribute('id')] = data; +} +function _callSuper$x(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$x() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$x() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$x = function _isNativeReflectConstruct() { return !!t; })(); } +var ColladaLoader = /*#__PURE__*/function (_Loader) { + function ColladaLoader() { + _classCallCheck(this, ColladaLoader); + return _callSuper$x(this, ColladaLoader, arguments); + } + _inherits(ColladaLoader, _Loader); + return _createClass(ColladaLoader, [{ + key: "load", + value: function load(url, onLoad, onProgress, onError) { + var scope = this; + var path = scope.path === '' ? LoaderUtils.extractUrlBase(url) : scope.path; + var 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(text, path)); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); } + }, { + key: "parse", + value: function parse(text, path) { + function getElementsByTagName(xml, name) { + // Non recursive xml.getElementsByTagName() ... + + var array = []; + var childNodes = xml.childNodes; + for (var i = 0, l = childNodes.length; i < l; i++) { + var child = childNodes[i]; + if (child.nodeName === name) { + array.push(child); + } + } + return array; + } + function parseStrings(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parts[i]; + } + return array; + } + function parseFloats(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parseFloat(parts[i]); + } + return array; + } + function parseInts(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parseInt(parts[i]); + } + return array; + } + function parseId(text) { + return text.substring(1); + } + function generateId() { + return 'three_default_' + count++; + } + function isEmpty(object) { + return Object.keys(object).length === 0; + } - function buildImage(data) { - - if (data.build !== undefined) { return data.build; } + // asset - return data.init_from; + function parseAsset(xml) { + return { + unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), + upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) + }; + } + function parseAssetUnit(xml) { + if (xml !== undefined && xml.hasAttribute('meter') === true) { + return parseFloat(xml.getAttribute('meter')); + } else { + return 1; // default 1 meter + } + } + function parseAssetUpAxis(xml) { + return xml !== undefined ? xml.textContent : 'Y_UP'; + } - } + // library - function getImage(id) { + function parseLibrary(xml, libraryName, nodeName, parser) { + var library = getElementsByTagName(xml, libraryName)[0]; + if (library !== undefined) { + var elements = getElementsByTagName(library, nodeName); + for (var i = 0; i < elements.length; i++) { + parser(elements[i]); + } + } + } + function buildLibrary(data, builder) { + for (var name in data) { + var object = data[name]; + object.build = builder(data[name]); + } + } - return getBuild(library.images[id], buildImage); + // get - } + function getBuild(data, builder) { + if (data.build !== undefined) return data.build; + data.build = builder(data); + return data.build; + } - // effect + // animation + + function parseAnimation(xml) { + var data = { + sources: {}, + samplers: {}, + channels: {} + }; + var hasChildren = false; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var id = void 0; + switch (child.nodeName) { + case 'source': + id = child.getAttribute('id'); + data.sources[id] = parseSource(child); + break; + case 'sampler': + id = child.getAttribute('id'); + data.samplers[id] = parseAnimationSampler(child); + break; + case 'channel': + id = child.getAttribute('target'); + data.channels[id] = parseAnimationChannel(child); + break; + case 'animation': + // hierarchy of related animations + parseAnimation(child); + hasChildren = true; + break; + default: + console.log(child); + } + } + if (hasChildren === false) { + // since 'id' attributes can be optional, it's necessary to generate a UUID for unqiue assignment - function parseEffect(xml) { + library.animations[xml.getAttribute('id') || MathUtils.generateUUID()] = data; + } + } + function parseAnimationSampler(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var id = parseId(child.getAttribute('source')); + var semantic = child.getAttribute('semantic'); + data.inputs[semantic] = id; + break; + } + } + return data; + } + function parseAnimationChannel(xml) { + var data = {}; + var target = xml.getAttribute('target'); - var data = {}; + // parsing SID Addressing Syntax - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var parts = target.split('/'); + var id = parts.shift(); + var sid = parts.shift(); - var child = xml.childNodes[i]; + // check selection syntax - if (child.nodeType !== 1) { continue; } + var arraySyntax = sid.indexOf('(') !== -1; + var memberSyntax = sid.indexOf('.') !== -1; + if (memberSyntax) { + // member selection access - switch (child.nodeName) { + parts = sid.split('.'); + sid = parts.shift(); + data.member = parts.shift(); + } else if (arraySyntax) { + // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. - case 'profile_COMMON': - data.profile = parseEffectProfileCOMMON(child); + var indices = sid.split('('); + sid = indices.shift(); + for (var i = 0; i < indices.length; i++) { + indices[i] = parseInt(indices[i].replace(/\)/, '')); + } + data.indices = indices; + } + data.id = id; + data.sid = sid; + data.arraySyntax = arraySyntax; + data.memberSyntax = memberSyntax; + data.sampler = parseId(xml.getAttribute('source')); + return data; + } + function buildAnimation(data) { + var tracks = []; + var channels = data.channels; + var samplers = data.samplers; + var sources = data.sources; + for (var target in channels) { + if (channels.hasOwnProperty(target)) { + var channel = channels[target]; + var sampler = samplers[channel.sampler]; + var inputId = sampler.inputs.INPUT; + var outputId = sampler.inputs.OUTPUT; + var inputSource = sources[inputId]; + var outputSource = sources[outputId]; + var animation = buildAnimationChannel(channel, inputSource, outputSource); + createKeyframeTracks(animation, tracks); + } + } + return tracks; + } + function getAnimation(id) { + return getBuild(library.animations[id], buildAnimation); + } + function buildAnimationChannel(channel, inputSource, outputSource) { + var node = library.nodes[channel.id]; + var object3D = getNode(node.id); + var transform = node.transforms[channel.sid]; + var defaultMatrix = node.matrix.clone().transpose(); + var time, stride; + var i, il, j, jl; + var data = {}; + + // the collada spec allows the animation of data in various ways. + // depending on the transform type (matrix, translate, rotate, scale), we execute different logic + + switch (transform) { + case 'matrix': + for (i = 0, il = inputSource.array.length; i < il; i++) { + time = inputSource.array[i]; + stride = i * outputSource.stride; + if (data[time] === undefined) data[time] = {}; + if (channel.arraySyntax === true) { + var value = outputSource.array[stride]; + var index = channel.indices[0] + 4 * channel.indices[1]; + data[time][index] = value; + } else { + for (j = 0, jl = outputSource.stride; j < jl; j++) { + data[time][j] = outputSource.array[stride + j]; + } + } + } + break; + case 'translate': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + case 'rotate': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + case 'scale': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); break; - } - + var keyframes = prepareAnimationData(data, defaultMatrix); + var animation = { + name: object3D.uuid, + keyframes: keyframes + }; + return animation; } + function prepareAnimationData(data, defaultMatrix) { + var keyframes = []; - library.effects[xml.getAttribute('id')] = data; + // transfer data into a sortable array - } + for (var time in data) { + keyframes.push({ + time: parseFloat(time), + value: data[time] + }); + } - function parseEffectProfileCOMMON(xml) { + // ensure keyframes are sorted by time - var data = { - surfaces: {}, - samplers: {} - }; + keyframes.sort(ascending); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // now we clean up all animation data, so we can use them for keyframe tracks - var child = xml.childNodes[i]; + for (var i = 0; i < 16; i++) { + transformAnimationData(keyframes, i, defaultMatrix.elements[i]); + } + return keyframes; - if (child.nodeType !== 1) { continue; } + // array sort function - switch (child.nodeName) { + function ascending(a, b) { + return a.time - b.time; + } + } + var position = new Vector3(); + var scale = new Vector3(); + var quaternion = new Quaternion(); + function createKeyframeTracks(animation, tracks) { + var keyframes = animation.keyframes; + var name = animation.name; + var times = []; + var positionData = []; + var quaternionData = []; + var scaleData = []; + for (var i = 0, l = keyframes.length; i < l; i++) { + var keyframe = keyframes[i]; + var time = keyframe.time; + var value = keyframe.value; + matrix.fromArray(value).transpose(); + matrix.decompose(position, quaternion, scale); + times.push(time); + positionData.push(position.x, position.y, position.z); + quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); + scaleData.push(scale.x, scale.y, scale.z); + } + if (positionData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.position', times, positionData)); + if (quaternionData.length > 0) tracks.push(new QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); + if (scaleData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.scale', times, scaleData)); + return tracks; + } + function transformAnimationData(keyframes, property, defaultValue) { + var keyframe; + var empty = true; + var i, l; - case 'newparam': - parseEffectNewparam(child, data); - break; + // check, if values of a property are missing in our keyframes - case 'technique': - data.technique = parseEffectTechnique(child); - break; + for (i = 0, l = keyframes.length; i < l; i++) { + keyframe = keyframes[i]; + if (keyframe.value[property] === undefined) { + keyframe.value[property] = null; // mark as missing + } else { + empty = false; + } + } + if (empty === true) { + // no values at all, so we set a default value + + for (i = 0, l = keyframes.length; i < l; i++) { + keyframe = keyframes[i]; + keyframe.value[property] = defaultValue; + } + } else { + // filling gaps + + createMissingKeyframes(keyframes, property); + } + } + function createMissingKeyframes(keyframes, property) { + var prev, next; + for (var i = 0, l = keyframes.length; i < l; i++) { + var keyframe = keyframes[i]; + if (keyframe.value[property] === null) { + prev = getPrev(keyframes, i, property); + next = getNext(keyframes, i, property); + if (prev === null) { + keyframe.value[property] = next.value[property]; + continue; + } + if (next === null) { + keyframe.value[property] = prev.value[property]; + continue; + } + interpolate(keyframe, prev, next, property); + } + } + } + function getPrev(keyframes, i, property) { + while (i >= 0) { + var keyframe = keyframes[i]; + if (keyframe.value[property] !== null) return keyframe; + i--; + } + return null; + } + function getNext(keyframes, i, property) { + while (i < keyframes.length) { + var keyframe = keyframes[i]; + if (keyframe.value[property] !== null) return keyframe; + i++; + } + return null; + } + function interpolate(key, prev, next, property) { + if (next.time - prev.time === 0) { + key.value[property] = prev.value[property]; + return; + } + key.value[property] = (key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time) + prev.value[property]; + } + // animation clips + + function parseAnimationClip(xml) { + var data = { + name: xml.getAttribute('id') || 'default', + start: parseFloat(xml.getAttribute('start') || 0), + end: parseFloat(xml.getAttribute('end') || 0), + animations: [] + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'instance_animation': + data.animations.push(parseId(child.getAttribute('url'))); + break; + } + } + library.clips[xml.getAttribute('id')] = data; + } + function buildAnimationClip(data) { + var tracks = []; + var name = data.name; + var duration = data.end - data.start || -1; + var animations = data.animations; + for (var i = 0, il = animations.length; i < il; i++) { + var animationTracks = getAnimation(animations[i]); + for (var j = 0, jl = animationTracks.length; j < jl; j++) { + tracks.push(animationTracks[j]); + } } + return new AnimationClip(name, duration, tracks); + } + function getAnimationClip(id) { + return getBuild(library.clips[id], buildAnimationClip); + } + // controller + + function parseController(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'skin': + // there is exactly one skin per controller + data.id = parseId(child.getAttribute('source')); + data.skin = parseSkin(child); + break; + case 'morph': + data.id = parseId(child.getAttribute('source')); + console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); + break; + } + } + library.controllers[xml.getAttribute('id')] = data; + } + function parseSkin(xml) { + var data = { + sources: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'bind_shape_matrix': + data.bindShapeMatrix = parseFloats(child.textContent); + break; + case 'source': + var id = child.getAttribute('id'); + data.sources[id] = parseSource(child); + break; + case 'joints': + data.joints = parseJoints(child); + break; + case 'vertex_weights': + data.vertexWeights = parseVertexWeights(child); + break; + } + } + return data; + } + function parseJoints(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var semantic = child.getAttribute('semantic'); + var id = parseId(child.getAttribute('source')); + data.inputs[semantic] = id; + break; + } + } + return data; + } + function parseVertexWeights(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var semantic = child.getAttribute('semantic'); + var id = parseId(child.getAttribute('source')); + var offset = parseInt(child.getAttribute('offset')); + data.inputs[semantic] = { + id: id, + offset: offset + }; + break; + case 'vcount': + data.vcount = parseInts(child.textContent); + break; + case 'v': + data.v = parseInts(child.textContent); + break; + } + } + return data; + } + function buildController(data) { + var build = { + id: data.id + }; + var geometry = library.geometries[build.id]; + if (data.skin !== undefined) { + build.skin = buildSkin(data.skin); + + // we enhance the 'sources' property of the corresponding geometry with our skin data + + geometry.sources.skinIndices = build.skin.indices; + geometry.sources.skinWeights = build.skin.weights; + } + return build; } + function buildSkin(data) { + var BONE_LIMIT = 4; + var build = { + joints: [], + // this must be an array to preserve the joint order + indices: { + array: [], + stride: BONE_LIMIT + }, + weights: { + array: [], + stride: BONE_LIMIT + } + }; + var sources = data.sources; + var vertexWeights = data.vertexWeights; + var vcount = vertexWeights.vcount; + var v = vertexWeights.v; + var jointOffset = vertexWeights.inputs.JOINT.offset; + var weightOffset = vertexWeights.inputs.WEIGHT.offset; + var jointSource = data.sources[data.joints.inputs.JOINT]; + var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; + var weights = sources[vertexWeights.inputs.WEIGHT.id].array; + var stride = 0; + var i, j, l; + + // process skin data for each vertex + + for (i = 0, l = vcount.length; i < l; i++) { + var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex + var vertexSkinData = []; + for (j = 0; j < jointCount; j++) { + var skinIndex = v[stride + jointOffset]; + var weightId = v[stride + weightOffset]; + var skinWeight = weights[weightId]; + vertexSkinData.push({ + index: skinIndex, + weight: skinWeight + }); + stride += 2; + } - return data; - - } + // we sort the joints in descending order based on the weights. + // this ensures, we only procced the most important joints of the vertex - function parseEffectNewparam(xml, data) { + vertexSkinData.sort(descending); - var sid = xml.getAttribute('sid'); + // now we provide for each vertex a set of four index and weight values. + // the order of the skin data matches the order of vertices - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + for (j = 0; j < BONE_LIMIT; j++) { + var d = vertexSkinData[j]; + if (d !== undefined) { + build.indices.array.push(d.index); + build.weights.array.push(d.weight); + } else { + build.indices.array.push(0); + build.weights.array.push(0); + } + } + } - var child = xml.childNodes[i]; + // setup bind matrix - if (child.nodeType !== 1) { continue; } + if (data.bindShapeMatrix) { + build.bindMatrix = new Matrix4().fromArray(data.bindShapeMatrix).transpose(); + } else { + build.bindMatrix = new Matrix4().identity(); + } - switch (child.nodeName) { + // process bones and inverse bind matrix data - case 'surface': - data.surfaces[sid] = parseEffectSurface(child); - break; + for (i = 0, l = jointSource.array.length; i < l; i++) { + var name = jointSource.array[i]; + var boneInverse = new Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); + build.joints.push({ + name: name, + boneInverse: boneInverse + }); + } + return build; - case 'sampler2D': - data.samplers[sid] = parseEffectSampler(child); - break; + // array sort function + function descending(a, b) { + return b.weight - a.weight; } - + } + function getController(id) { + return getBuild(library.controllers[id], buildController); } - } - - function parseEffectSurface(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'init_from': - data.init_from = child.textContent; - break; + // image + function parseImage(xml) { + var data = { + init_from: getElementsByTagName(xml, 'init_from')[0].textContent + }; + library.images[xml.getAttribute('id')] = data; + } + function buildImage(data) { + if (data.build !== undefined) return data.build; + return data.init_from; + } + function getImage(id) { + var data = library.images[id]; + if (data !== undefined) { + return getBuild(data, buildImage); } - + console.warn('THREE.ColladaLoader: Couldn\'t find image with ID:', id); + return null; } - return data; - - } - - function parseEffectSampler(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // effect - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { + function parseEffect(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'profile_COMMON': + data.profile = parseEffectProfileCOMMON(child); + break; + } + } + library.effects[xml.getAttribute('id')] = data; + } + function parseEffectProfileCOMMON(xml) { + var data = { + surfaces: {}, + samplers: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'newparam': + parseEffectNewparam(child, data); + break; + case 'technique': + data.technique = parseEffectTechnique(child); + break; + case 'extra': + data.extra = parseEffectExtra(child); + break; + } + } + return data; + } + function parseEffectNewparam(xml, data) { + var sid = xml.getAttribute('sid'); + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'surface': + data.surfaces[sid] = parseEffectSurface(child); + break; + case 'sampler2D': + data.samplers[sid] = parseEffectSampler(child); + break; + } + } + } + function parseEffectSurface(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'init_from': + data.init_from = child.textContent; + break; + } + } + return data; + } + function parseEffectSampler(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'source': + data.source = child.textContent; + break; + } + } + return data; + } + function parseEffectTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'constant': + case 'lambert': + case 'blinn': + case 'phong': + data.type = child.nodeName; + data.parameters = parseEffectParameters(child); + break; + case 'extra': + data.extra = parseEffectExtra(child); + break; + } + } + return data; + } + function parseEffectParameters(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'emission': + case 'diffuse': + case 'specular': + case 'bump': + case 'ambient': + case 'shininess': + case 'transparency': + data[child.nodeName] = parseEffectParameter(child); + break; + case 'transparent': + data[child.nodeName] = { + opaque: child.hasAttribute('opaque') ? child.getAttribute('opaque') : 'A_ONE', + data: parseEffectParameter(child) + }; + break; + } + } + return data; + } + function parseEffectParameter(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'color': + data[child.nodeName] = parseFloats(child.textContent); + break; + case 'float': + data[child.nodeName] = parseFloat(child.textContent); + break; + case 'texture': + data[child.nodeName] = { + id: child.getAttribute('texture'), + extra: parseEffectParameterTexture(child) + }; + break; + } + } + return data; + } + function parseEffectParameterTexture(xml) { + var data = { + technique: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'extra': + parseEffectParameterTextureExtra(child, data); + break; + } + } + return data; + } + function parseEffectParameterTextureExtra(xml, data) { + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique': + parseEffectParameterTextureExtraTechnique(child, data); + break; + } + } + } + function parseEffectParameterTextureExtraTechnique(xml, data) { + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'repeatU': + case 'repeatV': + case 'offsetU': + case 'offsetV': + data.technique[child.nodeName] = parseFloat(child.textContent); + break; + case 'wrapU': + case 'wrapV': + // some files have values for wrapU/wrapV which become NaN via parseInt + + if (child.textContent.toUpperCase() === 'TRUE') { + data.technique[child.nodeName] = 1; + } else if (child.textContent.toUpperCase() === 'FALSE') { + data.technique[child.nodeName] = 0; + } else { + data.technique[child.nodeName] = parseInt(child.textContent); + } + break; + case 'bump': + data[child.nodeName] = parseEffectExtraTechniqueBump(child); + break; + } + } + } + function parseEffectExtra(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique': + data.technique = parseEffectExtraTechnique(child); + break; + } + } + return data; + } + function parseEffectExtraTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'double_sided': + data[child.nodeName] = parseInt(child.textContent); + break; + case 'bump': + data[child.nodeName] = parseEffectExtraTechniqueBump(child); + break; + } + } + return data; + } + function parseEffectExtraTechniqueBump(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'texture': + data[child.nodeName] = { + id: child.getAttribute('texture'), + texcoord: child.getAttribute('texcoord'), + extra: parseEffectParameterTexture(child) + }; + break; + } + } + return data; + } + function buildEffect(data) { + return data; + } + function getEffect(id) { + return getBuild(library.effects[id], buildEffect); + } - case 'source': - data.source = child.textContent; + // material + + function parseMaterial(xml) { + var data = { + name: xml.getAttribute('name') + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'instance_effect': + data.url = parseId(child.getAttribute('url')); + break; + } + } + library.materials[xml.getAttribute('id')] = data; + } + function getTextureLoader(image) { + var loader; + var extension = image.slice((image.lastIndexOf('.') - 1 >>> 0) + 2); // http://www.jstips.co/en/javascript/get-file-extension/ + extension = extension.toLowerCase(); + switch (extension) { + case 'tga': + loader = tgaLoader; break; - + default: + loader = textureLoader; } - + return loader; } - - return data; - - } - - function parseEffectTechnique(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'constant': - case 'lambert': - case 'blinn': + function buildMaterial(data) { + var effect = getEffect(data.url); + var technique = effect.profile.technique; + var material; + switch (technique.type) { case 'phong': - data.type = child.nodeName; - data.parameters = parseEffectParameters(child); + case 'blinn': + material = new MeshPhongMaterial(); + break; + case 'lambert': + material = new MeshLambertMaterial(); + break; + default: + material = new MeshBasicMaterial(); break; - } + material.name = data.name || ''; + function getTexture(textureObject) { + var colorSpace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var sampler = effect.profile.samplers[textureObject.id]; + var image = null; - } + // get image - return data; + if (sampler !== undefined) { + var surface = effect.profile.surfaces[sampler.source]; + image = getImage(surface.init_from); + } else { + console.warn('THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530).'); + image = getImage(textureObject.id); + } - } + // create texture if image is avaiable + + if (image !== null) { + var loader = getTextureLoader(image); + if (loader !== undefined) { + var texture = loader.load(image); + var extra = textureObject.extra; + if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { + var _technique = extra.technique; + texture.wrapS = _technique.wrapU ? RepeatWrapping : ClampToEdgeWrapping; + texture.wrapT = _technique.wrapV ? RepeatWrapping : ClampToEdgeWrapping; + texture.offset.set(_technique.offsetU || 0, _technique.offsetV || 0); + texture.repeat.set(_technique.repeatU || 1, _technique.repeatV || 1); + } else { + texture.wrapS = RepeatWrapping; + texture.wrapT = RepeatWrapping; + } + if (colorSpace !== null) { + texture.colorSpace = colorSpace; + } + return texture; + } else { + console.warn('THREE.ColladaLoader: Loader for texture %s not found.', image); + return null; + } + } else { + console.warn('THREE.ColladaLoader: Couldn\'t create texture with ID:', textureObject.id); + return null; + } + } + var parameters = technique.parameters; + for (var key in parameters) { + var parameter = parameters[key]; + switch (key) { + case 'diffuse': + if (parameter.color) material.color.fromArray(parameter.color); + if (parameter.texture) material.map = getTexture(parameter.texture, SRGBColorSpace); + break; + case 'specular': + if (parameter.color && material.specular) material.specular.fromArray(parameter.color); + if (parameter.texture) material.specularMap = getTexture(parameter.texture); + break; + case 'bump': + if (parameter.texture) material.normalMap = getTexture(parameter.texture); + break; + case 'ambient': + if (parameter.texture) material.lightMap = getTexture(parameter.texture, SRGBColorSpace); + break; + case 'shininess': + if (parameter["float"] && material.shininess) material.shininess = parameter["float"]; + break; + case 'emission': + if (parameter.color && material.emissive) material.emissive.fromArray(parameter.color); + if (parameter.texture) material.emissiveMap = getTexture(parameter.texture, SRGBColorSpace); + break; + } + } + material.color.convertSRGBToLinear(); + if (material.specular) material.specular.convertSRGBToLinear(); + if (material.emissive) material.emissive.convertSRGBToLinear(); - function parseEffectParameters(xml) { + // - var data = {}; + var transparent = parameters['transparent']; + var transparency = parameters['transparency']; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // does not exist but - var child = xml.childNodes[i]; + if (transparency === undefined && transparent) { + transparency = { + "float": 1 + }; + } - if (child.nodeType !== 1) { continue; } + // does not exist but - switch (child.nodeName) { + if (transparent === undefined && transparency) { + transparent = { + opaque: 'A_ONE', + data: { + color: [1, 1, 1, 1] + } + }; + } + if (transparent && transparency) { + // handle case if a texture exists but no color - case 'emission': - case 'diffuse': - case 'specular': - case 'shininess': - case 'transparent': - case 'transparency': - data[child.nodeName] = parseEffectParameter(child); - break; + if (transparent.data.texture) { + // we do not set an alpha map (see #13792) + material.transparent = true; + } else { + var color = transparent.data.color; + switch (transparent.opaque) { + case 'A_ONE': + material.opacity = color[3] * transparency["float"]; + break; + case 'RGB_ZERO': + material.opacity = 1 - color[0] * transparency["float"]; + break; + case 'A_ZERO': + material.opacity = 1 - color[3] * transparency["float"]; + break; + case 'RGB_ONE': + material.opacity = color[0] * transparency["float"]; + break; + default: + console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.', transparent.opaque); + } + if (material.opacity < 1) material.transparent = true; + } } + // + + if (technique.extra !== undefined && technique.extra.technique !== undefined) { + var techniques = technique.extra.technique; + for (var k in techniques) { + var v = techniques[k]; + switch (k) { + case 'double_sided': + material.side = v === 1 ? DoubleSide : FrontSide; + break; + case 'bump': + material.normalMap = getTexture(v.texture); + material.normalScale = new Vector2(1, 1); + break; + } + } + } + return material; + } + function getMaterial(id) { + return getBuild(library.materials[id], buildMaterial); } - return data; - - } - - function parseEffectParameter(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } + // camera + + function parseCamera(xml) { + var data = { + name: xml.getAttribute('name') + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'optics': + data.optics = parseCameraOptics(child); + break; + } + } + library.cameras[xml.getAttribute('id')] = data; + } + function parseCameraOptics(xml) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'technique_common': + return parseCameraTechnique(child); + } + } + return {}; + } + function parseCameraTechnique(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'perspective': + case 'orthographic': + data.technique = child.nodeName; + data.parameters = parseCameraParameters(child); + break; + } + } + return data; + } + function parseCameraParameters(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'xfov': + case 'yfov': + case 'xmag': + case 'ymag': + case 'znear': + case 'zfar': + case 'aspect_ratio': + data[child.nodeName] = parseFloat(child.textContent); + break; + } + } + return data; + } + function buildCamera(data) { + var camera; + switch (data.optics.technique) { + case 'perspective': + camera = new PerspectiveCamera(data.optics.parameters.yfov, data.optics.parameters.aspect_ratio, data.optics.parameters.znear, data.optics.parameters.zfar); + break; + case 'orthographic': + var ymag = data.optics.parameters.ymag; + var xmag = data.optics.parameters.xmag; + var aspectRatio = data.optics.parameters.aspect_ratio; + xmag = xmag === undefined ? ymag * aspectRatio : xmag; + ymag = ymag === undefined ? xmag / aspectRatio : ymag; + xmag *= 0.5; + ymag *= 0.5; + camera = new OrthographicCamera(-xmag, xmag, ymag, -ymag, + // left, right, top, bottom + data.optics.parameters.znear, data.optics.parameters.zfar); + break; + default: + camera = new PerspectiveCamera(); + break; + } + camera.name = data.name || ''; + return camera; + } + function getCamera(id) { + var data = library.cameras[id]; + if (data !== undefined) { + return getBuild(data, buildCamera); + } + console.warn('THREE.ColladaLoader: Couldn\'t find camera with ID:', id); + return null; + } - switch (child.nodeName) { + // light - case 'color': - data[child.nodeName] = parseFloats(child.textContent); + function parseLight(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + data = parseLightTechnique(child); + break; + } + } + library.lights[xml.getAttribute('id')] = data; + } + function parseLightTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'directional': + case 'point': + case 'spot': + case 'ambient': + data.technique = child.nodeName; + data.parameters = parseLightParameters(child); + } + } + return data; + } + function parseLightParameters(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'color': + var array = parseFloats(child.textContent); + data.color = new Color().fromArray(array).convertSRGBToLinear(); + break; + case 'falloff_angle': + data.falloffAngle = parseFloat(child.textContent); + break; + case 'quadratic_attenuation': + var f = parseFloat(child.textContent); + data.distance = f ? Math.sqrt(1 / f) : 0; + break; + } + } + return data; + } + function buildLight(data) { + var light; + switch (data.technique) { + case 'directional': + light = new DirectionalLight(); break; - - case 'float': - data[child.nodeName] = parseFloat(child.textContent); + case 'point': + light = new PointLight(); break; - - case 'texture': - data[child.nodeName] = { id: child.getAttribute('texture'), extra: parseEffectParameterTexture(child) }; + case 'spot': + light = new SpotLight(); + break; + case 'ambient': + light = new AmbientLight(); break; + } + if (data.parameters.color) light.color.copy(data.parameters.color); + if (data.parameters.distance) light.distance = data.parameters.distance; + return light; + } + function getLight(id) { + var data = library.lights[id]; + if (data !== undefined) { + return getBuild(data, buildLight); + } + console.warn('THREE.ColladaLoader: Couldn\'t find light with ID:', id); + return null; + } + // geometry + + function parseGeometry(xml) { + var data = { + name: xml.getAttribute('name'), + sources: {}, + vertices: {}, + primitives: [] + }; + var mesh = getElementsByTagName(xml, 'mesh')[0]; + + // the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep + if (mesh === undefined) return; + for (var i = 0; i < mesh.childNodes.length; i++) { + var child = mesh.childNodes[i]; + if (child.nodeType !== 1) continue; + var id = child.getAttribute('id'); + switch (child.nodeName) { + case 'source': + data.sources[id] = parseSource(child); + break; + case 'vertices': + // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; + data.vertices = parseGeometryVertices(child); + break; + case 'polygons': + console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); + break; + case 'lines': + case 'linestrips': + case 'polylist': + case 'triangles': + data.primitives.push(parseGeometryPrimitive(child)); + break; + default: + console.log(child); + } + } + library.geometries[xml.getAttribute('id')] = data; + } + function parseSource(xml) { + var data = { + array: [], + stride: 3 + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'float_array': + data.array = parseFloats(child.textContent); + break; + case 'Name_array': + data.array = parseStrings(child.textContent); + break; + case 'technique_common': + var accessor = getElementsByTagName(child, 'accessor')[0]; + if (accessor !== undefined) { + data.stride = parseInt(accessor.getAttribute('stride')); + } + break; + } + } + return data; + } + function parseGeometryVertices(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + } + return data; + } + function parseGeometryPrimitive(xml) { + var primitive = { + type: xml.nodeName, + material: xml.getAttribute('material'), + count: parseInt(xml.getAttribute('count')), + inputs: {}, + stride: 0, + hasUV: false + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var id = parseId(child.getAttribute('source')); + var semantic = child.getAttribute('semantic'); + var offset = parseInt(child.getAttribute('offset')); + var set = parseInt(child.getAttribute('set')); + var inputname = set > 0 ? semantic + set : semantic; + primitive.inputs[inputname] = { + id: id, + offset: offset + }; + primitive.stride = Math.max(primitive.stride, offset + 1); + if (semantic === 'TEXCOORD') primitive.hasUV = true; + break; + case 'vcount': + primitive.vcount = parseInts(child.textContent); + break; + case 'p': + primitive.p = parseInts(child.textContent); + break; + } + } + return primitive; + } + function groupPrimitives(primitives) { + var build = {}; + for (var i = 0; i < primitives.length; i++) { + var primitive = primitives[i]; + if (build[primitive.type] === undefined) build[primitive.type] = []; + build[primitive.type].push(primitive); + } + return build; + } + function checkUVCoordinates(primitives) { + var count = 0; + for (var i = 0, l = primitives.length; i < l; i++) { + var primitive = primitives[i]; + if (primitive.hasUV === true) { + count++; + } + } + if (count > 0 && count < primitives.length) { + primitives.uvsNeedsFix = true; } - } + function buildGeometry(data) { + var build = {}; + var sources = data.sources; + var vertices = data.vertices; + var primitives = data.primitives; + if (primitives.length === 0) return {}; - return data; - - } - - function parseEffectParameterTexture(xml) { + // our goal is to create one buffer geometry for a single type of primitives + // first, we group all primitives by their type - var data = { - technique: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var groupedPrimitives = groupPrimitives(primitives); + for (var type in groupedPrimitives) { + var primitiveType = groupedPrimitives[type]; - var child = xml.childNodes[i]; + // second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines) - if (child.nodeType !== 1) { continue; } + checkUVCoordinates(primitiveType); - switch (child.nodeName) { - - case 'extra': - parseEffectParameterTextureExtra(child, data); - break; + // third, create a buffer geometry for each type of primitives + build[type] = buildGeometryType(primitiveType, sources, vertices); } - + return build; } + function buildGeometryType(primitives, sources, vertices) { + var build = {}; + var position = { + array: [], + stride: 0 + }; + var normal = { + array: [], + stride: 0 + }; + var uv = { + array: [], + stride: 0 + }; + var uv1 = { + array: [], + stride: 0 + }; + var color = { + array: [], + stride: 0 + }; + var skinIndex = { + array: [], + stride: 4 + }; + var skinWeight = { + array: [], + stride: 4 + }; + var geometry = new BufferGeometry(); + var materialKeys = []; + var start = 0; + for (var p = 0; p < primitives.length; p++) { + var primitive = primitives[p]; + var inputs = primitive.inputs; + + // groups + + var _count = 0; + switch (primitive.type) { + case 'lines': + case 'linestrips': + _count = primitive.count * 2; + break; + case 'triangles': + _count = primitive.count * 3; + break; + case 'polylist': + for (var g = 0; g < primitive.count; g++) { + var vc = primitive.vcount[g]; + switch (vc) { + case 3: + _count += 3; // single triangle + break; + case 4: + _count += 6; // quad, subdivided into two triangles + break; + default: + _count += (vc - 2) * 3; // polylist with more than four vertices + break; + } + } + break; + default: + console.warn('THREE.ColladaLoader: Unknow primitive type:', primitive.type); + } + geometry.addGroup(start, _count, p); + start += _count; - return data; - - } - - function parseEffectParameterTextureExtra(xml, data) { - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { + // material - case 'technique': - parseEffectParameterTextureExtraTechnique(child, data); - break; + if (primitive.material) { + materialKeys.push(primitive.material); + } + // geometry data + + for (var name in inputs) { + var input = inputs[name]; + switch (name) { + case 'VERTEX': + for (var key in vertices) { + var id = vertices[key]; + switch (key) { + case 'POSITION': + var prevLength = position.array.length; + buildGeometryData(primitive, sources[id], input.offset, position.array); + position.stride = sources[id].stride; + if (sources.skinWeights && sources.skinIndices) { + buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); + buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + } + + // see #3803 + + if (primitive.hasUV === false && primitives.uvsNeedsFix === true) { + var _count2 = (position.array.length - prevLength) / position.stride; + for (var i = 0; i < _count2; i++) { + // fill missing uv coordinates + + uv.array.push(0, 0); + } + } + break; + case 'NORMAL': + buildGeometryData(primitive, sources[id], input.offset, normal.array); + normal.stride = sources[id].stride; + break; + case 'COLOR': + buildGeometryData(primitive, sources[id], input.offset, color.array); + color.stride = sources[id].stride; + break; + case 'TEXCOORD': + buildGeometryData(primitive, sources[id], input.offset, uv.array); + uv.stride = sources[id].stride; + break; + case 'TEXCOORD1': + buildGeometryData(primitive, sources[id], input.offset, uv1.array); + uv.stride = sources[id].stride; + break; + default: + console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + } + } + break; + case 'NORMAL': + buildGeometryData(primitive, sources[input.id], input.offset, normal.array); + normal.stride = sources[input.id].stride; + break; + case 'COLOR': + buildGeometryData(primitive, sources[input.id], input.offset, color.array, true); + color.stride = sources[input.id].stride; + break; + case 'TEXCOORD': + buildGeometryData(primitive, sources[input.id], input.offset, uv.array); + uv.stride = sources[input.id].stride; + break; + case 'TEXCOORD1': + buildGeometryData(primitive, sources[input.id], input.offset, uv1.array); + uv1.stride = sources[input.id].stride; + break; + } + } } + // build geometry + + if (position.array.length > 0) geometry.setAttribute('position', new Float32BufferAttribute(position.array, position.stride)); + if (normal.array.length > 0) geometry.setAttribute('normal', new Float32BufferAttribute(normal.array, normal.stride)); + if (color.array.length > 0) geometry.setAttribute('color', new Float32BufferAttribute(color.array, color.stride)); + if (uv.array.length > 0) geometry.setAttribute('uv', new Float32BufferAttribute(uv.array, uv.stride)); + if (uv1.array.length > 0) geometry.setAttribute('uv1', new Float32BufferAttribute(uv1.array, uv1.stride)); + if (skinIndex.array.length > 0) geometry.setAttribute('skinIndex', new Float32BufferAttribute(skinIndex.array, skinIndex.stride)); + if (skinWeight.array.length > 0) geometry.setAttribute('skinWeight', new Float32BufferAttribute(skinWeight.array, skinWeight.stride)); + build.data = geometry; + build.type = primitives[0].type; + build.materialKeys = materialKeys; + return build; } - - } - - function parseEffectParameterTextureExtraTechnique(xml, data) { - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'repeatU': - case 'repeatV': - case 'offsetU': - case 'offsetV': - data.technique[child.nodeName] = parseFloat(child.textContent); - break; - - case 'wrapU': - case 'wrapV': - - // some files have values for wrapU/wrapV which become NaN via parseInt - - if (child.textContent.toUpperCase() === 'TRUE') { - - data.technique[child.nodeName] = 1; - - } else if (child.textContent.toUpperCase() === 'FALSE') { - - data.technique[child.nodeName] = 0; - - } else { - - data.technique[child.nodeName] = parseInt(child.textContent); - + function buildGeometryData(primitive, source, offset, array) { + var isColor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + var indices = primitive.p; + var stride = primitive.stride; + var vcount = primitive.vcount; + function pushVector(i) { + var index = indices[i + offset] * sourceStride; + var length = index + sourceStride; + for (; index < length; index++) { + array.push(sourceArray[index]); + } + if (isColor) { + // convert the vertex colors from srgb to linear if present + var startIndex = array.length - sourceStride - 1; + tempColor.setRGB(array[startIndex + 0], array[startIndex + 1], array[startIndex + 2]).convertSRGBToLinear(); + array[startIndex + 0] = tempColor.r; + array[startIndex + 1] = tempColor.g; + array[startIndex + 2] = tempColor.b; + } + } + var sourceArray = source.array; + var sourceStride = source.stride; + if (primitive.vcount !== undefined) { + var index = 0; + for (var i = 0, l = vcount.length; i < l; i++) { + var _count3 = vcount[i]; + if (_count3 === 4) { + var a = index + stride * 0; + var b = index + stride * 1; + var c = index + stride * 2; + var d = index + stride * 3; + pushVector(a); + pushVector(b); + pushVector(d); + pushVector(b); + pushVector(c); + pushVector(d); + } else if (_count3 === 3) { + var _a = index + stride * 0; + var _b = index + stride * 1; + var _c = index + stride * 2; + pushVector(_a); + pushVector(_b); + pushVector(_c); + } else if (_count3 > 4) { + for (var k = 1, kl = _count3 - 2; k <= kl; k++) { + var _a2 = index + stride * 0; + var _b2 = index + stride * k; + var _c2 = index + stride * (k + 1); + pushVector(_a2); + pushVector(_b2); + pushVector(_c2); + } } - - break; - + index += stride * _count3; + } + } else { + for (var _i = 0, _l = indices.length; _i < _l; _i += stride) { + pushVector(_i); + } } - + } + function getGeometry(id) { + return getBuild(library.geometries[id], buildGeometry); } - } - - function buildEffect(data) { - - return data; - - } - - function getEffect(id) { - - return getBuild(library.effects[id], buildEffect); - - } - - // material - - function parseMaterial(xml) { - - var data = { - name: xml.getAttribute('name') - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'instance_effect': - data.url = parseId(child.getAttribute('url')); - break; - + // kinematics + + function parseKinematicsModel(xml) { + var data = { + name: xml.getAttribute('name') || '', + joints: {}, + links: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + parseKinematicsTechniqueCommon(child, data); + break; + } } - + library.kinematicsModels[xml.getAttribute('id')] = data; } - - library.materials[xml.getAttribute('id')] = data; - - } - - function buildMaterial(data) { - - var effect = getEffect(data.url); - var technique = effect.profile.technique; - - var material; - - switch (technique.type) { - - case 'phong': - case 'blinn': - material = new THREE.MeshPhongMaterial(); - break; - - case 'lambert': - material = new THREE.MeshLambertMaterial(); - break; - - default: - material = new THREE.MeshBasicMaterial(); - break; - + function buildKinematicsModel(data) { + if (data.build !== undefined) return data.build; + return data; } - - material.name = data.name; - - function getTexture(textureObject) { - - var sampler = effect.profile.samplers[textureObject.id]; - - if (sampler !== undefined) { - - var surface = effect.profile.surfaces[sampler.source]; - - var texture = textureLoader.load(getImage(surface.init_from)); - - var extra = textureObject.extra; - - if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { - - var technique = extra.technique; - - texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; - texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; - - texture.offset.set(technique.offsetU || 0, technique.offsetV || 0); - texture.repeat.set(technique.repeatU || 1, technique.repeatV || 1); - - } else { - - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; - + function getKinematicsModel(id) { + return getBuild(library.kinematicsModels[id], buildKinematicsModel); + } + function parseKinematicsTechniqueCommon(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'joint': + data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); + break; + case 'link': + data.links.push(parseKinematicsLink(child)); + break; } - - return texture; - } - - console.error('THREE.ColladaLoader: Undefined sampler', textureObject.id); - - return null; - } + function parseKinematicsJoint(xml) { + var data; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'prismatic': + case 'revolute': + data = parseKinematicsJointParameter(child); + break; + } + } + return data; + } + function parseKinematicsJointParameter(xml) { + var data = { + sid: xml.getAttribute('sid'), + name: xml.getAttribute('name') || '', + axis: new Vector3(), + limits: { + min: 0, + max: 0 + }, + type: xml.nodeName, + "static": false, + zeroPosition: 0, + middlePosition: 0 + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'axis': + var array = parseFloats(child.textContent); + data.axis.fromArray(array); + break; + case 'limits': + var max = child.getElementsByTagName('max')[0]; + var min = child.getElementsByTagName('min')[0]; + data.limits.max = parseFloat(max.textContent); + data.limits.min = parseFloat(min.textContent); + break; + } + } - var parameters = technique.parameters; - - for (var key in parameters) { + // if min is equal to or greater than max, consider the joint static - var parameter = parameters[key]; + if (data.limits.min >= data.limits.max) { + data["static"] = true; + } - switch (key) { + // calculate middle position - case 'diffuse': - if (parameter.color) { material.color.fromArray(parameter.color); } - if (parameter.texture) { material.map = getTexture(parameter.texture); } - break; - case 'specular': - if (parameter.color && material.specular) { material.specular.fromArray(parameter.color); } - if (parameter.texture) { material.specularMap = getTexture(parameter.texture); } - break; - case 'shininess': - if (parameter.float && material.shininess) - { material.shininess = parameter.float; } - break; - case 'emission': - if (parameter.color && material.emissive) - { material.emissive.fromArray(parameter.color); } + data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + return data; + } + function parseKinematicsLink(xml) { + var data = { + sid: xml.getAttribute('sid'), + name: xml.getAttribute('name') || '', + attachments: [], + transforms: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'attachment_full': + data.attachments.push(parseKinematicsAttachment(child)); + break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push(parseKinematicsTransform(child)); + break; + } + } + return data; + } + function parseKinematicsAttachment(xml) { + var data = { + joint: xml.getAttribute('joint').split('/').pop(), + transforms: [], + links: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'link': + data.links.push(parseKinematicsLink(child)); + break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push(parseKinematicsTransform(child)); + break; + } + } + return data; + } + function parseKinematicsTransform(xml) { + var data = { + type: xml.nodeName + }; + var array = parseFloats(xml.textContent); + switch (data.type) { + case 'matrix': + data.obj = new Matrix4(); + data.obj.fromArray(array).transpose(); break; - case 'transparent': - // if ( parameter.texture ) material.alphaMap = getTexture( parameter.texture ); - material.transparent = true; + case 'translate': + data.obj = new Vector3(); + data.obj.fromArray(array); break; - case 'transparency': - if (parameter.float !== undefined) { material.opacity = parameter.float; } - material.transparent = true; + case 'rotate': + data.obj = new Vector3(); + data.obj.fromArray(array); + data.angle = MathUtils.degToRad(array[3]); break; - } - + return data; } - return material; - - } - - function getMaterial(id) { + // physics + + function parsePhysicsModel(xml) { + var data = { + name: xml.getAttribute('name') || '', + rigidBodies: {} + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'rigid_body': + data.rigidBodies[child.getAttribute('name')] = {}; + parsePhysicsRigidBody(child, data.rigidBodies[child.getAttribute('name')]); + break; + } + } + library.physicsModels[xml.getAttribute('id')] = data; + } + function parsePhysicsRigidBody(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + parsePhysicsTechniqueCommon(child, data); + break; + } + } + } + function parsePhysicsTechniqueCommon(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'inertia': + data.inertia = parseFloats(child.textContent); + break; + case 'mass': + data.mass = parseFloats(child.textContent)[0]; + break; + } + } + } - return getBuild(library.materials[id], buildMaterial); + // scene + + function parseKinematicsScene(xml) { + var data = { + bindJointAxis: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'bind_joint_axis': + data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); + break; + } + } + library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + } + function parseKinematicsBindJointAxis(xml) { + var data = { + target: xml.getAttribute('target').split('/').pop() + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'axis': + var param = child.getElementsByTagName('param')[0]; + data.axis = param.textContent; + var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; + data.jointIndex = tmpJointIndex.substring(0, tmpJointIndex.length - 1); + break; + } + } + return data; + } + function buildKinematicsScene(data) { + if (data.build !== undefined) return data.build; + return data; + } + function getKinematicsScene(id) { + return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + } + function setupKinematics() { + var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; + var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; + var visualSceneId = Object.keys(library.visualScenes)[0]; + if (kinematicsModelId === undefined || kinematicsSceneId === undefined) return; + var kinematicsModel = getKinematicsModel(kinematicsModelId); + var kinematicsScene = getKinematicsScene(kinematicsSceneId); + var visualScene = getVisualScene(visualSceneId); + var bindJointAxis = kinematicsScene.bindJointAxis; + var jointMap = {}; + for (var i = 0, l = bindJointAxis.length; i < l; i++) { + var axis = bindJointAxis[i]; + + // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' + + var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); + if (targetElement) { + // get the parent of the transform element + + var parentVisualElement = targetElement.parentElement; + + // connect the joint of the kinematics model with the element in the visual scene + + connect(axis.jointIndex, parentVisualElement); + } + } + function connect(jointIndex, visualElement) { + var visualElementName = visualElement.getAttribute('name'); + var joint = kinematicsModel.joints[jointIndex]; + visualScene.traverse(function (object) { + if (object.name === visualElementName) { + jointMap[jointIndex] = { + object: object, + transforms: buildTransformList(visualElement), + joint: joint, + position: joint.zeroPosition + }; + } + }); + } + var m0 = new Matrix4(); + kinematics = { + joints: kinematicsModel && kinematicsModel.joints, + getJointValue: function getJointValue(jointIndex) { + var jointData = jointMap[jointIndex]; + if (jointData) { + return jointData.position; + } else { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); + } + }, + setJointValue: function setJointValue(jointIndex, value) { + var jointData = jointMap[jointIndex]; + if (jointData) { + var joint = jointData.joint; + if (value > joint.limits.max || value < joint.limits.min) { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + } else if (joint["static"]) { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + } else { + var object = jointData.object; + var _axis = joint.axis; + var transforms = jointData.transforms; + matrix.identity(); + + // each update, we have to apply all transforms in the correct order + + for (var _i2 = 0; _i2 < transforms.length; _i2++) { + var transform = transforms[_i2]; + + // if there is a connection of the transform node with a joint, apply the joint value + + if (transform.sid && transform.sid.indexOf(jointIndex) !== -1) { + switch (joint.type) { + case 'revolute': + matrix.multiply(m0.makeRotationAxis(_axis, MathUtils.degToRad(value))); + break; + case 'prismatic': + matrix.multiply(m0.makeTranslation(_axis.x * value, _axis.y * value, _axis.z * value)); + break; + default: + console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); + break; + } + } else { + switch (transform.type) { + case 'matrix': + matrix.multiply(transform.obj); + break; + case 'translate': + matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); + break; + case 'scale': + matrix.scale(transform.obj); + break; + case 'rotate': + matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); + break; + } + } + } + object.matrix.copy(matrix); + object.matrix.decompose(object.position, object.quaternion, object.scale); + jointMap[jointIndex].position = value; + } + } else { + console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + } + } + }; + } + function buildTransformList(node) { + var transforms = []; + var xml = collada.querySelector('[id="' + node.id + '"]'); + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var array = void 0, + _vector = void 0; + switch (child.nodeName) { + case 'matrix': + array = parseFloats(child.textContent); + var _matrix = new Matrix4().fromArray(array).transpose(); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _matrix + }); + break; + case 'translate': + case 'scale': + array = parseFloats(child.textContent); + _vector = new Vector3().fromArray(array); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _vector + }); + break; + case 'rotate': + array = parseFloats(child.textContent); + _vector = new Vector3().fromArray(array); + var angle = MathUtils.degToRad(array[3]); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _vector, + angle: angle + }); + break; + } + } + return transforms; + } - } + // nodes - // camera + function prepareNodes(xml) { + var elements = xml.getElementsByTagName('node'); - function parseCamera(xml) { + // ensure all node elements have id attributes - var data = { - name: xml.getAttribute('name') - }; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (element.hasAttribute('id') === false) { + element.setAttribute('id', generateId()); + } + } + } + var matrix = new Matrix4(); + var vector = new Vector3(); + function parseNode(xml) { + var data = { + name: xml.getAttribute('name') || '', + type: xml.getAttribute('type'), + id: xml.getAttribute('id'), + sid: xml.getAttribute('sid'), + matrix: new Matrix4(), + nodes: [], + instanceCameras: [], + instanceControllers: [], + instanceLights: [], + instanceGeometries: [], + instanceNodes: [], + transforms: {} + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var array = void 0; + switch (child.nodeName) { + case 'node': + data.nodes.push(child.getAttribute('id')); + parseNode(child); + break; + case 'instance_camera': + data.instanceCameras.push(parseId(child.getAttribute('url'))); + break; + case 'instance_controller': + data.instanceControllers.push(parseNodeInstance(child)); + break; + case 'instance_light': + data.instanceLights.push(parseId(child.getAttribute('url'))); + break; + case 'instance_geometry': + data.instanceGeometries.push(parseNodeInstance(child)); + break; + case 'instance_node': + data.instanceNodes.push(parseId(child.getAttribute('url'))); + break; + case 'matrix': + array = parseFloats(child.textContent); + data.matrix.multiply(matrix.fromArray(array).transpose()); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'translate': + array = parseFloats(child.textContent); + vector.fromArray(array); + data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'rotate': + array = parseFloats(child.textContent); + var angle = MathUtils.degToRad(array[3]); + data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'scale': + array = parseFloats(child.textContent); + data.matrix.scale(vector.fromArray(array)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'extra': + break; + default: + console.log(child); + } + } + if (hasNode(data.id)) { + console.warn('THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id); + } else { + library.nodes[data.id] = data; + } + return data; + } + function parseNodeInstance(xml) { + var data = { + id: parseId(xml.getAttribute('url')), + materials: {}, + skeletons: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'bind_material': + var instances = child.getElementsByTagName('instance_material'); + for (var j = 0; j < instances.length; j++) { + var instance = instances[j]; + var symbol = instance.getAttribute('symbol'); + var target = instance.getAttribute('target'); + data.materials[symbol] = parseId(target); + } + break; + case 'skeleton': + data.skeletons.push(parseId(child.textContent)); + break; + } + } + return data; + } + function buildSkeleton(skeletons, joints) { + var boneData = []; + var sortedBoneData = []; + var i, j, data; + + // a skeleton can have multiple root bones. collada expresses this + // situtation with multiple "skeleton" tags per controller instance + + for (i = 0; i < skeletons.length; i++) { + var skeleton = skeletons[i]; + var root = void 0; + if (hasNode(skeleton)) { + root = getNode(skeleton); + buildBoneHierarchy(root, joints, boneData); + } else if (hasVisualScene(skeleton)) { + // handle case where the skeleton refers to the visual scene (#13335) + + var visualScene = library.visualScenes[skeleton]; + var children = visualScene.children; + for (var _j = 0; _j < children.length; _j++) { + var child = children[_j]; + if (child.type === 'JOINT') { + var _root = getNode(child.id); + buildBoneHierarchy(_root, joints, boneData); + } + } + } else { + console.error('THREE.ColladaLoader: Unable to find root bone of skeleton with ID:', skeleton); + } + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // sort bone data (the order is defined in the corresponding controller) - var child = xml.childNodes[i]; + for (i = 0; i < joints.length; i++) { + for (j = 0; j < boneData.length; j++) { + data = boneData[j]; + if (data.bone.name === joints[i].name) { + sortedBoneData[i] = data; + data.processed = true; + break; + } + } + } - if (child.nodeType !== 1) { continue; } + // add unprocessed bone data at the end of the list - switch (child.nodeName) { + for (i = 0; i < boneData.length; i++) { + data = boneData[i]; + if (data.processed === false) { + sortedBoneData.push(data); + data.processed = true; + } + } - case 'optics': - data.optics = parseCameraOptics(child); - break; + // setup arrays for skeleton creation + var bones = []; + var boneInverses = []; + for (i = 0; i < sortedBoneData.length; i++) { + data = sortedBoneData[i]; + bones.push(data.bone); + boneInverses.push(data.boneInverse); } - + return new Skeleton(bones, boneInverses); } + function buildBoneHierarchy(root, joints, boneData) { + // setup bone data from visual scene - library.cameras[xml.getAttribute('id')] = data; - - } - - function parseCameraOptics(xml) { + root.traverse(function (object) { + if (object.isBone === true) { + var boneInverse; - for (var i = 0; i < xml.childNodes.length; i++) { + // retrieve the boneInverse from the controller data - var child = xml.childNodes[i]; + for (var i = 0; i < joints.length; i++) { + var joint = joints[i]; + if (joint.name === object.name) { + boneInverse = joint.boneInverse; + break; + } + } + if (boneInverse === undefined) { + // Unfortunately, there can be joints in the visual scene that are not part of the + // corresponding controller. In this case, we have to create a dummy boneInverse matrix + // for the respective bone. This bone won't affect any vertices, because there are no skin indices + // and weights defined for it. But we still have to add the bone to the sorted bone list in order to + // ensure a correct animation of the model. + + boneInverse = new Matrix4(); + } + boneData.push({ + bone: object, + boneInverse: boneInverse, + processed: false + }); + } + }); + } + function buildNode(data) { + var objects = []; + var matrix = data.matrix; + var nodes = data.nodes; + var type = data.type; + var instanceCameras = data.instanceCameras; + var instanceControllers = data.instanceControllers; + var instanceLights = data.instanceLights; + var instanceGeometries = data.instanceGeometries; + var instanceNodes = data.instanceNodes; + + // nodes + + for (var i = 0, l = nodes.length; i < l; i++) { + objects.push(getNode(nodes[i])); + } - switch (child.nodeName) { + // instance cameras - case 'technique_common': - return parseCameraTechnique(child); + for (var _i3 = 0, _l2 = instanceCameras.length; _i3 < _l2; _i3++) { + var instanceCamera = getCamera(instanceCameras[_i3]); + if (instanceCamera !== null) { + objects.push(instanceCamera.clone()); + } + } + // instance controllers + + for (var _i4 = 0, _l3 = instanceControllers.length; _i4 < _l3; _i4++) { + var instance = instanceControllers[_i4]; + var controller = getController(instance.id); + var geometries = getGeometry(controller.id); + var newObjects = buildObjects(geometries, instance.materials); + var skeletons = instance.skeletons; + var joints = controller.skin.joints; + var skeleton = buildSkeleton(skeletons, joints); + for (var j = 0, jl = newObjects.length; j < jl; j++) { + var _object = newObjects[j]; + if (_object.isSkinnedMesh) { + _object.bind(skeleton, controller.skin.bindMatrix); + _object.normalizeSkinWeights(); + } + objects.push(_object); + } } - } + // instance lights - return {}; + for (var _i5 = 0, _l4 = instanceLights.length; _i5 < _l4; _i5++) { + var instanceLight = getLight(instanceLights[_i5]); + if (instanceLight !== null) { + objects.push(instanceLight.clone()); + } + } - } + // instance geometries - function parseCameraTechnique(xml) { + for (var _i6 = 0, _l5 = instanceGeometries.length; _i6 < _l5; _i6++) { + var _instance = instanceGeometries[_i6]; - var data = {}; + // a single geometry instance in collada can lead to multiple object3Ds. + // this is the case when primitives are combined like triangles and lines - for (var i = 0; i < xml.childNodes.length; i++) { + var _geometries = getGeometry(_instance.id); + var _newObjects = buildObjects(_geometries, _instance.materials); + for (var _j2 = 0, _jl = _newObjects.length; _j2 < _jl; _j2++) { + objects.push(_newObjects[_j2]); + } + } - var child = xml.childNodes[i]; + // instance nodes - switch (child.nodeName) { + for (var _i7 = 0, _l6 = instanceNodes.length; _i7 < _l6; _i7++) { + objects.push(getNode(instanceNodes[_i7]).clone()); + } + var object; + if (nodes.length === 0 && objects.length === 1) { + object = objects[0]; + } else { + object = type === 'JOINT' ? new Bone() : new Group(); + for (var _i8 = 0; _i8 < objects.length; _i8++) { + object.add(objects[_i8]); + } + } + object.name = type === 'JOINT' ? data.sid : data.name; + object.matrix.copy(matrix); + object.matrix.decompose(object.position, object.quaternion, object.scale); + return object; + } + var fallbackMaterial = new MeshBasicMaterial({ + name: Loader.DEFAULT_MATERIAL_NAME, + color: 0xff00ff + }); + function resolveMaterialBinding(keys, instanceMaterials) { + var materials = []; + for (var i = 0, l = keys.length; i < l; i++) { + var id = instanceMaterials[keys[i]]; + if (id === undefined) { + console.warn('THREE.ColladaLoader: Material with key %s not found. Apply fallback material.', keys[i]); + materials.push(fallbackMaterial); + } else { + materials.push(getMaterial(id)); + } + } + return materials; + } + function buildObjects(geometries, instanceMaterials) { + var objects = []; + for (var type in geometries) { + var geometry = geometries[type]; + var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); - case 'perspective': - case 'orthographic': + // handle case if no materials are defined - data.technique = child.nodeName; - data.parameters = parseCameraParameters(child); + if (materials.length === 0) { + if (type === 'lines' || type === 'linestrips') { + materials.push(new LineBasicMaterial()); + } else { + materials.push(new MeshPhongMaterial()); + } + } - break; + // Collada allows to use phong and lambert materials with lines. Replacing these cases with LineBasicMaterial. - } + if (type === 'lines' || type === 'linestrips') { + for (var i = 0, l = materials.length; i < l; i++) { + var _material = materials[i]; + if (_material.isMeshPhongMaterial === true || _material.isMeshLambertMaterial === true) { + var lineMaterial = new LineBasicMaterial(); - } + // copy compatible properties - return data; + lineMaterial.color.copy(_material.color); + lineMaterial.opacity = _material.opacity; + lineMaterial.transparent = _material.transparent; - } + // replace material - function parseCameraParameters(xml) { + materials[i] = lineMaterial; + } + } + } - var data = {}; + // regard skinning - for (var i = 0; i < xml.childNodes.length; i++) { + var skinning = geometry.data.attributes.skinIndex !== undefined; - var child = xml.childNodes[i]; + // choose between a single or multi materials (material array) - switch (child.nodeName) { + var material = materials.length === 1 ? materials[0] : materials; - case 'xfov': - case 'yfov': - case 'xmag': - case 'ymag': - case 'znear': - case 'zfar': - case 'aspect_ratio': - data[child.nodeName] = parseFloat(child.textContent); - break; + // now create a specific 3D object + var object = void 0; + switch (type) { + case 'lines': + object = new LineSegments(geometry.data, material); + break; + case 'linestrips': + object = new Line(geometry.data, material); + break; + case 'triangles': + case 'polylist': + if (skinning) { + object = new SkinnedMesh(geometry.data, material); + } else { + object = new Mesh(geometry.data, material); + } + break; + } + objects.push(object); } - + return objects; + } + function hasNode(id) { + return library.nodes[id] !== undefined; + } + function getNode(id) { + return getBuild(library.nodes[id], buildNode); } - return data; - - } - - function buildCamera(data) { + // visual scenes - var camera; + function parseVisualScene(xml) { + var data = { + name: xml.getAttribute('name'), + children: [] + }; + prepareNodes(xml); + var elements = getElementsByTagName(xml, 'node'); + for (var i = 0; i < elements.length; i++) { + data.children.push(parseNode(elements[i])); + } + library.visualScenes[xml.getAttribute('id')] = data; + } + function buildVisualScene(data) { + var group = new Group(); + group.name = data.name; + var children = data.children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + group.add(getNode(child.id)); + } + return group; + } + function hasVisualScene(id) { + return library.visualScenes[id] !== undefined; + } + function getVisualScene(id) { + return getBuild(library.visualScenes[id], buildVisualScene); + } - switch (data.optics.technique) { + // scenes - case 'perspective': - camera = new THREE.PerspectiveCamera( - data.optics.parameters.yfov, - data.optics.parameters.aspect_ratio, - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + function parseScene(xml) { + var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; + return getVisualScene(parseId(instance.getAttribute('url'))); + } + function setupAnimations() { + var clips = library.clips; + if (isEmpty(clips) === true) { + if (isEmpty(library.animations) === false) { + // if there are animations but no clips, we create a default clip for playback + + var tracks = []; + for (var id in library.animations) { + var animationTracks = getAnimation(id); + for (var i = 0, l = animationTracks.length; i < l; i++) { + tracks.push(animationTracks[i]); + } + } + animations.push(new AnimationClip('default', -1, tracks)); + } + } else { + for (var _id in clips) { + animations.push(getAnimationClip(_id)); + } + } + } - case 'orthographic': - var ymag = data.optics.parameters.ymag; - var xmag = data.optics.parameters.xmag; - var aspectRatio = data.optics.parameters.aspect_ratio; + // convert the parser error element into text with each child elements text + // separated by new lines. - xmag = (xmag === undefined) ? (ymag * aspectRatio) : xmag; - ymag = (ymag === undefined) ? (xmag / aspectRatio) : ymag; + function parserErrorToText(parserError) { + var result = ''; + var stack = [parserError]; + while (stack.length) { + var node = stack.shift(); + if (node.nodeType === Node.TEXT_NODE) { + result += node.textContent; + } else { + result += '\n'; + stack.push.apply(stack, node.childNodes); + } + } + return result.trim(); + } + if (text.length === 0) { + return { + scene: new Scene() + }; + } + var xml = new DOMParser().parseFromString(text, 'application/xml'); + var collada = getElementsByTagName(xml, 'COLLADA')[0]; + var parserError = xml.getElementsByTagName('parsererror')[0]; + if (parserError !== undefined) { + // Chrome will return parser error with a div in it + + var errorElement = getElementsByTagName(parserError, 'div')[0]; + var errorText; + if (errorElement) { + errorText = errorElement.textContent; + } else { + errorText = parserErrorToText(parserError); + } + console.error('THREE.ColladaLoader: Failed to parse collada file.\n', errorText); + return null; + } - xmag *= 0.5; - ymag *= 0.5; + // metadata + + var version = collada.getAttribute('version'); + console.debug('THREE.ColladaLoader: File version', version); + var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); + var textureLoader = new TextureLoader(this.manager); + textureLoader.setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin); + var tgaLoader; + if (TGALoader) { + tgaLoader = new TGALoader(this.manager); + tgaLoader.setPath(this.resourcePath || path); + } - camera = new THREE.OrthographicCamera( - - xmag, xmag, ymag, - ymag, // left, right, top, bottom - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + // - default: - camera = new THREE.PerspectiveCamera(); - break; + var tempColor = new Color(); + var animations = []; + var kinematics = {}; + var count = 0; - } + // - camera.name = data.name; + var library = { + animations: {}, + clips: {}, + controllers: {}, + images: {}, + effects: {}, + materials: {}, + cameras: {}, + lights: {}, + geometries: {}, + nodes: {}, + visualScenes: {}, + kinematicsModels: {}, + physicsModels: {}, + kinematicsScenes: {} + }; + parseLibrary(collada, 'library_animations', 'animation', parseAnimation); + parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); + parseLibrary(collada, 'library_controllers', 'controller', parseController); + parseLibrary(collada, 'library_images', 'image', parseImage); + parseLibrary(collada, 'library_effects', 'effect', parseEffect); + parseLibrary(collada, 'library_materials', 'material', parseMaterial); + parseLibrary(collada, 'library_cameras', 'camera', parseCamera); + parseLibrary(collada, 'library_lights', 'light', parseLight); + parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); + parseLibrary(collada, 'library_nodes', 'node', parseNode); + parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); + parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); + parseLibrary(collada, 'library_physics_models', 'physics_model', parsePhysicsModel); + parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + buildLibrary(library.animations, buildAnimation); + buildLibrary(library.clips, buildAnimationClip); + buildLibrary(library.controllers, buildController); + buildLibrary(library.images, buildImage); + buildLibrary(library.effects, buildEffect); + buildLibrary(library.materials, buildMaterial); + buildLibrary(library.cameras, buildCamera); + buildLibrary(library.lights, buildLight); + buildLibrary(library.geometries, buildGeometry); + buildLibrary(library.visualScenes, buildVisualScene); + setupAnimations(); + setupKinematics(); + var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + scene.animations = animations; + + // if ( asset.upAxis === 'Z_UP' ) { + + // console.warn( 'THREE.ColladaLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted, see #24289.' ); + // scene.rotation.set( - Math.PI / 2, 0, 0 ); + + // } + + scene.scale.multiplyScalar(asset.unit); + return { + get animations() { + console.warn('THREE.ColladaLoader: Please access animations over scene.animations now.'); + return animations; + }, + kinematics: kinematics, + library: library, + scene: scene + }; + } + }]); +}(Loader); - return camera; +// o object_name | g group_name +const _object_pattern = /^[og]\s*(.+)?/; +// mtllib file_reference +const _material_library_pattern = /^mtllib /; +// usemtl material_name +const _material_use_pattern = /^usemtl /; +// usemap map_name +const _map_use_pattern = /^usemap /; +const _face_vertex_data_separator_pattern = /\s+/; - } +const _vA = new Vector3(); +const _vB = new Vector3(); +const _vC = new Vector3(); - function getCamera(id) { - var data = library.cameras[id]; - if (data !== undefined) { - return getBuild(data, buildCamera); - } - return null; - } +const _ab = new Vector3(); +const _cb = new Vector3(); - // light +const _color = new Color(); - function parseLight(xml) { +function ParserState() { - var data = {}; + const state = { + objects: [], + object: {}, - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + vertices: [], + normals: [], + colors: [], + uvs: [], - var child = xml.childNodes[i]; + materials: {}, + materialLibraries: [], - if (child.nodeType !== 1) { continue; } + startObject: function ( name, fromDeclaration ) { - switch (child.nodeName) { + // If the current object (initial from reset) is not from a g/o declaration in the parsed + // file. We need to use it for the first parsed g/o to keep things in sync. + if ( this.object && this.object.fromDeclaration === false ) { - case 'technique_common': - data = parseLightTechnique(child); - break; + this.object.name = name; + this.object.fromDeclaration = ( fromDeclaration !== false ); + return; - } + } - } + const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); - library.lights[xml.getAttribute('id')] = data; + if ( this.object && typeof this.object._finalize === 'function' ) { - } + this.object._finalize( true ); - function parseLightTechnique(xml) { + } - var data = {}; + this.object = { + name: name || '', + fromDeclaration: ( fromDeclaration !== false ), - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + geometry: { + vertices: [], + normals: [], + colors: [], + uvs: [], + hasUVIndices: false + }, + materials: [], + smooth: true, - var child = xml.childNodes[i]; + startMaterial: function ( name, libraries ) { - if (child.nodeType !== 1) { continue; } + const previous = this._finalize( false ); - switch (child.nodeName) { + // New usemtl declaration overwrites an inherited material, except if faces were declared + // after the material, then it must be preserved for proper MultiMaterial continuation. + if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { - case 'directional': - case 'point': - case 'spot': - case 'ambient': + this.materials.splice( previous.index, 1 ); - data.technique = child.nodeName; - data.parameters = parseLightParameters(child); + } - } + const material = { + index: this.materials.length, + name: name || '', + mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), + smooth: ( previous !== undefined ? previous.smooth : this.smooth ), + groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), + groupEnd: - 1, + groupCount: - 1, + inherited: false, + + clone: function ( index ) { + + const cloned = { + index: ( typeof index === 'number' ? index : this.index ), + name: this.name, + mtllib: this.mtllib, + smooth: this.smooth, + groupStart: 0, + groupEnd: - 1, + groupCount: - 1, + inherited: false + }; + cloned.clone = this.clone.bind( cloned ); + return cloned; - } + } + }; - return data; + this.materials.push( material ); - } + return material; - function parseLightParameters(xml) { + }, - var data = {}; + currentMaterial: function () { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + if ( this.materials.length > 0 ) { - var child = xml.childNodes[i]; + return this.materials[ this.materials.length - 1 ]; - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + return undefined; - case 'color': - var array = parseFloats(child.textContent); - data.color = new THREE.Color().fromArray(array); - break; + }, - case 'falloff_angle': - data.falloffAngle = parseFloat(child.textContent); - break; + _finalize: function ( end ) { - case 'quadratic_attenuation': - var f = parseFloat(child.textContent); - data.distance = f ? Math.sqrt(1 / f) : 0; - break; + const lastMultiMaterial = this.currentMaterial(); + if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { - } + lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; + lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; + lastMultiMaterial.inherited = false; - } + } - return data; + // Ignore objects tail materials if no face declarations followed them before a new o/g started. + if ( end && this.materials.length > 1 ) { - } + for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) { - function buildLight(data) { + if ( this.materials[ mi ].groupCount <= 0 ) { - var light; + this.materials.splice( mi, 1 ); - switch (data.technique) { + } - case 'directional': - light = new THREE.DirectionalLight(); - break; + } - case 'point': - light = new THREE.PointLight(); - break; + } - case 'spot': - light = new THREE.SpotLight(); - break; + // Guarantee at least one empty material, this makes the creation later more straight forward. + if ( end && this.materials.length === 0 ) { - case 'ambient': - light = new THREE.AmbientLight(); - break; + this.materials.push( { + name: '', + smooth: this.smooth + } ); - } + } - if (data.parameters.color) { light.color.copy(data.parameters.color); } - if (data.parameters.distance) { light.distance = data.parameters.distance; } + return lastMultiMaterial; - return light; + } + }; - } + // Inherit previous objects material. + // Spec tells us that a declared material must be set to all objects until a new material is declared. + // If a usemtl declaration is encountered while this new object is being parsed, it will + // overwrite the inherited material. Exception being that there was already face declarations + // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - // geometry + if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - function parseGeometry(xml) { + const declared = previousMaterial.clone( 0 ); + declared.inherited = true; + this.object.materials.push( declared ); - var data = { - name: xml.getAttribute('name'), - sources: {}, - vertices: {}, - primitives: [] - }; + } - var mesh = getElementsByTagName(xml, 'mesh')[0]; + this.objects.push( this.object ); - for (var i = 0; i < mesh.childNodes.length; i++) { + }, - var child = mesh.childNodes[i]; + finalize: function () { - if (child.nodeType !== 1) { continue; } + if ( this.object && typeof this.object._finalize === 'function' ) { - var id = child.getAttribute('id'); + this.object._finalize( true ); - switch (child.nodeName) { + } - case 'source': - data.sources[id] = parseSource(child); - break; + }, - case 'vertices': - // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; - data.vertices = parseGeometryVertices(child); - break; + parseVertexIndex: function ( value, len ) { - case 'polygons': - console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); - break; + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - case 'lines': - case 'linestrips': - case 'polylist': - case 'triangles': - data.primitives.push(parseGeometryPrimitive(child)); - break; + }, - default: - console.log(child); + parseNormalIndex: function ( value, len ) { - } + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - } + }, - library.geometries[xml.getAttribute('id')] = data; + parseUVIndex: function ( value, len ) { - } + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; - function parseSource(xml) { + }, - var data = { - array: [], - stride: 3 - }; + addVertex: function ( a, b, c ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const src = this.vertices; + const dst = this.object.geometry.vertices; - var child = xml.childNodes[i]; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - if (child.nodeType !== 1) { continue; } + }, - switch (child.nodeName) { + addVertexPoint: function ( a ) { - case 'float_array': - data.array = parseFloats(child.textContent); - break; + const src = this.vertices; + const dst = this.object.geometry.vertices; - case 'Name_array': - data.array = parseStrings(child.textContent); - break; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - case 'technique_common': - var accessor = getElementsByTagName(child, 'accessor')[0]; + }, - if (accessor !== undefined) { + addVertexLine: function ( a ) { - data.stride = parseInt(accessor.getAttribute('stride')); + const src = this.vertices; + const dst = this.object.geometry.vertices; - } - break; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - } + }, - } + addNormal: function ( a, b, c ) { - return data; + const src = this.normals; + const dst = this.object.geometry.normals; - } + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - function parseGeometryVertices(xml) { + }, - var data = {}; + addFaceNormal: function ( a, b, c ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const src = this.vertices; + const dst = this.object.geometry.normals; - var child = xml.childNodes[i]; + _vA.fromArray( src, a ); + _vB.fromArray( src, b ); + _vC.fromArray( src, c ); - if (child.nodeType !== 1) { continue; } + _cb.subVectors( _vC, _vB ); + _ab.subVectors( _vA, _vB ); + _cb.cross( _ab ); - data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + _cb.normalize(); - } + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); - return data; + }, - } + addColor: function ( a, b, c ) { - function parseGeometryPrimitive(xml) { + const src = this.colors; + const dst = this.object.geometry.colors; - var primitive = { - type: xml.nodeName, - material: xml.getAttribute('material'), - count: parseInt(xml.getAttribute('count')), - inputs: {}, - stride: 0 - }; + if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + }, - var child = xml.childNodes[i]; + addUV: function ( a, b, c ) { - if (child.nodeType !== 1) { continue; } + const src = this.uvs; + const dst = this.object.geometry.uvs; - switch (child.nodeName) { + dst.push( src[ a + 0 ], src[ a + 1 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ] ); - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - var offset = parseInt(child.getAttribute('offset')); - primitive.inputs[semantic] = { id: id, offset: offset }; - primitive.stride = Math.max(primitive.stride, offset + 1); - break; + }, - case 'vcount': - primitive.vcount = parseInts(child.textContent); - break; + addDefaultUV: function () { - case 'p': - primitive.p = parseInts(child.textContent); - break; + const dst = this.object.geometry.uvs; - } + dst.push( 0, 0 ); + dst.push( 0, 0 ); + dst.push( 0, 0 ); - } + }, - return primitive; + addUVLine: function ( a ) { - } + const src = this.uvs; + const dst = this.object.geometry.uvs; - function groupPrimitives(primitives) { + dst.push( src[ a + 0 ], src[ a + 1 ] ); - var build = {}; + }, - for (var i = 0; i < primitives.length; i++) { + addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { - var primitive = primitives[i]; + const vLen = this.vertices.length; - if (build[primitive.type] === undefined) { build[primitive.type] = []; } + let ia = this.parseVertexIndex( a, vLen ); + let ib = this.parseVertexIndex( b, vLen ); + let ic = this.parseVertexIndex( c, vLen ); - build[primitive.type].push(primitive); + this.addVertex( ia, ib, ic ); + this.addColor( ia, ib, ic ); - } + // normals - return build; + if ( na !== undefined && na !== '' ) { - } + const nLen = this.normals.length; - function buildGeometry(data) { + ia = this.parseNormalIndex( na, nLen ); + ib = this.parseNormalIndex( nb, nLen ); + ic = this.parseNormalIndex( nc, nLen ); - var build = {}; + this.addNormal( ia, ib, ic ); - var sources = data.sources; - var vertices = data.vertices; - var primitives = data.primitives; + } else { - if (primitives.length === 0) { return {}; } + this.addFaceNormal( ia, ib, ic ); - // our goal is to create one buffer geoemtry for a single type of primitives - // first, we group all primitives by their type + } - var groupedPrimitives = groupPrimitives(primitives); + // uvs - for (var type in groupedPrimitives) { + if ( ua !== undefined && ua !== '' ) { - // second, we create for each type of primitives (polylist,triangles or lines) a buffer geometry + const uvLen = this.uvs.length; - build[type] = buildGeometryType(groupedPrimitives[type], sources, vertices); + ia = this.parseUVIndex( ua, uvLen ); + ib = this.parseUVIndex( ub, uvLen ); + ic = this.parseUVIndex( uc, uvLen ); - } + this.addUV( ia, ib, ic ); - return build; + this.object.geometry.hasUVIndices = true; - } + } else { - function buildGeometryType(primitives, sources, vertices) { + // add placeholder values (for inconsistent face definitions) - var build = {}; + this.addDefaultUV(); - var position = { array: [], stride: 0 }; - var normal = { array: [], stride: 0 }; - var uv = { array: [], stride: 0 }; - var color = { array: [], stride: 0 }; + } - var skinIndex = { array: [], stride: 4 }; - var skinWeight = { array: [], stride: 4 }; + }, - var geometry = new THREE.BufferGeometry(); + addPointGeometry: function ( vertices ) { - var materialKeys = []; + this.object.geometry.type = 'Points'; - var start = 0, count = 0; + const vLen = this.vertices.length; - for (var p = 0; p < primitives.length; p++) { + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - var primitive = primitives[p]; - var inputs = primitive.inputs; - var triangleCount = 1; + const index = this.parseVertexIndex( vertices[ vi ], vLen ); - if (primitive.vcount && primitive.vcount[0] === 4) { + this.addVertexPoint( index ); + this.addColor( index ); - triangleCount = 2; // one quad -> two triangles + } - } + }, - // groups + addLineGeometry: function ( vertices, uvs ) { - if (primitive.type === 'lines' || primitive.type === 'linestrips') { + this.object.geometry.type = 'Line'; - count = primitive.count * 2; + const vLen = this.vertices.length; + const uvLen = this.uvs.length; - } else { + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - count = primitive.count * 3 * triangleCount; + this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); - } + } - geometry.addGroup(start, count, p); - start += count; + for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { - // material + this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); - if (primitive.material) { + } - materialKeys.push(primitive.material); + } - } + }; - // geometry data + state.startObject( '', false ); - for (var name in inputs) { + return state; - var input = inputs[name]; +} - switch (name) { +// - case 'VERTEX': - for (var key in vertices) { +class OBJLoader extends Loader { - var id = vertices[key]; + constructor( manager ) { - switch (key) { + super( manager ); - case 'POSITION': - buildGeometryData(primitive, sources[id], input.offset, position.array); - position.stride = sources[id].stride; + this.materials = null; - if (sources.skinWeights && sources.skinIndices) { + } - buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); - buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + load( url, onLoad, onProgress, onError ) { - } - break; + const scope = this; - case 'NORMAL': - buildGeometryData(primitive, sources[id], input.offset, normal.array); - normal.stride = sources[id].stride; - break; + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - case 'COLOR': - buildGeometryData(primitive, sources[id], input.offset, color.array); - color.stride = sources[id].stride; - break; + try { - case 'TEXCOORD': - buildGeometryData(primitive, sources[id], input.offset, uv.array); - uv.stride = sources[id].stride; - break; + onLoad( scope.parse( text ) ); - default: - console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + } catch ( e ) { - } + if ( onError ) { - } - break; + onError( e ); - case 'NORMAL': - buildGeometryData(primitive, sources[input.id], input.offset, normal.array); - normal.stride = sources[input.id].stride; - break; + } else { - case 'COLOR': - buildGeometryData(primitive, sources[input.id], input.offset, color.array); - color.stride = sources[input.id].stride; - break; + console.error( e ); - case 'TEXCOORD': - buildGeometryData(primitive, sources[input.id], input.offset, uv.array); - uv.stride = sources[input.id].stride; - break; + } - } + scope.manager.itemError( url ); - } + } - } + }, onProgress, onError ); - // build geometry + } - if (position.array.length > 0) { geometry.addAttribute('position', new THREE.Float32BufferAttribute(position.array, position.stride)); } - if (normal.array.length > 0) { geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normal.array, normal.stride)); } - if (color.array.length > 0) { geometry.addAttribute('color', new THREE.Float32BufferAttribute(color.array, color.stride)); } - if (uv.array.length > 0) { geometry.addAttribute('uv', new THREE.Float32BufferAttribute(uv.array, uv.stride)); } + setMaterials( materials ) { - if (skinIndex.array.length > 0) { geometry.addAttribute('skinIndex', new THREE.Float32BufferAttribute(skinIndex.array, skinIndex.stride)); } - if (skinWeight.array.length > 0) { geometry.addAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeight.array, skinWeight.stride)); } + this.materials = materials; - build.data = geometry; - build.type = primitives[0].type; - build.materialKeys = materialKeys; + return this; - return build; + } - } + parse( text ) { - function buildGeometryData(primitive, source, offset, array) { + const state = new ParserState(); - var indices = primitive.p; - var stride = primitive.stride; - var vcount = primitive.vcount; + if ( text.indexOf( '\r\n' ) !== - 1 ) { - function pushVector(i) { + // This is faster than String.split with regex that splits on both + text = text.replace( /\r\n/g, '\n' ); - var index = indices[i + offset] * sourceStride; - var length = index + sourceStride; + } - for (; index < length; index++) { + if ( text.indexOf( '\\\n' ) !== - 1 ) { - array.push(sourceArray[index]); + // join lines separated by a line continuation character (\) + text = text.replace( /\\\n/g, '' ); - } + } - } + const lines = text.split( '\n' ); + let result = []; - var maxcount = 0; + for ( let i = 0, l = lines.length; i < l; i ++ ) { - var sourceArray = source.array; - var sourceStride = source.stride; + const line = lines[ i ].trimStart(); - if (primitive.vcount !== undefined) { + if ( line.length === 0 ) continue; - var index = 0; + const lineFirstChar = line.charAt( 0 ); - for (var i = 0, l = vcount.length; i < l; i++) { + // @todo invoke passed in handler if any + if ( lineFirstChar === '#' ) continue; // skip comments - var count = vcount[i]; + if ( lineFirstChar === 'v' ) { - if (count === 4) { + const data = line.split( _face_vertex_data_separator_pattern ); - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; - var d = index + stride * 3; + switch ( data[ 0 ] ) { - pushVector(a); pushVector(b); pushVector(d); - pushVector(b); pushVector(c); pushVector(d); + case 'v': + state.vertices.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + if ( data.length >= 7 ) { - } else if (count === 3) { + _color.setRGB( + parseFloat( data[ 4 ] ), + parseFloat( data[ 5 ] ), + parseFloat( data[ 6 ] ) + ).convertSRGBToLinear(); - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; + state.colors.push( _color.r, _color.g, _color.b ); - pushVector(a); pushVector(b); pushVector(c); + } else { - } else { + // if no colors are defined, add placeholders so color and vertex indices match - maxcount = Math.max(maxcount, count); + state.colors.push( undefined, undefined, undefined ); - } + } - index += stride * count; + break; + case 'vn': + state.normals.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + break; + case 'vt': + state.uvs.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ) + ); + break; - } + } - if (maxcount > 0) { + } else if ( lineFirstChar === 'f' ) { - console.log('THREE.ColladaLoader: Geometry has faces with more than 4 vertices.'); + const lineData = line.slice( 1 ).trim(); + const vertexData = lineData.split( _face_vertex_data_separator_pattern ); + const faceVertices = []; - } + // Parse the face vertex data into an easy to work with format - } else { + for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) { - for (var i = 0, l = indices.length; i < l; i += stride) { + const vertex = vertexData[ j ]; - pushVector(i); + if ( vertex.length > 0 ) { - } + const vertexParts = vertex.split( '/' ); + faceVertices.push( vertexParts ); - } + } - } + } - function getGeometry(id) { + // Draw an edge between the first vertex and all subsequent vertices to form an n-gon - return getBuild(library.geometries[id], buildGeometry); + const v1 = faceVertices[ 0 ]; - } + for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { - // kinematics + const v2 = faceVertices[ j ]; + const v3 = faceVertices[ j + 1 ]; - function parseKinematicsModel(xml) { + state.addFace( + v1[ 0 ], v2[ 0 ], v3[ 0 ], + v1[ 1 ], v2[ 1 ], v3[ 1 ], + v1[ 2 ], v2[ 2 ], v3[ 2 ] + ); - var data = { - name: xml.getAttribute('name') || '', - joints: {}, - links: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + } else if ( lineFirstChar === 'l' ) { - var child = xml.childNodes[i]; + const lineParts = line.substring( 1 ).trim().split( ' ' ); + let lineVertices = []; + const lineUVs = []; - if (child.nodeType !== 1) { continue; } + if ( line.indexOf( '/' ) === - 1 ) { - switch (child.nodeName) { + lineVertices = lineParts; - case 'technique_common': - parseKinematicsTechniqueCommon(child, data); - break; + } else { - } + for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) { - } + const parts = lineParts[ li ].split( '/' ); - library.kinematicsModels[xml.getAttribute('id')] = data; + if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] ); + if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] ); - } + } - function buildKinematicsModel(data) { + } - if (data.build !== undefined) { return data.build; } + state.addLineGeometry( lineVertices, lineUVs ); - return data; + } else if ( lineFirstChar === 'p' ) { - } + const lineData = line.slice( 1 ).trim(); + const pointData = lineData.split( ' ' ); - function getKinematicsModel(id) { + state.addPointGeometry( pointData ); - return getBuild(library.kinematicsModels[id], buildKinematicsModel); + } else if ( ( result = _object_pattern.exec( line ) ) !== null ) { - } + // o object_name + // or + // g group_name - function parseKinematicsTechniqueCommon(xml, data) { + // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 + // let name = result[ 0 ].slice( 1 ).trim(); + const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 ); - for (var i = 0; i < xml.childNodes.length; i++) { + state.startObject( name ); - var child = xml.childNodes[i]; + } else if ( _material_use_pattern.test( line ) ) { - if (child.nodeType !== 1) { continue; } + // material - switch (child.nodeName) { + state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); - case 'joint': - data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); - break; + } else if ( _material_library_pattern.test( line ) ) { - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + // mtl file - } + state.materialLibraries.push( line.substring( 7 ).trim() ); - } + } else if ( _map_use_pattern.test( line ) ) { - } + // the line is parsed but ignored since the loader assumes textures are defined MTL files + // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) - function parseKinematicsJoint(xml) { + console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); - var data; + } else if ( lineFirstChar === 's' ) { - for (var i = 0; i < xml.childNodes.length; i++) { + result = line.split( ' ' ); - var child = xml.childNodes[i]; + // smooth shading - if (child.nodeType !== 1) { continue; } + // @todo Handle files that have varying smooth values for a set of faces inside one geometry, + // but does not define a usemtl for each face set. + // This should be detected and a dummy material created (later MultiMaterial and geometry groups). + // This requires some care to not create extra material on each smooth value for "normal" obj files. + // where explicit usemtl defines geometry groups. + // Example asset: examples/models/obj/cerberus/Cerberus.obj - switch (child.nodeName) { + /* + * http://paulbourke.net/dataformats/obj/ + * + * From chapter "Grouping" Syntax explanation "s group_number": + * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. + * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form + * surfaces, smoothing groups are either turned on or off; there is no difference between values greater + * than 0." + */ + if ( result.length > 1 ) { - case 'prismatic': - case 'revolute': - data = parseKinematicsJointParameter(child); - break; + const value = result[ 1 ].trim().toLowerCase(); + state.object.smooth = ( value !== '0' && value !== 'off' ); - } + } else { - } + // ZBrush can produce "s" lines #11707 + state.object.smooth = true; - return data; + } - } + const material = state.object.currentMaterial(); + if ( material ) material.smooth = state.object.smooth; - function parseKinematicsJointParameter(xml, data) { + } else { - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - axis: new THREE.Vector3(), - limits: { - min: 0, - max: 0 - }, - type: xml.nodeName, - static: false, - zeroPosition: 0, - middlePosition: 0 - }; + // Handle null terminated files without exception + if ( line === '\0' ) continue; - for (var i = 0; i < xml.childNodes.length; i++) { + console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + state.finalize(); - case 'axis': - var array = parseFloats(child.textContent); - data.axis.fromArray(array); - break; - case 'limits': - var max = child.getElementsByTagName('max')[0]; - var min = child.getElementsByTagName('min')[0]; + const container = new Group(); + container.materialLibraries = [].concat( state.materialLibraries ); - data.limits.max = parseFloat(max.textContent); - data.limits.min = parseFloat(min.textContent); - break; + const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); - } + if ( hasPrimitives === true ) { - } + for ( let i = 0, l = state.objects.length; i < l; i ++ ) { - // if min is equal to or greater than max, consider the joint static + const object = state.objects[ i ]; + const geometry = object.geometry; + const materials = object.materials; + const isLine = ( geometry.type === 'Line' ); + const isPoints = ( geometry.type === 'Points' ); + let hasVertexColors = false; - if (data.limits.min >= data.limits.max) { + // Skip o/g line declarations that did not follow with any faces + if ( geometry.vertices.length === 0 ) continue; - data.static = true; + const buffergeometry = new BufferGeometry(); - } + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) ); - // calculate middle position + if ( geometry.normals.length > 0 ) { - data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) ); - return data; + } - } + if ( geometry.colors.length > 0 ) { - function parseKinematicsLink(xml) { + hasVertexColors = true; + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) ); - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - attachments: [], - transforms: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( geometry.hasUVIndices === true ) { - var child = xml.childNodes[i]; + buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) ); - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + // Create materials - case 'attachment_full': - data.attachments.push(parseKinematicsAttachment(child)); - break; + const createdMaterials = []; - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - } + const sourceMaterial = materials[ mi ]; + const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors; + let material = state.materials[ materialHash ]; - } + if ( this.materials !== null ) { - return data; + material = this.materials.create( sourceMaterial.name ); - } + // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. + if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) { - function parseKinematicsAttachment(xml) { + const materialLine = new LineBasicMaterial(); + Material.prototype.copy.call( materialLine, material ); + materialLine.color.copy( material.color ); + material = materialLine; - var data = { - joint: xml.getAttribute('joint').split('/').pop(), - transforms: [], - links: [] - }; + } else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } ); + Material.prototype.copy.call( materialPoints, material ); + materialPoints.color.copy( material.color ); + materialPoints.map = material.map; + material = materialPoints; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + if ( material === undefined ) { - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + if ( isLine ) { - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + material = new LineBasicMaterial(); - } + } else if ( isPoints ) { - } + material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - return data; + } else { - } + material = new MeshPhongMaterial(); - function parseKinematicsTransform(xml) { + } - var data = { - type: xml.nodeName - }; + material.name = sourceMaterial.name; + material.flatShading = sourceMaterial.smooth ? false : true; + material.vertexColors = hasVertexColors; - var array = parseFloats(xml.textContent); + state.materials[ materialHash ] = material; - switch (data.type) { + } - case 'matrix': - data.obj = new THREE.Matrix4(); - data.obj.fromArray(array).transpose(); - break; + createdMaterials.push( material ); - case 'translate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - break; + } - case 'rotate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - data.angle = THREE.Math.degToRad(array[3]); - break; + // Create mesh - } + let mesh; - return data; + if ( createdMaterials.length > 1 ) { - } + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - function parseKinematicsScene(xml) { + const sourceMaterial = materials[ mi ]; + buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); - var data = { - bindJointAxis: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( isLine ) { - var child = xml.childNodes[i]; + mesh = new LineSegments( buffergeometry, createdMaterials ); - if (child.nodeType !== 1) { continue; } + } else if ( isPoints ) { - switch (child.nodeName) { + mesh = new Points$1( buffergeometry, createdMaterials ); - case 'bind_joint_axis': - data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); - break; + } else { - } + mesh = new Mesh( buffergeometry, createdMaterials ); - } + } - library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + } else { - } + if ( isLine ) { - function parseKinematicsBindJointAxis(xml) { + mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] ); - var data = { - target: xml.getAttribute('target').split('/').pop() - }; + } else if ( isPoints ) { - for (var i = 0; i < xml.childNodes.length; i++) { + mesh = new Points$1( buffergeometry, createdMaterials[ 0 ] ); - var child = xml.childNodes[i]; + } else { - if (child.nodeType !== 1) { continue; } + mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] ); - switch (child.nodeName) { + } - case 'axis': - var param = child.getElementsByTagName('param')[0]; - data.axis = param.textContent; - var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; - data.jointIndex = tmpJointIndex.substr(0, tmpJointIndex.length - 1); - break; + } - } + mesh.name = object.name; - } + container.add( mesh ); - return data; + } - } + } else { - function buildKinematicsScene(data) { + // if there is only the default parser state object with no geometry data, interpret data as point cloud - if (data.build !== undefined) { return data.build; } + if ( state.vertices.length > 0 ) { - return data; + const material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - } + const buffergeometry = new BufferGeometry(); - function getKinematicsScene(id) { + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) ); - return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { - } + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) ); + material.vertexColors = true; - function setupKinematics() { + } - var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; - var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; - var visualSceneId = Object.keys(library.visualScenes)[0]; + const points = new Points$1( buffergeometry, material ); + container.add( points ); - if (kinematicsModelId === undefined || kinematicsSceneId === undefined) { return; } + } - var kinematicsModel = getKinematicsModel(kinematicsModelId); - var kinematicsScene = getKinematicsScene(kinematicsSceneId); - var visualScene = getVisualScene(visualSceneId); + } - var bindJointAxis = kinematicsScene.bindJointAxis; - var jointMap = {}; + return container; - for (var i = 0, l = bindJointAxis.length; i < l; i++) { + } - var axis = bindJointAxis[i]; +} - // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' +/** + * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. + * + * Supports both binary and ASCII encoded files, with automatic detection of type. + * + * The loader returns a non-indexed buffer geometry. + * + * Limitations: + * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). + * There is perhaps some question as to how valid it is to always assume little-endian-ness. + * ASCII decoding assumes file is UTF-8. + * + * Usage: + * const loader = new STLLoader(); + * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { + * scene.add( new THREE.Mesh( geometry ) ); + * }); + * + * For binary STLs geometry might contain colors for vertices. To use it: + * // use the same code to load STL as above + * if (geometry.hasColors) { + * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true }); + * } else { .... } + * const mesh = new THREE.Mesh( geometry, material ); + * + * For ASCII STLs containing multiple solids, each solid is assigned to a different group. + * Groups can be used to assign a different color by defining an array of materials with the same length of + * geometry.groups and passing it to the Mesh constructor: + * + * const mesh = new THREE.Mesh( geometry, material ); + * + * For example: + * + * const materials = []; + * const nGeometryGroups = geometry.groups.length; + * + * const colorMap = ...; // Some logic to index colors. + * + * for (let i = 0; i < nGeometryGroups; i++) { + * + * const material = new THREE.MeshPhongMaterial({ + * color: colorMap[i], + * wireframe: false + * }); + * + * } + * + * materials.push(material); + * const mesh = new THREE.Mesh(geometry, materials); + */ - var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); - if (targetElement) { +class STLLoader extends Loader { - // get the parent of the transfrom element + constructor( manager ) { - var parentVisualElement = targetElement.parentElement; + super( manager ); - // connect the joint of the kinematics model with the element in the visual scene + } - connect(axis.jointIndex, parentVisualElement); + load( url, onLoad, onProgress, onError ) { - } + const scope = this; - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); - function connect(jointIndex, visualElement) { + loader.load( url, function ( text ) { - var visualElementName = visualElement.getAttribute('name'); - var joint = kinematicsModel.joints[jointIndex]; + try { - visualScene.traverse(function (object) { + onLoad( scope.parse( text ) ); - if (object.name === visualElementName) { + } catch ( e ) { - jointMap[jointIndex] = { - object: object, - transforms: buildTransformList(visualElement), - joint: joint, - position: joint.zeroPosition - }; + if ( onError ) { - } + onError( e ); - }); + } else { - } + console.error( e ); - var m0 = new THREE.Matrix4(); + } - kinematics = { + scope.manager.itemError( url ); - joints: kinematicsModel && kinematicsModel.joints, + } - getJointValue: function (jointIndex) { + }, onProgress, onError ); - var jointData = jointMap[jointIndex]; + } - if (jointData) { + parse( data ) { - return jointData.position; + function isBinary( data ) { - } else { + const reader = new DataView( data ); + const face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 ); + const n_faces = reader.getUint32( 80, true ); + const expect = 80 + ( 32 / 8 ) + ( n_faces * face_size ); - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); + if ( expect === reader.byteLength ) { - } + return true; - }, + } - setJointValue: function (jointIndex, value) { + // An ASCII STL data must begin with 'solid ' as the first six bytes. + // However, ASCII STLs lacking the SPACE after the 'd' are known to be + // plentiful. So, check the first 5 bytes for 'solid'. - var jointData = jointMap[jointIndex]; + // Several encodings, such as UTF-8, precede the text with up to 5 bytes: + // https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding + // Search for "solid" to start anywhere after those prefixes. - if (jointData) { + // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' - var joint = jointData.joint; + const solid = [ 115, 111, 108, 105, 100 ]; - if (value > joint.limits.max || value < joint.limits.min) { + for ( let off = 0; off < 5; off ++ ) { - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + // If "solid" text is matched to the current offset, declare it to be an ASCII STL. - } else if (joint.static) { + if ( matchDataViewAt( solid, reader, off ) ) return false; - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + } - } else { + // Couldn't find "solid" text at the beginning; it is binary STL. - var object = jointData.object; - var axis = joint.axis; - var transforms = jointData.transforms; + return true; - matrix.identity(); + } - // each update, we have to apply all transforms in the correct order + function matchDataViewAt( query, reader, offset ) { - for (var i = 0; i < transforms.length; i++) { + // Check if each byte in query matches the corresponding byte from the current offset - var transform = transforms[i]; + for ( let i = 0, il = query.length; i < il; i ++ ) { - // if there is a connection of the transform node with a joint, apply the joint value + if ( query[ i ] !== reader.getUint8( offset + i ) ) return false; - if (transform.sid && transform.sid.indexOf(jointIndex) !== - 1) { + } - switch (joint.type) { + return true; - case 'revolute': - matrix.multiply(m0.makeRotationAxis(axis, THREE.Math.degToRad(value))); - break; + } - case 'prismatic': - matrix.multiply(m0.makeTranslation(axis.x * value, axis.y * value, axis.z * value)); - break; + function parseBinary( data ) { - default: - console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); - break; + const reader = new DataView( data ); + const faces = reader.getUint32( 80, true ); - } + let r, g, b, hasColors = false, colors; + let defaultR, defaultG, defaultB, alpha; - } else { + // process STL header + // check for default color in header ("COLOR=rgba" sequence). - switch (transform.type) { + for ( let index = 0; index < 80 - 10; index ++ ) { - case 'matrix': - matrix.multiply(transform.obj); - break; + if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) && + ( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) && + ( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) { - case 'translate': - matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); - break; + hasColors = true; + colors = new Float32Array( faces * 3 * 3 ); - case 'scale': - matrix.scale(transform.obj); - break; + defaultR = reader.getUint8( index + 6 ) / 255; + defaultG = reader.getUint8( index + 7 ) / 255; + defaultB = reader.getUint8( index + 8 ) / 255; + alpha = reader.getUint8( index + 9 ) / 255; - case 'rotate': - matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); - break; + } - } + } - } + const dataOffset = 84; + const faceLength = 12 * 4 + 2; - } + const geometry = new BufferGeometry(); - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + const vertices = new Float32Array( faces * 3 * 3 ); + const normals = new Float32Array( faces * 3 * 3 ); - jointMap[jointIndex].position = value; + const color = new Color(); - } + for ( let face = 0; face < faces; face ++ ) { - } else { + const start = dataOffset + face * faceLength; + const normalX = reader.getFloat32( start, true ); + const normalY = reader.getFloat32( start + 4, true ); + const normalZ = reader.getFloat32( start + 8, true ); - console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + if ( hasColors ) { - } + const packedColor = reader.getUint16( start + 48, true ); - } + if ( ( packedColor & 0x8000 ) === 0 ) { - }; + // facet has its own unique color - } + r = ( packedColor & 0x1F ) / 31; + g = ( ( packedColor >> 5 ) & 0x1F ) / 31; + b = ( ( packedColor >> 10 ) & 0x1F ) / 31; - function buildTransformList(node) { + } else { - var transforms = []; + r = defaultR; + g = defaultG; + b = defaultB; - var xml = collada.querySelector('[id="' + node.id + '"]'); + } - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + for ( let i = 1; i <= 3; i ++ ) { - if (child.nodeType !== 1) { continue; } + const vertexstart = start + i * 12; + const componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 ); - switch (child.nodeName) { + vertices[ componentIdx ] = reader.getFloat32( vertexstart, true ); + vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true ); + vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true ); - case 'matrix': - var array = parseFloats(child.textContent); - var matrix = new THREE.Matrix4().fromArray(array).transpose(); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: matrix - }); - break; + normals[ componentIdx ] = normalX; + normals[ componentIdx + 1 ] = normalY; + normals[ componentIdx + 2 ] = normalZ; - case 'translate': - case 'scale': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector - }); - break; + if ( hasColors ) { - case 'rotate': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - var angle = THREE.Math.degToRad(array[3]); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector, - angle: angle - }); - break; + color.set( r, g, b ).convertSRGBToLinear(); - } + colors[ componentIdx ] = color.r; + colors[ componentIdx + 1 ] = color.g; + colors[ componentIdx + 2 ] = color.b; - } + } - return transforms; + } - } + } - // nodes + geometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) ); - function prepareNodes(xml) { + if ( hasColors ) { - var elements = xml.getElementsByTagName('node'); + geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); + geometry.hasColors = true; + geometry.alpha = alpha; - // ensure all node elements have id attributes + } - for (var i = 0; i < elements.length; i++) { + return geometry; - var element = elements[i]; + } - if (element.hasAttribute('id') === false) { + function parseASCII( data ) { - element.setAttribute('id', generateId()); + const geometry = new BufferGeometry(); + const patternSolid = /solid([\s\S]*?)endsolid/g; + const patternFace = /facet([\s\S]*?)endfacet/g; + const patternName = /solid\s(.+)/; + let faceCounter = 0; - } + const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source; + const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' ); + const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' ); - } + const vertices = []; + const normals = []; + const groupNames = []; - } + const normal = new Vector3(); - var matrix = new THREE.Matrix4(); - var vector = new THREE.Vector3(); - - function parseNode(xml) { - - var data = { - name: xml.getAttribute('name') || '', - type: xml.getAttribute('type'), - id: xml.getAttribute('id'), - sid: xml.getAttribute('sid'), - matrix: new THREE.Matrix4(), - nodes: [], - instanceCameras: [], - instanceControllers: [], - instanceLights: [], - instanceGeometries: [], - instanceNodes: [], - transforms: {} - }; + let result; - for (var i = 0; i < xml.childNodes.length; i++) { + let groupCount = 0; + let startVertex = 0; + let endVertex = 0; - var child = xml.childNodes[i]; + while ( ( result = patternSolid.exec( data ) ) !== null ) { - if (child.nodeType !== 1) { continue; } + startVertex = endVertex; - switch (child.nodeName) { + const solid = result[ 0 ]; - case 'node': - data.nodes.push(child.getAttribute('id')); - parseNode(child); - break; + const name = ( result = patternName.exec( solid ) ) !== null ? result[ 1 ] : ''; + groupNames.push( name ); - case 'instance_camera': - data.instanceCameras.push(parseId(child.getAttribute('url'))); - break; + while ( ( result = patternFace.exec( solid ) ) !== null ) { - case 'instance_controller': - data.instanceControllers.push(parseNodeInstance(child)); - break; + let vertexCountPerFace = 0; + let normalCountPerFace = 0; - case 'instance_light': - data.instanceLights.push(parseId(child.getAttribute('url'))); - break; + const text = result[ 0 ]; - case 'instance_geometry': - data.instanceGeometries.push(parseNodeInstance(child)); - break; + while ( ( result = patternNormal.exec( text ) ) !== null ) { - case 'instance_node': - data.instanceNodes.push(parseId(child.getAttribute('url'))); - break; + normal.x = parseFloat( result[ 1 ] ); + normal.y = parseFloat( result[ 2 ] ); + normal.z = parseFloat( result[ 3 ] ); + normalCountPerFace ++; - case 'matrix': - var array = parseFloats(child.textContent); - data.matrix.multiply(matrix.fromArray(array).transpose()); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + } - case 'translate': - var array = parseFloats(child.textContent); - vector.fromArray(array); - data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + while ( ( result = patternVertex.exec( text ) ) !== null ) { - case 'rotate': - var array = parseFloats(child.textContent); - var angle = THREE.Math.degToRad(array[3]); - data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) ); + normals.push( normal.x, normal.y, normal.z ); + vertexCountPerFace ++; + endVertex ++; - case 'scale': - var array = parseFloats(child.textContent); - data.matrix.scale(vector.fromArray(array)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + } - case 'extra': - break; + // every face have to own ONE valid normal - default: - console.log(child); + if ( normalCountPerFace !== 1 ) { - } + console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter ); - } + } - library.nodes[data.id] = data; + // each face have to own THREE valid vertices - return data; + if ( vertexCountPerFace !== 3 ) { - } + console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter ); - function parseNodeInstance(xml) { + } - var data = { - id: parseId(xml.getAttribute('url')), - materials: {}, - skeletons: [] - }; + faceCounter ++; - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + const start = startVertex; + const count = endVertex - startVertex; - switch (child.nodeName) { + geometry.userData.groupNames = groupNames; - case 'bind_material': - var instances = child.getElementsByTagName('instance_material'); + geometry.addGroup( start, count, groupCount ); + groupCount ++; - for (var j = 0; j < instances.length; j++) { + } - var instance = instances[j]; - var symbol = instance.getAttribute('symbol'); - var target = instance.getAttribute('target'); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - data.materials[symbol] = parseId(target); + return geometry; - } + } - break; + function ensureString( buffer ) { - case 'skeleton': - data.skeletons.push(parseId(child.textContent)); - break; + if ( typeof buffer !== 'string' ) { - } + return new TextDecoder().decode( buffer ); - } + } - return data; + return buffer; - } + } - function buildSkeleton(skeletons, joints) { + function ensureBinary( buffer ) { - var boneData = []; - var sortedBoneData = []; + if ( typeof buffer === 'string' ) { - var i, j, data; + const array_buffer = new Uint8Array( buffer.length ); + for ( let i = 0; i < buffer.length; i ++ ) { - // a skeleton can have multiple root bones. collada expresses this - // situtation with multiple "skeleton" tags per controller instance + array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian - for (i = 0; i < skeletons.length; i++) { + } - var skeleton = skeletons[i]; - var root = getNode(skeleton); + return array_buffer.buffer || array_buffer; - // setup bone data for a single bone hierarchy + } else { - buildBoneHierarchy(root, joints, boneData); + return buffer; - } + } - // sort bone data (the order is defined in the corresponding controller) + } - for (i = 0; i < joints.length; i++) { + // start - for (j = 0; j < boneData.length; j++) { + const binData = ensureBinary( data ); - data = boneData[j]; + return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) ); - if (data.bone.name === joints[i].name) { + } - sortedBoneData[i] = data; - data.processed = true; - break; +} - } +/** + * Loads a Wavefront .mtl file specifying materials + */ - } +class MTLLoader extends Loader { - } + constructor( manager ) { - // add unprocessed bone data at the end of the list + super( manager ); - for (i = 0; i < boneData.length; i++) { + } - data = boneData[i]; + /** + * Loads and parses a MTL asset from a URL. + * + * @param {String} url - URL to the MTL file. + * @param {Function} [onLoad] - Callback invoked with the loaded object. + * @param {Function} [onProgress] - Callback for download progress. + * @param {Function} [onError] - Callback for download errors. + * + * @see setPath setResourcePath + * + * @note In order for relative texture references to resolve correctly + * you must call setResourcePath() explicitly prior to load. + */ + load( url, onLoad, onProgress, onError ) { - if (data.processed === false) { + const scope = this; - sortedBoneData.push(data); - data.processed = true; + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - } + try { - // setup arrays for skeleton creation + onLoad( scope.parse( text, path ) ); - var bones = []; - var boneInverses = []; + } catch ( e ) { - for (i = 0; i < sortedBoneData.length; i++) { + if ( onError ) { - data = sortedBoneData[i]; + onError( e ); - bones.push(data.bone); - boneInverses.push(data.boneInverse); + } else { - } + console.error( e ); - return new THREE.Skeleton(bones, boneInverses); + } - } + scope.manager.itemError( url ); - function buildBoneHierarchy(root, joints, boneData) { + } - // setup bone data from visual scene + }, onProgress, onError ); - root.traverse(function (object) { + } - if (object.isBone === true) { + setMaterialOptions( value ) { - var boneInverse; + this.materialOptions = value; + return this; - // retrieve the boneInverse from the controller data + } - for (var i = 0; i < joints.length; i++) { + /** + * Parses a MTL file. + * + * @param {String} text - Content of MTL file + * @return {MaterialCreator} + * + * @see setPath setResourcePath + * + * @note In order for relative texture references to resolve correctly + * you must call setResourcePath() explicitly prior to parse. + */ + parse( text, path ) { - var joint = joints[i]; + const lines = text.split( '\n' ); + let info = {}; + const delimiter_pattern = /\s+/; + const materialsInfo = {}; - if (joint.name === object.name) { + for ( let i = 0; i < lines.length; i ++ ) { - boneInverse = joint.boneInverse; - break; + let line = lines[ i ]; + line = line.trim(); - } + if ( line.length === 0 || line.charAt( 0 ) === '#' ) { - } + // Blank line or comment ignore + continue; - if (boneInverse === undefined) { + } - // Unfortunately, there can be joints in the visual scene that are not part of the - // corresponding controller. In this case, we have to create a dummy boneInverse matrix - // for the respective bone. This bone won't affect any vertices, because there are no skin indices - // and weights defined for it. But we still have to add the bone to the sorted bone list in order to - // ensure a correct animation of the model. + const pos = line.indexOf( ' ' ); - boneInverse = new THREE.Matrix4(); + let key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; + key = key.toLowerCase(); - } + let value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; + value = value.trim(); - boneData.push({ bone: object, boneInverse: boneInverse, processed: false }); + if ( key === 'newmtl' ) { - } + // New material - }); + info = { name: value }; + materialsInfo[ value ] = info; - } + } else { - function buildNode(data) { + if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { - var objects = []; + const ss = value.split( delimiter_pattern, 3 ); + info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; - var matrix = data.matrix; - var nodes = data.nodes; - var type = data.type; - var instanceCameras = data.instanceCameras; - var instanceControllers = data.instanceControllers; - var instanceLights = data.instanceLights; - var instanceGeometries = data.instanceGeometries; - var instanceNodes = data.instanceNodes; + } else { - // nodes + info[ key ] = value; - for (var i = 0, l = nodes.length; i < l; i++) { + } - objects.push(getNode(nodes[i])); + } - } + } - // instance cameras + const materialCreator = new MaterialCreator( this.resourcePath || path, this.materialOptions ); + materialCreator.setCrossOrigin( this.crossOrigin ); + materialCreator.setManager( this.manager ); + materialCreator.setMaterials( materialsInfo ); + return materialCreator; - for (var i = 0, l = instanceCameras.length; i < l; i++) { + } - var instanceCamera = getCamera(instanceCameras[i]); +} - if (instanceCamera !== null) { +/** + * Create a new MTLLoader.MaterialCreator + * @param baseUrl - Url relative to which textures are loaded + * @param options - Set of options on how to construct the materials + * side: Which side to apply the material + * FrontSide (default), THREE.BackSide, THREE.DoubleSide + * wrap: What type of wrapping to apply for textures + * RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping + * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 + * Default: false, assumed to be already normalized + * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's + * Default: false + * @constructor + */ - objects.push(instanceCamera.clone()); +class MaterialCreator { - } + constructor( baseUrl = '', options = {} ) { + this.baseUrl = baseUrl; + this.options = options; + this.materialsInfo = {}; + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; - } + this.crossOrigin = 'anonymous'; - // instance controllers + this.side = ( this.options.side !== undefined ) ? this.options.side : FrontSide; + this.wrap = ( this.options.wrap !== undefined ) ? this.options.wrap : RepeatWrapping; - for (var i = 0, l = instanceControllers.length; i < l; i++) { + } - var instance = instanceControllers[i]; - var controller = getController(instance.id); - var geometries = getGeometry(controller.id); - var newObjects = buildObjects(geometries, instance.materials); + setCrossOrigin( value ) { - var skeletons = instance.skeletons; - var joints = controller.skin.joints; + this.crossOrigin = value; + return this; - var skeleton = buildSkeleton(skeletons, joints); + } - for (var j = 0, jl = newObjects.length; j < jl; j++) { + setManager( value ) { - var object = newObjects[j]; + this.manager = value; - if (object.isSkinnedMesh) { + } - object.bind(skeleton, controller.skin.bindMatrix); - object.normalizeSkinWeights(); + setMaterials( materialsInfo ) { - } + this.materialsInfo = this.convert( materialsInfo ); + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; - objects.push(object); + } - } + convert( materialsInfo ) { - } + if ( ! this.options ) return materialsInfo; - // instance lights + const converted = {}; - for (var i = 0, l = instanceLights.length; i < l; i++) { - var instanceCamera = getCamera(instanceCameras[i]); + for ( const mn in materialsInfo ) { - if (instanceCamera !== null) { + // Convert materials info into normalized form based on options - objects.push(instanceCamera.clone()); + const mat = materialsInfo[ mn ]; - } + const covmat = {}; - } + converted[ mn ] = covmat; - // instance geometries + for ( const prop in mat ) { - for (var i = 0, l = instanceGeometries.length; i < l; i++) { + let save = true; + let value = mat[ prop ]; + const lprop = prop.toLowerCase(); - var instance = instanceGeometries[i]; + switch ( lprop ) { - // a single geometry instance in collada can lead to multiple object3Ds. - // this is the case when primitives are combined like triangles and lines + case 'kd': + case 'ka': + case 'ks': - var geometries = getGeometry(instance.id); - var newObjects = buildObjects(geometries, instance.materials); + // Diffuse color (color under white light) using RGB values - for (var j = 0, jl = newObjects.length; j < jl; j++) { + if ( this.options && this.options.normalizeRGB ) { - objects.push(newObjects[j]); + value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; - } + } - } + if ( this.options && this.options.ignoreZeroRGBs ) { - // instance nodes + if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { - for (var i = 0, l = instanceNodes.length; i < l; i++) { + // ignore - objects.push(getNode(instanceNodes[i]).clone()); + save = false; - } + } - var object; + } - if (nodes.length === 0 && objects.length === 1) { + break; - object = objects[0]; + } - } else { + if ( save ) { - object = (type === 'JOINT') ? new THREE.Bone() : new THREE.Object3D(); + covmat[ lprop ] = value; - for (var i = 0; i < objects.length; i++) { + } - object.add(objects[i]); + } - } + } - } + return converted; - object.name = (type === 'JOINT') ? data.sid : data.name; - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + } - return object; + preload() { - } + for ( const mn in this.materialsInfo ) { - function resolveMaterialBinding(keys, instanceMaterials) { + this.create( mn ); - var materials = []; + } - for (var i = 0, l = keys.length; i < l; i++) { + } - var id = instanceMaterials[keys[i]]; - materials.push(getMaterial(id)); + getIndex( materialName ) { - } + return this.nameLookup[ materialName ]; - return materials; + } - } + getAsArray() { - function buildObjects(geometries, instanceMaterials) { + let index = 0; - var objects = []; + for ( const mn in this.materialsInfo ) { - for (var type in geometries) { + this.materialsArray[ index ] = this.create( mn ); + this.nameLookup[ mn ] = index; + index ++; - var geometry = geometries[type]; + } - var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); + return this.materialsArray; - // handle case if no materials are defined + } - if (materials.length === 0) { + create( materialName ) { - if (type === 'lines' || type === 'linestrips') { + if ( this.materials[ materialName ] === undefined ) { - materials.push(new THREE.LineBasicMaterial()); + this.createMaterial_( materialName ); - } else { + } - materials.push(new THREE.MeshPhongMaterial()); + return this.materials[ materialName ]; - } + } - } + createMaterial_( materialName ) { - // regard skinning + // Create material - var skinning = (geometry.data.attributes.skinIndex !== undefined); + const scope = this; + const mat = this.materialsInfo[ materialName ]; + const params = { - if (skinning) { + name: materialName, + side: this.side - for (var i = 0, l = materials.length; i < l; i++) { + }; - materials[i].skinning = true; + function resolveURL( baseUrl, url ) { - } + if ( typeof url !== 'string' || url === '' ) + return ''; - } + // Absolute URL + if ( /^https?:\/\//i.test( url ) ) return url; - // choose between a single or multi materials (material array) + return baseUrl + url; - var material = (materials.length === 1) ? materials[0] : materials; + } - // now create a specific 3D object + function setMapForType( mapType, value ) { - var object; + if ( params[ mapType ] ) return; // Keep the first encountered texture - switch (type) { + const texParams = scope.getTextureParams( value, params ); + const map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); - case 'lines': - object = new THREE.LineSegments(geometry.data, material); - break; + map.repeat.copy( texParams.scale ); + map.offset.copy( texParams.offset ); - case 'linestrips': - object = new THREE.Line(geometry.data, material); - break; + map.wrapS = scope.wrap; + map.wrapT = scope.wrap; - case 'triangles': - case 'polylist': - if (skinning) { + if ( mapType === 'map' || mapType === 'emissiveMap' ) { - object = new THREE.SkinnedMesh(geometry.data, material); + map.colorSpace = SRGBColorSpace; - } else { + } - object = new THREE.Mesh(geometry.data, material); + params[ mapType ] = map; - } - break; + } - } + for ( const prop in mat ) { - objects.push(object); + const value = mat[ prop ]; + let n; - } + if ( value === '' ) continue; - return objects; + switch ( prop.toLowerCase() ) { - } + // Ns is material specular exponent - function getNode(id) { + case 'kd': - return getBuild(library.nodes[id], buildNode); + // Diffuse color (color under white light) using RGB values - } + params.color = new Color().fromArray( value ).convertSRGBToLinear(); - // visual scenes + break; - function parseVisualScene(xml) { + case 'ks': - var data = { - name: xml.getAttribute('name'), - children: [] - }; + // Specular color (color when light is reflected from shiny surface) using RGB values + params.specular = new Color().fromArray( value ).convertSRGBToLinear(); - prepareNodes(xml); + break; - var elements = getElementsByTagName(xml, 'node'); + case 'ke': - for (var i = 0; i < elements.length; i++) { + // Emissive using RGB values + params.emissive = new Color().fromArray( value ).convertSRGBToLinear(); - data.children.push(parseNode(elements[i])); + break; - } + case 'map_kd': - library.visualScenes[xml.getAttribute('id')] = data; + // Diffuse texture map - } + setMapForType( 'map', value ); - function buildVisualScene(data) { + break; - var group = new THREE.Object3D(); - group.name = data.name; + case 'map_ks': - var children = data.children; + // Specular map - for (var i = 0; i < children.length; i++) { + setMapForType( 'specularMap', value ); - var child = children[i]; + break; - if (child.id === null) { + case 'map_ke': - group.add(buildNode(child)); + // Emissive map - } else { + setMapForType( 'emissiveMap', value ); - // if there is an ID, let's try to get the finished build (e.g. joints are already build) + break; - group.add(getNode(child.id)); + case 'norm': - } + setMapForType( 'normalMap', value ); - } + break; - return group; + case 'map_bump': + case 'bump': - } + // Bump texture map - function getVisualScene(id) { + setMapForType( 'bumpMap', value ); - return getBuild(library.visualScenes[id], buildVisualScene); + break; - } + case 'map_d': - // scenes + // Alpha map - function parseScene(xml) { + setMapForType( 'alphaMap', value ); + params.transparent = true; - var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; - return getVisualScene(parseId(instance.getAttribute('url'))); + break; - } + case 'ns': - function setupAnimations() { + // The specular exponent (defines the focus of the specular highlight) + // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. - var clips = library.clips; + params.shininess = parseFloat( value ); - if (isEmpty(clips) === true) { + break; - if (isEmpty(library.animations) === false) { + case 'd': + n = parseFloat( value ); - // if there are animations but no clips, we create a default clip for playback + if ( n < 1 ) { - var tracks = []; + params.opacity = n; + params.transparent = true; - for (var id in library.animations) { + } - var animationTracks = getAnimation(id); + break; - for (var i = 0, l = animationTracks.length; i < l; i++) { + case 'tr': + n = parseFloat( value ); - tracks.push(animationTracks[i]); + if ( this.options && this.options.invertTrProperty ) n = 1 - n; - } + if ( n > 0 ) { - } + params.opacity = 1 - n; + params.transparent = true; - animations.push(new THREE.AnimationClip('default', - 1, tracks)); + } - } + break; - } else { + } - for (var id in clips) { + } - animations.push(getAnimationClip(id)); + this.materials[ materialName ] = new MeshPhongMaterial( params ); + return this.materials[ materialName ]; - } + } - } + getTextureParams( value, matParams ) { - } + const texParams = { - console.time('THREE.ColladaLoader'); + scale: new Vector2( 1, 1 ), + offset: new Vector2( 0, 0 ) - if (text.length === 0) { + }; - return { scene: new THREE.Scene() }; + const items = value.split( /\s+/ ); + let pos; - } + pos = items.indexOf( '-bm' ); - console.time('THREE.ColladaLoader: DOMParser'); + if ( pos >= 0 ) { - var xml = new DOMParser().parseFromString(text, 'application/xml'); + matParams.bumpScale = parseFloat( items[ pos + 1 ] ); + items.splice( pos, 2 ); - console.timeEnd('THREE.ColladaLoader: DOMParser'); + } - var collada = getElementsByTagName(xml, 'COLLADA')[0]; + pos = items.indexOf( '-s' ); - // metadata + if ( pos >= 0 ) { - var version = collada.getAttribute('version'); - console.log('THREE.ColladaLoader: File version', version); + texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! - var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); - var textureLoader = new THREE.TextureLoader(this.manager); - textureLoader.setPath(path).setCrossOrigin(this.crossOrigin); + } - // + pos = items.indexOf( '-o' ); - var animations = []; - var kinematics = {}; - var count = 0; + if ( pos >= 0 ) { - // + texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! - var library = { - animations: {}, - clips: {}, - controllers: {}, - images: {}, - effects: {}, - materials: {}, - cameras: {}, - lights: {}, - geometries: {}, - nodes: {}, - visualScenes: {}, - kinematicsModels: {}, - kinematicsScenes: {} - }; + } - console.time('THREE.ColladaLoader: Parse'); + texParams.url = items.join( ' ' ).trim(); + return texParams; - parseLibrary(collada, 'library_animations', 'animation', parseAnimation); - parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); - parseLibrary(collada, 'library_controllers', 'controller', parseController); - parseLibrary(collada, 'library_images', 'image', parseImage); - parseLibrary(collada, 'library_effects', 'effect', parseEffect); - parseLibrary(collada, 'library_materials', 'material', parseMaterial); - parseLibrary(collada, 'library_cameras', 'camera', parseCamera); - parseLibrary(collada, 'library_lights', 'light', parseLight); - parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); - parseLibrary(collada, 'library_nodes', 'node', parseNode); - parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); - parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); - parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + } - console.timeEnd('THREE.ColladaLoader: Parse'); + loadTexture( url, mapping, onLoad, onProgress, onError ) { - console.time('THREE.ColladaLoader: Build'); + const manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager; + let loader = manager.getHandler( url ); - buildLibrary(library.animations, buildAnimation); - buildLibrary(library.clips, buildAnimationClip); - buildLibrary(library.controllers, buildController); - buildLibrary(library.images, buildImage); - buildLibrary(library.effects, buildEffect); - buildLibrary(library.materials, buildMaterial); - buildLibrary(library.cameras, buildCamera); - buildLibrary(library.lights, buildLight); - buildLibrary(library.geometries, buildGeometry); - buildLibrary(library.visualScenes, buildVisualScene); + if ( loader === null ) { - console.timeEnd('THREE.ColladaLoader: Build'); + loader = new TextureLoader( manager ); - setupAnimations(); - setupKinematics(); + } - var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); - /* - * up_axis of some robot models in ROS world aren't properly set because - * rviz ignores this field. Thus, ignores Z_UP to show urdfs just like rviz. - * See https://github.com/ros-visualization/rviz/issues/1045 for the detail - if ( asset.upAxis === 'Z_UP' ) { + const texture = loader.load( url, onLoad, onProgress, onError ); - scene.rotation.x = - Math.PI / 2; + if ( mapping !== undefined ) texture.mapping = mapping; - } - */ + return texture; - scene.scale.multiplyScalar(asset.unit); + } - console.timeEnd('THREE.ColladaLoader'); +} - return { - animations: animations, - kinematics: kinematics, - library: library, - scene: scene - }; +var MeshLoader = { + onError: function onError(error) { + console.error(error); + }, + loaders: { + 'dae': function dae(meshRes, uri, options) { + var loader = new ColladaLoader(options.loader); + console.log('Loading collada: ' + uri); + loader.load(uri, function (collada_mesh) { + var model = collada_mesh.scene; + meshRes.add(model); + console.log('Done loading collada'); + }); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + return loader; + }, + 'obj': function obj(meshRes, uri, options) { + options.material; + var loader = new OBJLoader(options.loader); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + //Reload the mesh again after materials have been loaded + // @todo: this should be improved so that the file doesn't need to be + // reloaded however that would involve more changes within the OBJLoader. + function onMaterialsLoaded(loader, materials) { + loader.setMaterials(materials).load(uri, function OBJMaterialsReady(obj) { + // add the container group + meshRes.add(obj); + }, null, MeshLoader.onError); + } + loader.load(uri, function OBJFileReady(obj) { + var baseUri = LoaderUtils.extractUrlBase(uri); + if (obj.materialLibraries.length) { + // load the material libraries + var materialUri = obj.materialLibraries[0]; + new MTLLoader(options.loader).setPath(baseUri).load(materialUri, function (materials) { + materials.preload(); + onMaterialsLoaded(loader, materials); + }, null, MeshLoader.onError); + } else { + // add the container group + meshRes.add(obj); + } + }, /*onProgress=*/null, MeshLoader.onError); + return loader; + }, + 'stl': function stl(meshRes, uri, options) { + var material = options.material; + var loader = new STLLoader(options.loader); + { + loader.load(uri, function (geometry) { + geometry.computeVertexNormals(); + var mesh; + if (material !== null) { + mesh = new Mesh(geometry, material); + } else { + mesh = new Mesh(geometry, new MeshBasicMaterial({ + color: 0x999999 + })); + } + meshRes.add(mesh); + }, /*onProgress=*/null, MeshLoader.onError); + } + return loader; + } } - }; -/** - * @fileOverview - * @author Jose Rojas - jrojas@redlinesolutions.co - */ - - /** - * MeshLoader is a singleton factory class for using various helper classes to - * load mesh files of different types. - * - * It consists of one dictionary property 'loaders'. The dictionary keys consist - * of the file extension for each supported loader type. The dictionary values - * are functions used to construct the loader objects. The functions have the - * following parameters: - * - * * meshRes - the MeshResource that will contain the loaded mesh - * * uri - the uri path to the mesh file - * @returns loader object - */ -var MeshLoader = { - onError: function(error) { - console.error(error); - }, - loaders: { - 'dae': function(meshRes, uri, options) { - var material = options.material; - var loader = new THREE.ColladaLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - loader.load( - uri, - function colladaReady(collada) { - // check for a scale factor in ColladaLoader2 - // add a texture to anything that is missing one - if(material !== null) { - collada.scene.traverse(function(child) { - if(child instanceof THREE.Mesh) { - if(child.material === undefined) { - child.material = material; - } - } - }); - } - - meshRes.add(collada.scene); - }, - /*onProgress=*/null, - MeshLoader.onError); - return loader; - }, - - 'obj': function(meshRes, uri, options) { - options.material; - var loader = new THREE.OBJLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - - //Reload the mesh again after materials have been loaded - // @todo: this should be improved so that the file doesn't need to be - // reloaded however that would involve more changes within the OBJLoader. - function onMaterialsLoaded(loader, materials) { - loader. - setMaterials(materials). - load( - uri, - function OBJMaterialsReady(obj) { - // add the container group - meshRes.add(obj); - }, - null, - MeshLoader.onError); - } - - loader.load( - uri, - function OBJFileReady(obj) { - - var baseUri = THREE.LoaderUtils.extractUrlBase( uri ); - - if (obj.materialLibraries.length) { - // load the material libraries - var materialUri = obj.materialLibraries[0]; - new THREE.MTLLoader(options.loader).setPath(baseUri).load( - materialUri, - function(materials) { - materials.preload(); - onMaterialsLoaded(loader, materials); - }, - null, - MeshLoader.onError - ); - } else { - // add the container group - meshRes.add(obj); - } - - }, - /*onProgress=*/null, - MeshLoader.onError - ); - return loader; - }, - - 'stl': function(meshRes, uri, options) { - var material = options.material; - var loader = new THREE.STLLoader(options.loader); - { - loader.load(uri, - function ( geometry ) { - geometry.computeFaceNormals(); - var mesh; - if(material !== null) { - mesh = new THREE.Mesh( geometry, material ); - } else { - mesh = new THREE.Mesh( geometry, - new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); - } - meshRes.add(mesh); - }, - /*onProgress=*/null, - MeshLoader.onError); - } - return loader; - } - - } - }; +function _callSuper$w(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$w() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$w() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$w = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -51886,114 +42187,149 @@ var MeshLoader = { * @author Russell Toris - rctoris@wpi.edu */ -var MeshResource = /*@__PURE__*/(function (superclass) { +var MeshResource = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A MeshResource is an THREE object that will load from a external mesh file. Currently loads + * Collada files. + * + * @constructor + * @param options - object with following keys: + * + * * path (optional) - the base path to the associated models that will be loaded + * * resource - the resource file name to load + * * material (optional) - the material to use for the object + * * warnings (optional) - if warnings should be printed + */ function MeshResource(options) { - superclass.call(this); + var _this; + _classCallCheck(this, MeshResource); + _this = _callSuper$w(this, MeshResource); options = options || {}; var path = options.path || '/'; var resource = options.resource; options.material || null; - this.warnings = options.warnings; - + _this.warnings = options.warnings; // check for a trailing '/' if (path.substr(path.length - 1) !== '/') { path += '/'; } - var uri = path + resource; var fileType = uri.substr(-3).toLowerCase(); // check the type var loaderFunc = MeshLoader.loaders[fileType]; if (loaderFunc) { - loaderFunc(this, uri, options); + loaderFunc(_this, uri, options); } else { console.warn('Unsupported loader for file type: \'' + fileType + '\''); } + return _this; } + _inherits(MeshResource, _THREE$Object3D); + return _createClass(MeshResource); +}(Object3D); - if ( superclass ) MeshResource.__proto__ = superclass; - MeshResource.prototype = Object.create( superclass && superclass.prototype ); - MeshResource.prototype.constructor = MeshResource; - - return MeshResource; -}(THREE.Object3D)); +function _callSuper$v(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$v() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$v() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$v = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var TriangleList = /*@__PURE__*/(function (superclass) { +var TriangleList = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A TriangleList is a THREE object that can be used to display a list of triangles as a geometry. + * + * @constructor + * @param options - object with following keys: + * + * * material (optional) - the material to use for the object + * * vertices - the array of vertices to use + * * colors - the associated array of colors to use + */ function TriangleList(options) { + var _this; + _classCallCheck(this, TriangleList); options = options || {}; - var material = options.material || new THREE.MeshBasicMaterial(); + var material = options.material || new MeshBasicMaterial(); var vertices = options.vertices; var colors = options.colors; - - superclass.call(this); + _this = _callSuper$v(this, TriangleList); // set the material to be double sided - material.side = THREE.DoubleSide; - - // construct the geometry - var geometry = new THREE.Geometry(); - for (i = 0; i < vertices.length; i++) { - geometry.vertices.push(new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)); + material.side = DoubleSide; + + // Construct the geometry + var geometry = new BufferGeometry(); + var verticesArray = new Float32Array(vertices.length * 3); + for (var _i = 0; _i < vertices.length; _i++) { + verticesArray[_i * 3] = vertices[_i].x; + verticesArray[_i * 3 + 1] = vertices[_i].y; + verticesArray[_i * 3 + 2] = vertices[_i].z; } + geometry.setAttribute('position', new BufferAttribute(verticesArray, 3)); - // set the colors + // Set the colors var i, j; if (colors.length === vertices.length) { - // use per-vertex color - for (i = 0; i < vertices.length; i += 3) { - var faceVert = new THREE.Face3(i, i + 1, i + 2); - for (j = i * 3; j < i * 3 + 3; i++) { - var color = new THREE.Color(); - color.setRGB(colors[i].r, colors[i].g, colors[i].b); - faceVert.vertexColors.push(color); - } - geometry.faces.push(faceVert); + // Use per-vertex color + var vertexColors = new Float32Array(colors.length * 3); + for (i = 0; i < colors.length; i++) { + vertexColors[i * 3] = colors[i].r; + vertexColors[i * 3 + 1] = colors[i].g; + vertexColors[i * 3 + 2] = colors[i].b; } - material.vertexColors = THREE.VertexColors; + geometry.setAttribute('color', new BufferAttribute(vertexColors, 3)); + material.vertexColors = true; } else if (colors.length === vertices.length / 3) { - // use per-triangle color - for (i = 0; i < vertices.length; i += 3) { - var faceTri = new THREE.Face3(i, i + 1, i + 2); - faceTri.color.setRGB(colors[i / 3].r, colors[i / 3].g, colors[i / 3].b); - geometry.faces.push(faceTri); + // Use per-triangle color + var faceColors = new Float32Array(vertices.length); + for (i = 0; i < colors.length; i++) { + var color = new Color(colors[i].r, colors[i].g, colors[i].b); + for (j = 0; j < 9; j += 3) { + faceColors[i * 9 + j] = color.r; + faceColors[i * 9 + j + 1] = color.g; + faceColors[i * 9 + j + 2] = color.b; + } } - material.vertexColors = THREE.FaceColors; + geometry.setAttribute('color', new BufferAttribute(faceColors, 3)); + material.vertexColors = true; } else { - // use marker color + // Use marker color + var defaultColor = new Color(1, 1, 1); // Default color + var _faceColors = new Float32Array(vertices.length); for (i = 0; i < vertices.length; i += 3) { - var face = new THREE.Face3(i, i + 1, i + 2); - geometry.faces.push(face); + _faceColors[i * 3] = defaultColor.r; + _faceColors[i * 3 + 1] = defaultColor.g; + _faceColors[i * 3 + 2] = defaultColor.b; } + geometry.setAttribute('color', new BufferAttribute(_faceColors, 3)); } - geometry.computeBoundingBox(); geometry.computeBoundingSphere(); geometry.computeFaceNormals(); - - this.add(new THREE.Mesh(geometry, material)); + _this.add(new Mesh(geometry, material)); + return _this; } + _inherits(TriangleList, _THREE$Object3D); + return _createClass(TriangleList, [{ + key: "setColor", + value: + /** + * Set the color of this object to the given hex value. + * + * @param hex - the hex value of the color to set + */ + function setColor(hex) { + this.mesh.material.color.setHex(hex); + } + }]); +}(Object3D); - if ( superclass ) TriangleList.__proto__ = superclass; - TriangleList.prototype = Object.create( superclass && superclass.prototype ); - TriangleList.prototype.constructor = TriangleList; - /** - * Set the color of this object to the given hex value. - * - * @param hex - the hex value of the color to set - */ - TriangleList.prototype.setColor = function setColor (hex) { - this.mesh.material.color.setHex(hex); - }; - - return TriangleList; -}(THREE.Object3D)); +function _callSuper$u(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$u() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$u() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$u = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -52001,10 +42337,20 @@ var TriangleList = /*@__PURE__*/(function (superclass) { * @author Russell Toris - rctoris@wpi.edu */ -var Marker = /*@__PURE__*/(function (superclass) { +var Marker = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A Marker can convert a ROS marker message into a THREE object. + * + * @constructor + * @param options - object with following keys: + * + * * path - the base path or URL for any mesh files that will be loaded for this marker + * * message - the marker message + */ function Marker(options) { - superclass.call(this); - + var _this; + _classCallCheck(this, Marker); + _this = _callSuper$u(this, Marker); options = options || {}; var path = options.path || '/'; var message = options.message; @@ -52013,20 +42359,17 @@ var Marker = /*@__PURE__*/(function (superclass) { if (path.substr(path.length - 1) !== '/') { path += '/'; } - - if(message.scale) { - this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; - } - else { - this.msgScale = [1,1,1]; + if (message.scale) { + _this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } else { + _this.msgScale = [1, 1, 1]; } - this.msgColor = message.color; - this.msgMesh = undefined; + _this.msgColor = message.color; + _this.msgMesh = undefined; // set the pose and get the color - this.setPose(message.pose); - var colorMaterial = makeColorMaterial(this.msgColor.r, - this.msgColor.g, this.msgColor.b, this.msgColor.a); + _this.setPose(message.pose); + var colorMaterial = makeColorMaterial(_this.msgColor.r, _this.msgColor.g, _this.msgColor.b, _this.msgColor.a); // create the object based on the type switch (message.type) { @@ -52038,64 +42381,64 @@ var Marker = /*@__PURE__*/(function (superclass) { var shaftDiameter = headDiameter * 0.5; // determine the points - var direction, p1 = null; + var direction, + p1 = null; if (message.points.length === 2) { - p1 = new THREE.Vector3(message.points[0].x, message.points[0].y, message.points[0].z); - var p2 = new THREE.Vector3(message.points[1].x, message.points[1].y, message.points[1].z); + p1 = new Vector3(message.points[0].x, message.points[0].y, message.points[0].z); + var p2 = new Vector3(message.points[1].x, message.points[1].y, message.points[1].z); direction = p1.clone().negate().add(p2); // direction = p2 - p1; len = direction.length(); headDiameter = message.scale.y; shaftDiameter = message.scale.x; - if (message.scale.z !== 0.0) { headLength = message.scale.z; } } // add the marker - this.add(new Arrow({ - direction : direction, - origin : p1, - length : len, - headLength : headLength, - shaftDiameter : shaftDiameter, - headDiameter : headDiameter, - material : colorMaterial + _this.add(new Arrow({ + direction: direction, + origin: p1, + length: len, + headLength: headLength, + shaftDiameter: shaftDiameter, + headDiameter: headDiameter, + material: colorMaterial })); break; case MARKER_CUBE: // set the cube dimensions - var cubeGeom = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); - this.add(new THREE.Mesh(cubeGeom, colorMaterial)); + var cubeGeom = new BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + _this.add(new Mesh(cubeGeom, colorMaterial)); break; case MARKER_SPHERE: // set the sphere dimensions - var sphereGeom = new THREE.SphereGeometry(0.5); - var sphereMesh = new THREE.Mesh(sphereGeom, colorMaterial); + var sphereGeom = new SphereGeometry(0.5); + var sphereMesh = new Mesh(sphereGeom, colorMaterial); sphereMesh.scale.x = message.scale.x; sphereMesh.scale.y = message.scale.y; sphereMesh.scale.z = message.scale.z; - this.add(sphereMesh); + _this.add(sphereMesh); break; case MARKER_CYLINDER: // set the cylinder dimensions - var cylinderGeom = new THREE.CylinderGeometry(0.5, 0.5, 1, 16, 1, false); - var cylinderMesh = new THREE.Mesh(cylinderGeom, colorMaterial); - cylinderMesh.quaternion.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI * 0.5); + var cylinderGeom = new CylinderGeometry(0.5, 0.5, 1, 16, 1, false); + var cylinderMesh = new Mesh(cylinderGeom, colorMaterial); + cylinderMesh.quaternion.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI * 0.5); cylinderMesh.scale.set(message.scale.x, message.scale.z, message.scale.y); - this.add(cylinderMesh); + _this.add(cylinderMesh); break; case MARKER_LINE_STRIP: - var lineStripGeom = new THREE.Geometry(); - var lineStripMaterial = new THREE.LineBasicMaterial({ - linewidth : message.scale.x + var lineStripGeom = new BufferGeometry(); + var lineStripMaterial = new LineBasicMaterial({ + linewidth: message.scale.x }); // add the points var j; - for ( j = 0; j < message.points.length; j++) { - var pt = new THREE.Vector3(); + for (j = 0; j < message.points.length; j++) { + var pt = new Vector3(); pt.x = message.points[j].x; pt.y = message.points[j].y; pt.z = message.points[j].z; @@ -52105,8 +42448,8 @@ var Marker = /*@__PURE__*/(function (superclass) { // determine the colors for each if (message.colors.length === message.points.length) { lineStripMaterial.vertexColors = true; - for ( j = 0; j < message.points.length; j++) { - var clr = new THREE.Color(); + for (j = 0; j < message.points.length; j++) { + var clr = new Color(); clr.setRGB(message.colors[j].r, message.colors[j].g, message.colors[j].b); lineStripGeom.colors.push(clr); } @@ -52115,18 +42458,18 @@ var Marker = /*@__PURE__*/(function (superclass) { } // add the line - this.add(new THREE.Line(lineStripGeom, lineStripMaterial)); + _this.add(new Line(lineStripGeom, lineStripMaterial)); break; case MARKER_LINE_LIST: - var lineListGeom = new THREE.Geometry(); - var lineListMaterial = new THREE.LineBasicMaterial({ - linewidth : message.scale.x + var lineListGeom = new BufferGeometry(); + var lineListMaterial = new LineBasicMaterial({ + linewidth: message.scale.x }); // add the points var k; - for ( k = 0; k < message.points.length; k++) { - var v = new THREE.Vector3(); + for (k = 0; k < message.points.length; k++) { + var v = new Vector3(); v.x = message.points[k].x; v.y = message.points[k].y; v.z = message.points[k].z; @@ -52136,8 +42479,8 @@ var Marker = /*@__PURE__*/(function (superclass) { // determine the colors for each if (message.colors.length === message.points.length) { lineListMaterial.vertexColors = true; - for ( k = 0; k < message.points.length; k++) { - var c = new THREE.Color(); + for (k = 0; k < message.points.length; k++) { + var c = new Color(); c.setRGB(message.colors[k].r, message.colors[k].g, message.colors[k].b); lineListGeom.colors.push(c); } @@ -52146,62 +42489,59 @@ var Marker = /*@__PURE__*/(function (superclass) { } // add the line - this.add(new THREE.LineSegments(lineListGeom, lineListMaterial)); + _this.add(new LineSegments(lineListGeom, lineListMaterial)); break; case MARKER_CUBE_LIST: // holds the main object - var object = new THREE.Object3D(); + var object = new Object3D(); // check if custom colors should be used var numPoints = message.points.length; - var createColors = (numPoints === message.colors.length); + var createColors = numPoints === message.colors.length; // do not render giant lists var stepSize = Math.ceil(numPoints / 1250); // add the points var p, cube, curColor, newMesh; - for (p = 0; p < numPoints; p+=stepSize) { - cube = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + for (p = 0; p < numPoints; p += stepSize) { + cube = new BoxGeometry(message.scale.x, message.scale.y, message.scale.z); // check the color - if(createColors) { + if (createColors) { curColor = makeColorMaterial(message.colors[p].r, message.colors[p].g, message.colors[p].b, message.colors[p].a); } else { curColor = colorMaterial; } - - newMesh = new THREE.Mesh(cube, curColor); + newMesh = new Mesh(cube, curColor); newMesh.position.x = message.points[p].x; newMesh.position.y = message.points[p].y; newMesh.position.z = message.points[p].z; object.add(newMesh); } - - this.add(object); + _this.add(object); break; case MARKER_SPHERE_LIST: // holds the main object - var sphereObject = new THREE.Object3D(); + var sphereObject = new Object3D(); // check if custom colors should be used var numSpherePoints = message.points.length; - var createSphereColors = (numSpherePoints === message.colors.length); + var createSphereColors = numSpherePoints === message.colors.length; // do not render giant lists var sphereStepSize = Math.ceil(numSpherePoints / 1250); // add the points var q, sphere, curSphereColor, newSphereMesh; - for (q = 0; q < numSpherePoints; q+=sphereStepSize) { - sphere = new THREE.SphereGeometry(0.5, 8, 8); + for (q = 0; q < numSpherePoints; q += sphereStepSize) { + sphere = new SphereGeometry(0.5, 8, 8); // check the color - if(createSphereColors) { + if (createSphereColors) { curSphereColor = makeColorMaterial(message.colors[q].r, message.colors[q].g, message.colors[q].b, message.colors[q].a); } else { curSphereColor = colorMaterial; } - - newSphereMesh = new THREE.Mesh(sphere, curSphereColor); + newSphereMesh = new Mesh(sphere, curSphereColor); newSphereMesh.scale.x = message.scale.x; newSphereMesh.scale.y = message.scale.y; newSphereMesh.scale.z = message.scale.z; @@ -52210,19 +42550,19 @@ var Marker = /*@__PURE__*/(function (superclass) { newSphereMesh.position.z = message.points[q].z; sphereObject.add(newSphereMesh); } - this.add(sphereObject); + _this.add(sphereObject); break; case MARKER_POINTS: // for now, use a particle system for the lists - var geometry = new THREE.Geometry(); - var material = new THREE.PointsMaterial({ - size : message.scale.x + var geometry = new BufferGeometry(); + var material = new PointsMaterial({ + size: message.scale.x }); // add the points var i; - for ( i = 0; i < message.points.length; i++) { - var vertex = new THREE.Vector3(); + for (i = 0; i < message.points.length; i++) { + var vertex = new Vector3(); vertex.x = message.points[i].x; vertex.y = message.points[i].y; vertex.z = message.points[i].z; @@ -52232,8 +42572,8 @@ var Marker = /*@__PURE__*/(function (superclass) { // determine the colors for each if (message.colors.length === message.points.length) { material.vertexColors = true; - for ( i = 0; i < message.points.length; i++) { - var color = new THREE.Color(); + for (i = 0; i < message.points.length; i++) { + var color = new Color(); color.setRGB(message.colors[i].r, message.colors[i].g, message.colors[i].b); geometry.colors.push(color); } @@ -52242,23 +42582,21 @@ var Marker = /*@__PURE__*/(function (superclass) { } // add the particle system - this.add(new THREE.Points(geometry, material)); + _this.add(new Points$1(geometry, material)); break; case MARKER_TEXT_VIEW_FACING: // only work on non-empty text if (message.text.length > 0) { // Use a THREE.Sprite to always be view-facing // ( code from http://stackoverflow.com/a/27348780 ) - var textColor = this.msgColor; - + var textColor = _this.msgColor; var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var textHeight = 100; var fontString = 'normal ' + textHeight + 'px sans-serif'; context.font = fontString; - var metrics = context.measureText( message.text ); + var metrics = context.measureText(message.text); var textWidth = metrics.width; - canvas.width = textWidth; // To account for overhang (like the letter 'g'), make the canvas bigger // The non-text portion is transparent anyway @@ -52266,274 +42604,271 @@ var Marker = /*@__PURE__*/(function (superclass) { // this does need to be set again context.font = fontString; - context.fillStyle = 'rgba(' - + Math.round(255 * textColor.r) + ', ' - + Math.round(255 * textColor.g) + ', ' - + Math.round(255 * textColor.b) + ', ' - + textColor.a + ')'; + context.fillStyle = 'rgba(' + Math.round(255 * textColor.r) + ', ' + Math.round(255 * textColor.g) + ', ' + Math.round(255 * textColor.b) + ', ' + textColor.a + ')'; context.textAlign = 'left'; context.textBaseline = 'middle'; - context.fillText( message.text, 0, canvas.height/2); - - var texture = new THREE.Texture(canvas); + context.fillText(message.text, 0, canvas.height / 2); + var texture = new Texture(canvas); texture.needsUpdate = true; - - var spriteMaterial = new THREE.SpriteMaterial({ + var spriteMaterial = new SpriteMaterial({ map: texture, // NOTE: This is needed for THREE.js r61, unused in r70 - useScreenCoordinates: false }); - var sprite = new THREE.Sprite( spriteMaterial ); + useScreenCoordinates: false + }); + var sprite = new Sprite(spriteMaterial); var textSize = message.scale.x; sprite.scale.set(textWidth / canvas.height * textSize, textSize, 1); - - this.add(sprite); } + _this.add(sprite); + } break; case MARKER_MESH_RESOURCE: // load and add the mesh var meshColorMaterial = null; - if(message.color.r !== 0 || message.color.g !== 0 || - message.color.b !== 0 || message.color.a !== 0) { + if (message.color.r !== 0 || message.color.g !== 0 || message.color.b !== 0 || message.color.a !== 0) { meshColorMaterial = colorMaterial; } - this.msgMesh = message.mesh_resource.substr(10); + _this.msgMesh = message.mesh_resource.substr(10); var meshResource = new MeshResource({ - path : path, - resource : this.msgMesh, - material : meshColorMaterial, + path: path, + resource: _this.msgMesh, + material: meshColorMaterial }); - this.add(meshResource); + _this.add(meshResource); break; case MARKER_TRIANGLE_LIST: // create the list of triangles var tri = new TriangleList({ - material : colorMaterial, - vertices : message.points, - colors : message.colors + material: colorMaterial, + vertices: message.points, + colors: message.colors }); tri.scale.set(message.scale.x, message.scale.y, message.scale.z); - this.add(tri); + _this.add(tri); break; default: console.error('Currently unsupported marker type: ' + message.type); break; } + return _this; } + _inherits(Marker, _THREE$Object3D); + return _createClass(Marker, [{ + key: "setPose", + value: + /** + * Set the pose of this marker to the given values. + * + * @param pose - the pose to set for this marker + */ + function setPose(pose) { + // set position information + this.position.x = pose.position.x; + this.position.y = pose.position.y; + this.position.z = pose.position.z; - if ( superclass ) Marker.__proto__ = superclass; - Marker.prototype = Object.create( superclass && superclass.prototype ); - Marker.prototype.constructor = Marker; - /** - * Set the pose of this marker to the given values. - * - * @param pose - the pose to set for this marker - */ - Marker.prototype.setPose = function setPose (pose) { - // set position information - this.position.x = pose.position.x; - this.position.y = pose.position.y; - this.position.z = pose.position.z; - - // set the rotation - this.quaternion.set(pose.orientation.x, pose.orientation.y, - pose.orientation.z, pose.orientation.w); - this.quaternion.normalize(); - - // update the world - this.updateMatrixWorld(); - }; - /** - * Update this marker. - * - * @param message - the marker message - * @return true on success otherwhise false is returned - */ - Marker.prototype.update = function update (message) { - // set the pose and get the color - this.setPose(message.pose); + // set the rotation + this.quaternion.set(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + this.quaternion.normalize(); - // Update color - if(message.color.r !== this.msgColor.r || - message.color.g !== this.msgColor.g || - message.color.b !== this.msgColor.b || - message.color.a !== this.msgColor.a) - { - var colorMaterial = makeColorMaterial( - message.color.r, message.color.g, - message.color.b, message.color.a); + // update the world + this.updateMatrixWorld(); + } + }, { + key: "update", + value: + /** + * Update this marker. + * + * @param message - the marker message + * @return true on success otherwhise false is returned + */ + function update(message) { + // set the pose and get the color + this.setPose(message.pose); + // Update color + if (message.color.r !== this.msgColor.r || message.color.g !== this.msgColor.g || message.color.b !== this.msgColor.b || message.color.a !== this.msgColor.a) { + var colorMaterial = makeColorMaterial(message.color.r, message.color.g, message.color.b, message.color.a); switch (message.type) { - case MARKER_LINE_STRIP: - case MARKER_LINE_LIST: - case MARKER_POINTS: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_POINTS: break; - case MARKER_ARROW: - case MARKER_CUBE: - case MARKER_SPHERE: - case MARKER_CYLINDER: - case MARKER_TRIANGLE_LIST: - case MARKER_TEXT_VIEW_FACING: - this.traverse (function (child){ - if (child instanceof THREE.Mesh) { - child.material = colorMaterial; - } + case MARKER_ARROW: + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + case MARKER_TRIANGLE_LIST: + case MARKER_TEXT_VIEW_FACING: + this.traverse(function (child) { + if (child instanceof Mesh) { + child.material = colorMaterial; + } }); break; - case MARKER_MESH_RESOURCE: + case MARKER_MESH_RESOURCE: var meshColorMaterial = null; - if(message.color.r !== 0 || message.color.g !== 0 || - message.color.b !== 0 || message.color.a !== 0) { - meshColorMaterial = this.colorMaterial; + if (message.color.r !== 0 || message.color.g !== 0 || message.color.b !== 0 || message.color.a !== 0) { + meshColorMaterial = this.colorMaterial; } - this.traverse (function (child){ - if (child instanceof THREE.Mesh) { - child.material = meshColorMaterial; - } + this.traverse(function (child) { + if (child instanceof Mesh) { + child.material = meshColorMaterial; + } }); break; - case MARKER_CUBE_LIST: - case MARKER_SPHERE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: // TODO Support to update color for MARKER_CUBE_LIST & MARKER_SPHERE_LIST return false; - default: + default: return false; } - this.msgColor = message.color; - } - - // Update geometry - var scaleChanged = - Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || - Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || - Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; - this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } - switch (message.type) { - case MARKER_CUBE: - case MARKER_SPHERE: - case MARKER_CYLINDER: - if(scaleChanged) { - return false; + // Update geometry + var scaleChanged = Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; + this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + switch (message.type) { + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + if (scaleChanged) { + return false; } break; - case MARKER_TEXT_VIEW_FACING: - if(scaleChanged || this.text !== message.text) { - return false; + case MARKER_TEXT_VIEW_FACING: + if (scaleChanged || this.text !== message.text) { + return false; } break; - case MARKER_MESH_RESOURCE: + case MARKER_MESH_RESOURCE: var meshResource = message.mesh_resource.substr(10); - if(meshResource !== this.msgMesh) { - return false; - } - if(scaleChanged) { - return false; + if (meshResource !== this.msgMesh) { + return false; } - break; - case MARKER_ARROW: - case MARKER_LINE_STRIP: - case MARKER_LINE_LIST: - case MARKER_CUBE_LIST: - case MARKER_SPHERE_LIST: - case MARKER_POINTS: - case MARKER_TRIANGLE_LIST: + if (scaleChanged) { + return false; + } + break; + case MARKER_ARROW: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: + case MARKER_POINTS: + case MARKER_TRIANGLE_LIST: // TODO: Check if geometry changed return false; + } + return true; } - - return true; - }; - /* - * Free memory of elements in this marker. - */ - Marker.prototype.dispose = function dispose () { - this.children.forEach(function(element) { - if (element instanceof MeshResource) { - element.children.forEach(function(scene) { - if (scene.material !== undefined) { - scene.material.dispose(); - } - scene.children.forEach(function(mesh) { - if (mesh.geometry !== undefined) { - mesh.geometry.dispose(); - } - if (mesh.material !== undefined) { - mesh.material.dispose(); + }, { + key: "dispose", + value: + /* + * Free memory of elements in this marker. + */ + function dispose() { + this.children.forEach(function (element) { + if (element instanceof MeshResource) { + element.children.forEach(function (scene) { + if (scene.material !== undefined) { + scene.material.dispose(); } - scene.remove(mesh); + scene.children.forEach(function (mesh) { + if (mesh.geometry !== undefined) { + mesh.geometry.dispose(); + } + if (mesh.material !== undefined) { + mesh.material.dispose(); + } + scene.remove(mesh); + }); + element.remove(scene); }); - element.remove(scene); - }); - } else { - if (element.geometry !== undefined) { + } else { + if (element.geometry !== undefined) { element.geometry.dispose(); - } - if (element.material !== undefined) { + } + if (element.material !== undefined) { element.material.dispose(); + } } - } - element.parent.remove(element); - }); - }; + element.parent.remove(element); + }); + } + }]); +}(Object3D); - return Marker; -}(THREE.Object3D)); +function _callSuper$t(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$t() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$t() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$t = function _isNativeReflectConstruct() { return !!t; })(); } +function _superPropGet(t, e, r, o) { var p = _get(_getPrototypeOf(1 & o ? t.prototype : t), e, r); return 2 & o ? function (t) { return p.apply(r, t); } : p; } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { +var InteractiveMarkerControl = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The main marker control object for an interactive marker. + * + * @constructor + * @param options - object with following keys: + * + * * parent - the parent of this control + * * message - the interactive marker control message + * * camera - the main camera associated with the viewer for this marker client + * * path (optional) - the base path to any meshes that will be loaded + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ function InteractiveMarkerControl(options) { - superclass.call(this); - var that = this; - + var _this; + _classCallCheck(this, InteractiveMarkerControl); + _this = _callSuper$t(this, InteractiveMarkerControl); + var that = _this; options = options || {}; - this.parent = options.parent; + _this.parent = options.parent; var handle = options.handle; var message = options.message; - this.message = message; - this.name = message.name; - this.camera = options.camera; - this.path = options.path || '/'; - this.loader = options.loader; - this.dragging = false; - this.startMousePos = new THREE.Vector2(); - this.isShift = false; - + _this.message = message; + _this.name = message.name; + _this.camera = options.camera; + _this.path = options.path || '/'; + _this.loader = options.loader; + _this.dragging = false; + _this.startMousePos = new Vector2(); + _this.isShift = false; // orientation for the control - var controlOri = new THREE.Quaternion(message.orientation.x, message.orientation.y, - message.orientation.z, message.orientation.w); + var controlOri = new Quaternion(message.orientation.x, message.orientation.y, message.orientation.z, message.orientation.w); controlOri.normalize(); // transform x axis into local frame - var controlAxis = new THREE.Vector3(1, 0, 0); + var controlAxis = new Vector3(1, 0, 0); controlAxis.applyQuaternion(controlOri); - - this.currentControlOri = new THREE.Quaternion(); + _this.currentControlOri = new Quaternion(); // determine mouse interaction switch (message.interaction_mode) { case INTERACTIVE_MARKER_MOVE_ROTATE_3D: case INTERACTIVE_MARKER_MOVE_3D: - this.addEventListener('mousemove', this.parent.move3d.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.move3d.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_MOVE_AXIS: - this.addEventListener('mousemove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); - this.addEventListener('touchmove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.moveAxis.bind(_this.parent, _this, controlAxis)); + _this.addEventListener('touchmove', _this.parent.moveAxis.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_ROTATE_AXIS: - this - .addEventListener('mousemove', this.parent.rotateAxis.bind(this.parent, this, controlOri)); + _this.addEventListener('mousemove', _this.parent.rotateAxis.bind(_this.parent, _this, controlOri)); break; case INTERACTIVE_MARKER_MOVE_PLANE: - this - .addEventListener('mousemove', this.parent.movePlane.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.movePlane.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_BUTTON: - this.addEventListener('click', this.parent.buttonClick.bind(this.parent, this)); + _this.addEventListener('click', _this.parent.buttonClick.bind(_this.parent, _this)); break; } @@ -52548,38 +42883,38 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { // check the mode if (message.interaction_mode !== INTERACTIVE_MARKER_NONE) { - this.addEventListener('mousedown', this.parent.startDrag.bind(this.parent, this)); - this.addEventListener('mouseup', this.parent.stopDrag.bind(this.parent, this)); - this.addEventListener('contextmenu', this.parent.showMenu.bind(this.parent, this)); - this.addEventListener('mouseup', function(event3d) { + _this.addEventListener('mousedown', _this.parent.startDrag.bind(_this.parent, _this)); + _this.addEventListener('mouseup', _this.parent.stopDrag.bind(_this.parent, _this)); + _this.addEventListener('contextmenu', _this.parent.showMenu.bind(_this.parent, _this)); + _this.addEventListener('mouseup', function (event3d) { if (that.startMousePos.distanceToSquared(event3d.mousePos) === 0) { event3d.type = 'contextmenu'; that.dispatchEvent(event3d); } }); - this.addEventListener('mouseover', stopPropagation); - this.addEventListener('mouseout', stopPropagation); - this.addEventListener('click', stopPropagation); - this.addEventListener('mousedown', function(event3d) { + _this.addEventListener('mouseover', stopPropagation); + _this.addEventListener('mouseout', stopPropagation); + _this.addEventListener('click', stopPropagation); + _this.addEventListener('mousedown', function (event3d) { that.startMousePos = event3d.mousePos; }); // touch support - this.addEventListener('touchstart', function(event3d) { + _this.addEventListener('touchstart', function (event3d) { if (event3d.domEvent.touches.length === 1) { event3d.type = 'mousedown'; event3d.domEvent.button = 0; that.dispatchEvent(event3d); } }); - this.addEventListener('touchmove', function(event3d) { + _this.addEventListener('touchmove', function (event3d) { if (event3d.domEvent.touches.length === 1) { event3d.type = 'mousemove'; event3d.domEvent.button = 0; that.dispatchEvent(event3d); } }); - this.addEventListener('touchend', function(event3d) { + _this.addEventListener('touchend', function (event3d) { if (event3d.domEvent.touches.length === 0) { event3d.domEvent.button = 0; event3d.type = 'mouseup'; @@ -52588,25 +42923,24 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { that.dispatchEvent(event3d); } }); - - window.addEventListener('keydown', function(event){ - if(event.keyCode === 16){ + window.addEventListener('keydown', function (event) { + if (event.keyCode === 16) { that.isShift = true; } }); - window.addEventListener('keyup', function(event){ - if(event.keyCode === 16){ + window.addEventListener('keyup', function (event) { + if (event.keyCode === 16) { that.isShift = false; } }); } // rotation behavior - var rotInv = new THREE.Quaternion(); - var posInv = this.parent.position.clone().multiplyScalar(-1); + var rotInv = new Quaternion(); + var posInv = _this.parent.position.clone().multiplyScalar(-1); switch (message.orientation_mode) { case INTERACTIVE_MARKER_INHERIT: - rotInv = this.parent.quaternion.clone().inverse(); + rotInv = _this.parent.quaternion.clone().inverse(); break; case INTERACTIVE_MARKER_FIXED: break; @@ -52620,26 +42954,26 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { // temporary TFClient to get transformations from InteractiveMarker // frame to potential child Marker frames var localTfClient = new ROSLIB__namespace.TFClient({ - ros : handle.tfClient.ros, - fixedFrame : handle.message.header.frame_id, - serverName : handle.tfClient.serverName + ros: handle.tfClient.ros, + fixedFrame: handle.message.header.frame_id, + serverName: handle.tfClient.serverName }); // create visuals (markers) - message.markers.forEach(function(markerMsg) { - var addMarker = function(transformMsg) { + message.markers.forEach(function (markerMsg) { + var addMarker = function addMarker(transformMsg) { var markerHelper = new Marker({ - message : markerMsg, - path : that.path, - loader : that.loader + message: markerMsg, + path: that.path, + loader: that.loader }); // if transformMsg isn't null, this was called by TFClient if (transformMsg !== null) { // get the current pose as a ROSLIB.Pose... var newPose = new ROSLIB__namespace.Pose({ - position : markerHelper.position, - orientation : markerHelper.quaternion + position: markerHelper.position, + orientation: markerHelper.quaternion }); // so we can apply the transform provided by the TFClient newPose.applyTransform(new ROSLIB__namespace.Transform(transformMsg)); @@ -52648,24 +42982,22 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { // apply it to sub-marker position to get sub-marker position // relative to parent marker var transformMarker = new Marker({ - message : markerMsg, - path : that.path, - loader : that.loader + message: markerMsg, + path: that.path, + loader: that.loader }); transformMarker.position.add(posInv); transformMarker.position.applyQuaternion(rotInv); transformMarker.quaternion.multiplyQuaternions(rotInv, transformMarker.quaternion); - var translation = new THREE.Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); + var translation = new Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); var transform = new ROSLIB__namespace.Transform({ - translation : translation, - orientation : transformMarker.quaternion + translation: translation, + orientation: transformMarker.quaternion }); // apply that transform too newPose.applyTransform(transform); - markerHelper.setPose(newPose); - markerHelper.updateMatrixWorld(); // we only need to set the pose once - at least, this is what RViz seems to be doing, might change in the future localTfClient.unsubscribe(markerMsg.header.frame_id); @@ -52686,70 +43018,82 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { addMarker(null); } }); + return _this; } - - if ( superclass ) InteractiveMarkerControl.__proto__ = superclass; - InteractiveMarkerControl.prototype = Object.create( superclass && superclass.prototype ); - InteractiveMarkerControl.prototype.constructor = InteractiveMarkerControl; - InteractiveMarkerControl.prototype.updateMatrixWorld = function updateMatrixWorld (force) { - var that = this; - var message = this.message; - switch (message.orientation_mode) { - case INTERACTIVE_MARKER_INHERIT: - superclass.prototype.updateMatrixWorld.call(this, force); - that.currentControlOri.copy(that.quaternion); - that.currentControlOri.normalize(); - break; - case INTERACTIVE_MARKER_FIXED: - that.quaternion.copy(that.parent.quaternion.clone().inverse()); - that.updateMatrix(); - that.matrixWorldNeedsUpdate = true; - superclass.prototype.updateMatrixWorld.call(this, force); - that.currentControlOri.copy(that.quaternion); - break; - case INTERACTIVE_MARKER_VIEW_FACING: - that.camera.updateMatrixWorld(); - var cameraRot = new THREE.Matrix4().extractRotation(that.camera.matrixWorld); - - var ros2Gl = new THREE.Matrix4(); - var r90 = Math.PI * 0.5; - var rv = new THREE.Euler(-r90, 0, r90); - ros2Gl.makeRotationFromEuler(rv); - - var worldToLocal = new THREE.Matrix4(); - worldToLocal.getInverse(that.parent.matrixWorld); - - cameraRot.multiplyMatrices(cameraRot, ros2Gl); - cameraRot.multiplyMatrices(worldToLocal, cameraRot); - - that.currentControlOri.setFromRotationMatrix(cameraRot); - - // check the orientation - if (!message.independent_marker_orientation) { - that.quaternion.copy(that.currentControlOri); + _inherits(InteractiveMarkerControl, _THREE$Object3D); + return _createClass(InteractiveMarkerControl, [{ + key: "updateMatrixWorld", + value: function updateMatrixWorld(force) { + var that = this; + var message = this.message; + switch (message.orientation_mode) { + case INTERACTIVE_MARKER_INHERIT: + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + that.currentControlOri.copy(that.quaternion); + that.currentControlOri.normalize(); + break; + case INTERACTIVE_MARKER_FIXED: + that.quaternion.copy(that.parent.quaternion.clone().inverse()); that.updateMatrix(); that.matrixWorldNeedsUpdate = true; - } - superclass.prototype.updateMatrixWorld.call(this, force); - break; - default: - console.error('Unkown orientation mode: ' + message.orientation_mode); - break; + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + that.currentControlOri.copy(that.quaternion); + break; + case INTERACTIVE_MARKER_VIEW_FACING: + that.camera.updateMatrixWorld(); + var cameraRot = new Matrix4().extractRotation(that.camera.matrixWorld); + var ros2Gl = new Matrix4(); + var r90 = Math.PI * 0.5; + var rv = new Euler(-r90, 0, r90); + ros2Gl.makeRotationFromEuler(rv); + var worldToLocal = new Matrix4(); + worldToLocal.getInverse(that.parent.matrixWorld); + cameraRot.multiplyMatrices(cameraRot, ros2Gl); + cameraRot.multiplyMatrices(worldToLocal, cameraRot); + that.currentControlOri.setFromRotationMatrix(cameraRot); + + // check the orientation + if (!message.independent_marker_orientation) { + that.quaternion.copy(that.currentControlOri); + that.updateMatrix(); + that.matrixWorldNeedsUpdate = true; + } + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + break; + default: + console.error('Unkown orientation mode: ' + message.orientation_mode); + break; + } } - }; + }]); +}(Object3D); - return InteractiveMarkerControl; -}(THREE.Object3D)); +function _callSuper$s(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$s() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$s() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$s = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { +var InteractiveMarkerMenu = /*#__PURE__*/function (_THREE$EventDispatche) { + /** + * A menu for an interactive marker. This will be overlayed on the canvas. + * + * @constructor + * @param options - object with following keys: + * + * * menuEntries - the menu entries to add + * * className (optional) - a custom CSS class for the menu div + * * entryClassName (optional) - a custom CSS class for the menu entry + * * overlayClassName (optional) - a custom CSS class for the menu overlay + * * menuFontSize (optional) - the menu font size + */ function InteractiveMarkerMenu(options) { - superclass.call(this); - var that = this; + var _this; + _classCallCheck(this, InteractiveMarkerMenu); + _this = _callSuper$s(this, InteractiveMarkerMenu); + var that = _this; options = options || {}; var menuEntries = options.menuEntries; var className = options.className || 'default-interactive-marker-menu'; @@ -52760,75 +43104,58 @@ var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { // holds the menu tree var allMenus = []; allMenus[0] = { - children : [] + children: [] }; - // create the CSS for this marker if it has not been created if (document.getElementById('default-interactive-marker-menu-css') === null) { var style = document.createElement('style'); style.id = 'default-interactive-marker-menu-css'; style.type = 'text/css'; - style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' - + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' - + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize +';' + 'z-index: 1002;' - + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' - + 'margin: 0px;' + 'list-style-type: none;' + '}' - + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' - + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' - + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' - + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' - + ' background-color: #666666;' + ' cursor: pointer;' + '}' - + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' - + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' - + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' - + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' - + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; + style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize + ';' + 'z-index: 1002;' + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' + 'margin: 0px;' + 'list-style-type: none;' + '}' + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' + ' background-color: #666666;' + ' cursor: pointer;' + '}' + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; document.getElementsByTagName('head')[0].appendChild(style); } // place the menu in a div - this.menuDomElem = document.createElement('div'); - this.menuDomElem.style.position = 'absolute'; - this.menuDomElem.className = className; - this.menuDomElem.addEventListener('contextmenu', function(event) { + _this.menuDomElem = document.createElement('div'); + _this.menuDomElem.style.position = 'absolute'; + _this.menuDomElem.className = className; + _this.menuDomElem.addEventListener('contextmenu', function (event) { event.preventDefault(); }); // create the overlay DOM - this.overlayDomElem = document.createElement('div'); - this.overlayDomElem.className = overlayClassName; - - this.hideListener = this.hide.bind(this); - this.overlayDomElem.addEventListener('contextmenu', this.hideListener); - this.overlayDomElem.addEventListener('click', this.hideListener); - this.overlayDomElem.addEventListener('touchstart', this.hideListener); + _this.overlayDomElem = document.createElement('div'); + _this.overlayDomElem.className = overlayClassName; + _this.hideListener = _this.hide.bind(_this); + _this.overlayDomElem.addEventListener('contextmenu', _this.hideListener); + _this.overlayDomElem.addEventListener('click', _this.hideListener); + _this.overlayDomElem.addEventListener('touchstart', _this.hideListener); // parse all entries and link children to parents var i, entry, id; - for ( i = 0; i < menuEntries.length; i++) { + for (i = 0; i < menuEntries.length; i++) { entry = menuEntries[i]; id = entry.id; allMenus[id] = { - title : entry.title, - id : id, - children : [] + title: entry.title, + id: id, + children: [] }; } - for ( i = 0; i < menuEntries.length; i++) { + for (i = 0; i < menuEntries.length; i++) { entry = menuEntries[i]; id = entry.id; var menu = allMenus[id]; var parent = allMenus[entry.parent_id]; parent.children.push(menu); } - function emitMenuSelect(menuEntry, domEvent) { this.dispatchEvent({ - type : 'menu-select', - domEvent : domEvent, - id : menuEntry.id, - controlName : this.controlName + type: 'menu-select', + domEvent: domEvent, + id: menuEntry.id, + controlName: this.controlName }); this.hide(domEvent); } @@ -52840,19 +43167,15 @@ var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { * @param parentMenu - the parent menu */ function makeUl(parentDomElem, parentMenu) { - var ulElem = document.createElement('ul'); parentDomElem.appendChild(ulElem); - var children = parentMenu.children; - - for ( var i = 0; i < children.length; i++) { + for (var i = 0; i < children.length; i++) { var liElem = document.createElement('li'); var divElem = document.createElement('div'); divElem.appendChild(document.createTextNode(children[i].title)); ulElem.appendChild(liElem); liElem.appendChild(divElem); - if (children[i].children.length > 0) { makeUl(liElem, children[i]); divElem.addEventListener('click', that.hide.bind(that)); @@ -52863,751 +43186,2505 @@ var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { divElem.className = 'default-interactive-marker-menu-entry'; } } - } // construct DOM element - makeUl(this.menuDomElem, allMenus[0]); + makeUl(_this.menuDomElem, allMenus[0]); + return _this; } + _inherits(InteractiveMarkerMenu, _THREE$EventDispatche); + return _createClass(InteractiveMarkerMenu, [{ + key: "show", + value: + /** + * Shoe the menu DOM element. + * + * @param control - the control for the menu + * @param event - the event that caused this + */ + function show(control, event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + this.controlName = control.name; - if ( superclass ) InteractiveMarkerMenu.__proto__ = superclass; - InteractiveMarkerMenu.prototype = Object.create( superclass && superclass.prototype ); - InteractiveMarkerMenu.prototype.constructor = InteractiveMarkerMenu; - /** - * Shoe the menu DOM element. - * - * @param control - the control for the menu - * @param event - the event that caused this - */ - InteractiveMarkerMenu.prototype.show = function show (control, event) { - if (event && event.preventDefault) { - event.preventDefault(); - } - - this.controlName = control.name; - - // position it on the click - if (event.domEvent.changedTouches !== undefined) { - // touch click - this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; - this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; - } else { - // mouse click - this.menuDomElem.style.left = event.domEvent.clientX + 'px'; - this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + // position it on the click + if (event.domEvent.changedTouches !== undefined) { + // touch click + this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; + this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; + } else { + // mouse click + this.menuDomElem.style.left = event.domEvent.clientX + 'px'; + this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + } + document.body.appendChild(this.overlayDomElem); + document.body.appendChild(this.menuDomElem); } - document.body.appendChild(this.overlayDomElem); - document.body.appendChild(this.menuDomElem); - }; - /** - * Hide the menu DOM element. - * - * @param event (optional) - the event that caused this - */ - InteractiveMarkerMenu.prototype.hide = function hide (event) { - if (event && event.preventDefault) { - event.preventDefault(); + }, { + key: "hide", + value: + /** + * Hide the menu DOM element. + * + * @param event (optional) - the event that caused this + */ + function hide(event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + document.body.removeChild(this.overlayDomElem); + document.body.removeChild(this.menuDomElem); } + }]); +}(EventDispatcher); - document.body.removeChild(this.overlayDomElem); - document.body.removeChild(this.menuDomElem); - }; - - return InteractiveMarkerMenu; -}(THREE.EventDispatcher)); +function _callSuper$r(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$r() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$r() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$r = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarker = /*@__PURE__*/(function (superclass) { +var InteractiveMarker = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The main interactive marker object. + * + * @constructor + * @param options - object with following keys: + * + * * handle - the ROS3D.InteractiveMarkerHandle for this marker + * * camera - the main camera associated with the viewer for this marker + * * path (optional) - the base path to any meshes that will be loaded + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ function InteractiveMarker(options) { - superclass.call(this); + var _this; + _classCallCheck(this, InteractiveMarker); + _this = _callSuper$r(this, InteractiveMarker); options = options || {}; var handle = options.handle; - this.name = handle.name; + _this.name = handle.name; var camera = options.camera; var path = options.path || '/'; var loader = options.loader; - this.dragging = false; + _this.dragging = false; // set the initial pose - this.onServerSetPose({ - pose : handle.pose + _this.onServerSetPose({ + pose: handle.pose }); // information on where the drag started - this.dragStart = { - position : new THREE.Vector3(), - orientation : new THREE.Quaternion(), - positionWorld : new THREE.Vector3(), - orientationWorld : new THREE.Quaternion(), - event3d : {} + _this.dragStart = { + position: new Vector3(), + orientation: new Quaternion(), + positionWorld: new Vector3(), + orientationWorld: new Quaternion(), + event3d: {} }; // add each control message - handle.controls.forEach(function(controlMessage) { + handle.controls.forEach(function (controlMessage) { this.add(new InteractiveMarkerControl({ - parent : this, - handle : handle, - message : controlMessage, - camera : camera, - path : path, - loader : loader + parent: this, + handle: handle, + message: controlMessage, + camera: camera, + path: path, + loader: loader })); - }.bind(this)); + }.bind(_this)); // check for any menus if (handle.menuEntries.length > 0) { - this.menu = new InteractiveMarkerMenu({ - menuEntries : handle.menuEntries, - menuFontSize : handle.menuFontSize + _this.menu = new InteractiveMarkerMenu({ + menuEntries: handle.menuEntries, + menuFontSize: handle.menuFontSize }); // forward menu select events - this.menu.addEventListener('menu-select', function(event) { + _this.menu.addEventListener('menu-select', function (event) { this.dispatchEvent(event); - }.bind(this)); + }.bind(_this)); } + return _this; } - - if ( superclass ) InteractiveMarker.__proto__ = superclass; - InteractiveMarker.prototype = Object.create( superclass && superclass.prototype ); - InteractiveMarker.prototype.constructor = InteractiveMarker; - /** - * Show the interactive marker menu associated with this marker. - * - * @param control - the control to use - * @param event - the event that caused this - */ - InteractiveMarker.prototype.showMenu = function showMenu (control, event) { - if (this.menu) { - this.menu.show(control, event); + _inherits(InteractiveMarker, _THREE$Object3D); + return _createClass(InteractiveMarker, [{ + key: "showMenu", + value: + /** + * Show the interactive marker menu associated with this marker. + * + * @param control - the control to use + * @param event - the event that caused this + */ + function showMenu(control, event) { + if (this.menu) { + this.menu.show(control, event); + } } - }; - /** - * Move the axis based on the given event information. - * - * @param control - the control to use - * @param origAxis - the origin of the axis - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.moveAxis = function moveAxis (control, origAxis, event3d) { - if (this.dragging) { - var currentControlOri = control.currentControlOri; - var axis = origAxis.clone().applyQuaternion(currentControlOri); - // get move axis in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); - - var axisRay = new THREE.Ray(originWorld, axisWorld); - - // find closest point to mouse on axis - var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); - - // offset from drag start position - var p = new THREE.Vector3(); - p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation) - .multiplyScalar(t)); - this.setPosition(control, p); - - - event3d.stopPropagation(); + }, { + key: "moveAxis", + value: + /** + * Move the axis based on the given event information. + * + * @param control - the control to use + * @param origAxis - the origin of the axis + * @param event3d - the event that caused this + */ + function moveAxis(control, origAxis, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var axis = origAxis.clone().applyQuaternion(currentControlOri); + // get move axis in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); + var axisRay = new Ray(originWorld, axisWorld); + + // find closest point to mouse on axis + var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); + + // offset from drag start position + var p = new Vector3(); + p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(t)); + this.setPosition(control, p); + event3d.stopPropagation(); + } } - }; + }, { + key: "move3d", + value: + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + function move3d(control, origNormal, event3d) { + // by default, move in a plane + if (this.dragging) { + if (control.isShift) ; else { + // we want to use the origin plane that is closest to the camera + var cameraVector = control.camera.getWorldDirection(); + var x = Math.abs(cameraVector.x); + var y = Math.abs(cameraVector.y); + var z = Math.abs(cameraVector.z); + var controlOri = new Quaternion(1, 0, 0, 1); + if (y > x && y > z) { + // orientation for the control + controlOri = new Quaternion(0, 0, 1, 1); + } else if (z > x && z > y) { + // orientation for the control + controlOri = new Quaternion(0, 1, 0, 1); + } + controlOri.normalize(); - /** - * Move with respect to the plane based on the contorl and event. - * - * @param control - the control to use - * @param origNormal - the normal of the origin - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.move3d = function move3d (control, origNormal, event3d) { - // by default, move in a plane - if (this.dragging) { - - if(control.isShift);else { - // we want to use the origin plane that is closest to the camera - var cameraVector = control.camera.getWorldDirection(); - var x = Math.abs(cameraVector.x); - var y = Math.abs(cameraVector.y); - var z = Math.abs(cameraVector.z); - var controlOri = new THREE.Quaternion(1, 0, 0, 1); - if(y > x && y > z){ - // orientation for the control - controlOri = new THREE.Quaternion(0, 0, 1, 1); - }else if(z > x && z > y){ - // orientation for the control - controlOri = new THREE.Quaternion(0, 1, 0, 1); + // transform x axis into local frame + origNormal = new Vector3(1, 0, 0); + origNormal.applyQuaternion(controlOri); + this.movePlane(control, origNormal, event3d); } - controlOri.normalize(); - - // transform x axis into local frame - origNormal = new THREE.Vector3(1, 0, 0); - origNormal.applyQuaternion(controlOri); - this.movePlane(control, origNormal, event3d); } } - }; - /** - * Move with respect to the plane based on the contorl and event. - * - * @param control - the control to use - * @param origNormal - the normal of the origin - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.movePlane = function movePlane (control, origNormal, event3d) { - if (this.dragging) { - var currentControlOri = control.currentControlOri; - var normal = origNormal.clone().applyQuaternion(currentControlOri); - // get plane params in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); - - // intersect mouse ray with plane - var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); - - // offset from drag start position - var p = new THREE.Vector3(); - p.subVectors(intersection, originWorld); - p.add(this.dragStart.positionWorld); - this.setPosition(control, p); + }, { + key: "movePlane", + value: + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + function movePlane(control, origNormal, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var normal = origNormal.clone().applyQuaternion(currentControlOri); + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset from drag start position + var p = new Vector3(); + p.subVectors(intersection, originWorld); + p.add(this.dragStart.positionWorld); + this.setPosition(control, p); + event3d.stopPropagation(); + } + } + }, { + key: "rotateAxis", + value: + /** + * Rotate based on the control and event given. + * + * @param control - the control to use + * @param origOrientation - the orientation of the origin + * @param event3d - the event that caused this + */ + function rotateAxis(control, origOrientation, event3d) { + if (this.dragging) { + control.updateMatrixWorld(); + var currentControlOri = control.currentControlOri; + var orientation = currentControlOri.clone().multiply(origOrientation.clone()); + var normal = new Vector3(1, 0, 0).applyQuaternion(orientation); + + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset local origin to lie on intersection plane + var normalRay = new Ray(this.dragStart.positionWorld, normalWorld); + var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); + + // rotates from world to plane coords + var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); + var orientationWorldInv = orientationWorld.clone().inverse(); + + // rotate original and current intersection into local coords + intersection.sub(rotOrigin); + intersection.applyQuaternion(orientationWorldInv); + var origIntersection = this.dragStart.event3d.intersection.point.clone(); + origIntersection.sub(rotOrigin); + origIntersection.applyQuaternion(orientationWorldInv); + + // compute relative 2d angle + var a1 = Math.atan2(intersection.y, intersection.z); + var a2 = Math.atan2(origIntersection.y, origIntersection.z); + var a = a2 - a1; + var rot = new Quaternion(); + rot.setFromAxisAngle(normal, a); + + // rotate + this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); + + // offset from drag start position + event3d.stopPropagation(); + } + } + }, { + key: "feedbackEvent", + value: + /** + * Dispatch the given event type. + * + * @param type - the type of event + * @param control - the control to use + */ + function feedbackEvent(type, control) { + this.dispatchEvent({ + type: type, + position: this.position.clone(), + orientation: this.quaternion.clone(), + controlName: control.name + }); + } + }, { + key: "startDrag", + value: + /** + * Start a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function startDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = true; + this.updateMatrixWorld(true); + var scale = new Vector3(); + this.matrixWorld.decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); + this.dragStart.position = this.position.clone(); + this.dragStart.orientation = this.quaternion.clone(); + this.dragStart.event3d = event3d; + this.feedbackEvent('user-mousedown', control); + } + } + }, { + key: "stopDrag", + value: + /** + * Stop a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function stopDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = false; + this.dragStart.event3d = {}; + this.onServerSetPose(this.bufferedPoseEvent); + this.bufferedPoseEvent = undefined; + this.feedbackEvent('user-mouseup', control); + } + } + }, { + key: "buttonClick", + value: + /** + * Handle a button click. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function buttonClick(control, event3d) { event3d.stopPropagation(); + this.feedbackEvent('user-button-click', control); } - }; - /** - * Rotate based on the control and event given. - * - * @param control - the control to use - * @param origOrientation - the orientation of the origin - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.rotateAxis = function rotateAxis (control, origOrientation, event3d) { - if (this.dragging) { - control.updateMatrixWorld(); - - var currentControlOri = control.currentControlOri; - var orientation = currentControlOri.clone().multiply(origOrientation.clone()); - - var normal = (new THREE.Vector3(1, 0, 0)).applyQuaternion(orientation); - - // get plane params in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); - - // intersect mouse ray with plane - var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); - - // offset local origin to lie on intersection plane - var normalRay = new THREE.Ray(this.dragStart.positionWorld, normalWorld); - var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); - - // rotates from world to plane coords - var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); - var orientationWorldInv = orientationWorld.clone().inverse(); - - // rotate original and current intersection into local coords - intersection.sub(rotOrigin); - intersection.applyQuaternion(orientationWorldInv); + }, { + key: "setPosition", + value: + /** + * Handle a user pose change for the position. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function setPosition(control, position) { + this.position.copy(position); + this.feedbackEvent('user-pose-change', control); + } + }, { + key: "setOrientation", + value: + /** + * Handle a user pose change for the orientation. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function setOrientation(control, orientation) { + orientation.normalize(); + this.quaternion.copy(orientation); + this.feedbackEvent('user-pose-change', control); + } + }, { + key: "onServerSetPose", + value: + /** + * Update the marker based when the pose is set from the server. + * + * @param event - the event that caused this + */ + function onServerSetPose(event) { + if (event !== undefined) { + // don't update while dragging + if (this.dragging) { + this.bufferedPoseEvent = event; + } else { + var pose = event.pose; + this.position.copy(pose.position); + this.quaternion.copy(pose.orientation); + this.updateMatrixWorld(true); + } + } + } + }, { + key: "dispose", + value: + /** + * Free memory of elements in this marker. + */ + function dispose() { + this.children.forEach(function (intMarkerControl) { + intMarkerControl.children.forEach(function (marker) { + marker.dispose(); + intMarkerControl.remove(marker); + }); + this.remove(intMarkerControl); + }.bind(this)); + } + }]); +}(Object3D); - var origIntersection = this.dragStart.event3d.intersection.point.clone(); - origIntersection.sub(rotOrigin); - origIntersection.applyQuaternion(orientationWorldInv); +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} - // compute relative 2d angle - var a1 = Math.atan2(intersection.y, intersection.z); - var a2 = Math.atan2(origIntersection.y, origIntersection.z); - var a = a2 - a1; +var eventemitter2 = {exports: {}}; - var rot = new THREE.Quaternion(); - rot.setFromAxisAngle(normal, a); +/*! + * EventEmitter2 + * https://github.com/hij1nx/EventEmitter2 + * + * Copyright (c) 2013 hij1nx + * Licensed under the MIT license. + */ +eventemitter2.exports; + +(function (module, exports) { +!function(undefined$1) { + var hasOwnProperty= Object.hasOwnProperty; + var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + var defaultMaxListeners = 10; + var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; + var symbolsSupported= typeof Symbol==='function'; + var reflectSupported= typeof Reflect === 'object'; + var setImmediateSupported= typeof setImmediate === 'function'; + var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; + var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ + var arr= Object.getOwnPropertyNames(obj); + arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); + return arr; + }) : Object.keys; + + function init() { + this._events = {}; + if (this._conf) { + configure.call(this, this._conf); + } + } + + function configure(conf) { + if (conf) { + this._conf = conf; + + conf.delimiter && (this.delimiter = conf.delimiter); + + if(conf.maxListeners!==undefined$1){ + this._maxListeners= conf.maxListeners; + } + + conf.wildcard && (this.wildcard = conf.wildcard); + conf.newListener && (this._newListener = conf.newListener); + conf.removeListener && (this._removeListener = conf.removeListener); + conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); + conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); + + if (this.wildcard) { + this.listenerTree = {}; + } + } + } + + function logPossibleMemoryLeak(count, eventName) { + var errorMsg = '(node) warning: possible EventEmitter memory ' + + 'leak detected. ' + count + ' listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.'; + + if(this.verboseMemoryLeak){ + errorMsg += ' Event name: ' + eventName + '.'; + } + + if(typeof process !== 'undefined' && process.emitWarning){ + var e = new Error(errorMsg); + e.name = 'MaxListenersExceededWarning'; + e.emitter = this; + e.count = count; + process.emitWarning(e); + } else { + console.error(errorMsg); + + if (console.trace){ + console.trace(); + } + } + } + + var toArray = function (a, b, c) { + var n = arguments.length; + switch (n) { + case 0: + return []; + case 1: + return [a]; + case 2: + return [a, b]; + case 3: + return [a, b, c]; + default: + var arr = new Array(n); + while (n--) { + arr[n] = arguments[n]; + } + return arr; + } + }; + + function toObject(keys, values) { + var obj = {}; + var key; + var len = keys.length; + var valuesCount = values ? value.length : 0; + for (var i = 0; i < len; i++) { + key = keys[i]; + obj[key] = i < valuesCount ? values[i] : undefined$1; + } + return obj; + } + + function TargetObserver(emitter, target, options) { + this._emitter = emitter; + this._target = target; + this._listeners = {}; + this._listenersCount = 0; + + var on, off; + + if (options.on || options.off) { + on = options.on; + off = options.off; + } + + if (target.addEventListener) { + on = target.addEventListener; + off = target.removeEventListener; + } else if (target.addListener) { + on = target.addListener; + off = target.removeListener; + } else if (target.on) { + on = target.on; + off = target.off; + } + + if (!on && !off) { + throw Error('target does not implement any known event API'); + } + + if (typeof on !== 'function') { + throw TypeError('on method must be a function'); + } + + if (typeof off !== 'function') { + throw TypeError('off method must be a function'); + } + + this._on = on; + this._off = off; + + var _observers= emitter._observers; + if(_observers){ + _observers.push(this); + }else { + emitter._observers= [this]; + } + } + + Object.assign(TargetObserver.prototype, { + subscribe: function(event, localEvent, reducer){ + var observer= this; + var target= this._target; + var emitter= this._emitter; + var listeners= this._listeners; + var handler= function(){ + var args= toArray.apply(null, arguments); + var eventObj= { + data: args, + name: localEvent, + original: event + }; + if(reducer){ + var result= reducer.call(target, eventObj); + if(result!==false){ + emitter.emit.apply(emitter, [eventObj.name].concat(args)); + } + return; + } + emitter.emit.apply(emitter, [localEvent].concat(args)); + }; + + + if(listeners[event]){ + throw Error('Event \'' + event + '\' is already listening'); + } + + this._listenersCount++; + + if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ + + this._onNewListener = function (_event) { + if (_event === localEvent && listeners[event] === null) { + listeners[event] = handler; + observer._on.call(target, event, handler); + } + }; + + emitter.on('newListener', this._onNewListener); + + this._onRemoveListener= function(_event){ + if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ + listeners[event]= null; + observer._off.call(target, event, handler); + } + }; + + listeners[event]= null; + + emitter.on('removeListener', this._onRemoveListener); + }else { + listeners[event]= handler; + observer._on.call(target, event, handler); + } + }, + + unsubscribe: function(event){ + var observer= this; + var listeners= this._listeners; + var emitter= this._emitter; + var handler; + var events; + var off= this._off; + var target= this._target; + var i; + + if(event && typeof event!=='string'){ + throw TypeError('event must be a string'); + } + + function clearRefs(){ + if(observer._onNewListener){ + emitter.off('newListener', observer._onNewListener); + emitter.off('removeListener', observer._onRemoveListener); + observer._onNewListener= null; + observer._onRemoveListener= null; + } + var index= findTargetIndex.call(emitter, observer); + emitter._observers.splice(index, 1); + } + + if(event){ + handler= listeners[event]; + if(!handler) return; + off.call(target, event, handler); + delete listeners[event]; + if(!--this._listenersCount){ + clearRefs(); + } + }else { + events= ownKeys(listeners); + i= events.length; + while(i-->0){ + event= events[i]; + off.call(target, event, listeners[event]); + } + this._listeners= {}; + this._listenersCount= 0; + clearRefs(); + } + } + }); + + function resolveOptions(options, schema, reducers, allowUnknown) { + var computedOptions = Object.assign({}, schema); + + if (!options) return computedOptions; + + if (typeof options !== 'object') { + throw TypeError('options must be an object') + } + + var keys = Object.keys(options); + var length = keys.length; + var option, value; + var reducer; + + function reject(reason) { + throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) + } + + for (var i = 0; i < length; i++) { + option = keys[i]; + if (!allowUnknown && !hasOwnProperty.call(schema, option)) { + throw Error('Unknown "' + option + '" option'); + } + value = options[option]; + if (value !== undefined$1) { + reducer = reducers[option]; + computedOptions[option] = reducer ? reducer(value, reject) : value; + } + } + return computedOptions; + } + + function constructorReducer(value, reject) { + if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { + reject('value must be a constructor'); + } + return value; + } + + function makeTypeReducer(types) { + var message= 'value must be type of ' + types.join('|'); + var len= types.length; + var firstType= types[0]; + var secondType= types[1]; + + if (len === 1) { + return function (v, reject) { + if (typeof v === firstType) { + return v; + } + reject(message); + } + } + + if (len === 2) { + return function (v, reject) { + var kind= typeof v; + if (kind === firstType || kind === secondType) return v; + reject(message); + } + } + + return function (v, reject) { + var kind = typeof v; + var i = len; + while (i-- > 0) { + if (kind === types[i]) return v; + } + reject(message); + } + } + + var functionReducer= makeTypeReducer(['function']); + + var objectFunctionReducer= makeTypeReducer(['object', 'function']); + + function makeCancelablePromise(Promise, executor, options) { + var isCancelable; + var callbacks; + var timer= 0; + var subscriptionClosed; + + var promise = new Promise(function (resolve, reject, onCancel) { + options= resolveOptions(options, { + timeout: 0, + overload: false + }, { + timeout: function(value, reject){ + value*= 1; + if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { + reject('timeout must be a positive number'); + } + return value; + } + }); + + isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; + + function cleanup() { + if (callbacks) { + callbacks = null; + } + if (timer) { + clearTimeout(timer); + timer = 0; + } + } + + var _resolve= function(value){ + cleanup(); + resolve(value); + }; + + var _reject= function(err){ + cleanup(); + reject(err); + }; + + if (isCancelable) { + executor(_resolve, _reject, onCancel); + } else { + callbacks = [function(reason){ + _reject(reason || Error('canceled')); + }]; + executor(_resolve, _reject, function (cb) { + if (subscriptionClosed) { + throw Error('Unable to subscribe on cancel event asynchronously') + } + if (typeof cb !== 'function') { + throw TypeError('onCancel callback must be a function'); + } + callbacks.push(cb); + }); + subscriptionClosed= true; + } + + if (options.timeout > 0) { + timer= setTimeout(function(){ + var reason= Error('timeout'); + reason.code = 'ETIMEDOUT'; + timer= 0; + promise.cancel(reason); + reject(reason); + }, options.timeout); + } + }); + + if (!isCancelable) { + promise.cancel = function (reason) { + if (!callbacks) { + return; + } + var length = callbacks.length; + for (var i = 1; i < length; i++) { + callbacks[i](reason); + } + // internal callback to reject the promise + callbacks[0](reason); + callbacks = null; + }; + } + + return promise; + } + + function findTargetIndex(observer) { + var observers = this._observers; + if(!observers){ + return -1; + } + var len = observers.length; + for (var i = 0; i < len; i++) { + if (observers[i]._target === observer) return i; + } + return -1; + } + + // Attention, function return type now is array, always ! + // It has zero elements if no any matches found and one or more + // elements (leafs) if there are matches + // + function searchListenerTree(handlers, type, tree, i, typeLength) { + if (!tree) { + return null; + } + + if (i === 0) { + var kind = typeof type; + if (kind === 'string') { + var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; + if ((n = type.indexOf(delimiter)) !== -1) { + ns = new Array(5); + do { + ns[l++] = type.slice(j, n); + j = n + dl; + } while ((n = type.indexOf(delimiter, j)) !== -1); + + ns[l++] = type.slice(j); + type = ns; + typeLength = l; + } else { + type = [type]; + typeLength = 1; + } + } else if (kind === 'object') { + typeLength = type.length; + } else { + type = [type]; + typeLength = 1; + } + } + + var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], + nextType = type[i + 1], branches, _listeners; + + if (i === typeLength) { + // + // If at the end of the event(s) list and the tree has listeners + // invoke those listeners. + // + + if(tree._listeners) { + if (typeof tree._listeners === 'function') { + handlers && handlers.push(tree._listeners); + listeners = [tree]; + } else { + handlers && handlers.push.apply(handlers, tree._listeners); + listeners = [tree]; + } + } + } else { + + if (currentType === '*') { + // + // If the event emitted is '*' at this part + // or there is a concrete match at this patch + // + branches = ownKeys(tree); + n = branches.length; + while (n-- > 0) { + branch = branches[n]; + if (branch !== '_listeners') { + _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + } + return listeners; + } else if (currentType === '**') { + endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); + if (endReached && tree._listeners) { + // The next element has a _listeners, add it to the handlers. + listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); + } + + branches = ownKeys(tree); + n = branches.length; + while (n-- > 0) { + branch = branches[n]; + if (branch !== '_listeners') { + if (branch === '*' || branch === '**') { + if (tree[branch]._listeners && !endReached) { + _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); + } else if (branch === nextType) { + _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); + } else { + // No match on this one, shift into the tree but not in the type array. + _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); + } + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + } + return listeners; + } else if (tree[currentType]) { + listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); + } + } + + xTree = tree['*']; + if (xTree) { + // + // If the listener tree will allow any match for this part, + // then recursively explore all branches of the tree + // + searchListenerTree(handlers, type, xTree, i + 1, typeLength); + } + + xxTree = tree['**']; + if (xxTree) { + if (i < typeLength) { + if (xxTree._listeners) { + // If we have a listener on a '**', it will catch all, so add its handler. + searchListenerTree(handlers, type, xxTree, typeLength, typeLength); + } + + // Build arrays of matching next branches and others. + branches= ownKeys(xxTree); + n= branches.length; + while(n-->0){ + branch= branches[n]; + if (branch !== '_listeners') { + if (branch === nextType) { + // We know the next element will match, so jump twice. + searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); + } else if (branch === currentType) { + // Current node matches, move into the tree. + searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); + } else { + isolatedBranch = {}; + isolatedBranch[branch] = xxTree[branch]; + searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); + } + } + } + } else if (xxTree._listeners) { + // We have reached the end and still on a '**' + searchListenerTree(handlers, type, xxTree, typeLength, typeLength); + } else if (xxTree['*'] && xxTree['*']._listeners) { + searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); + } + } + + return listeners; + } + + function growListenerTree(type, listener, prepend) { + var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; + + if(typeof type==='string') { + if ((i = type.indexOf(delimiter)) !== -1) { + ns = new Array(5); + do { + ns[len++] = type.slice(j, i); + j = i + dl; + } while ((i = type.indexOf(delimiter, j)) !== -1); + + ns[len++] = type.slice(j); + }else { + ns= [type]; + len= 1; + } + }else { + ns= type; + len= type.length; + } + + // + // Looks for two consecutive '**', if so, don't add the event at all. + // + if (len > 1) { + for (i = 0; i + 1 < len; i++) { + if (ns[i] === '**' && ns[i + 1] === '**') { + return; + } + } + } + + + + var tree = this.listenerTree, name; + + for (i = 0; i < len; i++) { + name = ns[i]; + + tree = tree[name] || (tree[name] = {}); + + if (i === len - 1) { + if (!tree._listeners) { + tree._listeners = listener; + } else { + if (typeof tree._listeners === 'function') { + tree._listeners = [tree._listeners]; + } + + if (prepend) { + tree._listeners.unshift(listener); + } else { + tree._listeners.push(listener); + } + + if ( + !tree._listeners.warned && + this._maxListeners > 0 && + tree._listeners.length > this._maxListeners + ) { + tree._listeners.warned = true; + logPossibleMemoryLeak.call(this, tree._listeners.length, name); + } + } + return true; + } + } + + return true; + } + + function collectTreeEvents(tree, events, root, asArray){ + var branches= ownKeys(tree); + var i= branches.length; + var branch, branchName, path; + var hasListeners= tree['_listeners']; + var isArrayPath; + + while(i-->0){ + branchName= branches[i]; + + branch= tree[branchName]; + + if(branchName==='_listeners'){ + path= root; + }else { + path = root ? root.concat(branchName) : [branchName]; + } + + isArrayPath= asArray || typeof branchName==='symbol'; + + hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); + + if(typeof branch==='object'){ + collectTreeEvents.call(this, branch, events, path, isArrayPath); + } + } + + return events; + } + + function recursivelyGarbageCollect(root) { + var keys = ownKeys(root); + var i= keys.length; + var obj, key, flag; + while(i-->0){ + key = keys[i]; + obj = root[key]; + + if(obj){ + flag= true; + if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ + delete root[key]; + } + } + } + + return flag; + } + + function Listener(emitter, event, listener){ + this.emitter= emitter; + this.event= event; + this.listener= listener; + } + + Listener.prototype.off= function(){ + this.emitter.off(this.event, this.listener); + return this; + }; + + function setupListener(event, listener, options){ + if (options === true) { + promisify = true; + } else if (options === false) { + async = true; + } else { + if (!options || typeof options !== 'object') { + throw TypeError('options should be an object or true'); + } + var async = options.async; + var promisify = options.promisify; + var nextTick = options.nextTick; + var objectify = options.objectify; + } + + if (async || nextTick || promisify) { + var _listener = listener; + var _origin = listener._origin || listener; + + if (nextTick && !nextTickSupported) { + throw Error('process.nextTick is not supported'); + } + + if (promisify === undefined$1) { + promisify = listener.constructor.name === 'AsyncFunction'; + } + + listener = function () { + var args = arguments; + var context = this; + var event = this.event; + + return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { + _setImmediate(resolve); + }).then(function () { + context.event = event; + return _listener.apply(context, args) + })) : (nextTick ? process.nextTick : _setImmediate)(function () { + context.event = event; + _listener.apply(context, args); + }); + }; + + listener._async = true; + listener._origin = _origin; + } + + return [listener, objectify? new Listener(this, event, listener): this]; + } + + function EventEmitter(conf) { + this._events = {}; + this._newListener = false; + this._removeListener = false; + this.verboseMemoryLeak = false; + configure.call(this, conf); + } + + EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property + + EventEmitter.prototype.listenTo= function(target, events, options){ + if(typeof target!=='object'){ + throw TypeError('target musts be an object'); + } + + var emitter= this; + + options = resolveOptions(options, { + on: undefined$1, + off: undefined$1, + reducers: undefined$1 + }, { + on: functionReducer, + off: functionReducer, + reducers: objectFunctionReducer + }); + + function listen(events){ + if(typeof events!=='object'){ + throw TypeError('events must be an object'); + } + + var reducers= options.reducers; + var index= findTargetIndex.call(emitter, target); + var observer; + + if(index===-1){ + observer= new TargetObserver(emitter, target, options); + }else { + observer= emitter._observers[index]; + } + + var keys= ownKeys(events); + var len= keys.length; + var event; + var isSingleReducer= typeof reducers==='function'; + + for(var i=0; i 0) { + observer = observers[i]; + if (!target || observer._target === target) { + observer.unsubscribe(event); + matched= true; + } + } + + return matched; + }; + + // By default EventEmitters will print a warning if more than + // 10 listeners are added to it. This is a useful default which + // helps finding memory leaks. + // + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + + EventEmitter.prototype.delimiter = '.'; + + EventEmitter.prototype.setMaxListeners = function(n) { + if (n !== undefined$1) { + this._maxListeners = n; + if (!this._conf) this._conf = {}; + this._conf.maxListeners = n; + } + }; + + EventEmitter.prototype.getMaxListeners = function() { + return this._maxListeners; + }; + + EventEmitter.prototype.event = ''; + + EventEmitter.prototype.once = function(event, fn, options) { + return this._once(event, fn, false, options); + }; + + EventEmitter.prototype.prependOnceListener = function(event, fn, options) { + return this._once(event, fn, true, options); + }; + + EventEmitter.prototype._once = function(event, fn, prepend, options) { + return this._many(event, 1, fn, prepend, options); + }; + + EventEmitter.prototype.many = function(event, ttl, fn, options) { + return this._many(event, ttl, fn, false, options); + }; + + EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { + return this._many(event, ttl, fn, true, options); + }; + + EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { + var self = this; + + if (typeof fn !== 'function') { + throw new Error('many only accepts instances of Function'); + } + + function listener() { + if (--ttl === 0) { + self.off(event, listener); + } + return fn.apply(this, arguments); + } + + listener._origin = fn; + + return this._on(event, listener, prepend, options); + }; + + EventEmitter.prototype.emit = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0], ns, wildcard= this.wildcard; + var args,l,i,j, containsSymbol; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { + return false; + } + } + + if (wildcard) { + ns= type; + if(type!=='newListener' && type!=='removeListener'){ + if (typeof type === 'object') { + l = type.length; + if (symbolsSupported) { + for (i = 0; i < l; i++) { + if (typeof type[i] === 'symbol') { + containsSymbol = true; + break; + } + } + } + if (!containsSymbol) { + type = type.join(this.delimiter); + } + } + } + } + + var al = arguments.length; + var handler; + + if (this._all && this._all.length) { + handler = this._all.slice(); + + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this, type); + break; + case 2: + handler[i].call(this, type, arguments[1]); + break; + case 3: + handler[i].call(this, type, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, arguments); + } + } + } + + if (wildcard) { + handler = []; + searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); + } else { + handler = this._events[type]; + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + handler.apply(this, args); + } + return true; + } else if (handler) { + // need to make copy of handlers because list can change in the middle + // of emit call + handler = handler.slice(); + } + } + + if (handler && handler.length) { + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this); + break; + case 2: + handler[i].call(this, arguments[1]); + break; + case 3: + handler[i].call(this, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, args); + } + } + return true; + } else if (!this.ignoreErrors && !this._all && type === 'error') { + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + } + + return !!this._all; + }; + + EventEmitter.prototype.emitAsync = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; + var args,l,i,j; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { return Promise.resolve([false]); } + } + + if (wildcard) { + ns= type; + if(type!=='newListener' && type!=='removeListener'){ + if (typeof type === 'object') { + l = type.length; + if (symbolsSupported) { + for (i = 0; i < l; i++) { + if (typeof type[i] === 'symbol') { + containsSymbol = true; + break; + } + } + } + if (!containsSymbol) { + type = type.join(this.delimiter); + } + } + } + } + + var promises= []; + + var al = arguments.length; + var handler; + + if (this._all) { + for (i = 0, l = this._all.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(this._all[i].call(this, type)); + break; + case 2: + promises.push(this._all[i].call(this, type, arguments[1])); + break; + case 3: + promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); + break; + default: + promises.push(this._all[i].apply(this, arguments)); + } + } + } + + if (wildcard) { + handler = []; + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } else { + handler = this._events[type]; + } + + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + promises.push(handler.call(this)); + break; + case 2: + promises.push(handler.call(this, arguments[1])); + break; + case 3: + promises.push(handler.call(this, arguments[1], arguments[2])); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + promises.push(handler.apply(this, args)); + } + } else if (handler && handler.length) { + handler = handler.slice(); + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(handler[i].call(this)); + break; + case 2: + promises.push(handler[i].call(this, arguments[1])); + break; + case 3: + promises.push(handler[i].call(this, arguments[1], arguments[2])); + break; + default: + promises.push(handler[i].apply(this, args)); + } + } + } else if (!this.ignoreErrors && !this._all && type === 'error') { + if (arguments[1] instanceof Error) { + return Promise.reject(arguments[1]); // Unhandled 'error' event + } else { + return Promise.reject("Uncaught, unspecified 'error' event."); + } + } + + return Promise.all(promises); + }; + + EventEmitter.prototype.on = function(type, listener, options) { + return this._on(type, listener, false, options); + }; + + EventEmitter.prototype.prependListener = function(type, listener, options) { + return this._on(type, listener, true, options); + }; + + EventEmitter.prototype.onAny = function(fn) { + return this._onAny(fn, false); + }; + + EventEmitter.prototype.prependAny = function(fn) { + return this._onAny(fn, true); + }; + + EventEmitter.prototype.addListener = EventEmitter.prototype.on; + + EventEmitter.prototype._onAny = function(fn, prepend){ + if (typeof fn !== 'function') { + throw new Error('onAny only accepts instances of Function'); + } + + if (!this._all) { + this._all = []; + } + + // Add the function to the event listener collection. + if(prepend){ + this._all.unshift(fn); + }else { + this._all.push(fn); + } + + return this; + }; + + EventEmitter.prototype._on = function(type, listener, prepend, options) { + if (typeof type === 'function') { + this._onAny(type, listener); + return this; + } + + if (typeof listener !== 'function') { + throw new Error('on only accepts instances of Function'); + } + this._events || init.call(this); + + var returnValue= this, temp; + + if (options !== undefined$1) { + temp = setupListener.call(this, type, listener, options); + listener = temp[0]; + returnValue = temp[1]; + } + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + if (this._newListener) { + this.emit('newListener', type, listener); + } + + if (this.wildcard) { + growListenerTree.call(this, type, listener, prepend); + return returnValue; + } + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } else { + if (typeof this._events[type] === 'function') { + // Change to array. + this._events[type] = [this._events[type]]; + } + + // If we've already got an array, just add + if(prepend){ + this._events[type].unshift(listener); + }else { + this._events[type].push(listener); + } + + // Check for listener leak + if ( + !this._events[type].warned && + this._maxListeners > 0 && + this._events[type].length > this._maxListeners + ) { + this._events[type].warned = true; + logPossibleMemoryLeak.call(this, this._events[type].length, type); + } + } + + return returnValue; + }; + + EventEmitter.prototype.off = function(type, listener) { + if (typeof listener !== 'function') { + throw new Error('removeListener only takes instances of Function'); + } + + var handlers,leafs=[]; + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + if(!leafs) return this; + } else { + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events[type]) return this; + handlers = this._events[type]; + leafs.push({_listeners:handlers}); + } + + for (var iLeaf=0; iLeaf 0) { + fns = this._all; + for(i = 0, l = fns.length; i < l; i++) { + if(fn === fns[i]) { + fns.splice(i, 1); + if (this._removeListener) + this.emit("removeListenerAny", fn); + return this; + } + } + } else { + fns = this._all; + if (this._removeListener) { + for(i = 0, l = fns.length; i < l; i++) + this.emit("removeListenerAny", fns[i]); + } + this._all = []; + } + return this; + }; + + EventEmitter.prototype.removeListener = EventEmitter.prototype.off; + + EventEmitter.prototype.removeAllListeners = function (type) { + if (type === undefined$1) { + !this._events || init.call(this); + return this; + } + + if (this.wildcard) { + var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; + if (!leafs) return this; + for (i = 0; i < leafs.length; i++) { + leaf = leafs[i]; + leaf._listeners = null; + } + this.listenerTree && recursivelyGarbageCollect(this.listenerTree); + } else if (this._events) { + this._events[type] = null; + } + return this; + }; + + EventEmitter.prototype.listeners = function (type) { + var _events = this._events; + var keys, listeners, allListeners; + var i; + var listenerTree; + + if (type === undefined$1) { + if (this.wildcard) { + throw Error('event name required for wildcard emitter'); + } + + if (!_events) { + return []; + } + + keys = ownKeys(_events); + i = keys.length; + allListeners = []; + while (i-- > 0) { + listeners = _events[keys[i]]; + if (typeof listeners === 'function') { + allListeners.push(listeners); + } else { + allListeners.push.apply(allListeners, listeners); + } + } + return allListeners; + } else { + if (this.wildcard) { + listenerTree= this.listenerTree; + if(!listenerTree) return []; + var handlers = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handlers, ns, listenerTree, 0); + return handlers; + } + + if (!_events) { + return []; + } + + listeners = _events[type]; + + if (!listeners) { + return []; + } + return typeof listeners === 'function' ? [listeners] : listeners; + } + }; + + EventEmitter.prototype.eventNames = function(nsAsArray){ + var _events= this._events; + return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); + }; + + EventEmitter.prototype.listenerCount = function(type) { + return this.listeners(type).length; + }; + + EventEmitter.prototype.hasListeners = function (type) { + if (this.wildcard) { + var handlers = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); + return handlers.length > 0; + } + + var _events = this._events; + var _all = this._all; + + return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); + }; + + EventEmitter.prototype.listenersAny = function() { + + if(this._all) { + return this._all; + } + else { + return []; + } + + }; + + EventEmitter.prototype.waitFor = function (event, options) { + var self = this; + var type = typeof options; + if (type === 'number') { + options = {timeout: options}; + } else if (type === 'function') { + options = {filter: options}; + } + + options= resolveOptions(options, { + timeout: 0, + filter: undefined$1, + handleError: false, + Promise: Promise, + overload: false + }, { + filter: functionReducer, + Promise: constructorReducer + }); + + return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { + function listener() { + var filter= options.filter; + if (filter && !filter.apply(self, arguments)) { + return; + } + self.off(event, listener); + if (options.handleError) { + var err = arguments[0]; + err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); + } else { + resolve(toArray.apply(null, arguments)); + } + } + + onCancel(function(){ + self.off(event, listener); + }); + + self._on(event, listener, false); + }, { + timeout: options.timeout, + overload: options.overload + }) + }; + + function once(emitter, name, options) { + options= resolveOptions(options, { + Promise: Promise, + timeout: 0, + overload: false + }, { + Promise: constructorReducer + }); + + var _Promise= options.Promise; + + return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ + var handler; + if (typeof emitter.addEventListener === 'function') { + handler= function () { + resolve(toArray.apply(null, arguments)); + }; + + onCancel(function(){ + emitter.removeEventListener(name, handler); + }); + + emitter.addEventListener( + name, + handler, + {once: true} + ); + return; + } + + var eventListener = function(){ + errorListener && emitter.removeListener('error', errorListener); + resolve(toArray.apply(null, arguments)); + }; + + var errorListener; + + if (name !== 'error') { + errorListener = function (err){ + emitter.removeListener(name, eventListener); + reject(err); + }; + + emitter.once('error', errorListener); + } + + onCancel(function(){ + errorListener && emitter.removeListener('error', errorListener); + emitter.removeListener(name, eventListener); + }); + + emitter.once(name, eventListener); + }, { + timeout: options.timeout, + overload: options.overload + }); + } + + var prototype= EventEmitter.prototype; + + Object.defineProperties(EventEmitter, { + defaultMaxListeners: { + get: function () { + return prototype._maxListeners; + }, + set: function (n) { + if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { + throw TypeError('n must be a non-negative number') + } + prototype._maxListeners = n; + }, + enumerable: true + }, + once: { + value: once, + writable: true, + configurable: true + } + }); + + Object.defineProperties(prototype, { + _maxListeners: { + value: defaultMaxListeners, + writable: true, + configurable: true + }, + _observers: {value: null, writable: true, configurable: true} + }); + + if (typeof undefined$1 === 'function' && undefined$1.amd) { + // AMD. Register as an anonymous module. + undefined$1(function() { + return EventEmitter; + }); + } else { + // CommonJS + module.exports = EventEmitter; + } + }(); +} (eventemitter2, eventemitter2.exports)); + +var eventemitter2Exports = eventemitter2.exports; +var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); + +function _callSuper$q(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$q() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$q() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$q = function _isNativeReflectConstruct() { return !!t; })(); } - // rotate - this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ - // offset from drag start position - event3d.stopPropagation(); - } - }; +var InteractiveMarkerHandle = /*#__PURE__*/function (_EventEmitter) { /** - * Dispatch the given event type. + * Handle with signals for a single interactive marker. * - * @param type - the type of event - * @param control - the control to use - */ - InteractiveMarker.prototype.feedbackEvent = function feedbackEvent (type, control) { - this.dispatchEvent({ - type : type, - position : this.position.clone(), - orientation : this.quaternion.clone(), - controlName : control.name - }); - }; - /** - * Start a drag action. + * Emits the following events: * - * @param control - the control to use - * @param event3d - the event that caused this + * * 'pose' - emitted when a new pose comes from the server + * + * @constructor + * @param options - object with following keys: + * + * * message - the interactive marker message + * * feedbackTopic - the ROSLIB.Topic associated with the feedback + * * tfClient - a handle to the TF client to use + * * menuFontSize (optional) - the menu font size */ - InteractiveMarker.prototype.startDrag = function startDrag (control, event3d) { - if (event3d.domEvent.button === 0) { - event3d.stopPropagation(); + function InteractiveMarkerHandle(options) { + var _this; + _classCallCheck(this, InteractiveMarkerHandle); + _this = _callSuper$q(this, InteractiveMarkerHandle); + options = options || {}; + _this.message = options.message; + _this.feedbackTopic = options.feedbackTopic; + _this.tfClient = options.tfClient; + _this.menuFontSize = options.menuFontSize || '0.8em'; + _this.name = _this.message.name; + _this.header = _this.message.header; + _this.controls = _this.message.controls; + _this.menuEntries = _this.message.menu_entries; + _this.dragging = false; + _this.timeoutHandle = null; + _this.tfTransform = new ROSLIB__namespace.Transform(); + _this.pose = new ROSLIB__namespace.Pose(); + _this.setPoseFromClientBound = _this.setPoseFromClient.bind(_this); + _this.onMouseDownBound = _this.onMouseDown.bind(_this); + _this.onMouseUpBound = _this.onMouseUp.bind(_this); + _this.onButtonClickBound = _this.onButtonClick.bind(_this); + _this.onMenuSelectBound = _this.onMenuSelect.bind(_this); + + // start by setting the pose + _this.setPoseFromServer(_this.message.pose); + _this.tfUpdateBound = _this.tfUpdate.bind(_this); + return _this; + } + _inherits(InteractiveMarkerHandle, _EventEmitter); + return _createClass(InteractiveMarkerHandle, [{ + key: "subscribeTf", + value: + /** + * Subscribe to the TF associated with this interactive marker. + */ + function subscribeTf() { + // subscribe to tf updates if frame-fixed + if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { + this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + } + } + }, { + key: "unsubscribeTf", + value: function unsubscribeTf() { + this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); + } + }, { + key: "emitServerPoseUpdate", + value: + /** + * Emit the new pose that has come from the server. + */ + function emitServerPoseUpdate() { + var poseTransformed = new ROSLIB__namespace.Pose(this.pose); + poseTransformed.applyTransform(this.tfTransform); + this.emit('pose', poseTransformed); + } + }, { + key: "setPoseFromServer", + value: + /** + * Update the pose based on the pose given by the server. + * + * @param poseMsg - the pose given by the server + */ + function setPoseFromServer(poseMsg) { + this.pose = new ROSLIB__namespace.Pose(poseMsg); + this.emitServerPoseUpdate(); + } + }, { + key: "tfUpdate", + value: + /** + * Update the pose based on the TF given by the server. + * + * @param transformMsg - the TF given by the server + */ + function tfUpdate(transformMsg) { + this.tfTransform = new ROSLIB__namespace.Transform(transformMsg); + this.emitServerPoseUpdate(); + } + }, { + key: "setPoseFromClient", + value: + /** + * Set the pose from the client based on the given event. + * + * @param event - the event to base the change off of + */ + function setPoseFromClient(event) { + // apply the transform + this.pose = new ROSLIB__namespace.Pose(event); + var inv = this.tfTransform.clone(); + inv.rotation.invert(); + inv.translation.multiplyQuaternion(inv.rotation); + inv.translation.x *= -1; + inv.translation.y *= -1; + inv.translation.z *= -1; + this.pose.applyTransform(inv); + + // send feedback to the server + this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); + + // keep sending pose feedback until the mouse goes up + if (this.dragging) { + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); + } + this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); + } + } + }, { + key: "onButtonClick", + value: + /** + * Send the button click feedback to the server. + * + * @param event - the event associated with the button click + */ + function onButtonClick(event) { + this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, event.controlName); + } + }, { + key: "onMouseDown", + value: + /** + * Send the mousedown feedback to the server. + * + * @param event - the event associated with the mousedown + */ + function onMouseDown(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); this.dragging = true; - this.updateMatrixWorld(true); - var scale = new THREE.Vector3(); - this.matrixWorld - .decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); - this.dragStart.position = this.position.clone(); - this.dragStart.orientation = this.quaternion.clone(); - this.dragStart.event3d = event3d; - - this.feedbackEvent('user-mousedown', control); } - }; - /** - * Stop a drag action. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.stopDrag = function stopDrag (control, event3d) { - if (event3d.domEvent.button === 0) { - event3d.stopPropagation(); + }, { + key: "onMouseUp", + value: + /** + * Send the mouseup feedback to the server. + * + * @param event - the event associated with the mouseup + */ + function onMouseUp(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); this.dragging = false; - this.dragStart.event3d = {}; - this.onServerSetPose(this.bufferedPoseEvent); - this.bufferedPoseEvent = undefined; - - this.feedbackEvent('user-mouseup', control); - } - }; - /** - * Handle a button click. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.buttonClick = function buttonClick (control, event3d) { - event3d.stopPropagation(); - this.feedbackEvent('user-button-click', control); - }; - /** - * Handle a user pose change for the position. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.setPosition = function setPosition (control, position) { - this.position.copy(position); - this.feedbackEvent('user-pose-change', control); - }; - /** - * Handle a user pose change for the orientation. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.setOrientation = function setOrientation (control, orientation) { - orientation.normalize(); - this.quaternion.copy(orientation); - this.feedbackEvent('user-pose-change', control); - }; - /** - * Update the marker based when the pose is set from the server. - * - * @param event - the event that caused this - */ - InteractiveMarker.prototype.onServerSetPose = function onServerSetPose (event) { - if (event !== undefined) { - // don't update while dragging - if (this.dragging) { - this.bufferedPoseEvent = event; - } else { - var pose = event.pose; - this.position.copy(pose.position); - this.quaternion.copy(pose.orientation); - this.updateMatrixWorld(true); + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); } } - }; - /** - * Free memory of elements in this marker. - */ - InteractiveMarker.prototype.dispose = function dispose () { - this.children.forEach(function(intMarkerControl) { - intMarkerControl.children.forEach(function(marker) { - marker.dispose(); - intMarkerControl.remove(marker); - }); - this.remove(intMarkerControl); - }.bind(this)); - }; - - return InteractiveMarker; -}(THREE.Object3D)); + }, { + key: "onMenuSelect", + value: + /** + * Send the menu select feedback to the server. + * + * @param event - the event associated with the menu select + */ + function onMenuSelect(event) { + this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); + } + }, { + key: "sendFeedback", + value: + /** + * Send feedback to the interactive marker server. + * + * @param eventType - the type of event that happened + * @param clickPosition (optional) - the position in ROS space the click happened + * @param menuEntryID (optional) - the menu entry ID that is associated + * @param controlName - the name of the control + */ + function sendFeedback(eventType, clickPosition, menuEntryID, controlName) { + // check for the click position + var mousePointValid = clickPosition !== undefined; + clickPosition = clickPosition || { + x: 0, + y: 0, + z: 0 + }; + var feedback = { + header: this.header, + client_id: this.clientID, + marker_name: this.name, + control_name: controlName, + event_type: eventType, + pose: this.pose, + mouse_point: clickPosition, + mouse_point_valid: mousePointValid, + menu_entry_id: menuEntryID + }; + this.feedbackTopic.publish(feedback); + } + }]); +}(EventEmitter2); /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter3) { - function InteractiveMarkerHandle(options) { - EventEmitter3.call(this); +var InteractiveMarkerClient = /*#__PURE__*/function () { + /** + * A client for an interactive marker topic. + * + * @constructor + * @param options - object with following keys: + * + * * ros - a handle to the ROS connection + * * tfClient - a handle to the TF client + * * topic (optional) - the topic to subscribe to, like '/basic_controls', if not provided use subscribe() to start message receiving + * * path (optional) - the base path to any meshes that will be loaded + * * camera - the main camera associated with the viewer for this marker client + * * rootObject (optional) - the root THREE 3D object to render to + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + * * menuFontSize (optional) - the menu font size + */ + function InteractiveMarkerClient(options) { + _classCallCheck(this, InteractiveMarkerClient); options = options || {}; - this.message = options.message; - this.feedbackTopic = options.feedbackTopic; + this.ros = options.ros; this.tfClient = options.tfClient; + this.topicName = options.topic; + this.path = options.path || '/'; + this.camera = options.camera; + this.rootObject = options.rootObject || new Object3D(); + this.loader = options.loader; this.menuFontSize = options.menuFontSize || '0.8em'; - this.name = this.message.name; - this.header = this.message.header; - this.controls = this.message.controls; - this.menuEntries = this.message.menu_entries; - this.dragging = false; - this.timeoutHandle = null; - this.tfTransform = new ROSLIB__namespace.Transform(); - this.pose = new ROSLIB__namespace.Pose(); - - this.setPoseFromClientBound = this.setPoseFromClient.bind(this); - this.onMouseDownBound = this.onMouseDown.bind(this); - this.onMouseUpBound = this.onMouseUp.bind(this); - this.onButtonClickBound = this.onButtonClick.bind(this); - this.onMenuSelectBound = this.onMenuSelect.bind(this); - - // start by setting the pose - this.setPoseFromServer(this.message.pose); - this.tfUpdateBound = this.tfUpdate.bind(this); + this.interactiveMarkers = {}; + this.updateTopic = null; + this.feedbackTopic = null; + this.processUpdateBound = this.processUpdate.bind(this); + + // check for an initial topic + if (this.topicName) { + this.subscribe(this.topicName); + } } - - if ( EventEmitter3 ) InteractiveMarkerHandle.__proto__ = EventEmitter3; - InteractiveMarkerHandle.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - InteractiveMarkerHandle.prototype.constructor = InteractiveMarkerHandle; - /** - * Subscribe to the TF associated with this interactive marker. - */ - InteractiveMarkerHandle.prototype.subscribeTf = function subscribeTf () { - // subscribe to tf updates if frame-fixed - if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { - this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + return _createClass(InteractiveMarkerClient, [{ + key: "subscribe", + value: + /** + * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. + * + * @param topic - the topic to subscribe to, like '/basic_controls' + */ + function subscribe(topic) { + // unsubscribe to the other topics + this.unsubscribe(); + this.updateTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: topic + '/tunneled/update', + messageType: 'visualization_msgs/InteractiveMarkerUpdate', + compression: 'png' + }); + this.updateTopic.subscribe(this.processUpdateBound); + this.feedbackTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: topic + '/feedback', + messageType: 'visualization_msgs/InteractiveMarkerFeedback', + compression: 'png' + }); + this.feedbackTopic.advertise(); + this.initService = new ROSLIB__namespace.Service({ + ros: this.ros, + name: topic + '/tunneled/get_init', + serviceType: 'demo_interactive_markers/GetInit' + }); + var request = new ROSLIB__namespace.ServiceRequest({}); + this.initService.callService(request, this.processInit.bind(this)); } - }; - InteractiveMarkerHandle.prototype.unsubscribeTf = function unsubscribeTf () { - this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); - }; - /** - * Emit the new pose that has come from the server. - */ - InteractiveMarkerHandle.prototype.emitServerPoseUpdate = function emitServerPoseUpdate () { - var poseTransformed = new ROSLIB__namespace.Pose(this.pose); - poseTransformed.applyTransform(this.tfTransform); - this.emit('pose', poseTransformed); - }; - /** - * Update the pose based on the pose given by the server. - * - * @param poseMsg - the pose given by the server - */ - InteractiveMarkerHandle.prototype.setPoseFromServer = function setPoseFromServer (poseMsg) { - this.pose = new ROSLIB__namespace.Pose(poseMsg); - this.emitServerPoseUpdate(); - }; - /** - * Update the pose based on the TF given by the server. - * - * @param transformMsg - the TF given by the server - */ - InteractiveMarkerHandle.prototype.tfUpdate = function tfUpdate (transformMsg) { - this.tfTransform = new ROSLIB__namespace.Transform(transformMsg); - this.emitServerPoseUpdate(); - }; - /** - * Set the pose from the client based on the given event. - * - * @param event - the event to base the change off of - */ - InteractiveMarkerHandle.prototype.setPoseFromClient = function setPoseFromClient (event) { - // apply the transform - this.pose = new ROSLIB__namespace.Pose(event); - var inv = this.tfTransform.clone(); - inv.rotation.invert(); - inv.translation.multiplyQuaternion(inv.rotation); - inv.translation.x *= -1; - inv.translation.y *= -1; - inv.translation.z *= -1; - this.pose.applyTransform(inv); - - // send feedback to the server - this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); - - // keep sending pose feedback until the mouse goes up - if (this.dragging) { - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); + }, { + key: "unsubscribe", + value: + /** + * Unsubscribe from the current interactive marker topic. + */ + function unsubscribe() { + if (this.updateTopic) { + this.updateTopic.unsubscribe(this.processUpdateBound); } - this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); - } - }; - /** - * Send the button click feedback to the server. - * - * @param event - the event associated with the button click - */ - InteractiveMarkerHandle.prototype.onButtonClick = function onButtonClick (event) { - this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, - event.controlName); - }; - /** - * Send the mousedown feedback to the server. - * - * @param event - the event associated with the mousedown - */ - InteractiveMarkerHandle.prototype.onMouseDown = function onMouseDown (event) { - this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); - this.dragging = true; - }; - /** - * Send the mouseup feedback to the server. - * - * @param event - the event associated with the mouseup - */ - InteractiveMarkerHandle.prototype.onMouseUp = function onMouseUp (event) { - this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); - this.dragging = false; - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); + if (this.feedbackTopic) { + this.feedbackTopic.unadvertise(); + } + // erase all markers + for (var intMarkerName in this.interactiveMarkers) { + this.eraseIntMarker(intMarkerName); + } + this.interactiveMarkers = {}; } - }; - /** - * Send the menu select feedback to the server. - * - * @param event - the event associated with the menu select - */ - InteractiveMarkerHandle.prototype.onMenuSelect = function onMenuSelect (event) { - this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); - }; - /** - * Send feedback to the interactive marker server. - * - * @param eventType - the type of event that happened - * @param clickPosition (optional) - the position in ROS space the click happened - * @param menuEntryID (optional) - the menu entry ID that is associated - * @param controlName - the name of the control - */ - InteractiveMarkerHandle.prototype.sendFeedback = function sendFeedback (eventType, clickPosition, - menuEntryID, controlName) { - - // check for the click position - var mousePointValid = clickPosition !== undefined; - clickPosition = clickPosition || { - x : 0, - y : 0, - z : 0 - }; - - var feedback = { - header : this.header, - client_id : this.clientID, - marker_name : this.name, - control_name : controlName, - event_type : eventType, - pose : this.pose, - mouse_point : clickPosition, - mouse_point_valid : mousePointValid, - menu_entry_id : menuEntryID - }; - this.feedbackTopic.publish(feedback); - }; - - return InteractiveMarkerHandle; -}(EventEmitter3)); - -/** - * @fileOverview - * @author David Gossow - dgossow@willowgarage.com - */ - -var InteractiveMarkerClient = function InteractiveMarkerClient(options) { - options = options || {}; - this.ros = options.ros; - this.tfClient = options.tfClient; - this.topicName = options.topic; - this.path = options.path || '/'; - this.camera = options.camera; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.loader = options.loader; - this.menuFontSize = options.menuFontSize || '0.8em'; + }, { + key: "processInit", + value: + /** + * Process the given interactive marker initialization message. + * + * @param initMessage - the interactive marker initialization message to process + */ + function processInit(initMessage) { + var message = initMessage.msg; - this.interactiveMarkers = {}; - this.updateTopic = null; - this.feedbackTopic = null; - this.processUpdateBound = this.processUpdate.bind(this); + // erase any old markers + message.erases = []; + for (var intMarkerName in this.interactiveMarkers) { + message.erases.push(intMarkerName); + } + message.poses = []; - // check for an initial topic - if (this.topicName) { - this.subscribe(this.topicName); - } -}; -/** - * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. - * - * @param topic - the topic to subscribe to, like '/basic_controls' - */ -InteractiveMarkerClient.prototype.subscribe = function subscribe (topic) { - // unsubscribe to the other topics - this.unsubscribe(); - - this.updateTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : topic + '/tunneled/update', - messageType : 'visualization_msgs/InteractiveMarkerUpdate', - compression : 'png' - }); - this.updateTopic.subscribe(this.processUpdateBound); + // treat it as an update + this.processUpdate(message); + } + }, { + key: "processUpdate", + value: + /** + * Process the given interactive marker update message. + * + * @param initMessage - the interactive marker update message to process + */ + function processUpdate(message) { + // erase any markers + message.erases.forEach(function (name) { + this.eraseIntMarker(name); + }); - this.feedbackTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : topic + '/feedback', - messageType : 'visualization_msgs/InteractiveMarkerFeedback', - compression : 'png' - }); - this.feedbackTopic.advertise(); + // updates marker poses + message.poses.forEach(function (poseMessage) { + var marker = this.interactiveMarkers[poseMessage.name]; + if (marker) { + marker.setPoseFromServer(poseMessage.pose); + } + }); - this.initService = new ROSLIB__namespace.Service({ - ros : this.ros, - name : topic + '/tunneled/get_init', - serviceType : 'demo_interactive_markers/GetInit' - }); - var request = new ROSLIB__namespace.ServiceRequest({}); - this.initService.callService(request, this.processInit.bind(this)); -}; -/** - * Unsubscribe from the current interactive marker topic. - */ -InteractiveMarkerClient.prototype.unsubscribe = function unsubscribe () { - if (this.updateTopic) { - this.updateTopic.unsubscribe(this.processUpdateBound); - } - if (this.feedbackTopic) { - this.feedbackTopic.unadvertise(); - } - // erase all markers - for (var intMarkerName in this.interactiveMarkers) { - this.eraseIntMarker(intMarkerName); - } - this.interactiveMarkers = {}; -}; -/** - * Process the given interactive marker initialization message. - * - * @param initMessage - the interactive marker initialization message to process - */ -InteractiveMarkerClient.prototype.processInit = function processInit (initMessage) { - var message = initMessage.msg; + // add new markers + message.markers.forEach(function (msg) { + // get rid of anything with the same name + var oldhandle = this.interactiveMarkers[msg.name]; + if (oldhandle) { + this.eraseIntMarker(oldhandle.name); + } - // erase any old markers - message.erases = []; - for (var intMarkerName in this.interactiveMarkers) { - message.erases.push(intMarkerName); - } - message.poses = []; + // create the handle + var handle = new InteractiveMarkerHandle({ + message: msg, + feedbackTopic: this.feedbackTopic, + tfClient: this.tfClient, + menuFontSize: this.menuFontSize + }); + this.interactiveMarkers[msg.name] = handle; + + // create the actual marker + var intMarker = new InteractiveMarker({ + handle: handle, + camera: this.camera, + path: this.path, + loader: this.loader + }); + // add it to the scene + intMarker.name = msg.name; + this.rootObject.add(intMarker); + + // listen for any pose updates from the server + handle.on('pose', function (pose) { + intMarker.onServerSetPose({ + pose: pose + }); + }); - // treat it as an update - this.processUpdate(message); -}; -/** - * Process the given interactive marker update message. - * - * @param initMessage - the interactive marker update message to process - */ -InteractiveMarkerClient.prototype.processUpdate = function processUpdate (message) { - // erase any markers - message.erases.forEach(function(name) { - this.eraseIntMarker(name); - }); + // add bound versions of UI handlers + intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); + intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); + intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); + intMarker.addEventListener('user-button-click', handle.onButtonClickBound); + intMarker.addEventListener('menu-select', handle.onMenuSelectBound); - // updates marker poses - message.poses.forEach(function(poseMessage) { - var marker = this.interactiveMarkers[poseMessage.name]; - if (marker) { - marker.setPoseFromServer(poseMessage.pose); + // now listen for any TF changes + handle.subscribeTf(); + }); } - }); - - // add new markers - message.markers.forEach(function(msg) { - // get rid of anything with the same name - var oldhandle = this.interactiveMarkers[msg.name]; - if (oldhandle) { - this.eraseIntMarker(oldhandle.name); + }, { + key: "eraseIntMarker", + value: + /** + * Erase the interactive marker with the given name. + * + * @param intMarkerName - the interactive marker name to delete + */ + function eraseIntMarker(intMarkerName) { + if (this.interactiveMarkers[intMarkerName]) { + // remove the object + var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); + this.rootObject.remove(targetIntMarker); + // unsubscribe from TF topic! + var handle = this.interactiveMarkers[intMarkerName]; + handle.unsubscribeTf(); + + // remove all other listeners + + targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); + targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); + targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); + targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); + targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); + + // remove the handle from the map - after leaving this function's scope, there should be no references to the handle + delete this.interactiveMarkers[intMarkerName]; + targetIntMarker.dispose(); + } } + }]); +}(); - // create the handle - var handle = new InteractiveMarkerHandle({ - message : msg, - feedbackTopic : this.feedbackTopic, - tfClient : this.tfClient, - menuFontSize : this.menuFontSize - }); - this.interactiveMarkers[msg.name] = handle; - - // create the actual marker - var intMarker = new InteractiveMarker({ - handle : handle, - camera : this.camera, - path : this.path, - loader : this.loader - }); - // add it to the scene - intMarker.name = msg.name; - this.rootObject.add(intMarker); - - // listen for any pose updates from the server - handle.on('pose', function(pose) { - intMarker.onServerSetPose({ - pose : pose - }); - }); - - // add bound versions of UI handlers - intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); - intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); - intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); - intMarker.addEventListener('user-button-click', handle.onButtonClickBound); - intMarker.addEventListener('menu-select', handle.onMenuSelectBound); - - // now listen for any TF changes - handle.subscribeTf(); - }); -}; -/** - * Erase the interactive marker with the given name. - * - * @param intMarkerName - the interactive marker name to delete - */ -InteractiveMarkerClient.prototype.eraseIntMarker = function eraseIntMarker (intMarkerName) { - if (this.interactiveMarkers[intMarkerName]) { - // remove the object - var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); - this.rootObject.remove(targetIntMarker); - // unsubscribe from TF topic! - var handle = this.interactiveMarkers[intMarkerName]; - handle.unsubscribeTf(); - - // remove all other listeners - - targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); - targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); - targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); - targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); - targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); - - // remove the handle from the map - after leaving this function's scope, there should be no references to the handle - delete this.interactiveMarkers[intMarkerName]; - targetIntMarker.dispose(); - } -}; +function _callSuper$p(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$p() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$p() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$p = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -53615,27 +45692,39 @@ InteractiveMarkerClient.prototype.eraseIntMarker = function eraseIntMarker (intM * @author Russell Toris - rctoris@wpi.edu */ -var SceneNode = /*@__PURE__*/(function (superclass) { +var SceneNode = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A SceneNode can be used to keep track of a 3D object with respect to a ROS frame within a scene. + * + * @constructor + * @param options - object with following keys: + * + * * tfClient - a handle to the TF client + * * frameID - the frame ID this object belongs to + * * pose (optional) - the pose associated with this object + * * object - the THREE 3D object to be rendered + */ function SceneNode(options) { - superclass.call(this); + var _this; + _classCallCheck(this, SceneNode); + _this = _callSuper$p(this, SceneNode); options = options || {}; - this.tfClient = options.tfClient; - this.frameID = options.frameID; + _this.tfClient = options.tfClient; + _this.frameID = options.frameID; var object = options.object; - this.pose = options.pose || new ROSLIB__namespace.Pose(); + _this.pose = options.pose || new ROSLIB__namespace.Pose(); // Do not render this object until we receive a TF update - this.visible = false; + _this.visible = false; // add the model - this.add(object); + _this.add(object); // set the inital pose - this.updatePose(this.pose); + _this.updatePose(_this.pose); // save the TF handler so we can remove it later - this.tfUpdate = function(msg) { - + _this.tfUpdate = function (msg) { // apply the transform var tf = new ROSLIB__namespace.Transform(msg); var poseTransformed = new ROSLIB__namespace.Pose(this.pose); @@ -53647,30 +45736,34 @@ var SceneNode = /*@__PURE__*/(function (superclass) { }; // listen for TF updates - this.tfUpdateBound = this.tfUpdate.bind(this); - this.tfClient.subscribe(this.frameID, this.tfUpdateBound); + _this.tfUpdateBound = _this.tfUpdate.bind(_this); + _this.tfClient.subscribe(_this.frameID, _this.tfUpdateBound); + return _this; } + _inherits(SceneNode, _THREE$Object3D); + return _createClass(SceneNode, [{ + key: "updatePose", + value: + /** + * Set the pose of the associated model. + * + * @param pose - the pose to update with + */ + function updatePose(pose) { + this.position.set(pose.position.x, pose.position.y, pose.position.z); + this.quaternion.set(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + this.updateMatrixWorld(true); + } + }, { + key: "unsubscribeTf", + value: function unsubscribeTf() { + this.tfClient.unsubscribe(this.frameID, this.tfUpdateBound); + } + }]); +}(Object3D); - if ( superclass ) SceneNode.__proto__ = superclass; - SceneNode.prototype = Object.create( superclass && superclass.prototype ); - SceneNode.prototype.constructor = SceneNode; - /** - * Set the pose of the associated model. - * - * @param pose - the pose to update with - */ - SceneNode.prototype.updatePose = function updatePose (pose) { - this.position.set( pose.position.x, pose.position.y, pose.position.z ); - this.quaternion.set(pose.orientation.x, pose.orientation.y, - pose.orientation.z, pose.orientation.w); - this.updateMatrixWorld(true); - }; - SceneNode.prototype.unsubscribeTf = function unsubscribeTf () { - this.tfClient.unsubscribe(this.frameID, this.tfUpdateBound); - }; - - return SceneNode; -}(THREE.Object3D)); +function _callSuper$o(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$o() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$o() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$o = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -53678,253 +45771,338 @@ var SceneNode = /*@__PURE__*/(function (superclass) { * @author Nils Berg - berg.nils@gmail.com */ -var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter3) { +var MarkerArrayClient = /*#__PURE__*/function (_EventEmitter) { + /** + * A MarkerArray client that listens to a given topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the MarkerArray + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add the markers to + * * path (optional) - the base path to any meshes that will be loaded + */ function MarkerArrayClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, MarkerArrayClient); + _this = _callSuper$o(this, MarkerArrayClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.path = options.path || '/'; + _this.ros = options.ros; + _this.topicName = options.topic; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.path = options.path || '/'; // Markers that are displayed (Map ns+id--Marker) - this.markers = {}; - this.rosTopic = undefined; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.markers = {}; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) MarkerArrayClient.__proto__ = EventEmitter3; - MarkerArrayClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - MarkerArrayClient.prototype.constructor = MarkerArrayClient; - MarkerArrayClient.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to MarkerArray topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'visualization_msgs/MarkerArray', - compression : 'png' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - MarkerArrayClient.prototype.processMessage = function processMessage (arrayMessage){ - arrayMessage.markers.forEach(function(message) { - var key = message.ns + message.id; - if(message.action === 0) { - var updated = false; - if(key in this.markers) { // "MODIFY" - updated = this.markers[key].children[0].update(message); - if(!updated) { // "REMOVE" - this.removeMarker(key); + _inherits(MarkerArrayClient, _EventEmitter); + return _createClass(MarkerArrayClient, [{ + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to MarkerArray topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'visualization_msgs/MarkerArray', + compression: 'png' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(arrayMessage) { + arrayMessage.markers.forEach(function (message) { + var key = message.ns + message.id; + if (message.action === 0) { + var updated = false; + if (key in this.markers) { + // "MODIFY" + updated = this.markers[key].children[0].update(message); + if (!updated) { + // "REMOVE" + this.removeMarker(key); + } } + if (!updated) { + // "ADD" + var newMarker = new Marker({ + message: message, + path: this.path + }); + this.markers[key] = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newMarker + }); + this.rootObject.add(this.markers[key]); + } + } else if (message.action === 1) { + // "DEPRECATED" + console.warn('Received marker message with deprecated action identifier "1"'); + } else if (message.action === 2) { + // "DELETE" + this.removeMarker(key); + } else if (message.action === 3) { + // "DELETE ALL" + for (var m in this.markers) { + this.removeMarker(m); + } + this.markers = {}; + } else { + console.warn('Received marker message with unknown action identifier "' + message.action + '"'); } - if(!updated) { // "ADD" - var newMarker = new Marker({ - message : message, - path : this.path, - }); - this.markers[key] = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newMarker - }); - this.rootObject.add(this.markers[key]); - } - } - else if(message.action === 1) { // "DEPRECATED" - console.warn('Received marker message with deprecated action identifier "1"'); - } - else if(message.action === 2) { // "DELETE" - this.removeMarker(key); - } - else if(message.action === 3) { // "DELETE ALL" - for (var m in this.markers){ - this.removeMarker(m); - } - this.markers = {}; - } - else { - console.warn('Received marker message with unknown action identifier "'+message.action+'"'); + }.bind(this)); + this.emit('change'); + } + }, { + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); } - }.bind(this)); - - this.emit('change'); - }; - MarkerArrayClient.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); } - }; - MarkerArrayClient.prototype.removeMarker = function removeMarker (key) { - var oldNode = this.markers[key]; - if(!oldNode) { - return; + }, { + key: "removeMarker", + value: function removeMarker(key) { + var oldNode = this.markers[key]; + if (!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(function (child) { + child.dispose(); + }); + delete this.markers[key]; } - oldNode.unsubscribeTf(); - this.rootObject.remove(oldNode); - oldNode.children.forEach(function (child) { - child.dispose(); - }); - delete(this.markers[key]); - }; + }]); +}(EventEmitter2); - return MarkerArrayClient; -}(EventEmitter3)); +function _callSuper$n(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$n() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$n() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$n = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var MarkerClient = /*@__PURE__*/(function (EventEmitter3) { +var MarkerClient = /*#__PURE__*/function (_EventEmitter) { + /** + * A marker client that listens to a given marker topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * path (optional) - the base path to any meshes that will be loaded + * * lifetime - the lifetime of marker + */ function MarkerClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, MarkerClient); + _this = _callSuper$n(this, MarkerClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.path = options.path || '/'; - this.lifetime = options.lifetime || 0; + _this.ros = options.ros; + _this.topicName = options.topic; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.path = options.path || '/'; + _this.lifetime = options.lifetime || 0; // Markers that are displayed (Map ns+id--Marker) - this.markers = {}; - this.rosTopic = undefined; - this.updatedTime = {}; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.markers = {}; + _this.rosTopic = undefined; + _this.updatedTime = {}; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) MarkerClient.__proto__ = EventEmitter3; - MarkerClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - MarkerClient.prototype.constructor = MarkerClient; - MarkerClient.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(MarkerClient, _EventEmitter); + return _createClass(MarkerClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - MarkerClient.prototype.checkTime = function checkTime (name){ + }, { + key: "checkTime", + value: function checkTime(name) { var curTime = new Date().getTime(); if (curTime - this.updatedTime[name] > this.lifetime) { - this.removeMarker(name); - this.emit('change'); + this.removeMarker(name); + this.emit('change'); } else { - var that = this; - setTimeout(function() {that.checkTime(name);}, - 100); + var that = this; + setTimeout(function () { + that.checkTime(name); + }, 100); } - }; - MarkerClient.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'visualization_msgs/Marker', - compression : 'png' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - MarkerClient.prototype.processMessage = function processMessage (message){ - // remove old marker from Three.Object3D children buffer - var key = message.ns + message.id; - var oldNode = this.markers[key]; - this.updatedTime[key] = new Date().getTime(); - if (oldNode) { - this.removeMarker(key); - - } else if (this.lifetime) { - this.checkTime(message.ns + message.id); } - - if (message.action === 0) { // "ADD" or "MODIFY" - var newMarker = new Marker({ - message : message, - path : this.path, - }); - - this.markers[key] = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newMarker + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'visualization_msgs/Marker', + compression: 'png' }); - this.rootObject.add(this.markers[key]); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + // remove old marker from Three.Object3D children buffer + var key = message.ns + message.id; + var oldNode = this.markers[key]; + this.updatedTime[key] = new Date().getTime(); + if (oldNode) { + this.removeMarker(key); + } else if (this.lifetime) { + this.checkTime(message.ns + message.id); + } + if (message.action === 0) { + // "ADD" or "MODIFY" + var newMarker = new Marker({ + message: message, + path: this.path + }); + this.markers[key] = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newMarker + }); + this.rootObject.add(this.markers[key]); + } + this.emit('change'); } - - this.emit('change'); - }; - MarkerClient.prototype.removeMarker = function removeMarker (key) { - var oldNode = this.markers[key]; - if(!oldNode) { - return; + }, { + key: "removeMarker", + value: function removeMarker(key) { + var oldNode = this.markers[key]; + if (!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(function (child) { + child.dispose(); + }); + delete this.markers[key]; } - oldNode.unsubscribeTf(); - this.rootObject.remove(oldNode); - oldNode.children.forEach(function (child) { - child.dispose(); - }); - delete(this.markers[key]); - }; + }]); +}(EventEmitter2); - return MarkerClient; -}(EventEmitter3)); +function _callSuper$m(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$m() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$m() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$m = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Jihoon Lee - lee@magazino.eu */ -var Arrow2 = /*@__PURE__*/(function (superclass) { +var Arrow2 = /*#__PURE__*/function (_THREE$ArrowHelper) { + /** + * A Arrow is a THREE object that can be used to display an arrow model using ArrowHelper + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ function Arrow2(options) { + _classCallCheck(this, Arrow2); options = options || {}; - var origin = options.origin || new THREE.Vector3(0, 0, 0); - var direction = options.direction || new THREE.Vector3(1, 0, 0); + var origin = options.origin || new Vector3(0, 0, 0); + var direction = options.direction || new Vector3(1, 0, 0); var length = options.length || 1; options.headLength || 0.2; options.shaftDiameter || 0.05; options.headDiameter || 0.1; - options.material || new THREE.MeshBasicMaterial(); - - superclass.call(this, direction, origin, length, 0xff0000); - + options.material || new MeshBasicMaterial(); + return _callSuper$m(this, Arrow2, [direction, origin, length, 0xff0000]); } - - if ( superclass ) Arrow2.__proto__ = superclass; - Arrow2.prototype = Object.create( superclass && superclass.prototype ); - Arrow2.prototype.constructor = Arrow2; - - /* - * Free memory of elements in this object. - */ - Arrow2.prototype.dispose = function dispose () { - if (this.line !== undefined) { + _inherits(Arrow2, _THREE$ArrowHelper); + return _createClass(Arrow2, [{ + key: "dispose", + value: + /* + * Free memory of elements in this object. + */ + function dispose() { + if (this.line !== undefined) { this.line.material.dispose(); this.line.geometry.dispose(); - } - if (this.cone!== undefined) { + } + if (this.cone !== undefined) { this.cone.material.dispose(); this.cone.geometry.dispose(); + } } - }; + }]); +}(ArrowHelper); - return Arrow2; -}(THREE.ArrowHelper)); +function _callSuper$l(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$l() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$l() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$l = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var Axes = /*@__PURE__*/(function (superclass) { +var Axes = /*#__PURE__*/function (_THREE$Object3D) { + /** + * An Axes object can be used to display the axis of a particular coordinate frame. + * + * @constructor + * @param options - object with following keys: + * + * * shaftRadius (optional) - the radius of the shaft to render + * * headRadius (optional) - the radius of the head to render + * * headLength (optional) - the length of the head to render + * * scale (optional) - the scale of the frame (defaults to 1.0) + * * lineType (optional) - the line type for the axes. Supported line types: + * 'dashed' and 'full'. + * * lineDashLength (optional) - the length of the dashes, relative to the length of the axis. + * Maximum value is 1, which means the dash length is + * equal to the length of the axis. Parameter only applies when + * lineType is set to dashed. + */ function Axes(options) { - superclass.call(this); - var that = this; + var _this; + _classCallCheck(this, Axes); + _this = _callSuper$l(this, Axes); + var that = _this; options = options || {}; var shaftRadius = options.shaftRadius || 0.008; var headRadius = options.headRadius || 0.023; @@ -53932,13 +46110,11 @@ var Axes = /*@__PURE__*/(function (superclass) { var scaleArg = options.scale || 1.0; var lineType = options.lineType || 'full'; var lineDashLength = options.lineDashLength || 0.1; - - - this.scale.set(scaleArg, scaleArg, scaleArg); + _this.scale.set(scaleArg, scaleArg, scaleArg); // create the cylinders for the objects - this.lineGeom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); - this.headGeom = new THREE.CylinderGeometry(0, headRadius, headLength); + _this.lineGeom = new CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); + _this.headGeom = new CylinderGeometry(0, headRadius, headLength); /** * Adds an axis marker to this axes object. @@ -53947,20 +46123,20 @@ var Axes = /*@__PURE__*/(function (superclass) { */ function addAxis(axis) { // set the color of the axis - var color = new THREE.Color(); + var color = new Color(); color.setRGB(axis.x, axis.y, axis.z); - var material = new THREE.MeshBasicMaterial({ - color : color.getHex() + var material = new MeshBasicMaterial({ + color: color.getHex() }); // setup the rotation information - var rotAxis = new THREE.Vector3(); - rotAxis.crossVectors(axis, new THREE.Vector3(0, -1, 0)); - var rot = new THREE.Quaternion(); + var rotAxis = new Vector3(); + rotAxis.crossVectors(axis, new Vector3(0, -1, 0)); + var rot = new Quaternion(); rot.setFromAxisAngle(rotAxis, 0.5 * Math.PI); // create the arrow - var arrow = new THREE.Mesh(that.headGeom, material); + var arrow = new Mesh(that.headGeom, material); arrow.position.copy(axis); arrow.position.multiplyScalar(0.95); arrow.quaternion.copy(rot); @@ -53971,9 +46147,9 @@ var Axes = /*@__PURE__*/(function (superclass) { var line; if (lineType === 'dashed') { var l = lineDashLength; - for (var i = 0; (l / 2 + 3 * l * i + l / 2) <= 1; ++i) { - var geom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, l); - line = new THREE.Mesh(geom, material); + for (var i = 0; l / 2 + 3 * l * i + l / 2 <= 1; ++i) { + var geom = new CylinderGeometry(shaftRadius, shaftRadius, l); + line = new Mesh(geom, material); line.position.copy(axis); // Make spacing between dashes equal to 1.5 times the dash length. line.position.multiplyScalar(l / 2 + 3 * l * i); @@ -53982,7 +46158,7 @@ var Axes = /*@__PURE__*/(function (superclass) { that.add(line); } } else if (lineType === 'full') { - line = new THREE.Mesh(that.lineGeom, material); + line = new Mesh(that.lineGeom, material); line.position.copy(axis); line.position.multiplyScalar(0.45); line.quaternion.copy(rot); @@ -53994,315 +46170,413 @@ var Axes = /*@__PURE__*/(function (superclass) { } // add the three markers to the axes - addAxis(new THREE.Vector3(1, 0, 0)); - addAxis(new THREE.Vector3(0, 1, 0)); - addAxis(new THREE.Vector3(0, 0, 1)); + addAxis(new Vector3(1, 0, 0)); + addAxis(new Vector3(0, 1, 0)); + addAxis(new Vector3(0, 0, 1)); + return _this; } + _inherits(Axes, _THREE$Object3D); + return _createClass(Axes); +}(Object3D); - if ( superclass ) Axes.__proto__ = superclass; - Axes.prototype = Object.create( superclass && superclass.prototype ); - Axes.prototype.constructor = Axes; - - return Axes; -}(THREE.Object3D)); +function _callSuper$k(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$k() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$k() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$k = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var Grid = /*@__PURE__*/(function (superclass) { +var Grid = /*#__PURE__*/function (_THREE$Object3D) { + /** + * Create a grid object. + * + * @constructor + * @param options - object with following keys: + * + * * num_cells (optional) - The number of cells of the grid + * * color (optional) - the line color of the grid, like '#cccccc' + * * lineWidth (optional) - the width of the lines in the grid + * * cellSize (optional) - The length, in meters, of the side of each cell + */ + function Grid(options) { + var _this; + _classCallCheck(this, Grid); options = options || {}; var num_cells = options.num_cells || 10; var color = options.color || '#cccccc'; var lineWidth = options.lineWidth || 1; var cellSize = options.cellSize || 1; - - superclass.call(this); - - var material = new THREE.LineBasicMaterial({ + _this = _callSuper$k(this, Grid); + var material = new LineBasicMaterial({ color: color, linewidth: lineWidth }); - + var edges = []; for (var i = 0; i <= num_cells; ++i) { var edge = cellSize * num_cells / 2; - var position = edge - (i * cellSize); - var geometryH = new THREE.Geometry(); - geometryH.vertices.push( - new THREE.Vector3( -edge, position, 0 ), - new THREE.Vector3( edge, position, 0 ) - ); - var geometryV = new THREE.Geometry(); - geometryV.vertices.push( - new THREE.Vector3( position, -edge, 0 ), - new THREE.Vector3( position, edge, 0 ) - ); - this.add(new THREE.Line(geometryH, material)); - this.add(new THREE.Line(geometryV, material)); + var position = edge - i * cellSize; + + // Horizontal lines + edges.push(new Vector3(-edge, position, 0), new Vector3(edge, position, 0)); + + // Vertical lines + edges.push(new Vector3(position, -edge, 0), new Vector3(position, edge, 0)); } - } + var geometry = new BufferGeometry().setFromPoints(edges); - if ( superclass ) Grid.__proto__ = superclass; - Grid.prototype = Object.create( superclass && superclass.prototype ); - Grid.prototype.constructor = Grid; + // Define lines with the geometry + var lineSegments = new LineSegments(geometry, material); + _this.add(lineSegments); + return _this; + } + _inherits(Grid, _THREE$Object3D); + return _createClass(Grid); +}(Object3D); - return Grid; -}(THREE.Object3D)); +function _callSuper$j(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$j() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$j() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$j = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var OccupancyGrid = /*@__PURE__*/(function (superclass) { +var OccupancyGrid = /*#__PURE__*/function (_THREE$Mesh) { + /** + * An OccupancyGrid can convert a ROS occupancy grid message into a THREE object. + * + * @constructor + * @param options - object with following keys: + * + * * message - the occupancy grid message + * * color (optional) - color of the visualized grid + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + */ function OccupancyGrid(options) { + var _this; + _classCallCheck(this, OccupancyGrid); options = options || {}; var message = options.message; var opacity = options.opacity || 1.0; - var color = options.color || {r:255,g:255,b:255,a:255}; + var color = options.color || { + r: 255, + g: 255, + b: 255, + a: 255 + }; // create the geometry var info = message.info; var origin = info.origin; var width = info.width; var height = info.height; - var geom = new THREE.PlaneBufferGeometry(width, height); + var geom = new PlaneGeometry(width, height); // create the color material var imageData = new Uint8Array(width * height * 4); - var texture = new THREE.DataTexture(imageData, width, height, THREE.RGBAFormat); + var texture = new DataTexture(imageData, width, height, RGBAFormat); texture.flipY = true; - texture.minFilter = THREE.NearestFilter; - texture.magFilter = THREE.NearestFilter; + texture.minFilter = NearestFilter; + texture.magFilter = NearestFilter; texture.needsUpdate = true; - - var material = new THREE.MeshBasicMaterial({ - map : texture, - transparent : opacity < 1.0, - opacity : opacity + var material = new MeshBasicMaterial({ + map: texture, + transparent: opacity < 1.0, + opacity: opacity }); - material.side = THREE.DoubleSide; + material.side = DoubleSide; // create the mesh - superclass.call(this, geom, material); + _this = _callSuper$j(this, OccupancyGrid, [geom, material]); // move the map so the corner is at X, Y and correct orientation (informations from message.info) // assign options to this for subclasses - Object.assign(this, options); - - this.quaternion.copy(new THREE.Quaternion( - origin.orientation.x, - origin.orientation.y, - origin.orientation.z, - origin.orientation.w - )); - this.position.x = (width * info.resolution) / 2 + origin.position.x; - this.position.y = (height * info.resolution) / 2 + origin.position.y; - this.position.z = origin.position.z; - this.scale.x = info.resolution; - this.scale.y = info.resolution; - + Object.assign(_this, options); + _this.quaternion.copy(new Quaternion(origin.orientation.x, origin.orientation.y, origin.orientation.z, origin.orientation.w)); + _this.position.x = width * info.resolution / 2 + origin.position.x; + _this.position.y = height * info.resolution / 2 + origin.position.y; + _this.position.z = origin.position.z; + _this.scale.x = info.resolution; + _this.scale.y = info.resolution; var data = message.data; // update the texture (after the the super call and this are accessible) - this.color = color; - this.material = material; - this.texture = texture; - - for ( var row = 0; row < height; row++) { - for ( var col = 0; col < width; col++) { - + _this.color = color; + _this.material = material; + _this.texture = texture; + for (var row = 0; row < height; row++) { + for (var col = 0; col < width; col++) { // determine the index into the map data - var invRow = (height - row - 1); - var mapI = col + (invRow * width); + var invRow = height - row - 1; + var mapI = col + invRow * width; // determine the value - var val = this.getValue(mapI, invRow, col, data); + var val = _this.getValue(mapI, invRow, col, data); // determine the color - var color = this.getColor(mapI, invRow, col, val); + var color = _this.getColor(mapI, invRow, col, val); // determine the index into the image data array - var i = (col + (row * width)) * 4; + var i = (col + row * width) * 4; // copy the color imageData.set(color, i); } } - texture.needsUpdate = true; - + return _this; } + _inherits(OccupancyGrid, _THREE$Mesh); + return _createClass(OccupancyGrid, [{ + key: "dispose", + value: function dispose() { + this.material.dispose(); + this.texture.dispose(); + } + }, { + key: "getValue", + value: + /** + * Returns the value for a given grid cell + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {object} data the data buffer + */ + function getValue(index, row, col, data) { + return data[index]; + } + }, { + key: "getColor", + value: + /** + * Returns a color value given parameters of the position in the grid; the default implementation + * scales the default color value by the grid value. Subclasses can extend this functionality + * (e.g. lookup a color in a color map). + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {float} value the value of the cell + * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel + */ + function getColor(index, row, col, value) { + return [value * this.color.r / 255, value * this.color.g / 255, value * this.color.b / 255, 255]; + } + }]); +}(Mesh); - if ( superclass ) OccupancyGrid.__proto__ = superclass; - OccupancyGrid.prototype = Object.create( superclass && superclass.prototype ); - OccupancyGrid.prototype.constructor = OccupancyGrid; - OccupancyGrid.prototype.dispose = function dispose () { - this.material.dispose(); - this.texture.dispose(); - }; - /** - * Returns the value for a given grid cell - * @param {int} index the current index of the cell - * @param {int} row the row of the cell - * @param {int} col the column of the cell - * @param {object} data the data buffer - */ - OccupancyGrid.prototype.getValue = function getValue (index, row, col, data) { - return data[index]; - }; - /** - * Returns a color value given parameters of the position in the grid; the default implementation - * scales the default color value by the grid value. Subclasses can extend this functionality - * (e.g. lookup a color in a color map). - * @param {int} index the current index of the cell - * @param {int} row the row of the cell - * @param {int} col the column of the cell - * @param {float} value the value of the cell - * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel - */ - OccupancyGrid.prototype.getColor = function getColor (index, row, col, value) { - return [ - (value * this.color.r) / 255, - (value * this.color.g) / 255, - (value * this.color.b) / 255, - 255 - ]; - }; - - return OccupancyGrid; -}(THREE.Mesh)); +function _callSuper$i(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$i() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$i() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$i = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter3) { +var OccupancyGridClient = /*#__PURE__*/function (_EventEmitter) { + /** + * An occupancy grid client that listens to a given map topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic (optional) - the map topic to listen to + * * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM) + * * tfClient (optional) - the TF client handle to use for a scene node + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to + * * offsetPose (optional) - offset pose of the grid visualization, e.g. for z-offset (ROSLIB.Pose type) + * * color (optional) - color of the visualized grid + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + */ function OccupancyGridClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, OccupancyGridClient); + _this = _callSuper$i(this, OccupancyGridClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/map'; - this.compression = options.compression || 'cbor'; - this.continuous = options.continuous; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); - this.color = options.color || {r:255,g:255,b:255}; - this.opacity = options.opacity || 1.0; + _this.ros = options.ros; + _this.topicName = options.topic || '/map'; + _this.compression = options.compression || 'cbor'; + _this.continuous = options.continuous; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); + _this.color = options.color || { + r: 255, + g: 255, + b: 255 + }; + _this.opacity = options.opacity || 1.0; // current grid that is displayed - this.currentGrid = null; + _this.currentGrid = null; // subscribe to the topic - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) OccupancyGridClient.__proto__ = EventEmitter3; - OccupancyGridClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - OccupancyGridClient.prototype.constructor = OccupancyGridClient; - OccupancyGridClient.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(OccupancyGridClient, _EventEmitter); + return _createClass(OccupancyGridClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } + } + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'nav_msgs/OccupancyGrid', + queue_length: 1, + compression: this.compression + }); + this.sceneNode = null; + this.rosTopic.subscribe(this.processMessageBound); } - }; - OccupancyGridClient.prototype.subscribe = function subscribe (){ - this.unsubscribe(); + }, { + key: "processMessage", + value: function processMessage(message) { + // check for an old map + if (this.currentGrid) { + // check if it there is a tf client + if (this.tfClient) { + // grid is of type ROS3D.SceneNode + this.sceneNode.unsubscribeTf(); + this.sceneNode.remove(this.currentGrid); + } else { + this.rootObject.remove(this.currentGrid); + } + this.currentGrid.dispose(); + } + var newGrid = new OccupancyGrid({ + message: message, + color: this.color, + opacity: this.opacity + }); - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'nav_msgs/OccupancyGrid', - queue_length : 1, - compression : this.compression - }); - this.sceneNode = null; - this.rosTopic.subscribe(this.processMessageBound); - }; - OccupancyGridClient.prototype.processMessage = function processMessage (message){ - // check for an old map - if (this.currentGrid) { - // check if it there is a tf client + // check if we care about the scene if (this.tfClient) { - // grid is of type ROS3D.SceneNode - this.sceneNode.unsubscribeTf(); - this.sceneNode.remove(this.currentGrid); + this.currentGrid = newGrid; + if (this.sceneNode === null) { + this.sceneNode = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newGrid, + pose: this.offsetPose + }); + this.rootObject.add(this.sceneNode); + } else { + this.sceneNode.add(this.currentGrid); + } } else { - this.rootObject.remove(this.currentGrid); + this.sceneNode = this.currentGrid = newGrid; + this.rootObject.add(this.currentGrid); } - this.currentGrid.dispose(); - } - - var newGrid = new OccupancyGrid({ - message : message, - color : this.color, - opacity : this.opacity - }); + this.emit('change'); - // check if we care about the scene - if (this.tfClient) { - this.currentGrid = newGrid; - if (this.sceneNode === null) { - this.sceneNode = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newGrid, - pose : this.offsetPose - }); - this.rootObject.add(this.sceneNode); - } else { - this.sceneNode.add(this.currentGrid); + // check if we should unsubscribe + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessageBound); } - } else { - this.sceneNode = this.currentGrid = newGrid; - this.rootObject.add(this.currentGrid); } + }]); +}(EventEmitter2); - this.emit('change'); +function _arrayLikeToArray(r, a) { + (null == a || a > r.length) && (a = r.length); + for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; + return n; +} - // check if we should unsubscribe - if (!this.continuous) { - this.rosTopic.unsubscribe(this.processMessageBound); - } - }; +function _arrayWithoutHoles(r) { + if (Array.isArray(r)) return _arrayLikeToArray(r); +} + +function _iterableToArray(r) { + if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); +} + +function _unsupportedIterableToArray(r, a) { + if (r) { + if ("string" == typeof r) return _arrayLikeToArray(r, a); + var t = {}.toString.call(r).slice(8, -1); + return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; + } +} - return OccupancyGridClient; -}(EventEmitter3)); +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _toConsumableArray(r) { + return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); +} /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ -var OcTreeBaseNode = function OcTreeBaseNode() { - this._children = [null, null, null, null, null, null, null, null]; - this.value = null; -}; -OcTreeBaseNode.prototype.createChildNodeAt = function createChildNodeAt (newNode, index) { - this._children[index % 8] = newNode; -}; -OcTreeBaseNode.prototype.hasChildAt = function hasChildAt (index) { - return this._children[index % 8] !== null; -}; -OcTreeBaseNode.prototype.getChildAt = function getChildAt (index) { - return this._children[index % 8]; -}; -OcTreeBaseNode.prototype.isLeafNode = function isLeafNode () { - for (var i = 0; i < 8; ++i) { - if (this._children[i] !== null) { return false; } - } - return true; -}; -OcTreeBaseNode.prototype.hasChildren = function hasChildren () { - for (var i = 0; i < 8; ++i) { - if (this._children[i] !== null) { return true; } +var OcTreeBaseNode = /*#__PURE__*/function () { + /** + * Base node type that represents one voxel as a node of the tree + */ + + function OcTreeBaseNode() { + _classCallCheck(this, OcTreeBaseNode); + this._children = [null, null, null, null, null, null, null, null]; + this.value = null; } - return false; -}; + return _createClass(OcTreeBaseNode, [{ + key: "createChildNodeAt", + value: function createChildNodeAt(newNode, index) { + this._children[index % 8] = newNode; + } + }, { + key: "hasChildAt", + value: function hasChildAt(index) { + return this._children[index % 8] !== null; + } + }, { + key: "getChildAt", + value: function getChildAt(index) { + return this._children[index % 8]; + } + }, { + key: "isLeafNode", + value: function isLeafNode() { + for (var i = 0; i < 8; ++i) { + if (this._children[i] !== null) { + return false; + } + } + return true; + } + }, { + key: "hasChildren", + value: function hasChildren() { + for (var i = 0; i < 8; ++i) { + if (this._children[i] !== null) { + return true; + } + } + return false; + } + }]); +}(); /** * @fileOverview @@ -54319,7 +46593,7 @@ OcTreeBaseNode.prototype.hasChildren = function hasChildren () { var OcTreeVoxelRenderMode = { OCCUPIED: 'occupied', FREE: 'free', - ALL: 'all', + ALL: 'all' }; /** @@ -54342,719 +46616,781 @@ var OcTreeColorMode = { to read ArrayBuffer in a streamed data-like fashion with mixed types in it */ function InStream(data, isLittleEndian) { - var this$1$1 = this; - + var _this = this; this.buffer = data.buffer; this.length = data.length; - this.isLittleEndian = (typeof isLittleEndian !== 'undefined') ? !!isLittleEndian : true; + this.isLittleEndian = typeof isLittleEndian !== 'undefined' ? !!isLittleEndian : true; this._dataView = new DataView(this.buffer); this._cursor = 0; // Creates a set of wrapper functions for DataView // also flattens all dependencies - [ - { kind: 'Int8', width: 1 }, - { kind: 'Uint8', width: 1 }, - { kind: 'Int16', width: 2 }, - { kind: 'Uint16', width: 2 }, - { kind: 'Int32', width: 4 }, - { kind: 'Uint32', width: 4 }, - { kind: 'BigInt64', width: 8 }, - { kind: 'BigUint64', width: 8 }, - { kind: 'Float32', width: 4 }, - { kind: 'Float64', width: 8 } ] - .forEach(function (wrap) { - var interfaceFunction = 'read' + wrap.kind; - var wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView - - this$1$1[interfaceFunction] = function () { - if (this$1$1._cursor + wrap.width > this$1$1.length) { throw new Error('Cannot read data stream. Overflow. Len=' + this$1$1.length + ' crsr=' + this$1$1._cursor); } - var returningValue = this$1$1._dataView[wrappedFunction](this$1$1._cursor, this$1$1.isLittleEndian); - this$1$1._cursor += wrap.width; - return returningValue; - }; - }); - - Object.defineProperty(this, 'isEnd', { get: function () { return this$1$1.cursor >= this$1$1.data.length; } }); + [{ + kind: 'Int8', + width: 1 + }, { + kind: 'Uint8', + width: 1 + }, { + kind: 'Int16', + width: 2 + }, { + kind: 'Uint16', + width: 2 + }, { + kind: 'Int32', + width: 4 + }, { + kind: 'Uint32', + width: 4 + }, { + kind: 'BigInt64', + width: 8 + }, { + kind: 'BigUint64', + width: 8 + }, { + kind: 'Float32', + width: 4 + }, { + kind: 'Float64', + width: 8 + }].forEach(function (wrap) { + var interfaceFunction = 'read' + wrap.kind; + var wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView + + _this[interfaceFunction] = function () { + if (_this._cursor + wrap.width > _this.length) { + throw new Error('Cannot read data stream. Overflow. Len=' + _this.length + ' crsr=' + _this._cursor); + } + var returningValue = _this._dataView[wrappedFunction](_this._cursor, _this.isLittleEndian); + _this._cursor += wrap.width; + return returningValue; + }; + }); + Object.defineProperty(this, 'isEnd', { + get: function get() { + return _this.cursor >= _this.data.length; + } + }); return this; } -// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - -var OcTreeBase = function OcTreeBase(options) { - - this.resolution = (typeof options.resolution !== 'undefined') ? options.resolution : 1.; - this.color = new THREE.Color((typeof options.color !== 'undefined') ? options.color : 'green'); - this.opacity = (typeof options.opacity !== 'undefined') ? options.opacity : 1.; - - this.voxelRenderMode = (typeof options.voxelRenderMode !== 'undefined') ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; - - this._rootNode = null; - this._treeDepth = 16; - this._treeMaxKeyVal = 32768; - - this._BINARY_UNALLOCATED = 0; - this._BINARY_LEAF_FREE = 1; - this._BINARY_LEAF_OCCUPIED = 2; - this._BINARY_HAS_CHILDREN = 3; - this._BINARY_CHILD_BUILD_TABLE = {}; - - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE] = function (child) { - child.value = this._defaultFreeValue; - }; - - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED] = function (child) { - child.value = this._defaultOccupiedValue; - }; - - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN] = function (child) { - child.value = null; - }; +// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- +var OcTreeBase = /*#__PURE__*/function () { /** - * Table which we are building the geometry data from. + * Represensta a BaseTree that can be build from ros message and create a THREE node from it. + * Due a tree can be represented different ways in a message, this class is also a base class to + * represent specialized versions fo the ree. + * + * @constructor + * @param options - object with following keys: + * + * * resolution - the size of leaf nodes in meter + * * color - color of the visualized map (if solid coloring option was set) + * * voxelRenderMode - toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode */ - this._FACES = [ - { // 0. left (x=0) - normal: [-1, 0, 0 ], - vertices: [ - [0, 1, 0], - [0, 0, 0], - [0, 1, 1], - [0, 0, 1] ], - childIndex: [ - 1, - 3, - 5, - 7 - ] - }, - { // 1. right (x=1) - normal: [1, 0, 0 ], - vertices: [ - [1, 1, 1], - [1, 0, 1], - [1, 1, 0], - [1, 0, 0] ], - - childIndex: [ - 0, - 2, - 4, - 6 - ] - }, - { // 2. bottom (y=0) - normal: [0, -1, 0 ], - vertices: [ - [1, 0, 1], - [0, 0, 1], - [1, 0, 0], - [0, 0, 0] ], - childIndex: [ - 2, - 3, - 6, - 7 - ] - }, - { // 3. top (y=1) - normal: [0, 1, 0 ], - vertices: [ - [0, 1, 1], - [1, 1, 1], - [0, 1, 0], - [1, 1, 0] ], - childIndex: [ - 0, - 1, - 4, - 5 - ] - }, - { // 4. back (z=0) - normal: [0, 0, -1 ], - vertices: [ - [1, 0, 0], - [0, 0, 0], - [1, 1, 0], - [0, 1, 0] ], - childIndex: [ - 4, - 5, - 6, - 7 - ] - }, - { // 5.front (z=1) - normal: [0, 0, 1 ], - vertices: [ - [0, 0, 1], - [1, 0, 1], - [0, 1, 1], - [1, 1, 1] ], - childIndex: [ - 0, - 1, - 2, - 3 - ] - } ]; - - // Table of voxel size for each level of the tree - this.nodeSizeTable = new Array(this._treeDepth); - var _val = this.resolution; - for (var i = this._treeDepth - 1; i >= 0; --i) { - this.nodeSizeTable[i] = _val; - _val = 2. * _val; - } - - this._defaultOccupiedValue = true; - this._defaultFreeValue = false; - - this.object = null; -}; - -/* - * Finds a key in a given depth. Search is performed on the lowest level by default. - * @return the node at given position, null if not found - */ -OcTreeBase.prototype.searchAtDepth = function searchAtDepth (key, depth) { - depth = (typeof depth !== 'undefined') ? (depth > 0 ? depth : this._treeDepth) : this._treeDepth; - - var keyAtDepth = this._adjustKeyAtDepth(key, depth); - var diff = this._treeDepth - depth; - var currentNode = this._rootNode; - - // follow nodes down to requested level (for diff = 0 it's the last level) - // Return the closest node, or null if not any + function OcTreeBase(options) { + _classCallCheck(this, OcTreeBase); + this.resolution = typeof options.resolution !== 'undefined' ? options.resolution : 1.; + this.color = new Color(typeof options.color !== 'undefined' ? options.color : 'green'); + this.opacity = typeof options.opacity !== 'undefined' ? options.opacity : 1.; + this.voxelRenderMode = typeof options.voxelRenderMode !== 'undefined' ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; + this._rootNode = null; + this._treeDepth = 16; + this._treeMaxKeyVal = 32768; + this._BINARY_UNALLOCATED = 0; + this._BINARY_LEAF_FREE = 1; + this._BINARY_LEAF_OCCUPIED = 2; + this._BINARY_HAS_CHILDREN = 3; + this._BINARY_CHILD_BUILD_TABLE = {}; + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE] = function (child) { + child.value = this._defaultFreeValue; + }; + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED] = function (child) { + child.value = this._defaultOccupiedValue; + }; + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN] = function (child) { + child.value = null; + }; - for (var i = (this._treeDepth - 1); i >= diff; --i) { - var pos = this._computeChildIdx(keyAtDepth, i); - if (currentNode.hasChildAt(pos)) { - currentNode = currentNode.getChildAt(pos); - } else { - // we expected a child but did not get it - // is the current node a leaf already? - if (!currentNode.hasChildren()) { return currentNode; } - // it is not, search failed - return null; + /** + * Table which we are building the geometry data from. + */ + this._FACES = [{ + // 0. left (x=0) + normal: [-1, 0, 0], + vertices: [[0, 1, 0], [0, 0, 0], [0, 1, 1], [0, 0, 1]], + childIndex: [1, 3, 5, 7] + }, { + // 1. right (x=1) + normal: [1, 0, 0], + vertices: [[1, 1, 1], [1, 0, 1], [1, 1, 0], [1, 0, 0]], + childIndex: [0, 2, 4, 6] + }, { + // 2. bottom (y=0) + normal: [0, -1, 0], + vertices: [[1, 0, 1], [0, 0, 1], [1, 0, 0], [0, 0, 0]], + childIndex: [2, 3, 6, 7] + }, { + // 3. top (y=1) + normal: [0, 1, 0], + vertices: [[0, 1, 1], [1, 1, 1], [0, 1, 0], [1, 1, 0]], + childIndex: [0, 1, 4, 5] + }, { + // 4. back (z=0) + normal: [0, 0, -1], + vertices: [[1, 0, 0], [0, 0, 0], [1, 1, 0], [0, 1, 0]], + childIndex: [4, 5, 6, 7] + }, { + // 5.front (z=1) + normal: [0, 0, 1], + vertices: [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]], + childIndex: [0, 1, 2, 3] + }]; + + // Table of voxel size for each level of the tree + this.nodeSizeTable = new Array(this._treeDepth); + var _val = this.resolution; + for (var i = this._treeDepth - 1; i >= 0; --i) { + this.nodeSizeTable[i] = _val; + _val = 2. * _val; } + this._defaultOccupiedValue = true; + this._defaultFreeValue = false; + this.object = null; } - - return currentNode; - -}; -/** - * - */ -OcTreeBase.prototype._computeCoordFromKey = function _computeCoordFromKey (key) { - var this$1$1 = this; - - return key.map(function (keyVal) { return this$1$1.resolution * (keyVal - this$1$1._treeMaxKeyVal); }); -}; -OcTreeBase.prototype._computeChildIdx = function _computeChildIdx (key, depth) { - var pos = 0; - if (key[0] & (1 << depth)) { pos += 1; } - if (key[1] & (1 << depth)) { pos += 2; } - if (key[2] & (1 << depth)) { pos += 4; } - - return pos; -}; -OcTreeBase.prototype._computeKeyFromChildIdx = function _computeKeyFromChildIdx (index, offset, depth) { - var diff = this._treeDepth - depth - 1; - - return [ - offset[0] + (!!(index & 1) << diff), - offset[1] + (!!(index & 2) << diff), - offset[2] + (!!(index & 4) << diff) ]; - -}; -OcTreeBase.prototype._adjustKeyAtDepth = function _adjustKeyAtDepth (key, depth) { - var this$1$1 = this; - - // generate appropriate key_at_depth for queried depth - var diff = this._treeDepth - depth; - if (diff === 0) { return key; } - - return key.map(function (keyVal) { return (((keyVal - this$1$1._treeMaxKeyVal) >> diff) << diff) + (1 << (diff - 1)) + this$1$1._treeMaxKeyVal; }); -}; -OcTreeBase.prototype._newNode = function _newNode () { return new OcTreeBaseNode(); }; -/* - * Reads and builds a tree which was represented in a binary form from a message - * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, - * occupation is represented as a binary value. - * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) - * starting with the root node. - */ - -OcTreeBase.prototype.readBinary = function readBinary (data) { - if (this._rootNode !== null) { - delete this._rootNode; - } - this._rootNode = this._newNode(); - - var dataStream = new InStream(data, true); - - var stack = new Array(); - stack.push(this._rootNode); - - while (stack.length > 0) { - var node = stack.pop(); - - // 2 bits per children, 16 bit total - var childAllocationMap = dataStream.readUint16(); - - // Insert all children and leaves - var index = 8; - while (index !== 0) { - --index; - var allocation = (childAllocationMap & (3 << (2 * index))) >> (2 * index); - - if (allocation !== this._BINARY_UNALLOCATED) { - var child = this._newNode(); - - var fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); - fn(child); - - node.createChildNodeAt(child, index); - if (allocation === this._BINARY_HAS_CHILDREN) { stack.push(child); } + return _createClass(OcTreeBase, [{ + key: "searchAtDepth", + value: + /* + * Finds a key in a given depth. Search is performed on the lowest level by default. + * @return the node at given position, null if not found + */ + function searchAtDepth(key, depth) { + depth = typeof depth !== 'undefined' ? depth > 0 ? depth : this._treeDepth : this._treeDepth; + var keyAtDepth = this._adjustKeyAtDepth(key, depth); + var diff = this._treeDepth - depth; + var currentNode = this._rootNode; + + // follow nodes down to requested level (for diff = 0 it's the last level) + // Return the closest node, or null if not any + + for (var i = this._treeDepth - 1; i >= diff; --i) { + var pos = this._computeChildIdx(keyAtDepth, i); + if (currentNode.hasChildAt(pos)) { + currentNode = currentNode.getChildAt(pos); + } else { + // we expected a child but did not get it + // is the current node a leaf already? + if (!currentNode.hasChildren()) { + return currentNode; + } + // it is not, search failed + return null; + } } + return currentNode; } - } - -}; -/** - * Reads a full tree (with node data) from a message. - * A pacjet starts with the node data, followed by the allocation map of their children. - * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData - */ -OcTreeBase.prototype.read = function read (data) { - if (this._rootNode !== null) { - delete this._rootNode; - } - - this._rootNode = this._newNode(); - - var dataStream = new InStream(data, true); - - var stack = new Array(); - stack.push(this._rootNode); - - while (stack.length > 0) { - var node = stack.pop(); - - // Data comes first - this._readNodeData(dataStream, node); - - var childAllocationMap = dataStream.readUint8(); - - // Insert all children and leaves - var index = 8; - while (index !== 0) { - --index; - var hasChild = childAllocationMap & (1 << index); - if (hasChild) { - var child = this._newNode(); - child.value = null; - node.createChildNodeAt(child, index); - stack.push(child); + }, { + key: "_computeCoordFromKey", + value: + /** + * + */ + function _computeCoordFromKey(key) { + var _this2 = this; + return key.map(function (keyVal) { + return _this2.resolution * (keyVal - _this2._treeMaxKeyVal); + }); + } + }, { + key: "_computeChildIdx", + value: function _computeChildIdx(key, depth) { + var pos = 0; + if (key[0] & 1 << depth) { + pos += 1; + } + if (key[1] & 1 << depth) { + pos += 2; } + if (key[2] & 1 << depth) { + pos += 4; + } + return pos; } - } - -}; -/** - * Abstract function; Reads and sets data of a node - */ -OcTreeBase.prototype._readNodeData = function _readNodeData (dataStream, node) { - // This needs to be implemented by specialized tree - console.error('Not implemented'); -}; -/** -* Builds up THREE.js geometry from tree data. -*/ -OcTreeBase.prototype.buildGeometry = function buildGeometry () { - console.assert(this._rootNode !== null, 'No tree data'); - var ref = this._buildFaces(); - var vertices = ref.vertices; - var normals = ref.normals; - var colors = ref.colors; - var indices = ref.indices; - - var geometry = new THREE.BufferGeometry(); - - var material = new THREE.MeshBasicMaterial({ - color: 'white', - flatShading: true, - vertexColors: THREE.VertexColors, - transparent: this.opacity < 1.0, - opacity: this.opacity - }); + }, { + key: "_computeKeyFromChildIdx", + value: function _computeKeyFromChildIdx(index, offset, depth) { + var diff = this._treeDepth - depth - 1; + return [offset[0] + (!!(index & 1) << diff), offset[1] + (!!(index & 2) << diff), offset[2] + (!!(index & 4) << diff)]; + } + }, { + key: "_adjustKeyAtDepth", + value: function _adjustKeyAtDepth(key, depth) { + var _this3 = this; + // generate appropriate key_at_depth for queried depth + var diff = this._treeDepth - depth; + if (diff === 0) { + return key; + } + return key.map(function (keyVal) { + return (keyVal - _this3._treeMaxKeyVal >> diff << diff) + (1 << diff - 1) + _this3._treeMaxKeyVal; + }); + } + }, { + key: "_newNode", + value: function _newNode() { + return new OcTreeBaseNode(); + } + }, { + key: "readBinary", + value: + /* + * Reads and builds a tree which was represented in a binary form from a message + * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, + * occupation is represented as a binary value. + * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) + * starting with the root node. + */ - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); + function readBinary(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + var dataStream = new InStream(data, true); + var stack = new Array(); + stack.push(this._rootNode); + while (stack.length > 0) { + var node = stack.pop(); - geometry.setIndex(indices); + // 2 bits per children, 16 bit total + var childAllocationMap = dataStream.readUint16(); + + // Insert all children and leaves + var index = 8; + while (index !== 0) { + --index; + var allocation = (childAllocationMap & 3 << 2 * index) >> 2 * index; + if (allocation !== this._BINARY_UNALLOCATED) { + var child = this._newNode(); + var fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); + fn(child); + node.createChildNodeAt(child, index); + if (allocation === this._BINARY_HAS_CHILDREN) { + stack.push(child); + } + } + } + } + } + }, { + key: "read", + value: + /** + * Reads a full tree (with node data) from a message. + * A pacjet starts with the node data, followed by the allocation map of their children. + * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData + */ + function read(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + var dataStream = new InStream(data, true); + var stack = new Array(); + stack.push(this._rootNode); + while (stack.length > 0) { + var node = stack.pop(); - var mesh = new THREE.Mesh(geometry, material); - this.object = new THREE.Object3D(); - this.object.add(mesh); -}; -OcTreeBase.prototype._traverseLeaves = function _traverseLeaves (callback) { - var stack = new Array(); - stack.push({ node: this._rootNode, depth: 0, key: [0, 0, 0] }); - - while (stack.length > 0) { - var current = stack.pop(); - if (current.node.isLeafNode()) { - callback(current.node, current.key, current.depth - 1); - } else { - for (var index = 0; index < 8; ++index) { - if (current.node.hasChildAt(index)) { - var key = this._computeKeyFromChildIdx(index, current.key, current.depth); - stack.push({ - node: current.node.getChildAt(index), - depth: current.depth + 1, - key: key - }); + // Data comes first + this._readNodeData(dataStream, node); + var childAllocationMap = dataStream.readUint8(); + + // Insert all children and leaves + var index = 8; + while (index !== 0) { + --index; + var hasChild = childAllocationMap & 1 << index; + if (hasChild) { + var child = this._newNode(); + child.value = null; + node.createChildNodeAt(child, index); + stack.push(child); + } } } } - } -}; -/** - * Abstract function; to implement different coloring schemes - */ -OcTreeBase.prototype._obtainColor = function _obtainColor (node) { - return this.color; -}; -OcTreeBase.prototype._checkOccupied = function _checkOccupied (node) { - return node.value !== false; -}; -OcTreeBase.prototype._buildFaces = function _buildFaces () { - var this$1$1 = this; - - var geometry = { - vertices: [], - indices: [], - normals: [], - colors: [], - - _insertFace: function (face, pos, size, color) { - var ref, ref$1; - - var indexCount = this.vertices.length / 3; - - face.vertices.forEach(function(vertex) { - this.vertices.push( - pos[0] + vertex[0] * size, - pos[1] + vertex[1] * size, - pos[2] + vertex[2] * size - ); + }, { + key: "_readNodeData", + value: + /** + * Abstract function; Reads and sets data of a node + */ + function _readNodeData(dataStream, node) { + // This needs to be implemented by specialized tree + console.error('Not implemented'); + } + }, { + key: "buildGeometry", + value: + /** + * Builds up THREE.js geometry from tree data. + */ + function buildGeometry() { + console.assert(this._rootNode !== null, 'No tree data'); + var _this$_buildFaces = this._buildFaces(), + vertices = _this$_buildFaces.vertices, + normals = _this$_buildFaces.normals, + colors = _this$_buildFaces.colors, + indices = _this$_buildFaces.indices; + var geometry = new BufferGeometry(); + var material = new MeshBasicMaterial({ + color: 'white', + flatShading: true, + vertexColors: true, + transparent: this.opacity < 1.0, + opacity: this.opacity }); - - var colorArr = [color.r, color.g, color.b]; - - (ref = this.colors).push.apply(ref, colorArr.concat( colorArr, colorArr, colorArr )); - (ref$1 = this.normals).push.apply(ref$1, ( face.normal ).concat( face.normal, face.normal, face.normal )); - - this.indices.push( - indexCount, indexCount + 1, indexCount + 2, - indexCount + 2, indexCount + 1, indexCount + 3 - ); - }, - - _checkNeighborsTouchingFace: function (face, neighborNode, voxelRenderMode) { - // Finds if there's not a node at a given position, aka a 'hole' + geometry.addAttribute('position', new BufferAttribute(new Float32Array(vertices), 3)); + geometry.addAttribute('normal', new BufferAttribute(new Float32Array(normals), 3)); + geometry.addAttribute('color', new BufferAttribute(new Float32Array(colors), 3)); + geometry.setIndex(indices); + var mesh = new Mesh(geometry, material); + this.object = new Object3D(); + this.object.add(mesh); + } + }, { + key: "_traverseLeaves", + value: function _traverseLeaves(callback) { var stack = new Array(); - stack.push(neighborNode); - var loop = function () { - var node = stack.pop(); - if (node.hasChildren()) { - face.childIndex.forEach(function(childIndex) { - if (node.hasChildAt(childIndex)) { - var child = node.getChildAt(childIndex); - - // filter occupancy - var isOccupied = this._checkOccupied(node); - var isNeedsToRender = (isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED) || (!isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE); - - if (isNeedsToRender) { stack.push(child); } - } - else { - return true; + stack.push({ + node: this._rootNode, + depth: 0, + key: [0, 0, 0] + }); + while (stack.length > 0) { + var current = stack.pop(); + if (current.node.isLeafNode()) { + callback(current.node, current.key, current.depth - 1); + } else { + for (var index = 0; index < 8; ++index) { + if (current.node.hasChildAt(index)) { + var key = this._computeKeyFromChildIdx(index, current.key, current.depth); + stack.push({ + node: current.node.getChildAt(index), + depth: current.depth + 1, + key: key + }); } + } + } + } + } + }, { + key: "_obtainColor", + value: + /** + * Abstract function; to implement different coloring schemes + */ + function _obtainColor(node) { + return this.color; + } + }, { + key: "_checkOccupied", + value: function _checkOccupied(node) { + return node.value !== false; + } + }, { + key: "_buildFaces", + value: function _buildFaces() { + var _this4 = this; + var geometry = { + vertices: [], + indices: [], + normals: [], + colors: [], + _insertFace: function _insertFace(face, pos, size, color) { + var _this$colors, _this$normals; + var indexCount = this.vertices.length / 3; + face.vertices.forEach(function (vertex) { + this.vertices.push(pos[0] + vertex[0] * size, pos[1] + vertex[1] * size, pos[2] + vertex[2] * size); }); + var colorArr = [color.r, color.g, color.b]; + (_this$colors = this.colors).push.apply(_this$colors, colorArr.concat(colorArr, colorArr, colorArr)); + (_this$normals = this.normals).push.apply(_this$normals, _toConsumableArray(face.normal).concat(_toConsumableArray(face.normal), _toConsumableArray(face.normal), _toConsumableArray(face.normal))); + this.indices.push(indexCount, indexCount + 1, indexCount + 2, indexCount + 2, indexCount + 1, indexCount + 3); + }, + _checkNeighborsTouchingFace: function _checkNeighborsTouchingFace(face, neighborNode, voxelRenderMode) { + // Finds if there's not a node at a given position, aka a 'hole' + var stack = new Array(); + stack.push(neighborNode); + var _loop = function _loop() { + var node = stack.pop(); + if (node.hasChildren()) { + face.childIndex.forEach(function (childIndex) { + if (node.hasChildAt(childIndex)) { + var child = node.getChildAt(childIndex); + + // filter occupancy + var isOccupied = this._checkOccupied(node); + var isNeedsToRender = isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED || !isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE; + if (isNeedsToRender) { + stack.push(child); + } + } else { + return true; + } + }); + } + }; + while (stack.length !== 0) { + _loop(); + } + return false; } }; + this._traverseLeaves(function (node, key, depth) { + var pos = _this4._computeCoordFromKey(key); + var size = _this4.nodeSizeTable[depth]; + var diff = _this4._treeDepth - depth; + var isOccupied = _this4._checkOccupied(node); + + // By default it will show ALL + // Hide free voxels if set + if (!isOccupied && _this4.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { + return; + } - while (stack.length !== 0) loop(); - return false; - } - - }; - - this._traverseLeaves(function (node, key, depth) { - var pos = this$1$1._computeCoordFromKey(key); - var size = this$1$1.nodeSizeTable[depth]; - var diff = this$1$1._treeDepth - depth; - - var isOccupied = this$1$1._checkOccupied(node); - - // By default it will show ALL - // Hide free voxels if set - if (!isOccupied && this$1$1.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { return; } - - // Hide occuped voxels if set. - if (isOccupied && this$1$1.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { return; } - - this$1$1._FACES.forEach(function(face) { - // Add geometry where there is no neighbor voxel - var neighborKey = [ - key[0] + face.normal[0] * diff * diff, - key[1] + face.normal[1] * diff * diff, - key[2] + face.normal[2] * diff * diff ]; - var neighborNode = this.searchAtDepth(neighborKey); - if (neighborNode === null) { - // 1. Simply add geometry where there is no neighbors - geometry._insertFace(face, pos, size, this._obtainColor(node)); - } else if (depth < this._treeDepth) { - // 2. Special case, when a node (voxel) is not on the lowest level - // of the tree, but also need to add a geometry, because might - // not be "fully covered" by neighboring voxels on the lowest level - - if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) ; - } - - }); - - }); + // Hide occuped voxels if set. + if (isOccupied && _this4.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { + return; + } + _this4._FACES.forEach(function (face) { + // Add geometry where there is no neighbor voxel + var neighborKey = [key[0] + face.normal[0] * diff * diff, key[1] + face.normal[1] * diff * diff, key[2] + face.normal[2] * diff * diff]; + var neighborNode = this.searchAtDepth(neighborKey); + if (neighborNode === null) { + // 1. Simply add geometry where there is no neighbors + geometry._insertFace(face, pos, size, this._obtainColor(node)); + } else if (depth < this._treeDepth) { + // 2. Special case, when a node (voxel) is not on the lowest level + // of the tree, but also need to add a geometry, because might + // not be "fully covered" by neighboring voxels on the lowest level + + if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) ; + } + }); + }); - // return geometry; - return { - vertices: geometry.vertices, - normals: geometry.normals, - colors: geometry.colors, - indices: geometry.indices - }; + // return geometry; + return { + vertices: geometry.vertices, + normals: geometry.normals, + colors: geometry.colors, + indices: geometry.indices + }; + } + }]); +}(); -}; +function _callSuper$h(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$h() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$h() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$h = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ -var OcTree = /*@__PURE__*/(function (OcTreeBase) { - function OcTree(options) { - OcTreeBase.call(this, options); - - this._defaultOccupiedValue = 1.; - this._defaultFreeValue = -1.; - - this.occupancyThreshold = (typeof options.occupancyThreshold !== 'undefined') ? options.occupancyThreshold : 0.0000001; - - this.useFlatColoring = (typeof options.colorMode !== 'undefined') && options.colorMode === OcTreeColorMode.SOLID; - - this.palette = (typeof options.palette !== 'undefined') ? options.palette.map(function (color) { return new THREE.Color(color); }) : - [ - { r: 0, g: 0, b: 128, }, // dark blue (low) - { r: 0, g: 255, b: 0, }, // green - { r: 255, g: 255, b: 0, }, // yellow (mid) - { r: 255, g: 128, b: 0, }, // orange - { r: 255, g: 0, b: 0, } // red (high) - ]; +var OcTree = /*#__PURE__*/function (_OcTreeBase) { + /** + * Specilaization of BaseOcTree + * + * @constructor + * @param options - object with following keys: + * * inherited from BaseOctree + * * occupancyThreshold (optional) - threshold value that separates occupied and free voxels from each other. (Default: 0) + * * colorMode (optional) - Coloring mode @see ROS3D.OcTreeColorMode. + * * palette (optional) - Palette used for false-coloring (default: predefined palette) + * * paletteSclae (optional) - Scale of palette to represent a wider range of values (default: 1.) + */ - this.paletteScale = (typeof options.paletteScale !== 'undefined') ? options.paletteScale : 1.; + function OcTree(options) { + var _this; + _classCallCheck(this, OcTree); + _this = _callSuper$h(this, OcTree, [options]); + _this._defaultOccupiedValue = 1.; + _this._defaultFreeValue = -1.; + _this.occupancyThreshold = typeof options.occupancyThreshold !== 'undefined' ? options.occupancyThreshold : 0.0000001; + _this.useFlatColoring = typeof options.colorMode !== 'undefined' && options.colorMode === OcTreeColorMode.SOLID; + _this.palette = typeof options.palette !== 'undefined' ? options.palette.map(function (color) { + return new Color(color); + }) : [{ + r: 0, + g: 0, + b: 128 + }, + // dark blue (low) + { + r: 0, + g: 255, + b: 0 + }, + // green + { + r: 255, + g: 255, + b: 0 + }, + // yellow (mid) + { + r: 255, + g: 128, + b: 0 + }, + // orange + { + r: 255, + g: 0, + b: 0 + } // red (high) + ]; + _this.paletteScale = typeof options.paletteScale !== 'undefined' ? options.paletteScale : 1.; + return _this; } - - if ( OcTreeBase ) OcTree.__proto__ = OcTreeBase; - OcTree.prototype = Object.create( OcTreeBase && OcTreeBase.prototype ); - OcTree.prototype.constructor = OcTree; - - OcTree.prototype._readNodeData = function _readNodeData (dataStream, node) { - node.value = dataStream.readFloat32(); - }; - OcTree.prototype._obtainColor = function _obtainColor (node) { - if (this.useFlatColoring) { - return this.color; + _inherits(OcTree, _OcTreeBase); + return _createClass(OcTree, [{ + key: "_readNodeData", + value: function _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); } + }, { + key: "_obtainColor", + value: function _obtainColor(node) { + if (this.useFlatColoring) { + return this.color; + } - // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range - var value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize - - var intVal = Math.trunc(value); - var fracVal = value - intVal; - - if (intVal < 0) { return this.palette[0]; } - if (intVal >= this.palette.length - 1) { return this.palette[this.palette.length - 1]; } + // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range + var value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize - // Simple lerp - return { - r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, - g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, - b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b, - }; + var intVal = Math.trunc(value); + var fracVal = value - intVal; + if (intVal < 0) { + return this.palette[0]; + } + if (intVal >= this.palette.length - 1) { + return this.palette[this.palette.length - 1]; + } - }; - OcTree.prototype._checkOccupied = function _checkOccupied (node) { - return node.value >= this.occupancyThreshold; - }; + // Simple lerp + return { + r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, + g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, + b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b + }; + } + }, { + key: "_checkOccupied", + value: function _checkOccupied(node) { + return node.value >= this.occupancyThreshold; + } + }]); +}(OcTreeBase); - return OcTree; -}(OcTreeBase)); +function _callSuper$g(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$g() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$g() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$g = function _isNativeReflectConstruct() { return !!t; })(); } +var ColorOcTree = /*#__PURE__*/function (_OcTree) { + /** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ -var ColorOcTree = /*@__PURE__*/(function (OcTree) { function ColorOcTree(options) { - OcTree.call(this, options); - this.useOwnColor = (typeof options.palette !== 'undefined') && options.colorMode === OcTreeColorMode.COLOR; + var _this; + _classCallCheck(this, ColorOcTree); + _this = _callSuper$g(this, ColorOcTree, [options]); + _this.useOwnColor = typeof options.palette !== 'undefined' && options.colorMode === OcTreeColorMode.COLOR; + return _this; } + _inherits(ColorOcTree, _OcTree); + return _createClass(ColorOcTree, [{ + key: "_readNodeData", + value: function _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); // occupancy + node.color = { + r: dataStream.readUint8(), + // red + g: dataStream.readUint8(), + // green + b: dataStream.readUint8() // blue + }; + } + }, { + key: "_obtainColor", + value: function _obtainColor(node) { + if (!this.useOwnColor) { + return OcTree.prototype._obtainColor.call(this, node); + } + return node.color; + } + }]); +}(OcTree); - if ( OcTree ) ColorOcTree.__proto__ = OcTree; - ColorOcTree.prototype = Object.create( OcTree && OcTree.prototype ); - ColorOcTree.prototype.constructor = ColorOcTree; - - ColorOcTree.prototype._readNodeData = function _readNodeData (dataStream, node) { - node.value = dataStream.readFloat32(); // occupancy - node.color = { - r: dataStream.readUint8(), // red - g: dataStream.readUint8(), // green - b: dataStream.readUint8(), // blue - }; - - }; - ColorOcTree.prototype._obtainColor = function _obtainColor (node) { - if (!this.useOwnColor) { return OcTree.prototype._obtainColor.call(this, node); } - return node.color; - }; - - return ColorOcTree; -}(OcTree)); +function _callSuper$f(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$f() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$f() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$f = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ -var OcTreeClient = /*@__PURE__*/(function (EventEmitter3) { +var OcTreeClient = /*#__PURE__*/function (_EventEmitter) { + /** + * An OcTree client that listens to a given OcTree topic. + * + * Emits the following events: + * + * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic (optional) - the map topic to listen to + * * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM) + * * tfClient (optional) - the TF client handle to use for a scene node + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to + * * offsetPose (optional) - offset pose of the mao visualization, e.g. for z-offset (ROSLIB.Pose type) + * * colorMode (optional)) - colorization mode for each voxels @see RORS3D.OcTreeColorMode (default 'color') + * * color (optional) - color of the visualized map (if solid coloring option was set). Can be any value accepted by THREE.Color + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + * * palette (optional) - list of RGB colors to be used as palette (THREE.Color) + * * paletteScale (optional) - scale favtor of palette to cover wider range of values. (default: 1) + * * voxelRenderMode (optional)- toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode. (default `occupid`) + * + */ + function OcTreeClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, OcTreeClient); + _this = _callSuper$f(this, OcTreeClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/octomap'; - this.compression = options.compression || 'cbor'; - this.continuous = options.continuous; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); + _this.ros = options.ros; + _this.topicName = options.topic || '/octomap'; + _this.compression = options.compression || 'cbor'; + _this.continuous = options.continuous; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); // Options passed to converter - this.options = {}; + _this.options = {}; // Append only when it was set, otherwise defaults are provided by the underlying layer - if (typeof options.color !== 'undefined') { this.options['color'] = options.color; } - if (typeof options.opacity !== 'undefined') { this.options['opacity'] = options.opacity; } - if (typeof options.colorMode !== 'undefined') { this.options['colorMode'] = options.colorMode; } - if (typeof options.palette !== 'undefined') { this.options['palette'] = options.palette; } - if (typeof options.paletteScale !== 'undefined') { this.options['paletteScale'] = options.palette; } - if (typeof options.voxelRenderMode !== 'undefined') { this.options['voxelRenderMode'] = options.voxelRenderMode; } + if (typeof options.color !== 'undefined') { + _this.options['color'] = options.color; + } + if (typeof options.opacity !== 'undefined') { + _this.options['opacity'] = options.opacity; + } + if (typeof options.colorMode !== 'undefined') { + _this.options['colorMode'] = options.colorMode; + } + if (typeof options.palette !== 'undefined') { + _this.options['palette'] = options.palette; + } + if (typeof options.paletteScale !== 'undefined') { + _this.options['paletteScale'] = options.palette; + } + if (typeof options.voxelRenderMode !== 'undefined') { + _this.options['voxelRenderMode'] = options.voxelRenderMode; + } // current grid that is displayed - this.currentMap = null; + _this.currentMap = null; // subscribe to the topic - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) OcTreeClient.__proto__ = EventEmitter3; - OcTreeClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - OcTreeClient.prototype.constructor = OcTreeClient; - - OcTreeClient.prototype.unsubscribe = function unsubscribe () { - if (this.rosTopic) { - this.rosTopic.unsubscribe(this.processMessageBound); - } - }; - OcTreeClient.prototype.subscribe = function subscribe () { - this.unsubscribe(); - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros: this.ros, - name: this.topicName, - messageType: 'octomap_msgs/Octomap', - queue_length: 1, - compression: this.compression - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - OcTreeClient.prototype.processMessage = function processMessage (message) { - // check for an old map - if (this.currentMap) { - if (this.currentMap.tfClient) { - this.currentMap.unsubscribeTf(); + _inherits(OcTreeClient, _EventEmitter); + return _createClass(OcTreeClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); } } - - this._processMessagePrivate(message); - - if (!this.continuous) { - this.rosTopic.unsubscribe(this.processMessageBound); + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'octomap_msgs/Octomap', + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessageBound); } - }; - - OcTreeClient.prototype._loadOcTree = function _loadOcTree (message) { - - return new Promise( - function (resolve, reject) { - + }, { + key: "processMessage", + value: function processMessage(message) { + // check for an old map + if (this.currentMap) { + if (this.currentMap.tfClient) { + this.currentMap.unsubscribeTf(); + } + } + this._processMessagePrivate(message); + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessageBound); + } + } + }, { + key: "_loadOcTree", + value: function _loadOcTree(message) { + return new Promise(function (resolve, reject) { // 1. Create the corresponding octree object from message var options = Object.assign({ - resolution: message.resolution, + resolution: message.resolution }, this.options); - var newOcTree = null; { if (message.binary) { - newOcTree = new OcTreeBase( - options - ); + newOcTree = new OcTreeBase(options); newOcTree.readBinary(message.data); } else { - var ctorTable = { 'OcTree': OcTree, - 'ColorOcTree': ColorOcTree, + 'ColorOcTree': ColorOcTree }; - if (message.id in ctorTable) { console.log(message.id, ctorTable); - - newOcTree = new ctorTable[message.id]( - options - ); - + newOcTree = new ctorTable[message.id](options); newOcTree.read(message.data); } - } } - { newOcTree.buildGeometry(); } - resolve(newOcTree); }.bind(this)); - - }; - OcTreeClient.prototype._processMessagePrivate = function _processMessagePrivate (message) { - var promise = this._loadOcTree(message); - - promise.then( + } + }, { + key: "_processMessagePrivate", + value: function _processMessagePrivate(message) { + var promise = this._loadOcTree(message); + promise.then( // 3. Replace geometry function (newOcTree) { // check if we care about the scene @@ -55071,543 +47407,643 @@ var OcTreeClient = /*@__PURE__*/(function (EventEmitter3) { this.sceneNode = newOcTree.object; this.currentMap = newOcTree; } - this.rootObject.remove(oldNode); this.rootObject.add(this.sceneNode); - this.emit('change'); - }.bind(this) - ); - }; + }.bind(this)); + } + }]); +}(EventEmitter2); - return OcTreeClient; -}(EventEmitter3)); +function _callSuper$e(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$e() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$e() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$e = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David V. Lu!! - davidvlu@gmail.com */ -var Odometry = /*@__PURE__*/(function (superclass) { +var Odometry = /*#__PURE__*/function (_THREE$Object3D) { + /** + * An Odometry client + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * keep (optional) - number of markers to keep around (default: 1) + * * color (optional) - color for line (default: 0xcc00ff) + * * length (optional) - the length of the arrow (default: 1.0) + * * headLength (optional) - the head length of the arrow (default: 0.2) + * * shaftDiameter (optional) - the shaft diameter of the arrow (default: 0.05) + * * headDiameter (optional) - the head diameter of the arrow (default: 0.1) + */ function Odometry(options) { - superclass.call(this); - this.options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/particlecloud'; - this.tfClient = options.tfClient; - this.color = options.color || 0xcc00ff; - this.length = options.length || 1.0; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.keep = options.keep || 1; - - this.sns = []; - - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + var _this; + _classCallCheck(this, Odometry); + _this = _callSuper$e(this, Odometry); + _this.options = options || {}; + _this.ros = options.ros; + _this.topicName = options.topic || '/particlecloud'; + _this.tfClient = options.tfClient; + _this.color = options.color || 0xcc00ff; + _this.length = options.length || 1.0; + _this.rootObject = options.rootObject || new Object3D(); + _this.keep = options.keep || 1; + _this.sns = []; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) Odometry.__proto__ = superclass; - Odometry.prototype = Object.create( superclass && superclass.prototype ); - Odometry.prototype.constructor = Odometry; - - Odometry.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(Odometry, _THREE$Object3D); + return _createClass(Odometry, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - Odometry.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'nav_msgs/Odometry' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - Odometry.prototype.processMessage = function processMessage (message){ - if(this.sns.length >= this.keep) { + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'nav_msgs/Odometry' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + if (this.sns.length >= this.keep) { this.sns[0].unsubscribeTf(); this.rootObject.remove(this.sns[0]); this.sns.shift(); + } + this.options.origin = new Vector3(message.pose.pose.position.x, message.pose.pose.position.y, message.pose.pose.position.z); + var rot = new Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, message.pose.pose.orientation.z, message.pose.pose.orientation.w); + this.options.direction = new Vector3(1, 0, 0); + this.options.direction.applyQuaternion(rot); + this.options.material = new MeshBasicMaterial({ + color: this.color + }); + var arrow = new Arrow(this.options); + this.sns.push(new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: arrow + })); + this.rootObject.add(this.sns[this.sns.length - 1]); } + }]); +}(Object3D); - this.options.origin = new THREE.Vector3( message.pose.pose.position.x, message.pose.pose.position.y, - message.pose.pose.position.z); - - var rot = new THREE.Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, - message.pose.pose.orientation.z, message.pose.pose.orientation.w); - this.options.direction = new THREE.Vector3(1,0,0); - this.options.direction.applyQuaternion(rot); - this.options.material = new THREE.MeshBasicMaterial({color: this.color}); - var arrow = new Arrow(this.options); - - this.sns.push(new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : arrow - })); - - this.rootObject.add(this.sns[ this.sns.length - 1]); - }; - - return Odometry; -}(THREE.Object3D)); +function _callSuper$d(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$d() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$d() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$d = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David V. Lu!! - davidvlu@gmail.com */ -var Path = /*@__PURE__*/(function (superclass) { +var Path = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A Path client that listens to a given topic and displays a line connecting the poses. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * color (optional) - color for line (default: 0xcc00ff) + */ function Path(options) { - superclass.call(this); + var _this; + _classCallCheck(this, Path); + _this = _callSuper$d(this, Path); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/path'; - this.tfClient = options.tfClient; - this.color = options.color || 0xcc00ff; - this.rootObject = options.rootObject || new THREE.Object3D(); - - this.sn = null; - this.line = null; - - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.ros = options.ros; + _this.topicName = options.topic || '/path'; + _this.tfClient = options.tfClient; + _this.color = options.color || 0xcc00ff; + _this.rootObject = options.rootObject || new Object3D(); + _this.sn = null; + _this.line = null; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) Path.__proto__ = superclass; - Path.prototype = Object.create( superclass && superclass.prototype ); - Path.prototype.constructor = Path; - - Path.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(Path, _THREE$Object3D); + return _createClass(Path, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - Path.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'nav_msgs/Path' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - Path.prototype.processMessage = function processMessage (message){ - if(this.sn!==null){ + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'nav_msgs/Path' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + if (this.sn !== null) { this.sn.unsubscribeTf(); this.rootObject.remove(this.sn); - } - - var lineGeometry = new THREE.Geometry(); - for(var i=0; i= message.range_min && range <= message.range_max){ + }, { + key: "processMessage", + value: function processMessage(message) { + if (!this.points.setup(message.header.frame_id)) { + return; + } + var n = message.ranges.length; + var j = 0; + for (var i = 0; i < n; i += this.points.pointRatio) { + var range = message.ranges[i]; + if (range >= message.range_min && range <= message.range_max) { var angle = message.angle_min + i * message.angle_increment; this.points.positions.array[j++] = range * Math.cos(angle); this.points.positions.array[j++] = range * Math.sin(angle); this.points.positions.array[j++] = 0.0; + } } + this.points.update(j / 3); } - this.points.update(j/3); - }; + }]); +}(Object3D); - return LaserScan; -}(THREE.Object3D)); +function _callSuper$5(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$5() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$5() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$5 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Mathieu Bredif - mathieu.bredif@ign.fr */ -var NavSatFix = /*@__PURE__*/(function (superclass) { +var NavSatFix = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A NavSatFix client that listens to a given topic and displays a line connecting the gps fixes. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the NavSatFix topic to listen to + * * rootObject (optional) - the root object to add the trajectory line and the gps marker to + * * object3d (optional) - the object3d to be translated by the gps position + * * material (optional) - THREE.js material or options passed to a THREE.LineBasicMaterial, such as : + * * material.color (optional) - color for line + * * material.linewidth (optional) - line width + * * altitudeNaN (optional) - default altitude when the message altitude is NaN (default: 0) + * * keep (optional) - number of gps fix points to keep (default: 100) + * * convert (optional) - conversion function from lon/lat/alt to THREE.Vector3 (default: passthrough) + */ + function NavSatFix(options) { - - superclass.call(this); + var _this; + _classCallCheck(this, NavSatFix); + _this = _callSuper$5(this, NavSatFix); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/gps/fix'; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.object3d = options.object3d || new THREE.Object3D(); + _this.ros = options.ros; + _this.topicName = options.topic || '/gps/fix'; + _this.rootObject = options.rootObject || new Object3D(); + _this.object3d = options.object3d || new Object3D(); var material = options.material || {}; - this.altitudeNaN = options.altitudeNaN || 0; - this.keep = options.keep || 100; - this.convert = options.convert || function(lon,lat,alt) { return new THREE.Vector3(lon,lat,alt); }; - this.count = 0; - this.next1 = 0; - this.next2 = this.keep; - - this.geom = new THREE.BufferGeometry(); - this.vertices = new THREE.BufferAttribute(new Float32Array( 6 * this.keep ), 3 ); - this.geom.addAttribute( 'position', this.vertices); - this.material = material.isMaterial ? material : new THREE.LineBasicMaterial( material ); - this.line = new THREE.Line( this.geom, this.material ); - this.rootObject.add(this.object3d); - this.rootObject.add(this.line); - - this.rosTopic = undefined; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.altitudeNaN = options.altitudeNaN || 0; + _this.keep = options.keep || 100; + _this.convert = options.convert || function (lon, lat, alt) { + return new Vector3(lon, lat, alt); + }; + _this.count = 0; + _this.next1 = 0; + _this.next2 = _this.keep; + _this.geom = new BufferGeometry(); + _this.vertices = new BufferAttribute(new Float32Array(6 * _this.keep), 3); + _this.geom.addAttribute('position', _this.vertices); + _this.material = material.isMaterial ? material : new LineBasicMaterial(material); + _this.line = new Line(_this.geom, _this.material); + _this.rootObject.add(_this.object3d); + _this.rootObject.add(_this.line); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) NavSatFix.__proto__ = superclass; - NavSatFix.prototype = Object.create( superclass && superclass.prototype ); - NavSatFix.prototype.constructor = NavSatFix; - - NavSatFix.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(NavSatFix, _THREE$Object3D); + return _createClass(NavSatFix, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - NavSatFix.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'sensor_msgs/NavSatFix' - }); + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'sensor_msgs/NavSatFix' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; + var p = this.convert(message.longitude, message.latitude, altitude); + + // move the object3d to the gps position + this.object3d.position.copy(p); + this.object3d.updateMatrixWorld(true); + + // copy the position twice in the circular buffer + // the second half replicates the first to allow a single drawRange + this.vertices.array[3 * this.next1] = p.x; + this.vertices.array[3 * this.next1 + 1] = p.y; + this.vertices.array[3 * this.next1 + 2] = p.z; + this.vertices.array[3 * this.next2] = p.x; + this.vertices.array[3 * this.next2 + 1] = p.y; + this.vertices.array[3 * this.next2 + 2] = p.z; + this.vertices.needsUpdate = true; + this.next1 = (this.next1 + 1) % this.keep; + this.next2 = this.next1 + this.keep; + this.count = Math.min(this.count + 1, this.keep); + this.geom.setDrawRange(this.next2 - this.count, this.count); + } + }]); +}(Object3D); - this.rosTopic.subscribe(this.processMessageBound); - }; - NavSatFix.prototype.processMessage = function processMessage (message){ - var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; - var p = this.convert(message.longitude, message.latitude, altitude); - - // move the object3d to the gps position - this.object3d.position.copy(p); - this.object3d.updateMatrixWorld(true); - - // copy the position twice in the circular buffer - // the second half replicates the first to allow a single drawRange - this.vertices.array[3*this.next1 ] = p.x; - this.vertices.array[3*this.next1+1] = p.y; - this.vertices.array[3*this.next1+2] = p.z; - this.vertices.array[3*this.next2 ] = p.x; - this.vertices.array[3*this.next2+1] = p.y; - this.vertices.array[3*this.next2+2] = p.z; - this.vertices.needsUpdate = true; - - this.next1 = (this.next1+1) % this.keep; - this.next2 = this.next1 + this.keep; - this.count = Math.min(this.count+1, this.keep); - this.geom.setDrawRange(this.next2-this.count, this.count ); - }; - - return NavSatFix; -}(THREE.Object3D)); +function _callSuper$4(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$4() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$4() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$4 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -55878,156 +48374,200 @@ var NavSatFix = /*@__PURE__*/(function (superclass) { * returns the number of decoded records */ function decode64(inbytes, outbytes, record_size, pointRatio) { - var x,b=0,l=0,j=0,L=inbytes.length,A=outbytes.length; - record_size = record_size || A; // default copies everything (no skipping) - pointRatio = pointRatio || 1; // default copies everything (no skipping) - var bitskip = (pointRatio-1) * record_size * 8; - for(x=0;x=8){ - l-=8; - outbytes[j++]=(b>>>l)&0xff; - if((j % record_size) === 0) { // skip records - // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} - // first optimization: for(;l0){b=decode64.e[inbytes.charAt(x)];} - } + var x, + b = 0, + l = 0, + j = 0, + L = inbytes.length, + A = outbytes.length; + record_size = record_size || A; // default copies everything (no skipping) + pointRatio = pointRatio || 1; // default copies everything (no skipping) + var bitskip = (pointRatio - 1) * record_size * 8; + for (x = 0; x < L && j < A; x++) { + b = (b << 6) + decode64.e[inbytes.charAt(x)]; + l += 6; + if (l >= 8) { + l -= 8; + outbytes[j++] = b >>> l & 0xff; + if (j % record_size === 0) { + // skip records + // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} + // first optimization: for(;l 0) { + b = decode64.e[inbytes.charAt(x)]; } + } } - return Math.floor(j/record_size); + } + return Math.floor(j / record_size); } // initialize decoder with static lookup table 'e' -decode64.S='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; -decode64.e={}; -for(var i=0;i<64;i++){decode64.e[decode64.S.charAt(i)]=i;} - - -var PointCloud2 = /*@__PURE__*/(function (superclass) { +decode64.S = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +decode64.e = {}; +for (var i = 0; i < 64; i++) { + decode64.e[decode64.S.charAt(i)] = i; +} +var PointCloud2 = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A PointCloud2 client that listens to a given topic and displays the points. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to (default: '/points') + * * tfClient - the TF client handle to use + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to use for the points. + * * max_pts (optional) - number of points to draw (default: 10000) + * * pointRatio (optional) - point subsampling ratio (default: 1, no subsampling) + * * messageRatio (optional) - message subsampling ratio (default: 1, no subsampling) + * * material (optional) - a material object or an option to construct a PointsMaterial. + * * colorsrc (optional) - the field to be used for coloring (default: 'rgb') + * * colormap (optional) - function that turns the colorsrc field value to a color + */ function PointCloud2(options) { - superclass.call(this); + var _this; + _classCallCheck(this, PointCloud2); + _this = _callSuper$4(this, PointCloud2); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/points'; - this.throttle_rate = options.throttle_rate || null; - this.compression = options.compression || 'cbor'; - this.max_pts = options.max_pts || 10000; - this.points = new Points(options); - this.rosTopic = undefined; - this.buffer = null; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.ros = options.ros; + _this.topicName = options.topic || '/points'; + _this.throttle_rate = options.throttle_rate || null; + _this.compression = options.compression || 'cbor'; + _this.max_pts = options.max_pts || 10000; + _this.points = new Points(options); + _this.rosTopic = undefined; + _this.buffer = null; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) PointCloud2.__proto__ = superclass; - PointCloud2.prototype = Object.create( superclass && superclass.prototype ); - PointCloud2.prototype.constructor = PointCloud2; - - PointCloud2.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(PointCloud2, _THREE$Object3D); + return _createClass(PointCloud2, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - PointCloud2.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'sensor_msgs/PointCloud2', - throttle_rate : this.throttle_rate, - queue_length : 1, - compression: this.compression - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - PointCloud2.prototype.processMessage = function processMessage (msg){ - if(!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { - return; + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'sensor_msgs/PointCloud2', + throttle_rate: this.throttle_rate, + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessageBound); } - - var n, pointRatio = this.points.pointRatio; - var bufSz = this.max_pts * msg.point_step; - - if (msg.data.buffer) { - this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); - n = Math.min(msg.height*msg.width / pointRatio, this.points.positions.array.length / 3); - } else { - if (!this.buffer || this.buffer.byteLength < bufSz) { - this.buffer = new Uint8Array(bufSz); + }, { + key: "processMessage", + value: function processMessage(msg) { + if (!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { + return; } - n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); - pointRatio = 1; - } - - var dv = new DataView(this.buffer.buffer); - var littleEndian = !msg.is_bigendian; - var x = this.points.fields.x.offset; - var y = this.points.fields.y.offset; - var z = this.points.fields.z.offset; - var base, color; - for(var i = 0; i < n; i++){ - base = i * pointRatio * msg.point_step; - this.points.positions.array[3*i ] = dv.getFloat32(base+x, littleEndian); - this.points.positions.array[3*i + 1] = dv.getFloat32(base+y, littleEndian); - this.points.positions.array[3*i + 2] = dv.getFloat32(base+z, littleEndian); - - if(this.points.colors){ - color = this.points.colormap(this.points.getColor(dv,base,littleEndian)); - this.points.colors.array[3*i ] = color.r; - this.points.colors.array[3*i + 1] = color.g; - this.points.colors.array[3*i + 2] = color.b; + var n, + pointRatio = this.points.pointRatio; + var bufSz = this.max_pts * msg.point_step; + if (msg.data.buffer) { + this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); + n = Math.min(msg.height * msg.width / pointRatio, this.points.positions.array.length / 3); + } else { + if (!this.buffer || this.buffer.byteLength < bufSz) { + this.buffer = new Uint8Array(bufSz); + } + n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); + pointRatio = 1; + } + var dv = new DataView(this.buffer.buffer); + var littleEndian = !msg.is_bigendian; + var x = this.points.fields.x.offset; + var y = this.points.fields.y.offset; + var z = this.points.fields.z.offset; + var base, color; + for (var i = 0; i < n; i++) { + base = i * pointRatio * msg.point_step; + this.points.positions.array[3 * i] = dv.getFloat32(base + x, littleEndian); + this.points.positions.array[3 * i + 1] = dv.getFloat32(base + y, littleEndian); + this.points.positions.array[3 * i + 2] = dv.getFloat32(base + z, littleEndian); + if (this.points.colors) { + color = this.points.colormap(this.points.getColor(dv, base, littleEndian)); + this.points.colors.array[3 * i] = color.r; + this.points.colors.array[3 * i + 1] = color.g; + this.points.colors.array[3 * i + 2] = color.b; + } } + this.points.update(n); } - this.points.update(n); - }; + }]); +}(Object3D); - return PointCloud2; -}(THREE.Object3D)); +function _callSuper$3(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$3() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$3() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$3 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Jihoon Lee - jihoon.lee@kakaobrain.com */ -var TFAxes = /*@__PURE__*/(function (superclass) { +var TFAxes = /*#__PURE__*/function (_THREE$Object3D) { + /** + * An Axes node can be used to display the axis of a particular coordinate frame. + * + * @constructor + * @param options - object with following keys: + * + * * frame_id - the frame id to visualize axes + * * tfClient - the TF client handle to use + * * shaftRadius (optional) - the radius of the shaft to render + * * headRadius (optional) - the radius of the head to render + * * headLength (optional) - the length of the head to render + * * scale (optional) - the scale of the frame (defaults to 1.0) + * * lineType (optional) - the line type for the axes. Supported line types: + * 'dashed' and 'full'. + * * lineDashLength (optional) - the length of the dashes, relative to the length of the axis. + * Maximum value is 1, which means the dash length is + * equal to the length of the axis. Parameter only applies when + * lineType is set to dashed. + */ function TFAxes(options) { - superclass.call(this); + var _this; + _classCallCheck(this, TFAxes); + _this = _callSuper$3(this, TFAxes); options = options || {}; - - this.frame_id = options.frame_id; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.axes = new Axes( - { - shaftRadius: options.shaftRadius || 0.025, - headRadius: options.headRaidus || 0.07, - headLength: options.headLength || 0.2, - scale: options.scale || 1.0, - lineType: options.lineType || 'full', - lineDashLength: options.lineDashLength || 0.1 - }); - - this.sn = new SceneNode({ - frameID: this.frame_id, - tfClient : this.tfClient, - object : this.axes + _this.frame_id = options.frame_id; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.axes = new Axes({ + shaftRadius: options.shaftRadius || 0.025, + headRadius: options.headRaidus || 0.07, + headLength: options.headLength || 0.2, + scale: options.scale || 1.0, + lineType: options.lineType || 'full', + lineDashLength: options.lineDashLength || 0.1 }); - - this.rootObject.add(this.sn); - + _this.sn = new SceneNode({ + frameID: _this.frame_id, + tfClient: _this.tfClient, + object: _this.axes + }); + _this.rootObject.add(_this.sn); + return _this; } + _inherits(TFAxes, _THREE$Object3D); + return _createClass(TFAxes); +}(Object3D); - if ( superclass ) TFAxes.__proto__ = superclass; - TFAxes.prototype = Object.create( superclass && superclass.prototype ); - TFAxes.prototype.constructor = TFAxes; - - return TFAxes; -}(THREE.Object3D)); +function _callSuper$2(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$2() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$2() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$2 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -56035,22 +48575,36 @@ var TFAxes = /*@__PURE__*/(function (superclass) { * @author Russell Toris - rctoris@wpi.edu */ -var Urdf = /*@__PURE__*/(function (superclass) { +var Urdf = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A URDF can be used to load a ROSLIB.UrdfModel and its associated models into a 3D object. + * + * @constructor + * @param options - object with following keys: + * + * * urdfModel - the ROSLIB.UrdfModel to load + * * tfClient - the TF client handle to use + * * path (optional) - the base path to the associated Collada models that will be loaded + * * tfPrefix (optional) - the TF prefix to used for multi-robots + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ function Urdf(options) { + var _this; + _classCallCheck(this, Urdf); options = options || {}; var urdfModel = options.urdfModel; var path = options.path || '/'; var tfClient = options.tfClient; var tfPrefix = options.tfPrefix || ''; var loader = options.loader; - - superclass.call(this); + console.log('Path ' + path); + _this = _callSuper$2(this, Urdf); // load all models var links = urdfModel.links; - for ( var l in links) { + for (var l in links) { var link = links[l]; - for( var i=0; i 0) { - target = intersections[0].object; - event3D.intersection = this.lastIntersection = intersections[0]; - } else { - target = this.fallbackTarget; - } - - // if the mouse moves from one object to another (or from/to the 'null' object), notify both - if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { - - // Event Status. TODO: Make it as enum - // 0: Accepted - // 1: Failed - // 2: Continued - var eventStatus = this.notify(target, 'mouseover', event3D); - if (eventStatus === 0) { - this.notify(this.lastTarget, 'mouseout', event3D); - } else if(eventStatus === 1) { - // if target was null or no target has caught our event, fall back + // in the normal case, we need to check what is under the mouse + target = this.lastTarget; + var intersections = []; + intersections = mouseRaycaster.intersectObject(this.rootObject, true); + if (intersections.length > 0) { + target = intersections[0].object; + event3D.intersection = this.lastIntersection = intersections[0]; + } else { target = this.fallbackTarget; - if (target !== this.lastTarget) { - this.notify(target, 'mouseover', event3D); + } + + // if the mouse moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { + // Event Status. TODO: Make it as enum + // 0: Accepted + // 1: Failed + // 2: Continued + var eventStatus = this.notify(target, 'mouseover', event3D); + if (eventStatus === 0) { this.notify(this.lastTarget, 'mouseout', event3D); + } else if (eventStatus === 1) { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(target, 'mouseover', event3D); + this.notify(this.lastTarget, 'mouseout', event3D); + } } } - } - // if the finger moves from one object to another (or from/to the 'null' object), notify both - if (target !== this.lastTarget && domEvent.type.match(/touch/)) { - var toucheventAccepted = this.notify(target, domEvent.type, event3D); - if (toucheventAccepted) { - this.notify(this.lastTarget, 'touchleave', event3D); - this.notify(this.lastTarget, 'touchend', event3D); - } else { - // if target was null or no target has caught our event, fall back - target = this.fallbackTarget; - if (target !== this.lastTarget) { - this.notify(this.lastTarget, 'touchmove', event3D); + // if the finger moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/touch/)) { + var toucheventAccepted = this.notify(target, domEvent.type, event3D); + if (toucheventAccepted) { + this.notify(this.lastTarget, 'touchleave', event3D); this.notify(this.lastTarget, 'touchend', event3D); + } else { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(this.lastTarget, 'touchmove', event3D); + this.notify(this.lastTarget, 'touchend', event3D); + } } } - } - // pass through event - this.notify(target, domEvent.type, event3D); - if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { - this.dragging = true; + // pass through event + this.notify(target, domEvent.type, event3D); + if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { + this.dragging = true; + } + this.lastTarget = target; } - this.lastTarget = target; - }; - /** - * Notify the listener of the type of event that occurred. - * - * @param target - the target of the event - * @param type - the type of event that occurred - * @param event3D - the 3D mouse even information - * @returns if an event was canceled - */ - MouseHandler.prototype.notify = function notify (target, type, event3D) { - // ensure the type is set - // - event3D.type = type; - - // make the event cancelable - event3D.cancelBubble = false; - event3D.continueBubble = false; - event3D.stopPropagation = function() { - event3D.cancelBubble = true; - }; + }, { + key: "notify", + value: + /** + * Notify the listener of the type of event that occurred. + * + * @param target - the target of the event + * @param type - the type of event that occurred + * @param event3D - the 3D mouse even information + * @returns if an event was canceled + */ + function notify(target, type, event3D) { + // ensure the type is set + // + event3D.type = type; + + // make the event cancelable + event3D.cancelBubble = false; + event3D.continueBubble = false; + event3D.stopPropagation = function () { + event3D.cancelBubble = true; + }; - // it hit the selectable object but don't highlight - event3D.continuePropagation = function () { - event3D.continueBubble = true; - }; + // it hit the selectable object but don't highlight + event3D.continuePropagation = function () { + event3D.continueBubble = true; + }; - // walk up graph until event is canceled or root node has been reached - event3D.currentTarget = target; - - while (event3D.currentTarget) { - // try to fire event on object - if (event3D.currentTarget.dispatchEvent - && event3D.currentTarget.dispatchEvent instanceof Function) { - event3D.currentTarget.dispatchEvent(event3D); - if (event3D.cancelBubble) { - this.dispatchEvent(event3D); - return 0; // Event Accepted - } - else if(event3D.continueBubble) { - return 2; // Event Continued + // walk up graph until event is canceled or root node has been reached + event3D.currentTarget = target; + while (event3D.currentTarget) { + // try to fire event on object + if (event3D.currentTarget.dispatchEvent && event3D.currentTarget.dispatchEvent instanceof Function) { + event3D.currentTarget.dispatchEvent(event3D); + if (event3D.cancelBubble) { + this.dispatchEvent(event3D); + return 0; // Event Accepted + } else if (event3D.continueBubble) { + return 2; // Event Continued + } } + // walk up + event3D.currentTarget = event3D.currentTarget.parent; } - // walk up - event3D.currentTarget = event3D.currentTarget.parent; + return 1; // Event Failed } + }]); +}(EventDispatcher); - return 1; // Event Failed - }; - - return MouseHandler; -}(THREE.EventDispatcher)); +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -56544,65 +49155,80 @@ var MouseHandler = /*@__PURE__*/(function (superclass) { * @author AlteredQualia - http://alteredqualia.com */ -var OrbitControls = /*@__PURE__*/(function (superclass) { +var OrbitControls = /*#__PURE__*/function (_THREE$EventDispatche) { + /** + * Behaves like THREE.OrbitControls, but uses right-handed coordinates and z as up vector. + * + * @constructor + * @param scene - the global scene to use + * @param camera - the camera to use + * @param userZoomSpeed (optional) - the speed for zooming + * @param userRotateSpeed (optional) - the speed for rotating + * @param autoRotate (optional) - if the orbit should auto rotate + * @param autoRotateSpeed (optional) - the speed for auto rotating + * @param displayPanAndZoomFrame - whether to display a frame when panning/zooming + * (defaults to true) + * @param lineTypePanAndZoomFrame - line type for the frame that is displayed when + * panning/zooming. Only has effect when + * displayPanAndZoomFrame is set to true. + */ function OrbitControls(options) { - superclass.call(this); - var that = this; + var _this; + _classCallCheck(this, OrbitControls); + _this = _callSuper(this, OrbitControls); + var that = _this; options = options || {}; var scene = options.scene; - this.camera = options.camera; - this.center = new THREE.Vector3(); - this.userZoom = true; - this.userZoomSpeed = options.userZoomSpeed || 1.0; - this.userRotate = true; - this.userRotateSpeed = options.userRotateSpeed || 1.0; - this.autoRotate = options.autoRotate; - this.autoRotateSpeed = options.autoRotateSpeed || 2.0; - this.displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? - true : - !!options.displayPanAndZoomFrame; - this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; + _this.camera = options.camera; + _this.center = new Vector3(); + _this.userZoom = true; + _this.userZoomSpeed = options.userZoomSpeed || 1.0; + _this.userRotate = true; + _this.userRotateSpeed = options.userRotateSpeed || 1.0; + _this.autoRotate = options.autoRotate; + _this.autoRotateSpeed = options.autoRotateSpeed || 2.0; + _this.displayPanAndZoomFrame = options.displayPanAndZoomFrame === undefined ? true : !!options.displayPanAndZoomFrame; + _this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; // In ROS, z is pointing upwards - this.camera.up = new THREE.Vector3(0, 0, 1); + _this.camera.up = new Vector3(0, 0, 1); // internals var pixelsPerRound = 1800; var touchMoveThreshold = 10; - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); - var zoomStart = new THREE.Vector2(); - var zoomEnd = new THREE.Vector2(); - var zoomDelta = new THREE.Vector2(); - var moveStartCenter = new THREE.Vector3(); - var moveStartNormal = new THREE.Vector3(); - var moveStartPosition = new THREE.Vector3(); - var moveStartIntersection = new THREE.Vector3(); + var rotateStart = new Vector2(); + var rotateEnd = new Vector2(); + var rotateDelta = new Vector2(); + var zoomStart = new Vector2(); + var zoomEnd = new Vector2(); + var zoomDelta = new Vector2(); + var moveStartCenter = new Vector3(); + var moveStartNormal = new Vector3(); + var moveStartPosition = new Vector3(); + var moveStartIntersection = new Vector3(); var touchStartPosition = new Array(2); var touchMoveVector = new Array(2); - this.phiDelta = 0; - this.thetaDelta = 0; - this.scale = 1; - this.lastPosition = new THREE.Vector3(); + _this.phiDelta = 0; + _this.thetaDelta = 0; + _this.scale = 1; + _this.lastPosition = new Vector3(); // internal states var STATE = { - NONE : -1, - ROTATE : 0, - ZOOM : 1, - MOVE : 2 + NONE: -1, + ROTATE: 0, + ZOOM: 1, + MOVE: 2 }; var state = STATE.NONE; - - this.axes = new Axes({ - shaftRadius : 0.025, - headRadius : 0.07, - headLength : 0.2, - lineType: this.lineTypePanAndZoomFrame + _this.axes = new Axes({ + shaftRadius: 0.025, + headRadius: 0.07, + headLength: 0.2, + lineType: _this.lineTypePanAndZoomFrame }); - if (this.displayPanAndZoomFrame) { + if (_this.displayPanAndZoomFrame) { // initially not visible - scene.add(this.axes); - this.axes.traverse(function(obj) { + scene.add(_this.axes); + _this.axes.traverse(function (obj) { obj.visible = false; }); } @@ -56615,7 +49241,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { function onMouseDown(event3D) { var event = event3D.domEvent; event.preventDefault(); - switch (event.button) { case 0: state = STATE.ROTATE; @@ -56623,23 +49248,18 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { break; case 1: state = STATE.MOVE; - - moveStartNormal = new THREE.Vector3(0, 0, 1); - var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal = new Vector3(0, 0, 1); + var rMat = new Matrix4().extractRotation(this.camera.matrix); moveStartNormal.applyMatrix4(rMat); - moveStartCenter = that.center.clone(); moveStartPosition = that.camera.position.clone(); - moveStartIntersection = intersectViewPlane(event3D.mouseRay, - moveStartCenter, - moveStartNormal); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, moveStartCenter, moveStartNormal); break; case 2: state = STATE.ZOOM; zoomStart.set(event.clientX, event.clientY); break; } - this.showAxes(); } @@ -56651,38 +49271,28 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { function onMouseMove(event3D) { var event = event3D.domEvent; if (state === STATE.ROTATE) { - rotateEnd.set(event.clientX, event.clientY); rotateDelta.subVectors(rotateEnd, rotateStart); - that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); - rotateStart.copy(rotateEnd); this.showAxes(); } else if (state === STATE.ZOOM) { zoomEnd.set(event.clientX, event.clientY); zoomDelta.subVectors(zoomEnd, zoomStart); - if (zoomDelta.y > 0) { that.zoomIn(); } else { that.zoomOut(); } - zoomStart.copy(zoomEnd); this.showAxes(); - } else if (state === STATE.MOVE) { var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); - if (!intersection) { return; } - - var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), intersection - .clone()); - + var delta = new Vector3().subVectors(moveStartIntersection.clone(), intersection.clone()); that.center.addVectors(moveStartCenter.clone(), delta.clone()); that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); that.update(); @@ -56700,10 +49310,8 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { * @returns the intersection */ function intersectViewPlane(mouseRay, planeOrigin, planeNormal) { - - var vector = new THREE.Vector3(); - var intersection = new THREE.Vector3(); - + var vector = new Vector3(); + var intersection = new Vector3(); vector.subVectors(planeOrigin, mouseRay.origin); var dot = mouseRay.direction.dot(planeNormal); @@ -56714,7 +49322,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { // calc distance to plane var scalar = planeNormal.dot(vector) / dot; - intersection = mouseRay.direction.clone().multiplyScalar(scalar); return intersection; } @@ -56728,7 +49335,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { if (!that.userRotate) { return; } - state = STATE.NONE; } @@ -56741,11 +49347,10 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { if (!that.userZoom) { return; } - var event = event3D.domEvent; // wheelDelta --> Chrome, detail --> Firefox var delta; - if (typeof (event.wheelDelta) !== 'undefined') { + if (typeof event.wheelDelta !== 'undefined') { delta = event.wheelDelta; } else { delta = -event.detail; @@ -56755,7 +49360,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { } else { that.zoomOut(); } - this.showAxes(); } @@ -56769,31 +49373,24 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { switch (event.touches.length) { case 1: state = STATE.ROTATE; - rotateStart.set(event.touches[0].pageX - window.scrollX, - event.touches[0].pageY - window.scrollY); + rotateStart.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); break; case 2: state = STATE.NONE; /* ready for move */ - moveStartNormal = new THREE.Vector3(0, 0, 1); - var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal = new Vector3(0, 0, 1); + var rMat = new Matrix4().extractRotation(this.camera.matrix); moveStartNormal.applyMatrix4(rMat); moveStartCenter = that.center.clone(); moveStartPosition = that.camera.position.clone(); - moveStartIntersection = intersectViewPlane(event3D.mouseRay, - moveStartCenter, - moveStartNormal); - touchStartPosition[0] = new THREE.Vector2(event.touches[0].pageX, - event.touches[0].pageY); - touchStartPosition[1] = new THREE.Vector2(event.touches[1].pageX, - event.touches[1].pageY); - touchMoveVector[0] = new THREE.Vector2(0, 0); - touchMoveVector[1] = new THREE.Vector2(0, 0); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, moveStartCenter, moveStartNormal); + touchStartPosition[0] = new Vector2(event.touches[0].pageX, event.touches[0].pageY); + touchStartPosition[1] = new Vector2(event.touches[1].pageX, event.touches[1].pageY); + touchMoveVector[0] = new Vector2(0, 0); + touchMoveVector[1] = new Vector2(0, 0); break; } - this.showAxes(); - event.preventDefault(); } @@ -56805,236 +49402,222 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { function onTouchMove(event3D) { var event = event3D.domEvent; if (state === STATE.ROTATE) { - rotateEnd.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); rotateDelta.subVectors(rotateEnd, rotateStart); - that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); - rotateStart.copy(rotateEnd); this.showAxes(); } else { - touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, - touchStartPosition[0].y - event.touches[0].pageY); - touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, - touchStartPosition[1].y - event.touches[1].pageY); - if (touchMoveVector[0].lengthSq() > touchMoveThreshold && - touchMoveVector[1].lengthSq() > touchMoveThreshold) { - touchStartPosition[0].set(event.touches[0].pageX, - event.touches[0].pageY); - touchStartPosition[1].set(event.touches[1].pageX, - event.touches[1].pageY); - if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && - state !== STATE.ZOOM) { + touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, touchStartPosition[0].y - event.touches[0].pageY); + touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, touchStartPosition[1].y - event.touches[1].pageY); + if (touchMoveVector[0].lengthSq() > touchMoveThreshold && touchMoveVector[1].lengthSq() > touchMoveThreshold) { + touchStartPosition[0].set(event.touches[0].pageX, event.touches[0].pageY); + touchStartPosition[1].set(event.touches[1].pageX, event.touches[1].pageY); + if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && state !== STATE.ZOOM) { state = STATE.MOVE; - } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && - state !== STATE.MOVE) { + } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && state !== STATE.MOVE) { state = STATE.ZOOM; } if (state === STATE.ZOOM) { - var tmpVector = new THREE.Vector2(); - tmpVector.subVectors(touchStartPosition[0], - touchStartPosition[1]); - if (touchMoveVector[0].dot(tmpVector) < 0 && - touchMoveVector[1].dot(tmpVector) > 0) { + var tmpVector = new Vector2(); + tmpVector.subVectors(touchStartPosition[0], touchStartPosition[1]); + if (touchMoveVector[0].dot(tmpVector) < 0 && touchMoveVector[1].dot(tmpVector) > 0) { that.zoomOut(); - } else if (touchMoveVector[0].dot(tmpVector) > 0 && - touchMoveVector[1].dot(tmpVector) < 0) { + } else if (touchMoveVector[0].dot(tmpVector) > 0 && touchMoveVector[1].dot(tmpVector) < 0) { that.zoomIn(); } } } if (state === STATE.MOVE) { - var intersection = intersectViewPlane(event3D.mouseRay, - that.center, - moveStartNormal); + var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); if (!intersection) { return; } - var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), - intersection.clone()); + var delta = new Vector3().subVectors(moveStartIntersection.clone(), intersection.clone()); that.center.addVectors(moveStartCenter.clone(), delta.clone()); that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); that.update(); that.camera.updateMatrixWorld(); } - this.showAxes(); - event.preventDefault(); } } - function onTouchEnd(event3D) { var event = event3D.domEvent; - if (event.touches.length === 1 && - state !== STATE.ROTATE) { + if (event.touches.length === 1 && state !== STATE.ROTATE) { state = STATE.ROTATE; - rotateStart.set(event.touches[0].pageX - window.scrollX, - event.touches[0].pageY - window.scrollY); - } - else { - state = STATE.NONE; + rotateStart.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); + } else { + state = STATE.NONE; } } // add event listeners - this.addEventListener('mousedown', onMouseDown); - this.addEventListener('mouseup', onMouseUp); - this.addEventListener('mousemove', onMouseMove); - this.addEventListener('touchstart', onTouchDown); - this.addEventListener('touchmove', onTouchMove); - this.addEventListener('touchend', onTouchEnd); + _this.addEventListener('mousedown', onMouseDown); + _this.addEventListener('mouseup', onMouseUp); + _this.addEventListener('mousemove', onMouseMove); + _this.addEventListener('touchstart', onTouchDown); + _this.addEventListener('touchmove', onTouchMove); + _this.addEventListener('touchend', onTouchEnd); // Chrome/Firefox have different events here - this.addEventListener('mousewheel', onMouseWheel); - this.addEventListener('DOMMouseScroll', onMouseWheel); + _this.addEventListener('mousewheel', onMouseWheel); + _this.addEventListener('DOMMouseScroll', onMouseWheel); + return _this; } - - if ( superclass ) OrbitControls.__proto__ = superclass; - OrbitControls.prototype = Object.create( superclass && superclass.prototype ); - OrbitControls.prototype.constructor = OrbitControls; - /** - * Display the main axes for 1 second. - */ - OrbitControls.prototype.showAxes = function showAxes () { - var that = this; - - this.axes.traverse(function(obj) { - obj.visible = true; - }); - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - } - this.hideTimeout = setTimeout(function() { - that.axes.traverse(function(obj) { - obj.visible = false; + _inherits(OrbitControls, _THREE$EventDispatche); + return _createClass(OrbitControls, [{ + key: "showAxes", + value: + /** + * Display the main axes for 1 second. + */ + function showAxes() { + var that = this; + this.axes.traverse(function (obj) { + obj.visible = true; }); - that.hideTimeout = false; - }, 1000); - }; - /** - * Rotate the camera to the left by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateLeft = function rotateLeft (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + if (this.hideTimeout) { + clearTimeout(this.hideTimeout); + } + this.hideTimeout = setTimeout(function () { + that.axes.traverse(function (obj) { + obj.visible = false; + }); + that.hideTimeout = false; + }, 1000); } - this.thetaDelta -= angle; - }; - /** - * Rotate the camera to the right by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateRight = function rotateRight (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateLeft", + value: + /** + * Rotate the camera to the left by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateLeft(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta -= angle; } - this.thetaDelta += angle; - }; - /** - * Rotate the camera up by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateUp = function rotateUp (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateRight", + value: + /** + * Rotate the camera to the right by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateRight(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta += angle; } - this.phiDelta -= angle; - }; - /** - * Rotate the camera down by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateDown = function rotateDown (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateUp", + value: + /** + * Rotate the camera up by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateUp(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta -= angle; } - this.phiDelta += angle; - }; - /** - * Zoom in by the given scale. - * - * @param zoomScale (optional) - the scale to zoom in by - */ - OrbitControls.prototype.zoomIn = function zoomIn (zoomScale) { - if (zoomScale === undefined) { - zoomScale = Math.pow(0.95, this.userZoomSpeed); + }, { + key: "rotateDown", + value: + /** + * Rotate the camera down by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateDown(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta += angle; } - this.scale /= zoomScale; - }; - /** - * Zoom out by the given scale. - * - * @param zoomScale (optional) - the scale to zoom in by - */ - OrbitControls.prototype.zoomOut = function zoomOut (zoomScale) { - if (zoomScale === undefined) { - zoomScale = Math.pow(0.95, this.userZoomSpeed); + }, { + key: "zoomIn", + value: + /** + * Zoom in by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + function zoomIn(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale /= zoomScale; } - this.scale *= zoomScale; - }; - /** - * Update the camera to the current settings. - */ - OrbitControls.prototype.update = function update () { - // x->y, y->z, z->x - var position = this.camera.position; - var offset = position.clone().sub(this.center); - - // angle from z-axis around y-axis - var theta = Math.atan2(offset.y, offset.x); - - // angle from y-axis - var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); - - if (this.autoRotate) { - this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + }, { + key: "zoomOut", + value: + /** + * Zoom out by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + function zoomOut(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale *= zoomScale; } - - theta += this.thetaDelta; - phi += this.phiDelta; - - // restrict phi to be between EPS and PI-EPS - var eps = 0.000001; - phi = Math.max(eps, Math.min(Math.PI - eps, phi)); - - var radius = offset.length(); - offset.set( - radius * Math.sin(phi) * Math.cos(theta), - radius * Math.sin(phi) * Math.sin(theta), - radius * Math.cos(phi) - ); - offset.multiplyScalar(this.scale); - - position.copy(this.center).add(offset); - - this.camera.lookAt(this.center); - - radius = offset.length(); - this.axes.position.copy(this.center); - this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); - this.axes.updateMatrixWorld(true); - - this.thetaDelta = 0; - this.phiDelta = 0; - this.scale = 1; - - if (this.lastPosition.distanceTo(this.camera.position) > 0) { - this.dispatchEvent({ - type : 'change' - }); - this.lastPosition.copy(this.camera.position); + }, { + key: "update", + value: + /** + * Update the camera to the current settings. + */ + function update() { + // x->y, y->z, z->x + var position = this.camera.position; + var offset = position.clone().sub(this.center); + + // angle from z-axis around y-axis + var theta = Math.atan2(offset.y, offset.x); + + // angle from y-axis + var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); + if (this.autoRotate) { + this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + } + theta += this.thetaDelta; + phi += this.phiDelta; + + // restrict phi to be between EPS and PI-EPS + var eps = 0.000001; + phi = Math.max(eps, Math.min(Math.PI - eps, phi)); + var radius = offset.length(); + offset.set(radius * Math.sin(phi) * Math.cos(theta), radius * Math.sin(phi) * Math.sin(theta), radius * Math.cos(phi)); + offset.multiplyScalar(this.scale); + position.copy(this.center).add(offset); + this.camera.lookAt(this.center); + radius = offset.length(); + this.axes.position.copy(this.center); + this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); + this.axes.updateMatrixWorld(true); + this.thetaDelta = 0; + this.phiDelta = 0; + this.scale = 1; + if (this.lastPosition.distanceTo(this.camera.position) > 0) { + this.dispatchEvent({ + type: 'change' + }); + this.lastPosition.copy(this.camera.position); + } } - }; - - return OrbitControls; -}(THREE.EventDispatcher)); + }]); +}(EventDispatcher); /** * @fileOverview @@ -57043,152 +49626,196 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { * @author Jihoon Lee - jihoonlee.in@gmail.com */ -var Viewer = function Viewer(options) { - options = options || {}; - var divID = options.divID; - var elem = options.elem; - var width = options.width; - var height = options.height; - var background = options.background || '#111111'; - var antialias = options.antialias; - var intensity = options.intensity || 0.66; - var near = options.near || 0.01; - var far = options.far || 1000; - var alpha = options.alpha || 1.0; - var cameraPosition = options.cameraPose || { - x : 3, - y : 3, - z : 3 - }; - var cameraZoomSpeed = options.cameraZoomSpeed || 0.5; - var displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? true : !!options.displayPanAndZoomFrame; - var lineTypePanAndZoomFrame = options.lineTypePanAndZoomFrame || 'full'; - - // create the canvas to render to - this.renderer = new THREE.WebGLRenderer({ - antialias : antialias, - alpha: true - }); - this.renderer.setClearColor(parseInt(background.replace('#', '0x'), 16), alpha); - this.renderer.sortObjects = false; - this.renderer.setSize(width, height); - this.renderer.shadowMap.enabled = false; - this.renderer.autoClear = false; - - // create the global scene - this.scene = new THREE.Scene(); - - // create the global camera - this.camera = new THREE.PerspectiveCamera(40, width / height, near, far); - this.camera.position.x = cameraPosition.x; - this.camera.position.y = cameraPosition.y; - this.camera.position.z = cameraPosition.z; - // add controls to the camera - this.cameraControls = new OrbitControls({ - scene : this.scene, - camera : this.camera, - displayPanAndZoomFrame : displayPanAndZoomFrame, - lineTypePanAndZoomFrame: lineTypePanAndZoomFrame - }); - this.cameraControls.userZoomSpeed = cameraZoomSpeed; - - // lights - this.scene.add(new THREE.AmbientLight(0x555555)); - this.directionalLight = new THREE.DirectionalLight(0xffffff, intensity); - this.scene.add(this.directionalLight); - - // propagates mouse events to three.js objects - this.selectableObjects = new THREE.Group(); - this.scene.add(this.selectableObjects); - var mouseHandler = new MouseHandler({ - renderer : this.renderer, - camera : this.camera, - rootObject : this.selectableObjects, - fallbackTarget : this.cameraControls - }); +var Viewer = /*#__PURE__*/function () { + /** + * A Viewer can be used to render an interactive 3D scene to a HTML5 canvas. + * + * @constructor + * @param options - object with following keys: + * + * * divID - the ID of the div to place the viewer in + * * elem - the elem to place the viewer in (overrides divID if provided) + * * width - the initial width, in pixels, of the canvas + * * height - the initial height, in pixels, of the canvas + * * background (optional) - the color to render the background, like '#efefef' + * * alpha (optional) - the alpha of the background + * * antialias (optional) - if antialiasing should be used + * * intensity (optional) - the lighting intensity setting to use + * * cameraPosition (optional) - the starting position of the camera + * * displayPanAndZoomFrame (optional) - whether to display a frame when + * * panning/zooming. Defaults to true. + * * lineTypePanAndZoomFrame - line type for the frame that is displayed when + * * panning/zooming. Only has effect when + * * displayPanAndZoomFrame is set to true. + */ - // highlights the receiver of mouse events - this.highlighter = new Highlighter({ - mouseHandler : mouseHandler - }); + function Viewer(options) { + _classCallCheck(this, Viewer); + console.log('Here 1'); + options = options || {}; + var divID = options.divID; + var elem = options.elem; + var width = options.width; + var height = options.height; + var background = options.background || '#111111'; + var antialias = options.antialias; + var intensity = options.intensity || 0.66; + var near = options.near || 0.01; + var far = options.far || 1000; + var alpha = options.alpha || 1.0; + var cameraPosition = options.cameraPose || { + x: 3, + y: 3, + z: 3 + }; + var cameraZoomSpeed = options.cameraZoomSpeed || 0.5; + var displayPanAndZoomFrame = options.displayPanAndZoomFrame === undefined ? true : !!options.displayPanAndZoomFrame; + var lineTypePanAndZoomFrame = options.lineTypePanAndZoomFrame || 'full'; + + // create the canvas to render to + this.renderer = new WebGLRenderer({ + antialias: antialias, + alpha: true + }); + this.renderer.setClearColor(parseInt(background.replace('#', '0x'), 16), alpha); + this.renderer.sortObjects = false; + this.renderer.setSize(width, height); + this.renderer.shadowMap.enabled = false; + this.renderer.autoClear = false; + + // create the global scene + this.scene = new Scene(); + + // create the global camera + this.camera = new PerspectiveCamera(40, width / height, near, far); + this.camera.position.x = cameraPosition.x; + this.camera.position.y = cameraPosition.y; + this.camera.position.z = cameraPosition.z; + // add controls to the camera + this.cameraControls = new OrbitControls({ + scene: this.scene, + camera: this.camera, + displayPanAndZoomFrame: displayPanAndZoomFrame, + lineTypePanAndZoomFrame: lineTypePanAndZoomFrame + }); + this.cameraControls.userZoomSpeed = cameraZoomSpeed; + + // lights + this.scene.add(new AmbientLight(0x555555)); + this.directionalLight = new DirectionalLight(0xffffff, intensity); + this.scene.add(this.directionalLight); + console.log('Here 2'); + + // propagates mouse events to three.js objects + this.selectableObjects = new Group(); + this.scene.add(this.selectableObjects); + var mouseHandler = new MouseHandler({ + renderer: this.renderer, + camera: this.camera, + rootObject: this.selectableObjects, + fallbackTarget: this.cameraControls + }); - this.stopped = true; - this.animationRequestId = undefined; + // highlights the receiver of mouse events + this.highlighter = new Highlighter({ + mouseHandler: mouseHandler + }); + this.stopped = true; + this.animationRequestId = undefined; - // add the renderer to the page - var node = elem || document.getElementById(divID); - node.appendChild(this.renderer.domElement); + // add the renderer to the page + var node = elem || document.getElementById(divID); + node.appendChild(this.renderer.domElement); - // begin the render loop - this.start(); -}; -/** - *Start the render loop - */ -Viewer.prototype.start = function start (){ - this.stopped = false; - this.draw(); -}; -/** - * Renders the associated scene to the viewer. - */ -Viewer.prototype.draw = function draw (){ - if(this.stopped){ - // Do nothing if stopped - return; + // begin the render loop + this.start(); + console.log('Here 3'); } + return _createClass(Viewer, [{ + key: "start", + value: + /** + * Start the render loop + */ + function start() { + this.stopped = false; + this.draw(); + } + }, { + key: "draw", + value: + /** + * Renders the associated scene to the viewer. + */ + function draw() { + if (this.stopped) { + // Do nothing if stopped + return; + } - // update the controls - this.cameraControls.update(); + // update the controls + this.cameraControls.update(); + console.log('Here 5'); - // put light to the top-left of the camera - // BUG: position is a read-only property of DirectionalLight, - // attempting to assign to it either does nothing or throws an error. - //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); - this.directionalLight.position.normalize(); + // put light to the top-left of the camera + // BUG: position is a read-only property of DirectionalLight, + // attempting to assign to it either does nothing or throws an error. + //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); + this.directionalLight.position.normalize(); - // set the scene - this.renderer.clear(true, true, true); - this.renderer.render(this.scene, this.camera); - this.highlighter.renderHighlights(this.scene, this.renderer, this.camera); + // set the scene + this.renderer.clear(true, true, true); + this.renderer.render(this.scene, this.camera); + this.highlighter.renderHighlights(this.scene, this.renderer, this.camera); - // draw the frame - this.animationRequestId = requestAnimationFrame(this.draw.bind(this)); -}; -/** - *Stop the render loop - */ -Viewer.prototype.stop = function stop (){ - if(!this.stopped){ - // Stop animation render loop - cancelAnimationFrame(this.animationRequestId); - } - this.stopped = true; -}; -/** - * Add the given THREE Object3D to the global scene in the viewer. - * - * @param object - the THREE Object3D to add - * @param selectable (optional) - if the object should be added to the selectable list - */ -Viewer.prototype.addObject = function addObject (object, selectable) { - if (selectable) { - this.selectableObjects.add(object); - } else { - this.scene.add(object); - } -}; -/** - * Resize 3D viewer - * - * @param width - new width value - * @param height - new height value - */ -Viewer.prototype.resize = function resize (width, height) { - this.camera.aspect = width / height; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(width, height); -}; + // draw the frame + this.animationRequestId = requestAnimationFrame(this.draw.bind(this)); + } + }, { + key: "stop", + value: + /** + * Stop the render loop + */ + function stop() { + if (!this.stopped) { + // Stop animation render loop + cancelAnimationFrame(this.animationRequestId); + } + this.stopped = true; + } + }, { + key: "addObject", + value: + /** + * Add the given THREE Object3D to the global scene in the viewer. + * + * @param object - the THREE Object3D to add + * @param selectable (optional) - if the object should be added to the selectable list + */ + function addObject(object, selectable) { + if (selectable) { + this.selectableObjects.add(object); + } else { + this.scene.add(object); + } + } + }, { + key: "resize", + value: + /** + * Resize 3D viewer + * + * @param width - new width value + * @param height - new height value + */ + function resize(width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + }]); +}(); exports.Arrow = Arrow; exports.Arrow2 = Arrow2; diff --git a/build/ros3d.esm.js b/build/ros3d.esm.js index def9f892..1870b0bb 100644 --- a/build/ros3d.esm.js +++ b/build/ros3d.esm.js @@ -1,551 +1,674 @@ import * as ROSLIB from 'roslib'; -// Polyfills +/** + * @license + * Copyright 2010-2024 Three.js Authors + * SPDX-License-Identifier: MIT + */ +const REVISION = '167'; +const CullFaceNone = 0; +const CullFaceBack = 1; +const CullFaceFront = 2; +const PCFShadowMap = 1; +const PCFSoftShadowMap = 2; +const VSMShadowMap = 3; +const FrontSide = 0; +const BackSide = 1; +const DoubleSide = 2; +const NoBlending = 0; +const NormalBlending = 1; +const AdditiveBlending = 2; +const SubtractiveBlending = 3; +const MultiplyBlending = 4; +const CustomBlending = 5; +const AddEquation = 100; +const SubtractEquation = 101; +const ReverseSubtractEquation = 102; +const MinEquation = 103; +const MaxEquation = 104; +const ZeroFactor = 200; +const OneFactor = 201; +const SrcColorFactor = 202; +const OneMinusSrcColorFactor = 203; +const SrcAlphaFactor = 204; +const OneMinusSrcAlphaFactor = 205; +const DstAlphaFactor = 206; +const OneMinusDstAlphaFactor = 207; +const DstColorFactor = 208; +const OneMinusDstColorFactor = 209; +const SrcAlphaSaturateFactor = 210; +const ConstantColorFactor = 211; +const OneMinusConstantColorFactor = 212; +const ConstantAlphaFactor = 213; +const OneMinusConstantAlphaFactor = 214; +const NeverDepth = 0; +const AlwaysDepth = 1; +const LessDepth = 2; +const LessEqualDepth = 3; +const EqualDepth = 4; +const GreaterEqualDepth = 5; +const GreaterDepth = 6; +const NotEqualDepth = 7; +const MultiplyOperation = 0; +const MixOperation = 1; +const AddOperation = 2; +const NoToneMapping = 0; +const LinearToneMapping = 1; +const ReinhardToneMapping = 2; +const CineonToneMapping = 3; +const ACESFilmicToneMapping = 4; +const CustomToneMapping = 5; +const AgXToneMapping = 6; +const NeutralToneMapping = 7; +const AttachedBindMode = 'attached'; +const DetachedBindMode = 'detached'; + +const UVMapping = 300; +const CubeReflectionMapping = 301; +const CubeRefractionMapping = 302; +const EquirectangularReflectionMapping = 303; +const EquirectangularRefractionMapping = 304; +const CubeUVReflectionMapping = 306; +const RepeatWrapping = 1000; +const ClampToEdgeWrapping = 1001; +const MirroredRepeatWrapping = 1002; +const NearestFilter = 1003; +const NearestMipmapNearestFilter = 1004; +const NearestMipmapLinearFilter = 1005; +const LinearFilter = 1006; +const LinearMipmapNearestFilter = 1007; +const LinearMipmapLinearFilter = 1008; +const UnsignedByteType = 1009; +const ByteType = 1010; +const ShortType = 1011; +const UnsignedShortType = 1012; +const IntType = 1013; +const UnsignedIntType = 1014; +const FloatType = 1015; +const HalfFloatType = 1016; +const UnsignedShort4444Type = 1017; +const UnsignedShort5551Type = 1018; +const UnsignedInt248Type = 1020; +const UnsignedInt5999Type = 35902; +const AlphaFormat = 1021; +const RGBFormat = 1022; +const RGBAFormat = 1023; +const LuminanceFormat = 1024; +const LuminanceAlphaFormat = 1025; +const DepthFormat = 1026; +const DepthStencilFormat = 1027; +const RedFormat = 1028; +const RedIntegerFormat = 1029; +const RGFormat = 1030; +const RGIntegerFormat = 1031; +const RGBAIntegerFormat = 1033; + +const RGB_S3TC_DXT1_Format = 33776; +const RGBA_S3TC_DXT1_Format = 33777; +const RGBA_S3TC_DXT3_Format = 33778; +const RGBA_S3TC_DXT5_Format = 33779; +const RGB_PVRTC_4BPPV1_Format = 35840; +const RGB_PVRTC_2BPPV1_Format = 35841; +const RGBA_PVRTC_4BPPV1_Format = 35842; +const RGBA_PVRTC_2BPPV1_Format = 35843; +const RGB_ETC1_Format = 36196; +const RGB_ETC2_Format = 37492; +const RGBA_ETC2_EAC_Format = 37496; +const RGBA_ASTC_4x4_Format = 37808; +const RGBA_ASTC_5x4_Format = 37809; +const RGBA_ASTC_5x5_Format = 37810; +const RGBA_ASTC_6x5_Format = 37811; +const RGBA_ASTC_6x6_Format = 37812; +const RGBA_ASTC_8x5_Format = 37813; +const RGBA_ASTC_8x6_Format = 37814; +const RGBA_ASTC_8x8_Format = 37815; +const RGBA_ASTC_10x5_Format = 37816; +const RGBA_ASTC_10x6_Format = 37817; +const RGBA_ASTC_10x8_Format = 37818; +const RGBA_ASTC_10x10_Format = 37819; +const RGBA_ASTC_12x10_Format = 37820; +const RGBA_ASTC_12x12_Format = 37821; +const RGBA_BPTC_Format = 36492; +const RGB_BPTC_SIGNED_Format = 36494; +const RGB_BPTC_UNSIGNED_Format = 36495; +const RED_RGTC1_Format = 36283; +const SIGNED_RED_RGTC1_Format = 36284; +const RED_GREEN_RGTC2_Format = 36285; +const SIGNED_RED_GREEN_RGTC2_Format = 36286; +const InterpolateDiscrete = 2300; +const InterpolateLinear = 2301; +const InterpolateSmooth = 2302; +const ZeroCurvatureEnding = 2400; +const ZeroSlopeEnding = 2401; +const WrapAroundEnding = 2402; +const NormalAnimationBlendMode = 2500; +const BasicDepthPacking = 3200; +const RGBADepthPacking = 3201; +const TangentSpaceNormalMap = 0; +const ObjectSpaceNormalMap = 1; + +// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. +const NoColorSpace = ''; +const SRGBColorSpace = 'srgb'; +const LinearSRGBColorSpace = 'srgb-linear'; +const DisplayP3ColorSpace = 'display-p3'; +const LinearDisplayP3ColorSpace = 'display-p3-linear'; + +const LinearTransfer = 'linear'; +const SRGBTransfer = 'srgb'; + +const Rec709Primaries = 'rec709'; +const P3Primaries = 'p3'; +const KeepStencilOp = 7680; +const AlwaysStencilFunc = 519; + +const NeverCompare = 512; +const LessCompare = 513; +const EqualCompare = 514; +const LessEqualCompare = 515; +const GreaterCompare = 516; +const NotEqualCompare = 517; +const GreaterEqualCompare = 518; +const AlwaysCompare = 519; + +const StaticDrawUsage = 35044; +const DynamicDrawUsage = 35048; +const GLSL3 = '300 es'; + +const WebGLCoordinateSystem = 2000; +const WebGPUCoordinateSystem = 2001; -if ( Number.EPSILON === undefined ) { +/** + * https://github.com/mrdoob/eventdispatcher.js/ + */ - Number.EPSILON = Math.pow( 2, - 52 ); +class EventDispatcher { -} + addEventListener( type, listener ) { -if ( Number.isInteger === undefined ) { + if ( this._listeners === undefined ) this._listeners = {}; - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger + const listeners = this._listeners; - Number.isInteger = function ( value ) { + if ( listeners[ type ] === undefined ) { - return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value; + listeners[ type ] = []; - }; + } -} + if ( listeners[ type ].indexOf( listener ) === - 1 ) { -// + listeners[ type ].push( listener ); -if ( Math.sign === undefined ) { + } - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign + } - Math.sign = function ( x ) { + hasEventListener( type, listener ) { - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x; + if ( this._listeners === undefined ) return false; - }; + const listeners = this._listeners; -} + return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; + + } -if ( 'name' in Function.prototype === false ) { + removeEventListener( type, listener ) { + + if ( this._listeners === undefined ) return; + + const listeners = this._listeners; + const listenerArray = listeners[ type ]; + + if ( listenerArray !== undefined ) { - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + const index = listenerArray.indexOf( listener ); - Object.defineProperty( Function.prototype, 'name', { + if ( index !== - 1 ) { - get: function () { + listenerArray.splice( index, 1 ); - return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ]; + } } - } ); + } -} + dispatchEvent( event ) { -if ( Object.assign === undefined ) { + if ( this._listeners === undefined ) return; - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign + const listeners = this._listeners; + const listenerArray = listeners[ event.type ]; - ( function () { + if ( listenerArray !== undefined ) { - Object.assign = function ( target ) { - var arguments$1 = arguments; + event.target = this; + // Make a copy, in case listeners are removed while iterating. + const array = listenerArray.slice( 0 ); - if ( target === undefined || target === null ) { + for ( let i = 0, l = array.length; i < l; i ++ ) { - throw new TypeError( 'Cannot convert undefined or null to object' ); + array[ i ].call( this, event ); } - var output = Object( target ); + event.target = null; - for ( var index = 1; index < arguments.length; index ++ ) { + } - var source = arguments$1[ index ]; + } - if ( source !== undefined && source !== null ) { +} - for ( var nextKey in source ) { +const _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' ]; - if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) { +let _seed = 1234567; - output[ nextKey ] = source[ nextKey ]; - } +const DEG2RAD = Math.PI / 180; +const RAD2DEG = 180 / Math.PI; - } +// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 +function generateUUID() { - } + const d0 = Math.random() * 0xffffffff | 0; + const d1 = Math.random() * 0xffffffff | 0; + const d2 = Math.random() * 0xffffffff | 0; + const d3 = Math.random() * 0xffffffff | 0; + const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + + _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + + _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + + _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; - } + // .toLowerCase() here flattens concatenated strings to save heap memory space. + return uuid.toLowerCase(); - return output; +} - }; +function clamp( value, min, max ) { - } )(); + return Math.max( min, Math.min( max, value ) ); } -/** - * https://github.com/mrdoob/eventdispatcher.js/ - */ +// compute euclidean modulo of m % n +// https://en.wikipedia.org/wiki/Modulo_operation +function euclideanModulo( n, m ) { -function EventDispatcher() {} + return ( ( n % m ) + m ) % m; -Object.assign( EventDispatcher.prototype, { +} - addEventListener: function ( type, listener ) { +// Linear mapping from range to range +function mapLinear( x, a1, a2, b1, b2 ) { - if ( this._listeners === undefined ) { this._listeners = {}; } + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); - var listeners = this._listeners; +} - if ( listeners[ type ] === undefined ) { +// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ +function inverseLerp( x, y, value ) { - listeners[ type ] = []; + if ( x !== y ) { - } + return ( value - x ) / ( y - x ); - if ( listeners[ type ].indexOf( listener ) === - 1 ) { + } else { - listeners[ type ].push( listener ); + return 0; - } + } - }, +} - hasEventListener: function ( type, listener ) { +// https://en.wikipedia.org/wiki/Linear_interpolation +function lerp( x, y, t ) { - if ( this._listeners === undefined ) { return false; } + return ( 1 - t ) * x + t * y; - var listeners = this._listeners; +} - return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; +// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ +function damp( x, y, lambda, dt ) { - }, + return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); - removeEventListener: function ( type, listener ) { +} - if ( this._listeners === undefined ) { return; } +// https://www.desmos.com/calculator/vcsjnyz7x4 +function pingpong( x, length = 1 ) { - var listeners = this._listeners; - var listenerArray = listeners[ type ]; + return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); - if ( listenerArray !== undefined ) { +} - var index = listenerArray.indexOf( listener ); +// http://en.wikipedia.org/wiki/Smoothstep +function smoothstep( x, min, max ) { - if ( index !== - 1 ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - listenerArray.splice( index, 1 ); + x = ( x - min ) / ( max - min ); - } + return x * x * ( 3 - 2 * x ); - } +} - }, +function smootherstep( x, min, max ) { - dispatchEvent: function ( event ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - if ( this._listeners === undefined ) { return; } + x = ( x - min ) / ( max - min ); - var listeners = this._listeners; - var listenerArray = listeners[ event.type ]; + return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); - if ( listenerArray !== undefined ) { +} - event.target = this; +// Random integer from interval +function randInt( low, high ) { - var array = listenerArray.slice( 0 ); + return low + Math.floor( Math.random() * ( high - low + 1 ) ); - for ( var i = 0, l = array.length; i < l; i ++ ) { +} - array[ i ].call( this, event ); +// Random float from interval +function randFloat( low, high ) { - } + return low + Math.random() * ( high - low ); - } +} - } +// Random float from <-range/2, range/2> interval +function randFloatSpread( range ) { -} ); - -var REVISION = '89'; -var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; -var CullFaceNone = 0; -var CullFaceBack = 1; -var CullFaceFront = 2; -var CullFaceFrontBack = 3; -var FrontFaceDirectionCW = 0; -var FrontFaceDirectionCCW = 1; -var BasicShadowMap = 0; -var PCFShadowMap = 1; -var PCFSoftShadowMap = 2; -var FrontSide = 0; -var BackSide = 1; -var DoubleSide = 2; -var FlatShading = 1; -var SmoothShading = 2; -var NoColors = 0; -var FaceColors = 1; -var VertexColors = 2; -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 Uncharted2ToneMapping = 3; -var CineonToneMapping = 4; -var UVMapping = 300; -var CubeReflectionMapping = 301; -var CubeRefractionMapping = 302; -var EquirectangularReflectionMapping = 303; -var EquirectangularRefractionMapping = 304; -var SphericalReflectionMapping = 305; -var CubeUVReflectionMapping = 306; -var CubeUVRefractionMapping = 307; -var RepeatWrapping = 1000; -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 UnsignedShort565Type = 1019; -var UnsignedInt248Type = 1020; -var AlphaFormat = 1021; -var RGBFormat = 1022; -var RGBAFormat = 1023; -var LuminanceFormat = 1024; -var LuminanceAlphaFormat = 1025; -var RGBEFormat = RGBAFormat; -var DepthFormat = 1026; -var DepthStencilFormat = 1027; -var RGB_S3TC_DXT1_Format = 2001; -var RGBA_S3TC_DXT1_Format = 2002; -var RGBA_S3TC_DXT3_Format = 2003; -var RGBA_S3TC_DXT5_Format = 2004; -var RGB_PVRTC_4BPPV1_Format = 2100; -var RGB_PVRTC_2BPPV1_Format = 2101; -var RGBA_PVRTC_4BPPV1_Format = 2102; -var RGBA_PVRTC_2BPPV1_Format = 2103; -var RGB_ETC1_Format = 2151; -var LoopOnce = 2200; -var LoopRepeat = 2201; -var LoopPingPong = 2202; -var InterpolateDiscrete = 2300; -var InterpolateLinear = 2301; -var InterpolateSmooth = 2302; -var ZeroCurvatureEnding = 2400; -var ZeroSlopeEnding = 2401; -var WrapAroundEnding = 2402; -var TrianglesDrawMode = 0; -var TriangleStripDrawMode = 1; -var TriangleFanDrawMode = 2; -var LinearEncoding = 3000; -var sRGBEncoding = 3001; -var GammaEncoding = 3007; -var RGBEEncoding = 3002; -var LogLuvEncoding = 3003; -var RGBM7Encoding = 3004; -var RGBM16Encoding = 3005; -var RGBDEncoding = 3006; -var BasicDepthPacking = 3200; -var RGBADepthPacking = 3201; + return range * ( 0.5 - Math.random() ); -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ +} -var _Math = { +// Deterministic pseudo-random float in the interval [ 0, 1 ] +function seededRandom( s ) { - DEG2RAD: Math.PI / 180, - RAD2DEG: 180 / Math.PI, + if ( s !== undefined ) _seed = s; - generateUUID: ( function () { + // Mulberry32 generator - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 + let t = _seed += 0x6D2B79F5; - var lut = []; + t = Math.imul( t ^ t >>> 15, t | 1 ); - for ( var i = 0; i < 256; i ++ ) { + t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); - lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 ).toUpperCase(); + return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; - } +} - return function () { +function degToRad( degrees ) { - var d0 = Math.random() * 0xffffffff | 0; - var d1 = Math.random() * 0xffffffff | 0; - var d2 = Math.random() * 0xffffffff | 0; - var d3 = Math.random() * 0xffffffff | 0; - return lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' + - lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' + - lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] + - lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ]; + return degrees * DEG2RAD; - }; +} - } )(), +function radToDeg( radians ) { - clamp: function ( value, min, max ) { + return radians * RAD2DEG; - return Math.max( min, Math.min( max, value ) ); +} - }, +function isPowerOfTwo( value ) { - // compute euclidian modulo of m % n - // https://en.wikipedia.org/wiki/Modulo_operation + return ( value & ( value - 1 ) ) === 0 && value !== 0; - euclideanModulo: function ( n, m ) { +} - return ( ( n % m ) + m ) % m; +function ceilPowerOfTwo( value ) { - }, + return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); - // Linear mapping from range to range +} - mapLinear: function ( x, a1, a2, b1, b2 ) { +function floorPowerOfTwo( value ) { - return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); + return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); - }, +} - // https://en.wikipedia.org/wiki/Linear_interpolation +function setQuaternionFromProperEuler( q, a, b, c, order ) { - lerp: function ( x, y, t ) { + // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles - return ( 1 - t ) * x + t * y; + // rotations are applied to the axes in the order specified by 'order' + // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' + // angles are in radians - }, + const cos = Math.cos; + const sin = Math.sin; - // http://en.wikipedia.org/wiki/Smoothstep + const c2 = cos( b / 2 ); + const s2 = sin( b / 2 ); - smoothstep: function ( x, min, max ) { + const c13 = cos( ( a + c ) / 2 ); + const s13 = sin( ( a + c ) / 2 ); - if ( x <= min ) { return 0; } - if ( x >= max ) { return 1; } + const c1_3 = cos( ( a - c ) / 2 ); + const s1_3 = sin( ( a - c ) / 2 ); - x = ( x - min ) / ( max - min ); + const c3_1 = cos( ( c - a ) / 2 ); + const s3_1 = sin( ( c - a ) / 2 ); - return x * x * ( 3 - 2 * x ); + switch ( order ) { - }, + case 'XYX': + q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); + break; - smootherstep: function ( x, min, max ) { + case 'YZY': + q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); + break; - if ( x <= min ) { return 0; } - if ( x >= max ) { return 1; } + case 'ZXZ': + q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); + break; - x = ( x - min ) / ( max - min ); + case 'XZX': + q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); + break; - return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); + case 'YXY': + q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); + break; - }, + case 'ZYZ': + q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); + break; - // Random integer from interval + default: + console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); - randInt: function ( low, high ) { + } - return low + Math.floor( Math.random() * ( high - low + 1 ) ); +} - }, +function denormalize( value, array ) { - // Random float from interval + switch ( array.constructor ) { - randFloat: function ( low, high ) { + case Float32Array: - return low + Math.random() * ( high - low ); + return value; - }, + case Uint32Array: - // Random float from <-range/2, range/2> interval + return value / 4294967295.0; - randFloatSpread: function ( range ) { + case Uint16Array: - return range * ( 0.5 - Math.random() ); + return value / 65535.0; - }, + case Uint8Array: - degToRad: function ( degrees ) { + return value / 255.0; - return degrees * _Math.DEG2RAD; + case Int32Array: - }, + return Math.max( value / 2147483647.0, - 1.0 ); - radToDeg: function ( radians ) { + case Int16Array: - return radians * _Math.RAD2DEG; + return Math.max( value / 32767.0, - 1.0 ); - }, + case Int8Array: - isPowerOfTwo: function ( value ) { + return Math.max( value / 127.0, - 1.0 ); - return ( value & ( value - 1 ) ) === 0 && value !== 0; + default: - }, + throw new Error( 'Invalid component type.' ); - ceilPowerOfTwo: function ( value ) { + } - return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); +} - }, +function normalize( value, array ) { - floorPowerOfTwo: function ( value ) { + switch ( array.constructor ) { - return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); + case Float32Array: - } + return value; -}; + case Uint32Array: -/** - * @author mrdoob / http://mrdoob.com/ - * @author philogb / http://blog.thejit.org/ - * @author egraether / http://egraether.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - */ + return Math.round( value * 4294967295.0 ); -function Vector2( x, y ) { + case Uint16Array: - this.x = x || 0; - this.y = y || 0; + return Math.round( value * 65535.0 ); -} + case Uint8Array: -Object.defineProperties( Vector2.prototype, { + return Math.round( value * 255.0 ); - "width": { + case Int32Array: - get: function () { + return Math.round( value * 2147483647.0 ); - return this.x; + case Int16Array: - }, + return Math.round( value * 32767.0 ); - set: function ( value ) { + case Int8Array: - this.x = value; + return Math.round( value * 127.0 ); - } + default: - }, + throw new Error( 'Invalid component type.' ); + + } + +} + +const MathUtils = { + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler, + normalize: normalize, + denormalize: denormalize +}; - "height": { +class Vector2 { - get: function () { + constructor( x = 0, y = 0 ) { - return this.y; + Vector2.prototype.isVector2 = true; - }, + this.x = x; + this.y = y; - set: function ( value ) { + } - this.y = value; + get width() { - } + return this.x; + + } + + set width( value ) { + + this.x = value; + + } + + get height() { + + return this.y; } -} ); + set height( value ) { -Object.assign( Vector2.prototype, { + this.y = value; - isVector2: true, + } - set: function ( x, y ) { + set( x, y ) { this.x = x; this.y = y; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { @@ -557,9 +680,9 @@ Object.assign( Vector2.prototype, { return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { @@ -569,164 +692,150 @@ Object.assign( Vector2.prototype, { } - }, + } - clone: function () { + clone() { return new this.constructor( this.x, this.y ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; return this; - }, + } - addScaledVector: function ( v, s ) { + addScaledVector( v, s ) { this.x += v.x * s; this.y += v.y * s; return this; - }, - - sub: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; return this; - }, + } - multiply: function ( v ) { + multiply( v ) { this.x *= v.x; this.y *= v.y; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; return this; - }, + } - divide: function ( v ) { + divide( v ) { this.x /= v.x; this.y /= v.y; return this; - }, + } - divideScalar: function ( scalar ) { + divideScalar( scalar ) { return this.multiplyScalar( 1 / scalar ); - }, + } - applyMatrix3: function ( m ) { + applyMatrix3( m ) { - var x = this.x, y = this.y; - var e = m.elements; + const x = this.x, y = this.y; + const e = m.elements; this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; return this; - }, + } - min: function ( v ) { + min( v ) { this.x = Math.min( this.x, v.x ); this.y = Math.min( this.y, v.y ); return this; - }, + } - max: function ( v ) { + max( v ) { this.x = Math.max( this.x, v.x ); this.y = Math.max( this.y, v.y ); return this; - }, + } - clamp: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise @@ -735,209 +844,212 @@ Object.assign( Vector2.prototype, { return this; - }, - - clampScalar: function () { - - var min = new Vector2(); - var max = new Vector2(); - - return function clampScalar( minVal, maxVal ) { + } - min.set( minVal, minVal ); - max.set( maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - }; + return this; - }(), + } - clampLength: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + floor() { this.x = Math.floor( this.x ); this.y = Math.floor( this.y ); return this; - }, + } - ceil: function () { + ceil() { this.x = Math.ceil( this.x ); this.y = Math.ceil( this.y ); return this; - }, + } - round: function () { + round() { this.x = Math.round( this.x ); this.y = Math.round( this.y ); return this; - }, + } - roundToZero: function () { + 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.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; return this; - }, + } - dot: function ( v ) { + dot( v ) { return this.x * v.x + this.y * v.y; - }, + } + + cross( v ) { + + return this.x * v.y - this.y * v.x; + + } - lengthSq: function () { + lengthSq() { return this.x * this.x + this.y * this.y; - }, + } - length: function () { + length() { return Math.sqrt( this.x * this.x + this.y * this.y ); - }, + } - manhattanLength: function () { + manhattanLength() { return Math.abs( this.x ) + Math.abs( this.y ); - }, + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - angle: function () { + angle() { // computes the angle in radians with respect to the positive x-axis - var angle = Math.atan2( this.y, this.x ); - - if ( angle < 0 ) { angle += 2 * Math.PI; } + const angle = Math.atan2( - this.y, - this.x ) + Math.PI; return angle; - }, + } + + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; - distanceTo: function ( v ) { + // clamp, to handle numerical problems + + return Math.acos( clamp( theta, - 1, 1 ) ); + + } + + distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); - }, + } - distanceToSquared: function ( v ) { + distanceToSquared( v ) { - var dx = this.x - v.x, dy = this.y - v.y; + const dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; - }, + } - manhattanDistanceTo: function ( v ) { + manhattanDistanceTo( v ) { return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + lerp( v, alpha ) { this.x += ( v.x - this.x ) * alpha; this.y += ( v.y - this.y ) * alpha; return this; - }, + } - lerpVectors: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; - }, + return this; - equals: function ( v ) { + } - return ( ( v.x === this.x ) && ( v.y === this.y ) ); + equals( v ) { - }, + return ( ( v.x === this.x ) && ( v.y === this.y ) ); - fromArray: function ( array, offset ) { + } - if ( offset === undefined ) { offset = 0; } + fromArray( array, offset = 0 ) { this.x = array[ offset ]; this.y = array[ offset + 1 ]; return this; - }, + } - toArray: function ( array, offset ) { - - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + toArray( array = [], offset = 0 ) { array[ offset ] = this.x; array[ offset + 1 ] = this.y; return array; - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' ); + } - } + fromBufferAttribute( attribute, index ) { this.x = attribute.getX( index ); this.y = attribute.getY( index ); return this; - }, + } - rotateAround: function ( center, angle ) { + rotateAround( center, angle ) { - var c = Math.cos( angle ), s = Math.sin( angle ); + const c = Math.cos( angle ), s = Math.sin( angle ); - var x = this.x - center.x; - var y = this.y - center.y; + const x = this.x - center.x; + const y = this.y - center.y; this.x = x * c - y * s + center.x; this.y = x * s + y * c + center.y; @@ -946,21197 +1058,10283 @@ Object.assign( Vector2.prototype, { } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author jordi_ros / http://plattsoft.com - * @author D1plo1d / http://github.com/D1plo1d - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author timknip / http://www.floorplanner.com/ - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - */ - -function Matrix4() { + random() { - this.elements = [ + this.x = Math.random(); + this.y = Math.random(); - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + return this; - ]; + } - if ( arguments.length > 0 ) { + *[ Symbol.iterator ]() { - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + yield this.x; + yield this.y; } } -Object.assign( Matrix4.prototype, { +class Matrix3 { - isMatrix4: true, + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + Matrix3.prototype.isMatrix3 = true; - var te = this.elements; + 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; + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 - return this; + ]; - }, + if ( n11 !== undefined ) { - identity: function () { + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); - this.set( + } - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + } - ); + set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - return this; + 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; - clone: function () { + return this; - return new Matrix4().fromArray( this.elements ); + } - }, + identity() { - copy: function ( m ) { + this.set( - var te = this.elements; - var me = m.elements; + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 - 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: function ( m ) { + copy( m ) { - var te = this.elements, me = m.elements; + const te = this.elements; + const me = m.elements; - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; + 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: function ( xAxis, yAxis, zAxis ) { + extractBasis( xAxis, yAxis, zAxis ) { - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); + xAxis.setFromMatrix3Column( this, 0 ); + yAxis.setFromMatrix3Column( this, 1 ); + zAxis.setFromMatrix3Column( this, 2 ); return this; - }, + } + + setFromMatrix4( m ) { - makeBasis: function ( xAxis, yAxis, zAxis ) { + const me = m.elements; 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; + me[ 0 ], me[ 4 ], me[ 8 ], + me[ 1 ], me[ 5 ], me[ 9 ], + me[ 2 ], me[ 6 ], me[ 10 ] - }, + ); - extractRotation: function () { + return this; - var v1 = new Vector3(); + } - return function extractRotation( m ) { + multiply( m ) { - var te = this.elements; - var me = m.elements; + return this.multiplyMatrices( this, m ); - var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); - var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); - var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); + } - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; + premultiply( m ) { - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; + return this.multiplyMatrices( m, this ); - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; + } - return this; + multiplyMatrices( a, b ) { - }; + const ae = a.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 ]; - makeRotationFromEuler: function ( euler ) { + 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 ]; - if ( ! ( euler && euler.isEuler ) ) { + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; + te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; + te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + 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; - var te = this.elements; + return this; - var x = euler.x, y = euler.y, z = euler.z; - var a = Math.cos( x ), b = Math.sin( x ); - var c = Math.cos( y ), d = Math.sin( y ); - var e = Math.cos( z ), f = Math.sin( z ); + } - if ( euler.order === 'XYZ' ) { + multiplyScalar( s ) { - var ae = a * e, af = a * f, be = b * e, bf = b * f; + const te = this.elements; - te[ 0 ] = c * e; - te[ 4 ] = - c * f; - te[ 8 ] = d; + 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; - te[ 1 ] = af + be * d; - te[ 5 ] = ae - bf * d; - te[ 9 ] = - b * c; + return this; - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'YXZ' ) { + determinant() { - var ce = c * e, cf = c * f, de = d * e, df = d * f; + const te = this.elements; - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; + const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], + d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], + g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'ZXY' ) { + invert() { - var ce = c * e, cf = c * f, de = d * e, df = d * f; + const te = this.elements, - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; + 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 ], - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; + t11 = n33 * n22 - n32 * n23, + t12 = n32 * n13 - n33 * n12, + t13 = n23 * n12 - n22 * n13, - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; + det = n11 * t11 + n21 * t12 + n31 * t13; - } else if ( euler.order === 'ZYX' ) { + if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var ae = a * e, af = a * f, be = b * e, bf = b * f; + const detInv = 1 / det; - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; + te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; + te[ 3 ] = t12 * detInv; + te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; + te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; + te[ 6 ] = t13 * detInv; + te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; + te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; - } else if ( euler.order === 'YZX' ) { + return this; - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + } - te[ 0 ] = c * e; - te[ 4 ] = bd - ac * f; - te[ 8 ] = bc * f + ad; + transpose() { - te[ 1 ] = f; - te[ 5 ] = a * e; - te[ 9 ] = - b * e; + let tmp; + const m = this.elements; - te[ 2 ] = - d * e; - te[ 6 ] = ad * f + bc; - te[ 10 ] = ac - bd * f; + tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; + tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; + tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; - } else if ( euler.order === 'XZY' ) { + return this; - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + } - te[ 0 ] = c * e; - te[ 4 ] = - f; - te[ 8 ] = d * e; + getNormalMatrix( matrix4 ) { - te[ 1 ] = ac * f + bd; - te[ 5 ] = a * e; - te[ 9 ] = ad * f - bc; + return this.setFromMatrix4( matrix4 ).invert().transpose(); - te[ 2 ] = bc * f - ad; - te[ 6 ] = b * e; - te[ 10 ] = bd * f + ac; + } - } + transposeIntoArray( r ) { - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + const m = this.elements; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + r[ 0 ] = m[ 0 ]; + r[ 1 ] = m[ 3 ]; + r[ 2 ] = m[ 6 ]; + r[ 3 ] = m[ 1 ]; + r[ 4 ] = m[ 4 ]; + r[ 5 ] = m[ 7 ]; + r[ 6 ] = m[ 2 ]; + r[ 7 ] = m[ 5 ]; + r[ 8 ] = m[ 8 ]; return this; - }, + } - makeRotationFromQuaternion: function ( q ) { + setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { - var te = this.elements; + const c = Math.cos( rotation ); + const s = Math.sin( rotation ); - var x = q._x, y = q._y, z = q._z, w = q._w; - var x2 = x + x, y2 = y + y, z2 = z + z; - var xx = x * x2, xy = x * y2, xz = x * z2; - var yy = y * y2, yz = y * z2, zz = z * z2; - var wx = w * x2, wy = w * y2, wz = w * z2; + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 1 + ); - te[ 0 ] = 1 - ( yy + zz ); - te[ 4 ] = xy - wz; - te[ 8 ] = xz + wy; + return this; - te[ 1 ] = xy + wz; - te[ 5 ] = 1 - ( xx + zz ); - te[ 9 ] = yz - wx; + } - te[ 2 ] = xz - wy; - te[ 6 ] = yz + wx; - te[ 10 ] = 1 - ( xx + yy ); + // - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + scale( sx, sy ) { - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + this.premultiply( _m3.makeScale( sx, sy ) ); return this; - }, + } - lookAt: function () { + rotate( theta ) { - var x = new Vector3(); - var y = new Vector3(); - var z = new Vector3(); + this.premultiply( _m3.makeRotation( - theta ) ); - return function lookAt( eye, target, up ) { + return this; - var te = this.elements; + } - z.subVectors( eye, target ); + translate( tx, ty ) { - if ( z.lengthSq() === 0 ) { + this.premultiply( _m3.makeTranslation( tx, ty ) ); - // eye and target are in the same position + return this; - z.z = 1; + } - } + // for 2D Transforms - z.normalize(); - x.crossVectors( up, z ); + makeTranslation( x, y ) { - if ( x.lengthSq() === 0 ) { + if ( x.isVector2 ) { - // up and z are parallel + this.set( - if ( Math.abs( up.z ) === 1 ) { + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 - z.x += 0.0001; + ); - } else { + } else { - z.z += 0.0001; + this.set( - } + 1, 0, x, + 0, 1, y, + 0, 0, 1 - z.normalize(); - x.crossVectors( up, z ); + ); - } + } - x.normalize(); - y.crossVectors( z, x ); + return this; - 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; + makeRotation( theta ) { - }; + // counterclockwise - }(), + const c = Math.cos( theta ); + const s = Math.sin( theta ); - multiply: function ( m, n ) { + this.set( - if ( n !== undefined ) { + c, - s, 0, + s, c, 0, + 0, 0, 1 - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); - return this.multiplyMatrices( m, n ); + ); - } + return this; - return this.multiplyMatrices( this, m ); + } - }, + makeScale( x, y ) { - premultiply: function ( m ) { + this.set( - return this.multiplyMatrices( m, this ); + x, 0, 0, + 0, y, 0, + 0, 0, 1 - }, + ); - multiplyMatrices: function ( a, b ) { + return this; - var ae = a.elements; - var be = b.elements; - var te = this.elements; + } - var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; - var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; - var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; - var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; + // - var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; - var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; - var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; - var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; + equals( matrix ) { - 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; + const te = this.elements; + const me = matrix.elements; - 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; + for ( let i = 0; i < 9; i ++ ) { - 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; + if ( te[ i ] !== me[ i ] ) return false; - 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; + return true; - }, + } - multiplyScalar: function ( s ) { + fromArray( array, offset = 0 ) { - var te = this.elements; + for ( let i = 0; i < 9; i ++ ) { - 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; + this.elements[ i ] = array[ i + offset ]; + + } return this; - }, + } - applyToBufferAttribute: function () { + toArray( array = [], offset = 0 ) { - var v1 = new Vector3(); + const te = this.elements; - return function applyToBufferAttribute( attribute ) { + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + array[ offset + 3 ] = te[ 3 ]; + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; + array[ offset + 8 ] = te[ 8 ]; - v1.applyMatrix4( this ); + return array; - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + } - } + clone() { - return attribute; + return new this.constructor().fromArray( this.elements ); - }; + } - }(), +} - determinant: function () { +const _m3 = /*@__PURE__*/ new Matrix3(); - var te = this.elements; +function arrayNeedsUint32( array ) { - var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; - var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; - var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; - var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; + // assumes larger values usually on last - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + for ( let i = array.length - 1; i >= 0; -- i ) { - 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 - ) + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 - ); + } - }, + return false; - transpose: function () { +} - var te = this.elements; - var tmp; +function createElementNS( name ) { - 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; + return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); - 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; +function createCanvasElement() { - }, + const canvas = createElementNS( 'canvas' ); + canvas.style.display = 'block'; + return canvas; - setPosition: function ( v ) { +} - var te = this.elements; +const _cache = {}; - te[ 12 ] = v.x; - te[ 13 ] = v.y; - te[ 14 ] = v.z; +function warnOnce( message ) { - return this; + if ( message in _cache ) return; - }, + _cache[ message ] = true; - getInverse: function ( m, throwOnDegenerate ) { + console.warn( message ); - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - var te = this.elements, - me = m.elements, +} - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ], - n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ], - n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ], - n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ], +function probeAsync( gl, sync, interval ) { - 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; + return new Promise( function ( resolve, reject ) { - var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + function probe() { - if ( det === 0 ) { + switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) { - var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; + case gl.WAIT_FAILED: + reject(); + break; - if ( throwOnDegenerate === true ) { + case gl.TIMEOUT_EXPIRED: + setTimeout( probe, interval ); + break; - throw new Error( msg ); + default: + resolve(); - } else { + } - console.warn( msg ); + } - } + setTimeout( probe, interval ); - return this.identity(); + } ); - } +} - var detInv = 1 / det; +/** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + +const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( + 0.8224621, 0.177538, 0.0, + 0.0331941, 0.9668058, 0.0, + 0.0170827, 0.0723974, 0.9105199, +); + +const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( + 1.2249401, - 0.2249404, 0.0, + - 0.0420569, 1.0420571, 0.0, + - 0.0196376, - 0.0786361, 1.0982735 +); + +/** + * Defines supported color spaces by transfer function and primaries, + * and provides conversions to/from the Linear-sRGB reference space. + */ +const COLOR_SPACES = { + [ LinearSRGBColorSpace ]: { + transfer: LinearTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color, + fromReference: ( color ) => color, + }, + [ SRGBColorSpace ]: { + transfer: SRGBTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color.convertSRGBToLinear(), + fromReference: ( color ) => color.convertLinearToSRGB(), + }, + [ LinearDisplayP3ColorSpace ]: { + transfer: LinearTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), + }, + [ DisplayP3ColorSpace ]: { + transfer: SRGBTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), + }, +}; - 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; +const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); - 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; +const ColorManagement = { - 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; + enabled: true, - 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; + _workingColorSpace: LinearSRGBColorSpace, - return this; + get workingColorSpace() { + + return this._workingColorSpace; }, - scale: function ( v ) { + set workingColorSpace( colorSpace ) { - var te = this.elements; - var x = v.x, y = v.y, z = v.z; + if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { - te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; - te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; - te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; - te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; + throw new Error( `Unsupported working color space, "${ colorSpace }".` ); - return this; + } + + this._workingColorSpace = colorSpace; }, - getMaxScaleOnAxis: function () { + convert: function ( color, sourceColorSpace, targetColorSpace ) { - var te = this.elements; + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { - var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; - var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; - var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; + return color; - return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); + } + + const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; + const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; + + return targetFromReference( sourceToReference( color ) ); }, - makeTranslation: function ( x, y, z ) { + fromWorkingColorSpace: function ( color, targetColorSpace ) { - this.set( + return this.convert( color, this._workingColorSpace, targetColorSpace ); - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + }, - ); + toWorkingColorSpace: function ( color, sourceColorSpace ) { - return this; + return this.convert( color, sourceColorSpace, this._workingColorSpace ); }, - makeRotationX: function ( theta ) { + getPrimaries: function ( colorSpace ) { - var c = Math.cos( theta ), s = Math.sin( theta ); + return COLOR_SPACES[ colorSpace ].primaries; - this.set( + }, - 1, 0, 0, 0, - 0, c, - s, 0, - 0, s, c, 0, - 0, 0, 0, 1 + getTransfer: function ( colorSpace ) { - ); + if ( colorSpace === NoColorSpace ) return LinearTransfer; - return this; + return COLOR_SPACES[ colorSpace ].transfer; }, - makeRotationY: function ( theta ) { + getLuminanceCoefficients: function ( target, colorSpace = this._workingColorSpace ) { - var c = Math.cos( theta ), s = Math.sin( theta ); + return target.fromArray( COLOR_SPACES[ colorSpace ].luminanceCoefficients ); - this.set( + }, - c, 0, s, 0, - 0, 1, 0, 0, - - s, 0, c, 0, - 0, 0, 0, 1 +}; - ); - return this; +function SRGBToLinear( c ) { - }, + return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); - makeRotationZ: function ( theta ) { +} - var c = Math.cos( theta ), s = Math.sin( theta ); +function LinearToSRGB( c ) { - this.set( + return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; - c, - s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 +} - ); +let _canvas; - return this; +class ImageUtils { - }, + static getDataURL( image ) { - makeRotationAxis: function ( axis, angle ) { + if ( /^data:/i.test( image.src ) ) { - // Based on http://www.gamedev.net/reference/articles/article1199.asp + return image.src; - var c = Math.cos( angle ); - var s = Math.sin( angle ); - var t = 1 - c; - var x = axis.x, y = axis.y, z = axis.z; - var tx = t * x, ty = t * y; + } - this.set( + if ( typeof HTMLCanvasElement === 'undefined' ) { - tx * x + c, tx * y - s * z, tx * z + s * y, 0, - tx * y + s * z, ty * y + c, ty * z - s * x, 0, - tx * z - s * y, ty * z + s * x, t * z * z + c, 0, - 0, 0, 0, 1 + return image.src; - ); + } - return this; + let canvas; - }, + if ( image instanceof HTMLCanvasElement ) { - makeScale: function ( x, y, z ) { + canvas = image; - this.set( + } else { - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - ); + _canvas.width = image.width; + _canvas.height = image.height; - return this; + const context = _canvas.getContext( '2d' ); - }, + if ( image instanceof ImageData ) { - makeShear: function ( x, y, z ) { + context.putImageData( image, 0, 0 ); - this.set( + } else { - 1, y, z, 0, - x, 1, z, 0, - x, y, 1, 0, - 0, 0, 0, 1 + context.drawImage( image, 0, 0, image.width, image.height ); - ); + } - return this; + canvas = _canvas; - }, + } - compose: function ( position, quaternion, scale ) { + if ( canvas.width > 2048 || canvas.height > 2048 ) { - this.makeRotationFromQuaternion( quaternion ); - this.scale( scale ); - this.setPosition( position ); + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - return this; + return canvas.toDataURL( 'image/jpeg', 0.6 ); - }, + } else { - decompose: function () { + return canvas.toDataURL( 'image/png' ); - var vector = new Vector3(); - var matrix = new Matrix4(); + } - return function decompose( position, quaternion, scale ) { + } - var te = this.elements; + static sRGBToLinear( image ) { - var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); - var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); - var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - // if determine is negative, we need to invert one scale - var det = this.determinant(); - if ( det < 0 ) { sx = - sx; } + const canvas = createElementNS( 'canvas' ); - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; + canvas.width = image.width; + canvas.height = image.height; - // scale the rotation part - matrix.copy( this ); + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - matrix.elements[ 0 ] *= invSX; - matrix.elements[ 1 ] *= invSX; - matrix.elements[ 2 ] *= invSX; + for ( let i = 0; i < data.length; i ++ ) { - matrix.elements[ 4 ] *= invSY; - matrix.elements[ 5 ] *= invSY; - matrix.elements[ 6 ] *= invSY; + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - matrix.elements[ 8 ] *= invSZ; - matrix.elements[ 9 ] *= invSZ; - matrix.elements[ 10 ] *= invSZ; + } - quaternion.setFromRotationMatrix( matrix ); + context.putImageData( imageData, 0, 0 ); - scale.x = sx; - scale.y = sy; - scale.z = sz; + return canvas; - return this; + } else if ( image.data ) { - }; + const data = image.data.slice( 0 ); - }(), + for ( let i = 0; i < data.length; i ++ ) { - makePerspective: function ( left, right, top, bottom, near, far ) { + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - if ( far === undefined ) { + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); + } else { - } + // assuming float - var te = this.elements; - var x = 2 * near / ( right - left ); - var y = 2 * near / ( top - bottom ); + data[ i ] = SRGBToLinear( data[ i ] ); - var a = ( right + left ) / ( right - left ); - var b = ( top + bottom ) / ( top - bottom ); - var c = - ( far + near ) / ( far - near ); - var d = - 2 * far * near / ( far - near ); + } - te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; - te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; - te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; - te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; + } - return this; + return { + data: data, + width: image.width, + height: image.height + }; - }, + } else { - makeOrthographic: function ( left, right, top, bottom, near, far ) { + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; + + } - var te = this.elements; - var w = 1.0 / ( right - left ); - var h = 1.0 / ( top - bottom ); - var p = 1.0 / ( far - near ); + } - var x = ( right + left ) * w; - var y = ( top + bottom ) * h; - var z = ( far + near ) * p; +} - te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; - te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; - 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; +let _sourceId = 0; - return this; +class Source { - }, + constructor( data = null ) { - equals: function ( matrix ) { + this.isSource = true; - var te = this.elements; - var me = matrix.elements; + Object.defineProperty( this, 'id', { value: _sourceId ++ } ); - for ( var i = 0; i < 16; i ++ ) { + this.uuid = generateUUID(); - if ( te[ i ] !== me[ i ] ) { return false; } + this.data = data; + this.dataReady = true; - } + this.version = 0; - return true; + } - }, + set needsUpdate( value ) { - fromArray: function ( array, offset ) { + if ( value === true ) this.version ++; - if ( offset === undefined ) { offset = 0; } + } - for ( var i = 0; i < 16; i ++ ) { + toJSON( meta ) { - this.elements[ i ] = array[ i + offset ]; + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { + + return meta.images[ this.uuid ]; } - return this; + const output = { + uuid: this.uuid, + url: '' + }; - }, + const data = this.data; - toArray: function ( array, offset ) { + if ( data !== null ) { - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + let url; - var te = this.elements; + if ( Array.isArray( data ) ) { - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - array[ offset + 3 ] = te[ 3 ]; + // cube texture - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; + url = []; - array[ offset + 8 ] = te[ 8 ]; - array[ offset + 9 ] = te[ 9 ]; - array[ offset + 10 ] = te[ 10 ]; - array[ offset + 11 ] = te[ 11 ]; - - array[ offset + 12 ] = te[ 12 ]; - array[ offset + 13 ] = te[ 13 ]; - array[ offset + 14 ] = te[ 14 ]; - array[ offset + 15 ] = te[ 15 ]; - - return array; + for ( let i = 0, l = data.length; i < l; i ++ ) { - } + if ( data[ i ].isDataTexture ) { -} ); + url.push( serializeImage( data[ i ].image ) ); -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - */ + } else { -function Quaternion( x, y, z, w ) { + url.push( serializeImage( data[ i ] ) ); - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._w = ( w !== undefined ) ? w : 1; + } -} + } -Object.assign( Quaternion, { + } else { - slerp: function ( qa, qb, qm, t ) { + // texture - return qm.copy( qa ).slerp( qb, t ); + url = serializeImage( data ); - }, + } - slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + output.url = url; - // fuzz-free, array-based Quaternion SLERP operation + } - var x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ], + if ( ! isRootObject ) { - x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + meta.images[ this.uuid ] = output; - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + } - var s = 1 - t, + return output; - cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + } - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; +} - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { +function serializeImage( image ) { - var sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + // default images - } + return ImageUtils.getDataURL( image ); - var tDir = t * dir; + } else { - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + if ( image.data ) { - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + // images of DataTexture - var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + return { + data: Array.from( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + } else { - } + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; } - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - } -} ); +} -Object.defineProperties( Quaternion.prototype, { +let _textureId = 0; - x: { +class Texture extends EventDispatcher { - get: function () { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { - return this._x; + super(); - }, + this.isTexture = true; - set: function ( value ) { + Object.defineProperty( this, 'id', { value: _textureId ++ } ); - this._x = value; - this.onChangeCallback(); + this.uuid = generateUUID(); - } + this.name = ''; - }, + this.source = new Source( image ); + this.mipmaps = []; - y: { + this.mapping = mapping; + this.channel = 0; - get: function () { + this.wrapS = wrapS; + this.wrapT = wrapT; - return this._y; + this.magFilter = magFilter; + this.minFilter = minFilter; - }, + this.anisotropy = anisotropy; - set: function ( value ) { + this.format = format; + this.internalFormat = null; + this.type = type; - this._y = value; - this.onChangeCallback(); + 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; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - z: { + this.colorSpace = colorSpace; - get: function () { + this.userData = {}; - return this._z; + this.version = 0; + this.onUpdate = null; - }, + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) - set: function ( value ) { + } - this._z = value; - this.onChangeCallback(); + get image() { - } + return this.source.data; - }, + } - w: { + set image( value = null ) { - get: function () { + this.source.data = value; - return this._w; + } - }, + updateMatrix() { - set: function ( value ) { + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); - this._w = value; - this.onChangeCallback(); + } - } + clone() { + + return new this.constructor().copy( this ); } -} ); + copy( source ) { -Object.assign( Quaternion.prototype, { + this.name = source.name; - set: function ( x, y, z, w ) { + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); - this._x = x; - this._y = y; - this._z = z; - this._w = w; + this.mapping = source.mapping; + this.channel = source.channel; - this.onChangeCallback(); + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - return this; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - }, + this.anisotropy = source.anisotropy; - clone: function () { + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return new this.constructor( this._x, this._y, this._z, this._w ); + 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 ); - copy: function ( quaternion ) { + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - this.onChangeCallback(); + this.needsUpdate = true; return this; - }, - - setFromEuler: function ( euler, update ) { + } - if ( ! ( euler && euler.isEuler ) ) { + toJSON( meta ) { - throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - } + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - var x = euler._x, y = euler._y, z = euler._z, order = euler.order; + return meta.textures[ this.uuid ]; - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m + } - var cos = Math.cos; - var sin = Math.sin; + const output = { - var c1 = cos( x / 2 ); - var c2 = cos( y / 2 ); - var c3 = cos( z / 2 ); + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, - var s1 = sin( x / 2 ); - var s2 = sin( y / 2 ); - var s3 = sin( z / 2 ); + uuid: this.uuid, + name: this.name, - if ( order === 'XYZ' ) { + image: this.source.toJSON( meta ).uuid, - 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; + mapping: this.mapping, + channel: this.channel, - } else if ( order === 'YXZ' ) { + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - 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; + wrap: [ this.wrapS, this.wrapT ], - } else if ( order === 'ZXY' ) { + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, - 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; + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - } else if ( order === 'ZYX' ) { + flipY: this.flipY, - 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; + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - } else if ( order === '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; + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; - } else if ( order === 'XZY' ) { + if ( ! isRootObject ) { - 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; + meta.textures[ this.uuid ] = output; } - if ( update !== false ) { this.onChangeCallback(); } + return output; - return this; + } - }, + dispose() { - setFromAxisAngle: function ( axis, angle ) { + this.dispatchEvent( { type: 'dispose' } ); - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + } - // assumes axis is normalized + transformUv( uv ) { - var halfAngle = angle / 2, s = Math.sin( halfAngle ); + if ( this.mapping !== UVMapping ) return uv; - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + uv.applyMatrix3( this.matrix ); - this.onChangeCallback(); + if ( uv.x < 0 || uv.x > 1 ) { - return this; + switch ( this.wrapS ) { - }, + case RepeatWrapping: - setFromRotationMatrix: function ( m ) { + uv.x = uv.x - Math.floor( uv.x ); + break; - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + case ClampToEdgeWrapping: - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + uv.x = uv.x < 0 ? 0 : 1; + break; - var te = m.elements, + case MirroredRepeatWrapping: - 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( Math.floor( uv.x ) % 2 ) === 1 ) { - trace = m11 + m22 + m33, - s; + uv.x = Math.ceil( uv.x ) - uv.x; - if ( trace > 0 ) { + } else { - s = 0.5 / Math.sqrt( trace + 1.0 ); + uv.x = uv.x - Math.floor( uv.x ); - 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 ) { + break; - s = 2.0 * Math.sqrt( 1.0 + 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 ) { + if ( uv.y < 0 || uv.y > 1 ) { - s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + switch ( this.wrapT ) { - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + case RepeatWrapping: - } else { + uv.y = uv.y - Math.floor( uv.y ); + break; - s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + case ClampToEdgeWrapping: - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + uv.y = uv.y < 0 ? 0 : 1; + break; - } + case MirroredRepeatWrapping: - this.onChangeCallback(); + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - return this; + uv.y = Math.ceil( uv.y ) - uv.y; - }, + } else { - setFromUnitVectors: function () { + uv.y = uv.y - Math.floor( uv.y ); - // assumes direction vectors vFrom and vTo are normalized + } - var v1 = new Vector3(); - var r; + break; - var EPS = 0.000001; + } - return function setFromUnitVectors( vFrom, vTo ) { + } - if ( v1 === undefined ) { v1 = new Vector3(); } + if ( this.flipY ) { - r = vFrom.dot( vTo ) + 1; + uv.y = 1 - uv.y; - if ( r < EPS ) { + } - r = 0; + return uv; - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + } - v1.set( - vFrom.y, vFrom.x, 0 ); + set needsUpdate( value ) { - } else { + if ( value === true ) { - v1.set( 0, - vFrom.z, vFrom.y ); + this.version ++; + this.source.needsUpdate = true; - } + } - } else { + } - v1.crossVectors( vFrom, vTo ); + set needsPMREMUpdate( value ) { - } + if ( value === true ) { - this._x = v1.x; - this._y = v1.y; - this._z = v1.z; - this._w = r; + this.pmremVersion ++; - return this.normalize(); + } - }; + } - }(), +} - inverse: function () { +Texture.DEFAULT_IMAGE = null; +Texture.DEFAULT_MAPPING = UVMapping; +Texture.DEFAULT_ANISOTROPY = 1; - return this.conjugate().normalize(); +class Vector4 { - }, + constructor( x = 0, y = 0, z = 0, w = 1 ) { - conjugate: function () { + Vector4.prototype.isVector4 = true; - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; + this.x = x; + this.y = y; + this.z = z; + this.w = w; - this.onChangeCallback(); + } - return this; + get width() { - }, + return this.z; - dot: function ( v ) { + } - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + set width( value ) { - }, + this.z = value; - lengthSq: function () { + } - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + get height() { - }, + return this.w; - length: function () { + } - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); + set height( value ) { - }, + this.w = value; - normalize: function () { - - var 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: function ( q, p ) { - - if ( p !== undefined ) { - - console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); - return this.multiplyQuaternions( q, p ); - - } - - return this.multiplyQuaternions( this, q ); - - }, - - premultiply: function ( q ) { - - return this.multiplyQuaternions( q, this ); - - }, - - multiplyQuaternions: function ( a, b ) { - - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - - var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - var 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: function ( qb, t ) { - - if ( t === 0 ) { return this; } - if ( t === 1 ) { return this.copy( qb ); } - - var x = this._x, y = this._y, z = this._z, w = this._w; - - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - - var cosHalfTheta = w * qb._w + x * qb._x + y * 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.0 ) { - - this._w = w; - this._x = x; - this._y = y; - this._z = z; - - return this; - - } - - var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - - this._w = 0.5 * ( w + this._w ); - this._x = 0.5 * ( x + this._x ); - this._y = 0.5 * ( y + this._y ); - this._z = 0.5 * ( z + this._z ); - - return this; - - } - - var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); - - this.onChangeCallback(); - - return this; - - }, - - equals: function ( quaternion ) { - - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) { offset = 0; } - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this.onChangeCallback(); - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; - - return array; - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; - - }, - - onChangeCallback: function () {} - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ - -function Vector3( x, y, z ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - -} - -Object.assign( Vector3.prototype, { - - isVector3: true, + } - set: function ( x, y, z ) { + set( x, y, z, w ) { this.x = x; this.y = y; this.z = z; + this.w = w; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; this.z = scalar; + this.w = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setZ: function ( z ) { + setZ( z ) { this.z = z; return this; - }, + } + + setW( w ) { + + this.w = w; + + return this; + + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { 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: ' + index ); } return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { 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: ' + index ); } - }, + } - clone: function () { + clone() { - return new this.constructor( this.x, this.y, this.z ); + return new this.constructor( this.x, this.y, this.z, this.w ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; this.z += v.z; + this.w += v.w; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; this.z += s; + this.w += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; + this.w = a.w + b.w; return this; - }, + } - addScaledVector: function ( v, s ) { + 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: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; + this.w -= v.w; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; this.z -= s; + this.w -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; + this.w = a.w - b.w; return this; - }, - - multiply: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); - return this.multiplyVectors( v, w ); + } - } + multiply( v ) { this.x *= v.x; this.y *= v.y; this.z *= v.z; + this.w *= v.w; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; this.z *= scalar; + this.w *= scalar; return this; - }, + } - multiplyVectors: function ( a, b ) { + applyMatrix4( m ) { - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; return this; - }, + } - applyEuler: function () { + divideScalar( scalar ) { - var quaternion = new Quaternion(); + return this.multiplyScalar( 1 / scalar ); - return function applyEuler( euler ) { + } - if ( ! ( euler && euler.isEuler ) ) { + setAxisAngleFromQuaternion( q ) { - console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - } + // q is assumed to be normalized - return this.applyQuaternion( quaternion.setFromEuler( euler ) ); + this.w = 2 * Math.acos( q.w ); - }; + const s = Math.sqrt( 1 - q.w * q.w ); - }(), + if ( s < 0.0001 ) { - applyAxisAngle: function () { + this.x = 1; + this.y = 0; + this.z = 0; - var quaternion = new Quaternion(); + } else { - return function applyAxisAngle( axis, angle ) { + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; - return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) ); + } - }; + return this; - }(), + } - applyMatrix3: function ( m ) { + setAxisAngleFromRotationMatrix( m ) { - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - return this; + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - }, + te = m.elements, - applyMatrix4: function ( m ) { + 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 ]; - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { - var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - return this; + // this singularity is identity matrix so angle = 0 - }, + this.set( 1, 0, 0, 0 ); - applyQuaternion: function ( q ) { + return this; // zero angle, arbitrary axis - var x = this.x, y = this.y, z = this.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; + } - // calculate quat * vector + // otherwise this singularity is angle = 180 - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = - qx * x - qy * y - qz * z; + angle = Math.PI; - // calculate result * inverse quat + 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; - 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; + if ( ( xx > yy ) && ( xx > zz ) ) { - return this; + // m11 is the largest diagonal term - }, + if ( xx < epsilon ) { - project: function () { + x = 0; + y = 0.707106781; + z = 0.707106781; - var matrix = new Matrix4(); + } else { - return function project( camera ) { + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) ); - return this.applyMatrix4( matrix ); + } - }; + } else if ( yy > zz ) { - }(), + // m22 is the largest diagonal term - unproject: function () { + if ( yy < epsilon ) { - var matrix = new Matrix4(); + x = 0.707106781; + y = 0; + z = 0.707106781; - return function unproject( camera ) { + } else { - matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) ); - return this.applyMatrix4( matrix ); + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - }; + } - }(), + } else { - transformDirection: function ( m ) { + // m33 is the largest diagonal term so base result on this - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction + if ( zz < epsilon ) { - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + x = 0.707106781; + y = 0.707106781; + z = 0; - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; + } else { - return this.normalize(); + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - }, + } - divide: function ( v ) { + } - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; + this.set( x, y, z, angle ); + + return this; // return 180 deg rotation + + } + + // as we have reached here there are no singularities so we can handle normally + + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + + if ( Math.abs( s ) < 0.001 ) s = 1; + + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case + + 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; - }, + } - divideScalar: function ( scalar ) { + setFromMatrixPosition( m ) { - return this.multiplyScalar( 1 / scalar ); + const e = m.elements; - }, + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + this.w = e[ 15 ]; + + return this; + + } - min: function ( v ) { + 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: function ( v ) { + 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: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); return this; - }, - - clampScalar: function () { - - var min = new Vector3(); - var max = new Vector3(); - - return function clampScalar( minVal, maxVal ) { + } - min.set( minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + 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: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + 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: function () { + 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: function () { + 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: function () { + 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.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); + this.w = Math.trunc( this.w ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; this.z = - this.z; + this.w = - this.w; return this; - }, - - dot: function ( v ) { + } - return this.x * v.x + this.y * v.y + this.z * v.z; + dot( v ) { - }, + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - // TODO lengthSquared? + } - lengthSq: function () { + lengthSq() { - return this.x * this.x + this.y * this.y + this.z * this.z; + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - }, + } - length: function () { + length() { - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - }, + } - manhattanLength: function () { + manhattanLength() { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - }, + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + 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: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + 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; - cross: function ( v, w ) { + } - if ( w !== undefined ) { + equals( v ) { - console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); - return this.crossVectors( v, w ); + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - } + } - return this.crossVectors( this, v ); + fromArray( array, offset = 0 ) { - }, + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - crossVectors: function ( a, b ) { + return this; - var ax = a.x, ay = a.y, az = a.z; - var 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; + toArray( array = [], offset = 0 ) { - return this; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; - }, + return array; - projectOnVector: function ( vector ) { + } - var scalar = vector.dot( this ) / vector.lengthSq(); + fromBufferAttribute( attribute, index ) { - return this.copy( vector ).multiplyScalar( scalar ); + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); - }, + return this; - projectOnPlane: function () { + } - var v1 = new Vector3(); + random() { - return function projectOnPlane( planeNormal ) { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); - v1.copy( this ).projectOnVector( planeNormal ); + return this; - return this.sub( v1 ); + } - }; + *[ Symbol.iterator ]() { - }(), + yield this.x; + yield this.y; + yield this.z; + yield this.w; - reflect: function () { + } - // reflect incident vector off plane orthogonal to normal - // normal is assumed to have unit length +} - var v1 = new Vector3(); +/* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers +*/ +class RenderTarget extends EventDispatcher { - return function reflect( normal ) { + constructor( width = 1, height = 1, options = {} ) { - return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + super(); - }; + this.isRenderTarget = true; - }(), + this.width = width; + this.height = height; + this.depth = 1; - angleTo: function ( v ) { + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); + this.viewport = new Vector4( 0, 0, width, height ); - // clamp, to handle numerical problems + const image = { width: width, height: height, depth: 1 }; - return Math.acos( _Math.clamp( theta, - 1, 1 ) ); + options = Object.assign( { + generateMipmaps: false, + internalFormat: null, + minFilter: LinearFilter, + depthBuffer: true, + stencilBuffer: false, + resolveDepthBuffer: true, + resolveStencilBuffer: true, + depthTexture: null, + samples: 0, + count: 1 + }, options ); - }, + const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); - distanceTo: function ( v ) { + texture.flipY = false; + texture.generateMipmaps = options.generateMipmaps; + texture.internalFormat = options.internalFormat; - return Math.sqrt( this.distanceToSquared( v ) ); + this.textures = []; - }, + const count = options.count; + for ( let i = 0; i < count; i ++ ) { - distanceToSquared: function ( v ) { + this.textures[ i ] = texture.clone(); + this.textures[ i ].isRenderTargetTexture = true; - var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + } - return dx * dx + dy * dy + dz * dz; + this.depthBuffer = options.depthBuffer; + this.stencilBuffer = options.stencilBuffer; - }, + this.resolveDepthBuffer = options.resolveDepthBuffer; + this.resolveStencilBuffer = options.resolveStencilBuffer; - manhattanDistanceTo: function ( v ) { + this.depthTexture = options.depthTexture; - return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); + this.samples = options.samples; - }, + } - setFromSpherical: function ( s ) { + get texture() { - var sinPhiRadius = Math.sin( s.phi ) * s.radius; + return this.textures[ 0 ]; - this.x = sinPhiRadius * Math.sin( s.theta ); - this.y = Math.cos( s.phi ) * s.radius; - this.z = sinPhiRadius * Math.cos( s.theta ); + } - return this; + set texture( value ) { - }, + this.textures[ 0 ] = value; - setFromCylindrical: function ( c ) { + } - this.x = c.radius * Math.sin( c.theta ); - this.y = c.y; - this.z = c.radius * Math.cos( c.theta ); + setSize( width, height, depth = 1 ) { - return this; + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - }, + this.width = width; + this.height = height; + this.depth = depth; - setFromMatrixPosition: function ( m ) { + for ( let i = 0, il = this.textures.length; i < il; i ++ ) { - var e = m.elements; + this.textures[ i ].image.width = width; + this.textures[ i ].image.height = height; + this.textures[ i ].image.depth = depth; - this.x = e[ 12 ]; - this.y = e[ 13 ]; - this.z = e[ 14 ]; + } - return this; + this.dispose(); - }, + } - setFromMatrixScale: function ( m ) { + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - var sx = this.setFromMatrixColumn( m, 0 ).length(); - var sy = this.setFromMatrixColumn( m, 1 ).length(); - var sz = this.setFromMatrixColumn( m, 2 ).length(); + } - this.x = sx; - this.y = sy; - this.z = sz; + clone() { - return this; + return new this.constructor().copy( this ); - }, + } - setFromMatrixColumn: function ( m, index ) { + copy( source ) { - return this.fromArray( m.elements, index * 4 ); + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - }, + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - equals: function ( v ) { + this.viewport.copy( source.viewport ); - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); + this.textures.length = 0; - }, + for ( let i = 0, il = source.textures.length; i < il; i ++ ) { - fromArray: function ( array, offset ) { + this.textures[ i ] = source.textures[ i ].clone(); + this.textures[ i ].isRenderTargetTexture = true; - if ( offset === undefined ) { offset = 0; } + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; + // ensure image object is not shared, see #20328 - return this; + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); - }, + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - toArray: function ( array, offset ) { + this.resolveDepthBuffer = source.resolveDepthBuffer; + this.resolveStencilBuffer = source.resolveStencilBuffer; - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); + this.samples = source.samples; return this; } -} ); + dispose() { -/** - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - * @author tschw - */ + this.dispatchEvent( { type: 'dispose' } ); -function Matrix3() { + } - this.elements = [ +} - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 +class WebGLRenderTarget extends RenderTarget { - ]; + constructor( width = 1, height = 1, options = {} ) { - if ( arguments.length > 0 ) { + super( width, height, options ); - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); + this.isWebGLRenderTarget = true; } } -Object.assign( Matrix3.prototype, { +class DataArrayTexture extends Texture { - isMatrix3: true, + constructor( data = null, width = 1, height = 1, depth = 1 ) { - set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { + super( null ); - var te = this.elements; + this.isDataArrayTexture = true; - 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; + this.image = { data, width, height, depth }; - return this; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - }, + this.wrapR = ClampToEdgeWrapping; - identity: function () { + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - this.set( + this.layerUpdates = new Set(); - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 + } - ); + addLayerUpdate( layerIndex ) { - return this; + this.layerUpdates.add( layerIndex ); - }, + } - clone: function () { + clearLayerUpdates() { - return new this.constructor().fromArray( this.elements ); + this.layerUpdates.clear(); - }, + } - copy: function ( m ) { +} - var te = this.elements; - var me = m.elements; +class Data3DTexture extends Texture { - 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 ]; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - return this; + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 - }, + super( null ); - setFromMatrix4: function ( m ) { + this.isData3DTexture = true; - var me = m.elements; + this.image = { data, width, height, depth }; - this.set( + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - me[ 0 ], me[ 4 ], me[ 8 ], - me[ 1 ], me[ 5 ], me[ 9 ], - me[ 2 ], me[ 6 ], me[ 10 ] + this.wrapR = ClampToEdgeWrapping; - ); + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - return this; + } - }, +} - applyToBufferAttribute: function () { +class Quaternion { - var v1 = new Vector3(); + constructor( x = 0, y = 0, z = 0, w = 1 ) { - return function applyToBufferAttribute( attribute ) { + this.isQuaternion = true; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + this._x = x; + this._y = y; + this._z = z; + this._w = w; - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + } - v1.applyMatrix3( this ); + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + // fuzz-free, array-based Quaternion SLERP operation - } + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; - return attribute; + 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; - multiply: function ( m ) { + } - return this.multiplyMatrices( this, m ); + if ( t === 1 ) { - }, + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; - premultiply: function ( m ) { + } - return this.multiplyMatrices( m, this ); + 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; - multiplyMatrices: function ( a, b ) { + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - var ae = a.elements; - var be = b.elements; - var te = this.elements; + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; - var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; - var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; - var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; - var 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; + const tDir = t * dir; - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; - te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; - te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; - te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; - te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - return this; + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - }, + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - multiplyScalar: function ( s ) { + } - var 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; + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; - return this; + } - }, + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - determinant: function () { + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - var te = this.elements; + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; - var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], - d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], - g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; + 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 a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; + return dst; - }, + } - getInverse: function ( matrix, throwOnDegenerate ) { + get x() { - if ( matrix && matrix.isMatrix4 ) { + return this._x; - console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); + } - } + set x( value ) { - var me = matrix.elements, - te = this.elements, + this._x = value; + this._onChangeCallback(); - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], - n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ], - n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ], + } - t11 = n33 * n22 - n32 * n23, - t12 = n32 * n13 - n33 * n12, - t13 = n23 * n12 - n22 * n13, + get y() { - det = n11 * t11 + n21 * t12 + n31 * t13; + return this._y; - if ( det === 0 ) { + } - var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; + set y( value ) { - if ( throwOnDegenerate === true ) { + this._y = value; + this._onChangeCallback(); - throw new Error( msg ); + } - } else { + get z() { - console.warn( msg ); + return this._z; - } + } - return this.identity(); + set z( value ) { - } + this._z = value; + this._onChangeCallback(); - var detInv = 1 / det; + } - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; - te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; + get w() { - te[ 3 ] = t12 * detInv; - te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; - te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; + return this._w; - te[ 6 ] = t13 * detInv; - te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; - te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; + } - return this; + set w( value ) { - }, + this._w = value; + this._onChangeCallback(); - transpose: function () { + } - var tmp, m = this.elements; + set( x, y, z, w ) { - tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; - tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; - tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; + this._x = x; + this._y = y; + this._z = z; + this._w = w; + + this._onChangeCallback(); return this; - }, + } - getNormalMatrix: function ( matrix4 ) { + clone() { - return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); + return new this.constructor( this._x, this._y, this._z, this._w ); - }, + } - transposeIntoArray: function ( r ) { + copy( quaternion ) { - var m = this.elements; + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; - r[ 0 ] = m[ 0 ]; - r[ 1 ] = m[ 3 ]; - r[ 2 ] = m[ 6 ]; - r[ 3 ] = m[ 1 ]; - r[ 4 ] = m[ 4 ]; - r[ 5 ] = m[ 7 ]; - r[ 6 ] = m[ 2 ]; - r[ 7 ] = m[ 5 ]; - r[ 8 ] = m[ 8 ]; + this._onChangeCallback(); return this; - }, + } - setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { + setFromEuler( euler, update = true ) { - var c = Math.cos( rotation ); - var s = Math.sin( rotation ); + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - this.set( - sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, - - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, - 0, 0, 1 - ); + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - }, + const cos = Math.cos; + const sin = Math.sin; - scale: function ( sx, sy ) { + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - var te = this.elements; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; - te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; + switch ( order ) { - return this; + 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; - rotate: function ( theta ) { + 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; - var c = Math.cos( theta ); - var s = Math.sin( theta ); + 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; - var te = this.elements; + 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; - var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ]; - var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ]; + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); - te[ 0 ] = c * a11 + s * a21; - te[ 3 ] = c * a12 + s * a22; - te[ 6 ] = c * a13 + s * a23; + } - te[ 1 ] = - s * a11 + c * a21; - te[ 4 ] = - s * a12 + c * a22; - te[ 7 ] = - s * a13 + c * a23; + if ( update === true ) this._onChangeCallback(); return this; - }, + } - translate: function ( tx, ty ) { + setFromAxisAngle( axis, angle ) { - var te = this.elements; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - 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 ]; + // assumes axis is normalized - return this; + 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 ); - equals: function ( matrix ) { + this._onChangeCallback(); - var te = this.elements; - var me = matrix.elements; + return this; - for ( var i = 0; i < 9; i ++ ) { + } - if ( te[ i ] !== me[ i ] ) { return false; } + setFromRotationMatrix( m ) { - } + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - return true; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - }, + const te = m.elements, - fromArray: function ( array, offset ) { + 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 ( offset === undefined ) { offset = 0; } + trace = m11 + m22 + m33; - for ( var i = 0; i < 9; i ++ ) { + if ( trace > 0 ) { - this.elements[ i ] = array[ i + offset ]; + const s = 0.5 / Math.sqrt( trace + 1.0 ); - } + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; - return this; + } else if ( m11 > m22 && m11 > m33 ) { - }, + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - toArray: function ( array, offset ) { + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + } else if ( m22 > m33 ) { - var te = this.elements; + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - array[ offset + 3 ] = te[ 3 ]; - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; + } else { - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; - array[ offset + 8 ] = te[ 8 ]; + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - return array; + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; - } + } -} ); + this._onChangeCallback(); -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - */ + return this; -var textureId = 0; + } -function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + setFromUnitVectors( vFrom, vTo ) { - Object.defineProperty( this, 'id', { value: textureId ++ } ); + // assumes direction vectors vFrom and vTo are normalized - this.uuid = _Math.generateUUID(); + let r = vFrom.dot( vTo ) + 1; - this.name = ''; + if ( r < Number.EPSILON ) { - this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; - this.mipmaps = []; + // vFrom and vTo point in opposite directions - this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + r = 0; - this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + } else { - this.format = format !== undefined ? format : RGBAFormat; - this.type = type !== undefined ? type : UnsignedByteType; + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - 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(); + } else { - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding !== undefined ? encoding : LinearEncoding; + 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; - this.version = 0; - this.onUpdate = null; + } -} + return this.normalize(); -Texture.DEFAULT_IMAGE = undefined; -Texture.DEFAULT_MAPPING = UVMapping; + } -Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + angleTo( q ) { - constructor: Texture, + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); - isTexture: true, + } - clone: function () { + rotateTowards( q, step ) { - return new this.constructor().copy( this ); + const angle = this.angleTo( q ); - }, + if ( angle === 0 ) return this; - copy: function ( source ) { + const t = Math.min( 1, step / angle ); - this.name = source.name; + this.slerp( q, t ); - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); + return this; - this.mapping = source.mapping; + } - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + identity() { - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + return this.set( 0, 0, 0, 1 ); - this.anisotropy = source.anisotropy; + } - this.format = source.format; - this.type = source.type; + invert() { - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + // quaternion is assumed to have unit length - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + return this.conjugate(); - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + } + + conjugate() { + + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; + + this._onChangeCallback(); return this; - }, + } - toJSON: function ( meta ) { + dot( v ) { - var isRootObject = ( meta === undefined || typeof meta === 'string' ); + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { + } - return meta.textures[ this.uuid ]; + lengthSq() { - } + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - function getDataURL( image ) { + } - var canvas; + length() { - if ( image instanceof HTMLCanvasElement ) { + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); - canvas = image; + } - } else { + normalize() { - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; + let l = this.length(); - var context = canvas.getContext( '2d' ); + if ( l === 0 ) { - if ( image instanceof ImageData ) { + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - context.putImageData( image, 0, 0 ); + } else { - } else { + l = 1 / l; - context.drawImage( image, 0, 0, image.width, image.height ); + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - } + } - } + this._onChangeCallback(); - if ( canvas.width > 2048 || canvas.height > 2048 ) { + return this; - return canvas.toDataURL( 'image/jpeg', 0.6 ); + } - } else { + multiply( q ) { - return canvas.toDataURL( 'image/png' ); + return this.multiplyQuaternions( this, q ); - } + } - } + premultiply( q ) { - var output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + return this.multiplyQuaternions( q, this ); - uuid: this.uuid, - name: this.name, + } - mapping: this.mapping, + multiplyQuaternions( a, b ) { - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - wrap: [ this.wrapS, this.wrapT ], + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + 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; - flipY: this.flipY - }; + this._onChangeCallback(); - if ( this.image !== undefined ) { + return this; - // TODO: Move to THREE.Image + } - var image = this.image; + slerp( qb, t ) { - if ( image.uuid === undefined ) { + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - image.uuid = _Math.generateUUID(); // UGH + const x = this._x, y = this._y, z = this._z, w = this._w; - } + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: getDataURL( image ) - }; + if ( cosHalfTheta < 0 ) { - } + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; + + cosHalfTheta = - cosHalfTheta; + + } else { - output.image = image.uuid; + this.copy( qb ); } - if ( ! isRootObject ) { + if ( cosHalfTheta >= 1.0 ) { - meta.textures[ this.uuid ] = output; + this._w = w; + this._x = x; + this._y = y; + this._z = z; + + return this; } - return output; + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - }, + if ( sqrSinHalfTheta <= Number.EPSILON ) { - dispose: function () { + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - this.dispatchEvent( { type: 'dispose' } ); + this.normalize(); // normalize calls _onChangeCallback() - }, + return this; - transformUv: function ( uv ) { + } - if ( this.mapping !== UVMapping ) { return; } + 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; - uv.applyMatrix3( this.matrix ); + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - if ( uv.x < 0 || uv.x > 1 ) { + this._onChangeCallback(); - switch ( this.wrapS ) { + return this; - case RepeatWrapping: + } - uv.x = uv.x - Math.floor( uv.x ); - break; + slerpQuaternions( qa, qb, t ) { - case ClampToEdgeWrapping: + return this.copy( qa ).slerp( qb, t ); - uv.x = uv.x < 0 ? 0 : 1; - break; + } - case MirroredRepeatWrapping: + random() { - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + // sets this quaternion to a uniform random unit quaternnion - uv.x = Math.ceil( uv.x ) - uv.x; + // Ken Shoemake + // Uniform random rotations + // D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992. - } else { + const theta1 = 2 * Math.PI * Math.random(); + const theta2 = 2 * Math.PI * Math.random(); - uv.x = uv.x - Math.floor( uv.x ); + const x0 = Math.random(); + const r1 = Math.sqrt( 1 - x0 ); + const r2 = Math.sqrt( x0 ); - } - break; + return this.set( + r1 * Math.sin( theta1 ), + r1 * Math.cos( theta1 ), + r2 * Math.sin( theta2 ), + r2 * Math.cos( theta2 ), + ); - } + } - } + equals( quaternion ) { - if ( uv.y < 0 || uv.y > 1 ) { + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - switch ( this.wrapT ) { + } - case RepeatWrapping: + fromArray( array, offset = 0 ) { - uv.y = uv.y - Math.floor( uv.y ); - break; + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - case ClampToEdgeWrapping: + this._onChangeCallback(); - uv.y = uv.y < 0 ? 0 : 1; - break; + return this; - case MirroredRepeatWrapping: + } - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + toArray( array = [], offset = 0 ) { - uv.y = Math.ceil( uv.y ) - uv.y; + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; - } else { + return array; - uv.y = uv.y - Math.floor( uv.y ); + } - } - break; + fromBufferAttribute( attribute, index ) { - } + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); - } + this._onChangeCallback(); - if ( this.flipY ) { + return this; - uv.y = 1 - uv.y; + } - } + toJSON() { - } + return this.toArray(); -} ); + } -Object.defineProperty( Texture.prototype, "needsUpdate", { + _onChange( callback ) { - set: function ( value ) { + this._onChangeCallback = callback; - if ( value === true ) { this.version ++; } + return this; } -} ); + _onChangeCallback() {} -/** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ + *[ Symbol.iterator ]() { -function Vector4( x, y, z, w ) { + yield this._x; + yield this._y; + yield this._z; + yield this._w; - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; + } } -Object.assign( Vector4.prototype, { +class Vector3 { - isVector4: true, + constructor( x = 0, y = 0, z = 0 ) { - set: function ( x, y, z, w ) { + Vector3.prototype.isVector3 = true; + + this.x = x; + this.y = y; + this.z = z; + + } + + set( x, y, z ) { + + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) this.x = x; this.y = y; this.z = z; - this.w = w; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; this.z = scalar; - this.w = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setZ: function ( z ) { + setZ( z ) { this.z = z; return this; - }, - - setW: function ( w ) { - - this.w = w; - - return this; - - }, + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { 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: ' + index ); } return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { 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: ' + index ); } - }, + } - clone: function () { + clone() { - return new this.constructor( this.x, this.y, this.z, this.w ); + return new this.constructor( this.x, this.y, this.z ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; this.z += v.z; - this.w += v.w; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; this.z += s; - this.w += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; - this.w = a.w + b.w; return this; - }, + } - addScaledVector: function ( v, s ) { + 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: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; - this.w -= v.w; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; this.z -= s; - this.w -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; - this.w = a.w - b.w; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiply( v ) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; return this; - }, - - applyMatrix4: function ( m ) { + } - var x = this.x, y = this.y, z = this.z, w = this.w; - var e = m.elements; + multiplyScalar( scalar ) { - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; return this; - }, - - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - setAxisAngleFromQuaternion: function ( q ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - - // q is assumed to be normalized - - this.w = 2 * Math.acos( q.w ); - - var s = Math.sqrt( 1 - q.w * q.w ); - - if ( s < 0.0001 ) { - - 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; + multiplyVectors( a, b ) { - } + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; return this; - }, - - setAxisAngleFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + } - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + applyEuler( euler ) { - var angle, x, y, z, // variables for result - epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - te = m.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 ]; + applyAxisAngle( axis, angle ) { - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + } - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + applyMatrix3( m ) { - // this singularity is identity matrix so angle = 0 + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - this.set( 1, 0, 0, 0 ); + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - return this; // zero angle, arbitrary axis + return this; - } + } - // otherwise this singularity is angle = 180 + applyNormalMatrix( m ) { - angle = Math.PI; + return this.applyMatrix3( m ).normalize(); - var xx = ( m11 + 1 ) / 2; - var yy = ( m22 + 1 ) / 2; - var zz = ( m33 + 1 ) / 2; - var xy = ( m12 + m21 ) / 4; - var xz = ( m13 + m31 ) / 4; - var yz = ( m23 + m32 ) / 4; + } - if ( ( xx > yy ) && ( xx > zz ) ) { + applyMatrix4( m ) { - // m11 is the largest diagonal term + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - if ( xx < epsilon ) { + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - x = 0; - y = 0.707106781; - z = 0.707106781; + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - } else { + return this; - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + } - } + applyQuaternion( q ) { - } else if ( yy > zz ) { + // quaternion q is assumed to have unit length - // m22 is the largest diagonal term + const vx = this.x, vy = this.y, vz = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - if ( yy < epsilon ) { + // t = 2 * cross( q.xyz, v ); + const tx = 2 * ( qy * vz - qz * vy ); + const ty = 2 * ( qz * vx - qx * vz ); + const tz = 2 * ( qx * vy - qy * vx ); - x = 0.707106781; - y = 0; - z = 0.707106781; + // v + q.w * t + cross( q.xyz, t ); + this.x = vx + qw * tx + qy * tz - qz * ty; + this.y = vy + qw * ty + qz * tx - qx * tz; + this.z = vz + qw * tz + qx * ty - qy * tx; - } else { + return this; - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + } - } + project( camera ) { - } else { + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - // m33 is the largest diagonal term so base result on this + } - if ( zz < epsilon ) { + unproject( camera ) { - x = 0.707106781; - y = 0.707106781; - z = 0; + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); - } else { + } - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + transformDirection( m ) { - } + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - this.set( x, y, z, angle ); + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - return this; // return 180 deg rotation + return this.normalize(); - } + } - // as we have reached here there are no singularities so we can handle normally + divide( v ) { - var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; - if ( Math.abs( s ) < 0.001 ) { s = 1; } + return this; - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + } - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + divideScalar( scalar ) { - return this; + return this.multiplyScalar( 1 / scalar ); - }, + } - min: function ( v ) { + 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: function ( v ) { + 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: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); return this; - }, - - clampScalar: function () { - - var min, max; - - return function clampScalar( minVal, maxVal ) { - - if ( min === undefined ) { - - min = new Vector4(); - max = new Vector4(); - - } + } - min.set( minVal, minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + 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: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + 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: function () { + 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: function () { + 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: function () { + 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 ); + this.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; this.z = - this.z; - this.w = - this.w; return this; - }, + } - dot: function ( v ) { + dot( v ) { - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + return this.x * v.x + this.y * v.y + this.z * v.z; - }, + } - lengthSq: function () { + // TODO lengthSquared? - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + lengthSq() { - }, + return this.x * this.x + this.y * this.y + this.z * this.z; - length: function () { + } - return Math.sqrt( 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 ); - manhattanLength: function () { + } - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + manhattanLength() { - }, + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); + + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + 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: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + 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; - equals: function ( v ) { + } - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + cross( v ) { - }, + return this.crossVectors( this, v ); - fromArray: function ( array, offset ) { + } - if ( offset === undefined ) { offset = 0; } + crossVectors( a, b ) { - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + const ax = a.x, ay = a.y, az = a.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; - }, + } - toArray: function ( array, offset ) { + projectOnVector( v ) { - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + const denominator = v.lengthSq(); - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + if ( denominator === 0 ) return this.set( 0, 0, 0 ); - return array; + const scalar = v.dot( this ) / denominator; - }, + return this.copy( v ).multiplyScalar( scalar ); - fromBufferAttribute: function ( attribute, index, offset ) { + } - if ( offset !== undefined ) { + projectOnPlane( planeNormal ) { - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); + _vector$c.copy( this ).projectOnVector( planeNormal ); - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); - - return this; + return this.sub( _vector$c ); } -} ); - -/** - * @author szimek / https://github.com/szimek/ - * @author alteredq / http://alteredqualia.com/ - * @author Marius Kintel / https://github.com/kintel - */ - -/* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers -*/ -function WebGLRenderTarget( width, height, options ) { - - this.uuid = _Math.generateUUID(); + reflect( normal ) { - this.width = width; - this.height = height; + // reflect incident vector off plane orthogonal to normal + // normal is assumed to have unit length - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); - this.viewport = new Vector4( 0, 0, width, height ); + } - options = options || {}; + angleTo( v ) { - if ( options.minFilter === undefined ) { options.minFilter = LinearFilter; } + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); - this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( denominator === 0 ) return Math.PI / 2; - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + const theta = this.dot( v ) / denominator; -} + // clamp, to handle numerical problems -WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + return Math.acos( clamp( theta, - 1, 1 ) ); - constructor: WebGLRenderTarget, + } - isWebGLRenderTarget: true, + distanceTo( v ) { - setSize: function ( width, height ) { + return Math.sqrt( this.distanceToSquared( v ) ); - if ( this.width !== width || this.height !== height ) { + } - this.width = width; - this.height = height; + distanceToSquared( v ) { - this.dispose(); + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; - } + return dx * dx + dy * dy + dz * dz; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + } - }, + manhattanDistanceTo( v ) { - clone: function () { + return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); - return new this.constructor().copy( this ); + } - }, + setFromSpherical( s ) { - copy: function ( source ) { + return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); - this.width = source.width; - this.height = source.height; + } - this.viewport.copy( source.viewport ); + setFromSphericalCoords( radius, phi, theta ) { - this.texture = source.texture.clone(); + const sinPhiRadius = Math.sin( phi ) * radius; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + this.x = sinPhiRadius * Math.sin( theta ); + this.y = Math.cos( phi ) * radius; + this.z = sinPhiRadius * Math.cos( theta ); return this; - }, + } - dispose: function () { + setFromCylindrical( c ) { - this.dispatchEvent( { type: 'dispose' } ); + return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); } -} ); - -/** - * @author alteredq / http://alteredqualia.com - */ + setFromCylindricalCoords( radius, theta, y ) { -function WebGLRenderTargetCube( width, height, options ) { + this.x = radius * Math.sin( theta ); + this.y = y; + this.z = radius * Math.cos( theta ); - WebGLRenderTarget.call( this, width, height, options ); + return this; - this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 - this.activeMipMapLevel = 0; + } -} + setFromMatrixPosition( m ) { -WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); -WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; + const e = m.elements; -WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; -/** - * @author alteredq / http://alteredqualia.com/ - */ + return this; -function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + } - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + setFromMatrixScale( m ) { - this.image = { data: data, width: width, height: height }; + const sx = this.setFromMatrixColumn( m, 0 ).length(); + const sy = this.setFromMatrixColumn( m, 1 ).length(); + const sz = this.setFromMatrixColumn( m, 2 ).length(); - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + this.x = sx; + this.y = sy; + this.z = sz; - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; -} + } -DataTexture.prototype = Object.create( Texture.prototype ); -DataTexture.prototype.constructor = DataTexture; + setFromMatrixColumn( m, index ) { -DataTexture.prototype.isDataTexture = true; + return this.fromArray( m.elements, index * 4 ); -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + setFromMatrix3Column( m, index ) { - images = images !== undefined ? images : []; - mapping = mapping !== undefined ? mapping : CubeReflectionMapping; + return this.fromArray( m.elements, index * 3 ); - Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + } - this.flipY = false; + setFromEuler( e ) { -} + this.x = e._x; + this.y = e._y; + this.z = e._z; -CubeTexture.prototype = Object.create( Texture.prototype ); -CubeTexture.prototype.constructor = CubeTexture; + return this; -CubeTexture.prototype.isCubeTexture = true; + } -Object.defineProperty( CubeTexture.prototype, 'images', { + setFromColor( c ) { - get: function () { + this.x = c.r; + this.y = c.g; + this.z = c.b; - return this.image; + return this; - }, + } - set: function ( value ) { + equals( v ) { - this.image = value; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); } -} ); - -/** - * @author tschw - * - * Uniforms of a program. - * Those form a tree structure with a special top-level container for the root, - * which you get by calling 'new WebGLUniforms( gl, program, renderer )'. - * - * - * Properties of inner nodes including the top-level container: - * - * .seq - array of nested uniforms - * .map - nested uniforms by name - * - * - * Methods of all nodes except the top-level container: - * - * .setValue( gl, value, [renderer] ) - * - * uploads a uniform value(s) - * the 'renderer' parameter is needed for sampler uniforms - * - * - * Static methods of the top-level container (renderer factorizations): - * - * .upload( gl, seq, values, renderer ) - * - * sets uniforms in 'seq' to 'values[id].value' - * - * .seqWithValue( seq, values ) : filteredSeq - * - * filters 'seq' entries with corresponding entry in values - * - * - * Methods of the top-level container (renderer factorizations): - * - * .setValue( gl, name, value ) - * - * sets uniform with name 'name' to 'value' - * - * .set( gl, obj, prop ) - * - * sets uniform from object and property with same name than uniform - * - * .setOptional( gl, obj, prop ) - * - * like .set for an optional property of the object - * - */ + fromArray( array, offset = 0 ) { -var emptyTexture = new Texture(); -var emptyCubeTexture = new CubeTexture(); + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; -// --- Base for inner nodes (including the root) --- + return this; -function UniformContainer() { + } - this.seq = []; - this.map = {}; + toArray( array = [], offset = 0 ) { -} + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; -// --- Utilities --- + return array; -// Array Caches (provide typed arrays for temporary by size) + } -var arrayCacheF32 = []; -var arrayCacheI32 = []; + fromBufferAttribute( attribute, index ) { -// Float32Array caches used for uploading Matrix uniforms + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); -var mat4array = new Float32Array( 16 ); -var mat3array = new Float32Array( 9 ); + return this; -// Flattening for arrays of vectors and matrices + } -function flatten( array, nBlocks, blockSize ) { + random() { - var firstElem = array[ 0 ]; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); - if ( firstElem <= 0 || firstElem > 0 ) { return array; } - // unoptimized: ! isNaN( firstElem ) - // see http://jacksondunstan.com/articles/983 + return this; - var n = nBlocks * blockSize, - r = arrayCacheF32[ n ]; + } - if ( r === undefined ) { + randomDirection() { - r = new Float32Array( n ); - arrayCacheF32[ n ] = r; + // https://mathworld.wolfram.com/SpherePointPicking.html - } + const theta = Math.random() * Math.PI * 2; + const u = Math.random() * 2 - 1; + const c = Math.sqrt( 1 - u * u ); - if ( nBlocks !== 0 ) { + this.x = c * Math.cos( theta ); + this.y = u; + this.z = c * Math.sin( theta ); - firstElem.toArray( r, 0 ); + return this; - for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) { + } - offset += blockSize; - array[ i ].toArray( r, offset ); + *[ Symbol.iterator ]() { - } + yield this.x; + yield this.y; + yield this.z; } - return r; - } -// Texture unit allocation +const _vector$c = /*@__PURE__*/ new Vector3(); +const _quaternion$4 = /*@__PURE__*/ new Quaternion(); -function allocTexUnits( renderer, n ) { +class Box3 { - var r = arrayCacheI32[ n ]; + constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { - if ( r === undefined ) { + this.isBox3 = true; - r = new Int32Array( n ); - arrayCacheI32[ n ] = r; + this.min = min; + this.max = max; } - for ( var i = 0; i !== n; ++ i ) - { r[ i ] = renderer.allocTextureUnit(); } - - return r; + set( min, max ) { -} + this.min.copy( min ); + this.max.copy( max ); -// --- Setters --- + return this; -// Note: Defining these methods externally, because they come in a bunch -// and this way their names minify. + } -// Single scalar + setFromArray( array ) { -function setValue1f( gl, v ) { + this.makeEmpty(); - gl.uniform1f( this.addr, v ); + for ( let i = 0, il = array.length; i < il; i += 3 ) { -} + this.expandByPoint( _vector$b.fromArray( array, i ) ); -function setValue1i( gl, v ) { + } - gl.uniform1i( this.addr, v ); + return this; -} + } -// Single float vector (from flat array or THREE.VectorN) + setFromBufferAttribute( attribute ) { -function setValue2fv( gl, v ) { + this.makeEmpty(); - if ( v.x === undefined ) { + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - gl.uniform2fv( this.addr, v ); + this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); - } else { + } - gl.uniform2f( this.addr, v.x, v.y ); + return this; } -} + setFromPoints( points ) { -function setValue3fv( gl, v ) { + this.makeEmpty(); - if ( v.x !== undefined ) { + for ( let i = 0, il = points.length; i < il; i ++ ) { - gl.uniform3f( this.addr, v.x, v.y, v.z ); + this.expandByPoint( points[ i ] ); - } else if ( v.r !== undefined ) { + } - gl.uniform3f( this.addr, v.r, v.g, v.b ); + return this; - } else { + } - gl.uniform3fv( this.addr, v ); + setFromCenterAndSize( center, size ) { - } + const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); -} + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); -function setValue4fv( gl, v ) { + return this; - if ( v.x === undefined ) { + } - gl.uniform4fv( this.addr, v ); + setFromObject( object, precise = false ) { - } else { + this.makeEmpty(); - gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); + return this.expandByObject( object, precise ); } -} + clone() { -// Single matrix (from flat array or MatrixN) + return new this.constructor().copy( this ); -function setValue2fm( gl, v ) { + } - gl.uniformMatrix2fv( this.addr, false, v.elements || v ); + copy( box ) { -} + this.min.copy( box.min ); + this.max.copy( box.max ); -function setValue3fm( gl, v ) { + return this; - if ( v.elements === undefined ) { + } - gl.uniformMatrix3fv( this.addr, false, v ); + makeEmpty() { - } else { + this.min.x = this.min.y = this.min.z = + Infinity; + this.max.x = this.max.y = this.max.z = - Infinity; - mat3array.set( v.elements ); - gl.uniformMatrix3fv( this.addr, false, mat3array ); + return this; } -} + isEmpty() { -function setValue4fm( gl, v ) { + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - if ( v.elements === undefined ) { + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); - gl.uniformMatrix4fv( this.addr, false, v ); + } - } else { + getCenter( target ) { - mat4array.set( v.elements ); - gl.uniformMatrix4fv( this.addr, false, mat4array ); + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); } -} + getSize( target ) { -// Single texture (2D / Cube) + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); -function setValueT1( gl, v, renderer ) { + } - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTexture2D( v || emptyTexture, unit ); + expandByPoint( point ) { -} + this.min.min( point ); + this.max.max( point ); -function setValueT6( gl, v, renderer ) { + return this; - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTextureCube( v || emptyCubeTexture, unit ); + } -} + expandByVector( vector ) { -// Integer / Boolean vectors or arrays thereof (always flat arrays) + this.min.sub( vector ); + this.max.add( vector ); -function setValue2iv( gl, v ) { + return this; - gl.uniform2iv( this.addr, v ); + } -} + expandByScalar( scalar ) { -function setValue3iv( gl, v ) { + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); - gl.uniform3iv( this.addr, v ); + return this; -} + } -function setValue4iv( gl, v ) { + expandByObject( object, precise = false ) { - gl.uniform4iv( this.addr, v ); + // Computes the world-axis-aligned bounding box of an object (including its children), + // accounting for both the object's, and children's, world transforms -} + object.updateWorldMatrix( false, false ); -// Helper to pick the right setter for the singular case + const geometry = object.geometry; -function getSingularSetter( type ) { + if ( geometry !== undefined ) { - switch ( type ) { + const positionAttribute = geometry.getAttribute( 'position' ); - case 0x1406: return setValue1f; // FLOAT - case 0x8b50: return setValue2fv; // _VEC2 - case 0x8b51: return setValue3fv; // _VEC3 - case 0x8b52: return setValue4fv; // _VEC4 + // precise AABB computation based on vertex data requires at least a position attribute. + // instancing isn't supported so far and uses the normal (conservative) code path. - case 0x8b5a: return setValue2fm; // _MAT2 - case 0x8b5b: return setValue3fm; // _MAT3 - case 0x8b5c: return setValue4fm; // _MAT4 + if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { - case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES - case 0x8b60: return setValueT6; // SAMPLER_CUBE + for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { - case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 + if ( object.isMesh === true ) { - } + object.getVertexPosition( i, _vector$b ); -} + } else { -// Array of scalars + _vector$b.fromBufferAttribute( positionAttribute, i ); -function setValue1fv( gl, v ) { + } - gl.uniform1fv( this.addr, v ); + _vector$b.applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$b ); -} -function setValue1iv( gl, v ) { - - gl.uniform1iv( this.addr, v ); + } -} + } else { -// Array of vectors (flat or from THREE classes) + if ( object.boundingBox !== undefined ) { -function setValueV2a( gl, v ) { + // object-level bounding box - gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) ); + if ( object.boundingBox === null ) { -} + object.computeBoundingBox(); -function setValueV3a( gl, v ) { + } - gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) ); + _box$4.copy( object.boundingBox ); -} -function setValueV4a( gl, v ) { + } else { - gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) ); + // geometry-level bounding box -} + if ( geometry.boundingBox === null ) { -// Array of matrices (flat or from THREE clases) + geometry.computeBoundingBox(); -function setValueM2a( gl, v ) { + } - gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) ); + _box$4.copy( geometry.boundingBox ); -} + } -function setValueM3a( gl, v ) { + _box$4.applyMatrix4( object.matrixWorld ); - gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) ); + this.union( _box$4 ); -} + } -function setValueM4a( gl, v ) { + } - gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) ); + const children = object.children; -} + for ( let i = 0, l = children.length; i < l; i ++ ) { -// Array of textures (2D / Cube) + this.expandByObject( children[ i ], precise ); -function setValueT1a( gl, v, renderer ) { + } - var n = v.length, - units = allocTexUnits( renderer, n ); + return this; - gl.uniform1iv( this.addr, units ); + } - for ( var i = 0; i !== n; ++ i ) { + containsPoint( point ) { - renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); + 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; } -} + containsBox( box ) { -function setValueT6a( gl, v, renderer ) { + 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; - var n = v.length, - units = allocTexUnits( renderer, n ); + } - gl.uniform1iv( this.addr, units ); + getParameter( point, target ) { - for ( var i = 0; i !== n; ++ i ) { + // This can potentially have a divide by zero if the box + // has a size dimension of 0. - renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); + 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 ) + ); } -} - -// Helper to pick the right setter for a pure (bottom-level) array - -function getPureArraySetter( type ) { + intersectsBox( box ) { - switch ( type ) { + // using 6 splitting planes to rule out intersections. + 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; - case 0x1406: return setValue1fv; // FLOAT - case 0x8b50: return setValueV2a; // _VEC2 - case 0x8b51: return setValueV3a; // _VEC3 - case 0x8b52: return setValueV4a; // _VEC4 + } - case 0x8b5a: return setValueM2a; // _MAT2 - case 0x8b5b: return setValueM3a; // _MAT3 - case 0x8b5c: return setValueM4a; // _MAT4 + intersectsSphere( sphere ) { - case 0x8b5e: return setValueT1a; // SAMPLER_2D - case 0x8b60: return setValueT6a; // SAMPLER_CUBE + // Find the point on the AABB closest to the sphere center. + this.clampPoint( sphere.center, _vector$b ); - case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 + // If that point is inside the sphere, the AABB and sphere intersect. + return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); } -} + intersectsPlane( plane ) { -// --- Uniform Classes --- + // We compute the minimum and maximum dot product values. If those values + // are on the same side (back or front) of the plane, then there is no intersection. -function SingleUniform( id, activeInfo, addr ) { + let min, max; - this.id = id; - this.addr = addr; - this.setValue = getSingularSetter( activeInfo.type ); + if ( plane.normal.x > 0 ) { - // this.path = activeInfo.name; // DEBUG + min = plane.normal.x * this.min.x; + max = plane.normal.x * this.max.x; -} + } else { -function PureArrayUniform( id, activeInfo, addr ) { + min = plane.normal.x * this.max.x; + max = plane.normal.x * this.min.x; - this.id = id; - this.addr = addr; - this.size = activeInfo.size; - this.setValue = getPureArraySetter( activeInfo.type ); + } - // this.path = activeInfo.name; // DEBUG + if ( plane.normal.y > 0 ) { -} + min += plane.normal.y * this.min.y; + max += plane.normal.y * this.max.y; -function StructuredUniform( id ) { + } else { - this.id = id; + min += plane.normal.y * this.max.y; + max += plane.normal.y * this.min.y; - UniformContainer.call( this ); // mix-in + } -} + if ( plane.normal.z > 0 ) { -StructuredUniform.prototype.setValue = function ( gl, value ) { + min += plane.normal.z * this.min.z; + max += plane.normal.z * this.max.z; - // Note: Don't need an extra 'renderer' parameter, since samplers - // are not allowed in structured uniforms. + } else { - var seq = this.seq; + min += plane.normal.z * this.max.z; + max += plane.normal.z * this.min.z; - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + } - var u = seq[ i ]; - u.setValue( gl, value[ u.id ] ); + return ( min <= - plane.constant && max >= - plane.constant ); } -}; + intersectsTriangle( triangle ) { -// --- Top-level --- + if ( this.isEmpty() ) { -// Parser - builds up the property tree from the path strings + return false; -var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g; + } -// extracts -// - the identifier (member name or array index) -// - followed by an optional right bracket (found when array index) -// - followed by an optional left bracket or dot (type of subscript) -// -// Note: These portions can be read in a non-overlapping fashion and -// allow straightforward parsing of the hierarchy that WebGL encodes -// in the uniform names. + // compute box center and extents + this.getCenter( _center ); + _extents.subVectors( this.max, _center ); -function addUniform( container, uniformObject ) { + // translate triangle to aabb origin + _v0$3.subVectors( triangle.a, _center ); + _v1$7.subVectors( triangle.b, _center ); + _v2$4.subVectors( triangle.c, _center ); - container.seq.push( uniformObject ); - container.map[ uniformObject.id ] = uniformObject; + // compute edge vectors for triangle + _f0.subVectors( _v1$7, _v0$3 ); + _f1.subVectors( _v2$4, _v1$7 ); + _f2.subVectors( _v0$3, _v2$4 ); -} + // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb + // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation + // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) + 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$3, _v1$7, _v2$4, _extents ) ) { -function parseUniform( activeInfo, addr, container ) { + return false; - var path = activeInfo.name, - pathLength = path.length; + } - // reset RegExp object, because of the early exit of a previous run - RePathPart.lastIndex = 0; + // test 3 face normals from the aabb + axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; + if ( ! satForAxes( axes, _v0$3, _v1$7, _v2$4, _extents ) ) { - for ( ; ; ) { + return false; - var match = RePathPart.exec( path ), - matchEnd = RePathPart.lastIndex, + } - id = match[ 1 ], - idIsIndex = match[ 2 ] === ']', - subscript = match[ 3 ]; + // finally testing the face normal of the triangle + // use already existing triangle edge vectors here + _triangleNormal.crossVectors( _f0, _f1 ); + axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; - if ( idIsIndex ) { id = id | 0; } // convert to integer + return satForAxes( axes, _v0$3, _v1$7, _v2$4, _extents ); - if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { + } - // bare name or "pure" bottom-level array "[0]" suffix + clampPoint( point, target ) { - addUniform( container, subscript === undefined ? - new SingleUniform( id, activeInfo, addr ) : - new PureArrayUniform( id, activeInfo, addr ) ); + return target.copy( point ).clamp( this.min, this.max ); - break; + } - } else { + distanceToPoint( point ) { - // step into inner node / create it in case it doesn't exist + return this.clampPoint( point, _vector$b ).distanceTo( point ); - var map = container.map, next = map[ id ]; + } - if ( next === undefined ) { + getBoundingSphere( target ) { - next = new StructuredUniform( id ); - addUniform( container, next ); + if ( this.isEmpty() ) { - } + target.makeEmpty(); - container = next; + } else { + + this.getCenter( target.center ); + + target.radius = this.getSize( _vector$b ).length() * 0.5; } - } + return target; -} + } -// Root Container + intersect( box ) { -function WebGLUniforms( gl, program, renderer ) { + this.min.max( box.min ); + this.max.min( box.max ); - UniformContainer.call( this ); + // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. + if ( this.isEmpty() ) this.makeEmpty(); - this.renderer = renderer; + return this; - var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); + } - for ( var i = 0; i < n; ++ i ) { + union( box ) { - var info = gl.getActiveUniform( program, i ), - path = info.name, - addr = gl.getUniformLocation( program, path ); + this.min.min( box.min ); + this.max.max( box.max ); - parseUniform( info, addr, this ); + return this; } -} + applyMatrix4( matrix ) { -WebGLUniforms.prototype.setValue = function ( gl, name, value ) { + // transform of empty box is an empty box. + if ( this.isEmpty() ) return this; - var u = this.map[ name ]; + // NOTE: I am using a binary pattern to specify all 2^3 combinations below + _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 + _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 + _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 + _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 + _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 + _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 + _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 + _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 - if ( u !== undefined ) { u.setValue( gl, value, this.renderer ); } + this.setFromPoints( _points ); -}; + return this; -WebGLUniforms.prototype.setOptional = function ( gl, object, name ) { + } - var v = object[ name ]; + translate( offset ) { - if ( v !== undefined ) { this.setValue( gl, name, v ); } + this.min.add( offset ); + this.max.add( offset ); -}; + return this; + + } + + equals( box ) { + return box.min.equals( this.min ) && box.max.equals( this.max ); -// Static interface + } -WebGLUniforms.upload = function ( gl, seq, values, renderer ) { +} - for ( var i = 0, n = seq.length; i !== n; ++ i ) { +const _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 u = seq[ i ], - v = values[ u.id ]; +const _vector$b = /*@__PURE__*/ new Vector3(); - if ( v.needsUpdate !== false ) { +const _box$4 = /*@__PURE__*/ new Box3(); - // note: always updating when .needsUpdate is undefined - u.setValue( gl, v.value, renderer ); +// triangle centered vertices - } +const _v0$3 = /*@__PURE__*/ new Vector3(); +const _v1$7 = /*@__PURE__*/ new Vector3(); +const _v2$4 = /*@__PURE__*/ new Vector3(); - } +// triangle edge vectors -}; +const _f0 = /*@__PURE__*/ new Vector3(); +const _f1 = /*@__PURE__*/ new Vector3(); +const _f2 = /*@__PURE__*/ new Vector3(); + +const _center = /*@__PURE__*/ new Vector3(); +const _extents = /*@__PURE__*/ new Vector3(); +const _triangleNormal = /*@__PURE__*/ new Vector3(); +const _testAxis = /*@__PURE__*/ new Vector3(); + +function satForAxes( axes, v0, v1, v2, extents ) { -WebGLUniforms.seqWithValue = function ( seq, values ) { + for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { - var r = []; + _testAxis.fromArray( axes, i ); + // project the aabb onto the separating axis + const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); + // project all 3 vertices of the triangle onto the separating axis + const p0 = v0.dot( _testAxis ); + const p1 = v1.dot( _testAxis ); + const p2 = v2.dot( _testAxis ); + // actual test, basically see if either of the most extreme of the triangle points intersects r + if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + // points of the projected triangle are outside the projected half-length of the aabb + // the axis is separating and we can exit + return false; - var u = seq[ i ]; - if ( u.id in values ) { r.push( u ); } + } } - return r; + return true; -}; +} -/** - * @author mrdoob / http://mrdoob.com/ - */ +const _box$3 = /*@__PURE__*/ new Box3(); +const _v1$6 = /*@__PURE__*/ new Vector3(); +const _v2$3 = /*@__PURE__*/ new Vector3(); -var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; +class Sphere { -function Color( r, g, b ) { + constructor( center = new Vector3(), radius = - 1 ) { - if ( g === undefined && b === undefined ) { + this.isSphere = true; - // r is THREE.Color, hex or string - return this.set( r ); + this.center = center; + this.radius = radius; } - return this.setRGB( r, g, b ); + set( center, radius ) { -} + this.center.copy( center ); + this.radius = radius; + + return this; + + } -Object.assign( Color.prototype, { + setFromPoints( points, optionalCenter ) { - isColor: true, + const center = this.center; - r: 1, g: 1, b: 1, + if ( optionalCenter !== undefined ) { - set: function ( value ) { + center.copy( optionalCenter ); - if ( value && value.isColor ) { + } else { - this.copy( value ); + _box$3.setFromPoints( points ).getCenter( center ); - } else if ( typeof value === 'number' ) { + } - this.setHex( value ); + let maxRadiusSq = 0; - } else if ( typeof value === 'string' ) { + for ( let i = 0, il = points.length; i < il; i ++ ) { - this.setStyle( value ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); } + this.radius = Math.sqrt( maxRadiusSq ); + return this; - }, + } - setScalar: function ( scalar ) { + copy( sphere ) { - this.r = scalar; - this.g = scalar; - this.b = scalar; + this.center.copy( sphere.center ); + this.radius = sphere.radius; return this; - }, - - setHex: function ( hex ) { - - hex = Math.floor( hex ); + } - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + isEmpty() { - return this; + return ( this.radius < 0 ); - }, + } - setRGB: function ( r, g, b ) { + makeEmpty() { - this.r = r; - this.g = g; - this.b = b; + this.center.set( 0, 0, 0 ); + this.radius = - 1; return this; - }, + } - setHSL: function () { + containsPoint( point ) { - function hue2rgb( p, q, t ) { + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - 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; + } - } + distanceToPoint( point ) { - return function setHSL( h, s, l ) { + return ( point.distanceTo( this.center ) - this.radius ); - // h,s,l ranges are in 0.0 - 1.0 - h = _Math.euclideanModulo( h, 1 ); - s = _Math.clamp( s, 0, 1 ); - l = _Math.clamp( l, 0, 1 ); + } - if ( s === 0 ) { + intersectsSphere( sphere ) { - this.r = this.g = this.b = l; + const radiusSum = this.radius + sphere.radius; - } else { + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - var 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 ); + intersectsBox( box ) { - } + return box.intersectsSphere( this ); - return this; + } - }; + intersectsPlane( plane ) { - }(), + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - setStyle: function ( style ) { + } - function handleAlpha( string ) { + clampPoint( point, target ) { - if ( string === undefined ) { return; } + const deltaLengthSq = this.center.distanceToSquared( point ); - if ( parseFloat( string ) < 1 ) { + target.copy( point ); - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + if ( deltaLengthSq > ( this.radius * this.radius ) ) { - } + target.sub( this.center ).normalize(); + target.multiplyScalar( this.radius ).add( this.center ); } + return target; - var m; + } - if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) { + getBoundingBox( target ) { - // rgb / hsl + if ( this.isEmpty() ) { - var color; - var name = m[ 1 ]; - var components = m[ 2 ]; + // Empty sphere produces empty bounding box + target.makeEmpty(); + return target; - switch ( name ) { + } - case 'rgb': - case 'rgba': + target.set( this.center, this.center ); + target.expandByScalar( this.radius ); - if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + return target; - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; + } - handleAlpha( color[ 5 ] ); + applyMatrix4( matrix ) { - return this; + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); - } + return this; - if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + } - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; + translate( offset ) { - handleAlpha( color[ 5 ] ); + this.center.add( offset ); - return this; + return this; - } + } - break; + expandByPoint( point ) { - case 'hsl': - case 'hsla': + if ( this.isEmpty() ) { - if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + this.center.copy( point ); - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - var h = parseFloat( color[ 1 ] ) / 360; - var s = parseInt( color[ 2 ], 10 ) / 100; - var l = parseInt( color[ 3 ], 10 ) / 100; + this.radius = 0; - handleAlpha( color[ 5 ] ); + return this; - return this.setHSL( h, s, l ); + } - } + _v1$6.subVectors( point, this.center ); - break; + const lengthSq = _v1$6.lengthSq(); - } + if ( lengthSq > ( this.radius * this.radius ) ) { - } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) { + // calculate the minimal sphere - // hex color + const length = Math.sqrt( lengthSq ); - var hex = m[ 1 ]; - var size = hex.length; + const delta = ( length - this.radius ) * 0.5; - if ( size === 3 ) { + this.center.addScaledVector( _v1$6, delta / length ); - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; + this.radius += delta; - return this; + } - } else if ( size === 6 ) { + return this; - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + } - return this; + union( sphere ) { - } + if ( sphere.isEmpty() ) { + + return this; } - if ( style && style.length > 0 ) { + if ( this.isEmpty() ) { - // color keywords - var hex = ColorKeywords[ style ]; + this.copy( sphere ); - if ( hex !== undefined ) { + return this; - // red - this.setHex( hex ); + } - } else { + if ( this.center.equals( sphere.center ) === true ) { - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + this.radius = Math.max( this.radius, sphere.radius ); - } + } else { + + _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); + + this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); + + this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); } return this; - }, + } - clone: function () { + equals( sphere ) { - return new this.constructor( this.r, this.g, this.b ); + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - }, + } - copy: function ( color ) { + clone() { - this.r = color.r; - this.g = color.g; - this.b = color.b; + return new this.constructor().copy( this ); - return this; + } - }, +} - copyGammaToLinear: function ( color, gammaFactor ) { +const _vector$a = /*@__PURE__*/ new Vector3(); +const _segCenter = /*@__PURE__*/ new Vector3(); +const _segDir = /*@__PURE__*/ new Vector3(); +const _diff = /*@__PURE__*/ new Vector3(); - if ( gammaFactor === undefined ) { gammaFactor = 2.0; } +const _edge1 = /*@__PURE__*/ new Vector3(); +const _edge2 = /*@__PURE__*/ new Vector3(); +const _normal$1 = /*@__PURE__*/ new Vector3(); - this.r = Math.pow( color.r, gammaFactor ); - this.g = Math.pow( color.g, gammaFactor ); - this.b = Math.pow( color.b, gammaFactor ); +class Ray { - return this; + 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 ); - copyLinearToGamma: function ( color, gammaFactor ) { + return this; - if ( gammaFactor === undefined ) { gammaFactor = 2.0; } + } - var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; + copy( ray ) { - this.r = Math.pow( color.r, safeInverse ); - this.g = Math.pow( color.g, safeInverse ); - this.b = Math.pow( color.b, safeInverse ); + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); return this; - }, + } + + at( t, target ) { - convertGammaToLinear: function () { + return target.copy( this.origin ).addScaledVector( this.direction, t ); - var r = this.r, g = this.g, b = this.b; + } + + lookAt( v ) { - this.r = r * r; - this.g = g * g; - this.b = b * b; + this.direction.copy( v ).sub( this.origin ).normalize(); return this; - }, + } - convertLinearToGamma: function () { + recast( t ) { - this.r = Math.sqrt( this.r ); - this.g = Math.sqrt( this.g ); - this.b = Math.sqrt( this.b ); + this.origin.copy( this.at( t, _vector$a ) ); return this; - }, - - getHex: function () { + } - return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; + closestPointToPoint( point, target ) { - }, + target.subVectors( point, this.origin ); - getHexString: function () { + const directionDistance = target.dot( this.direction ); - return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); + if ( directionDistance < 0 ) { - }, + return target.copy( this.origin ); - getHSL: function ( optionalTarget ) { + } - // h,s,l ranges are in 0.0 - 1.0 + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - var hsl = optionalTarget || { h: 0, s: 0, l: 0 }; + } - var r = this.r, g = this.g, b = this.b; + distanceToPoint( point ) { - var max = Math.max( r, g, b ); - var min = Math.min( r, g, b ); + return Math.sqrt( this.distanceSqToPoint( point ) ); - var hue, saturation; - var lightness = ( min + max ) / 2.0; + } - if ( min === max ) { + distanceSqToPoint( point ) { - hue = 0; - saturation = 0; + const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); - } else { + // point behind the ray - var delta = max - min; + if ( directionDistance < 0 ) { - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + return this.origin.distanceToSquared( point ); - switch ( max ) { + } - 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; + _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - } + return _vector$a.distanceToSquared( point ); - hue /= 6; + } - } + distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - hsl.h = hue; - hsl.s = saturation; - hsl.l = lightness; + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h + // It returns the min distance between the ray and the segment + // defined by v0 and v1 + // It can also set two optional targets : + // - The closest point on the ray + // - The closest point on the segment - return hsl; + _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 c = _diff.lengthSq(); + const det = Math.abs( 1 - a01 * a01 ); + let s0, s1, sqrDist, extDet; - getStyle: function () { + if ( det > 0 ) { - return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; + // The ray and segment are not parallel. - }, + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; - offsetHSL: function ( h, s, l ) { + if ( s0 >= 0 ) { - var hsl = this.getHSL(); + if ( s1 >= - extDet ) { - hsl.h += h; hsl.s += s; hsl.l += l; + if ( s1 <= extDet ) { - this.setHSL( hsl.h, hsl.s, hsl.l ); + // region 0 + // Minimum at interior points of ray and segment. - return this; + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - }, + } else { - add: function ( color ) { + // region 1 - this.r += color.r; - this.g += color.g; - this.b += color.b; + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + } else { - addColors: function ( color1, color2 ) { + // region 5 - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + } else { - addScalar: function ( s ) { + if ( s1 <= - extDet ) { - this.r += s; - this.g += s; - this.b += s; + // region 4 - return this; + 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 ) + c; - }, + } else if ( s1 <= extDet ) { - sub: function ( color ) { + // region 3 - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; - return this; + } else { - }, + // region 2 - multiply: function ( color ) { + 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 ) + c; - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + } - return this; + } - }, + } else { - multiplyScalar: function ( s ) { + // Ray and segment are parallel. - this.r *= s; - this.g *= s; - this.b *= s; + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + if ( optionalPointOnRay ) { - lerp: function ( color, alpha ) { + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + } - return this; + if ( optionalPointOnSegment ) { - }, + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); - equals: function ( c ) { + } - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + return sqrDist; - }, + } - fromArray: function ( array, offset ) { + intersectSphere( sphere, target ) { - if ( offset === undefined ) { offset = 0; } + _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; - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + if ( d2 > radius2 ) return null; - return this; + const thc = Math.sqrt( radius2 - d2 ); - }, + // t0 = first intersect point - entrance on front of sphere + const t0 = tca - thc; - toArray: function ( array, offset ) { + // t1 = second intersect point - exit point on back of sphere + const t1 = tca + thc; - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + // test to see if t0 is behind the ray: + // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, + // in order to always return an intersect point that is in front of the ray. + if ( t0 < 0 ) return this.at( t1, target ); - return array; + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, target ); - }, + } - toJSON: function () { + intersectsSphere( sphere ) { - return this.getHex(); + return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); } -} ); + distanceToPlane( plane ) { -/** - * Uniforms library for shared webgl shaders - */ + const denominator = plane.normal.dot( this.direction ); -var UniformsLib = { + if ( denominator === 0 ) { - common: { + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, + return 0; - map: { value: null }, - uvTransform: { value: new Matrix3() }, + } - alphaMap: { value: null }, + // Null is preferable to undefined since undefined means.... it is undefined - }, + return null; - specularmap: { + } - specularMap: { value: null }, + const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - }, + // Return if the ray never intersects the plane - envmap: { + return t >= 0 ? t : null; - envMap: { value: null }, - flipEnvMap: { value: - 1 }, - reflectivity: { value: 1.0 }, - refractionRatio: { value: 0.98 } + } - }, + intersectPlane( plane, target ) { - aomap: { + const t = this.distanceToPlane( plane ); - aoMap: { value: null }, - aoMapIntensity: { value: 1 } + if ( t === null ) { - }, + return null; - lightmap: { + } - lightMap: { value: null }, - lightMapIntensity: { value: 1 } + return this.at( t, target ); - }, + } - emissivemap: { + intersectsPlane( plane ) { - emissiveMap: { value: null } + // check if the ray lies on the plane first - }, + const distToPoint = plane.distanceToPoint( this.origin ); - bumpmap: { + if ( distToPoint === 0 ) { - bumpMap: { value: null }, - bumpScale: { value: 1 } + return true; - }, + } - normalmap: { + const denominator = plane.normal.dot( this.direction ); - normalMap: { value: null }, - normalScale: { value: new Vector2( 1, 1 ) } + if ( denominator * distToPoint < 0 ) { - }, + return true; - displacementmap: { + } - displacementMap: { value: null }, - displacementScale: { value: 1 }, - displacementBias: { value: 0 } + // ray origin is behind the plane (and is pointing behind it) - }, + return false; - roughnessmap: { + } - roughnessMap: { value: null } + intersectBox( box, target ) { - }, + let tmin, tmax, tymin, tymax, tzmin, tzmax; - metalnessmap: { + const invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; - metalnessMap: { value: null } + const origin = this.origin; - }, + if ( invdirx >= 0 ) { - gradientmap: { + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; - gradientMap: { value: null } + } else { - }, + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; - fog: { + } - fogDensity: { value: 0.00025 }, - fogNear: { value: 1 }, - fogFar: { value: 2000 }, - fogColor: { value: new Color( 0xffffff ) } + if ( invdiry >= 0 ) { - }, + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; - lights: { + } else { - ambientLightColor: { value: [] }, + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; - directionalLights: { value: [], properties: { - direction: {}, - color: {}, + } - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; - directionalShadowMap: { value: [] }, - directionalShadowMatrix: { value: [] }, + if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; - spotLights: { value: [], properties: { - color: {}, - position: {}, - direction: {}, - distance: {}, - coneCos: {}, - penumbraCos: {}, - decay: {}, + if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, + if ( invdirz >= 0 ) { - spotShadowMap: { value: [] }, - spotShadowMatrix: { value: [] }, + tzmin = ( box.min.z - origin.z ) * invdirz; + tzmax = ( box.max.z - origin.z ) * invdirz; - pointLights: { value: [], properties: { - color: {}, - position: {}, - decay: {}, - distance: {}, + } else { - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {}, - shadowCameraNear: {}, - shadowCameraFar: {} - } }, + tzmin = ( box.max.z - origin.z ) * invdirz; + tzmax = ( box.min.z - origin.z ) * invdirz; - pointShadowMap: { value: [] }, - pointShadowMatrix: { value: [] }, + } - hemisphereLights: { value: [], properties: { - direction: {}, - skyColor: {}, - groundColor: {} - } }, + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; - // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src - rectAreaLights: { value: [], properties: { - color: {}, - position: {}, - width: {}, - height: {} - } } + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; - }, + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; - points: { + //return point closest to the ray (positive side) - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, - size: { value: 1.0 }, - scale: { value: 1.0 }, - map: { value: null }, - uvTransform: { value: new Matrix3() } + if ( tmax < 0 ) return null; + + return this.at( tmin >= 0 ? tmin : tmax, target ); } -}; + intersectsBox( box ) { -/** - * Uniform Utilities - */ + return this.intersectBox( box, _vector$a ) !== null; + + } -var UniformsUtils = { + intersectTriangle( a, b, c, backfaceCulling, target ) { - merge: function ( uniforms ) { + // Compute the offset origin, edges, and normal. - var merged = {}; + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - for ( var u = 0; u < uniforms.length; u ++ ) { + _edge1.subVectors( b, a ); + _edge2.subVectors( c, a ); + _normal$1.crossVectors( _edge1, _edge2 ); - var tmp = this.clone( uniforms[ u ] ); + // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, + // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by + // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) + // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) + // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) + let DdN = this.direction.dot( _normal$1 ); + let sign; - for ( var p in tmp ) { + if ( DdN > 0 ) { - merged[ p ] = tmp[ p ]; + if ( backfaceCulling ) return null; + sign = 1; - } + } else if ( DdN < 0 ) { + + sign = - 1; + DdN = - DdN; + + } else { + + return null; } - return merged; + _diff.subVectors( this.origin, a ); + const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); - }, + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { - clone: function ( uniforms_src ) { + return null; + + } - var uniforms_dst = {}; + const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); - for ( var u in uniforms_src ) { + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { - uniforms_dst[ u ] = {}; + return null; - for ( var p in uniforms_src[ u ] ) { + } - var parameter_src = uniforms_src[ u ][ p ]; + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { - if ( parameter_src && ( parameter_src.isColor || - parameter_src.isMatrix3 || parameter_src.isMatrix4 || - parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 || - parameter_src.isTexture ) ) { + return null; - uniforms_dst[ u ][ p ] = parameter_src.clone(); + } - } else if ( Array.isArray( parameter_src ) ) { + // Line intersects triangle, check if ray does. + const QdN = - sign * _diff.dot( _normal$1 ); - uniforms_dst[ u ][ p ] = parameter_src.slice(); + // t < 0, no intersection + if ( QdN < 0 ) { - } else { + return null; - uniforms_dst[ u ][ p ] = parameter_src; + } - } + // Ray intersects triangle. + 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 ); + + } + +} + +class Matrix4 { + + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + Matrix4.prototype.isMatrix4 = true; + + this.elements = [ + + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ]; + + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); } - return uniforms_dst; + } + + 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() { -var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n"; + this.set( -var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n"; + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 -var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n"; + ); -var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n"; + return this; -var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; + } -var begin_vertex = "\nvec3 transformed = vec3( position );\n"; + clone() { -var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n"; + return new Matrix4().fromArray( this.elements ); -var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; + } -var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n"; + copy( m ) { -var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n"; + const te = this.elements; + const me = m.elements; -var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n"; + 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 ]; -var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n"; + return this; -var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n"; + } -var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif"; + copyPosition( m ) { -var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n"; + const te = this.elements, me = m.elements; -var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif"; + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; -var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif"; + return this; -var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n"; + } -var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n"; + setFromMatrix3( m ) { -var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n"; + const me = m.elements; -var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n"; + this.set( -var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; + 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 -var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n"; + ); -var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n"; + return this; -var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n"; + } -var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n"; + extractBasis( xAxis, yAxis, zAxis ) { -var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n"; + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); -var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n"; + return this; -var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n"; + } -var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n"; + makeBasis( xAxis, yAxis, zAxis ) { -var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif"; + 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 + ); -var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n"; + return this; -var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n"; + } -var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n"; + extractRotation( m ) { -var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n"; + // this method does not support reflection matrices -var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n"; + const te = this.elements; + const me = m.elements; -var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; + const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); + const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); + const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); -var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n"; + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; + te[ 3 ] = 0; -var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; + te[ 7 ] = 0; -var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n"; + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; + te[ 11 ] = 0; -var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n"; + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; -var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n"; + return this; -var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n"; + } -var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; + makeRotationFromEuler( euler ) { -var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; + const te = this.elements; -var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n"; + const x = euler.x, y = euler.y, z = euler.z; + const a = Math.cos( x ), b = Math.sin( x ); + const c = Math.cos( y ), d = Math.sin( y ); + const e = Math.cos( z ), f = Math.sin( z ); -var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif"; + if ( euler.order === 'XYZ' ) { -var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n"; + const ae = a * e, af = a * f, be = b * e, bf = b * f; -var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; -var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n"; + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; -var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; -var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n"; + } else if ( euler.order === 'YXZ' ) { -var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n"; + const ce = c * e, cf = c * f, de = d * e, df = d * f; -var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; -var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n"; + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; -var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif"; + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; -var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n"; + } else if ( euler.order === 'ZXY' ) { -var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; + const ce = c * e, cf = c * f, de = d * e, df = d * f; -var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; -var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 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\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; -var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n"; + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; -var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n"; + } else if ( euler.order === 'ZYX' ) { -var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n"; + const ae = a * e, af = a * f, be = b * e, bf = b * f; -var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; -var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n"; + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; -var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; -var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n"; + } else if ( euler.order === 'YZX' ) { -var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n"; + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; -var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = bd - ac * f; + te[ 8 ] = bc * f + ad; -var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n"; + te[ 1 ] = f; + te[ 5 ] = a * e; + te[ 9 ] = - b * e; -var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; + te[ 2 ] = - d * e; + te[ 6 ] = ad * f + bc; + te[ 10 ] = ac - bd * f; -var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n"; + } else if ( euler.order === 'XZY' ) { -var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n"; + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; -var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n"; + te[ 0 ] = c * e; + te[ 4 ] = - f; + te[ 8 ] = d * e; -var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; + te[ 1 ] = ac * f + bd; + te[ 5 ] = a * e; + te[ 9 ] = ad * f - bc; -var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; + te[ 2 ] = bc * f - ad; + te[ 6 ] = b * e; + te[ 10 ] = bd * f + ac; -var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n"; + } -var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n"; + // bottom row + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; -var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif"; + // last column + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; -var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n"; + return this; -var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; + } -var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; + makeRotationFromQuaternion( q ) { -var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif"; + return this.compose( _zero, q, _one ); -var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif"; + } -var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n"; + lookAt( eye, target, up ) { -var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; + const te = this.elements; -var cube_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n"; + _z.subVectors( eye, target ); -var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n"; + if ( _z.lengthSq() === 0 ) { -var depth_vert = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + // eye and target are in the same position -var distanceRGBA_frag = "#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n"; + _z.z = 1; -var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n"; + } -var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; + _z.normalize(); + _x.crossVectors( up, _z ); -var equirect_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; + if ( _x.lengthSq() === 0 ) { -var linedashed_frag = "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\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + // up and z are parallel -var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n"; + if ( Math.abs( up.z ) === 1 ) { -var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _z.x += 0.0001; -var meshbasic_vert = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } else { -var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _z.z += 0.0001; -var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } -var meshphong_frag = "#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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _z.normalize(); + _x.crossVectors( up, _z ); -var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } -var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + _x.normalize(); + _y.crossVectors( _z, _x ); -var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n"; + 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; -var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; + return this; -var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; + } -var points_frag = "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\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + multiply( m ) { -var points_vert = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + return this.multiplyMatrices( this, m ); -var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n"; + } -var shadow_vert = "#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + premultiply( m ) { -var ShaderChunk = { - alphamap_fragment: alphamap_fragment, - alphamap_pars_fragment: alphamap_pars_fragment, - alphatest_fragment: alphatest_fragment, - aomap_fragment: aomap_fragment, - aomap_pars_fragment: aomap_pars_fragment, - begin_vertex: begin_vertex, - beginnormal_vertex: beginnormal_vertex, - bsdfs: bsdfs, - bumpmap_pars_fragment: bumpmap_pars_fragment, - clipping_planes_fragment: clipping_planes_fragment, - clipping_planes_pars_fragment: clipping_planes_pars_fragment, - clipping_planes_pars_vertex: clipping_planes_pars_vertex, - clipping_planes_vertex: clipping_planes_vertex, - color_fragment: color_fragment, - color_pars_fragment: color_pars_fragment, - color_pars_vertex: color_pars_vertex, - color_vertex: color_vertex, - common: common, - cube_uv_reflection_fragment: cube_uv_reflection_fragment, - defaultnormal_vertex: defaultnormal_vertex, - displacementmap_pars_vertex: displacementmap_pars_vertex, - displacementmap_vertex: displacementmap_vertex, - emissivemap_fragment: emissivemap_fragment, - emissivemap_pars_fragment: emissivemap_pars_fragment, - encodings_fragment: encodings_fragment, - encodings_pars_fragment: encodings_pars_fragment, - envmap_fragment: envmap_fragment, - envmap_pars_fragment: envmap_pars_fragment, - envmap_pars_vertex: envmap_pars_vertex, - envmap_vertex: envmap_vertex, - fog_vertex: fog_vertex, - fog_pars_vertex: fog_pars_vertex, - fog_fragment: fog_fragment, - fog_pars_fragment: fog_pars_fragment, - gradientmap_pars_fragment: gradientmap_pars_fragment, - lightmap_fragment: lightmap_fragment, - lightmap_pars_fragment: lightmap_pars_fragment, - lights_lambert_vertex: lights_lambert_vertex, - lights_pars: lights_pars, - lights_phong_fragment: lights_phong_fragment, - lights_phong_pars_fragment: lights_phong_pars_fragment, - lights_physical_fragment: lights_physical_fragment, - lights_physical_pars_fragment: lights_physical_pars_fragment, - lights_template: lights_template, - logdepthbuf_fragment: logdepthbuf_fragment, - logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, - logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, - logdepthbuf_vertex: logdepthbuf_vertex, - map_fragment: map_fragment, - map_pars_fragment: map_pars_fragment, - map_particle_fragment: map_particle_fragment, - map_particle_pars_fragment: map_particle_pars_fragment, - metalnessmap_fragment: metalnessmap_fragment, - metalnessmap_pars_fragment: metalnessmap_pars_fragment, - morphnormal_vertex: morphnormal_vertex, - morphtarget_pars_vertex: morphtarget_pars_vertex, - morphtarget_vertex: morphtarget_vertex, - normal_fragment: normal_fragment, - normalmap_pars_fragment: normalmap_pars_fragment, - packing: packing, - premultiplied_alpha_fragment: premultiplied_alpha_fragment, - project_vertex: project_vertex, - dithering_fragment: dithering_fragment, - dithering_pars_fragment: dithering_pars_fragment, - roughnessmap_fragment: roughnessmap_fragment, - roughnessmap_pars_fragment: roughnessmap_pars_fragment, - shadowmap_pars_fragment: shadowmap_pars_fragment, - shadowmap_pars_vertex: shadowmap_pars_vertex, - shadowmap_vertex: shadowmap_vertex, - shadowmask_pars_fragment: shadowmask_pars_fragment, - skinbase_vertex: skinbase_vertex, - skinning_pars_vertex: skinning_pars_vertex, - skinning_vertex: skinning_vertex, - skinnormal_vertex: skinnormal_vertex, - specularmap_fragment: specularmap_fragment, - specularmap_pars_fragment: specularmap_pars_fragment, - tonemapping_fragment: tonemapping_fragment, - tonemapping_pars_fragment: tonemapping_pars_fragment, - uv_pars_fragment: uv_pars_fragment, - uv_pars_vertex: uv_pars_vertex, - uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, - worldpos_vertex: worldpos_vertex, - - cube_frag: cube_frag, - cube_vert: cube_vert, - depth_frag: depth_frag, - depth_vert: depth_vert, - distanceRGBA_frag: distanceRGBA_frag, - distanceRGBA_vert: distanceRGBA_vert, - equirect_frag: equirect_frag, - equirect_vert: equirect_vert, - linedashed_frag: linedashed_frag, - linedashed_vert: linedashed_vert, - meshbasic_frag: meshbasic_frag, - meshbasic_vert: meshbasic_vert, - meshlambert_frag: meshlambert_frag, - meshlambert_vert: meshlambert_vert, - meshphong_frag: meshphong_frag, - meshphong_vert: meshphong_vert, - meshphysical_frag: meshphysical_frag, - meshphysical_vert: meshphysical_vert, - normal_frag: normal_frag, - normal_vert: normal_vert, - points_frag: points_frag, - points_vert: points_vert, - shadow_frag: shadow_frag, - shadow_vert: shadow_vert -}; - -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -var ShaderLib = { - - basic: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.meshbasic_vert, - fragmentShader: ShaderChunk.meshbasic_frag - - }, - - lambert: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) } - } - ] ), - - vertexShader: ShaderChunk.meshlambert_vert, - fragmentShader: ShaderChunk.meshlambert_frag - - }, - - phong: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - UniformsLib.gradientmap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) }, - specular: { value: new Color( 0x111111 ) }, - shininess: { value: 30 } - } - ] ), - - vertexShader: ShaderChunk.meshphong_vert, - fragmentShader: ShaderChunk.meshphong_frag - - }, - - standard: { - - uniforms: UniformsUtils.merge( [ - 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: new Color( 0x000000 ) }, - roughness: { value: 0.5 }, - metalness: { value: 0.5 }, - envMapIntensity: { value: 1 } // temporary - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - - }, - - points: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.points, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.points_vert, - fragmentShader: ShaderChunk.points_frag - - }, - - dashed: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.fog, - { - scale: { value: 1 }, - dashSize: { value: 1 }, - totalSize: { value: 2 } - } - ] ), - - vertexShader: ShaderChunk.linedashed_vert, - fragmentShader: ShaderChunk.linedashed_frag - - }, - - depth: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap - ] ), - - vertexShader: ShaderChunk.depth_vert, - fragmentShader: ShaderChunk.depth_frag - - }, - - normal: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - { - opacity: { value: 1.0 } - } - ] ), - - vertexShader: ShaderChunk.normal_vert, - fragmentShader: ShaderChunk.normal_frag - - }, - - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ - - cube: { - - uniforms: { - tCube: { value: null }, - tFlip: { value: - 1 }, - opacity: { value: 1.0 } - }, - - vertexShader: ShaderChunk.cube_vert, - fragmentShader: ShaderChunk.cube_frag - - }, - - equirect: { - - uniforms: { - tEquirect: { value: null }, - }, - - vertexShader: ShaderChunk.equirect_vert, - fragmentShader: ShaderChunk.equirect_frag - - }, - - distanceRGBA: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap, - { - referencePosition: { value: new Vector3() }, - nearDistance: { value: 1 }, - farDistance: { value: 1000 } - } - ] ), - - vertexShader: ShaderChunk.distanceRGBA_vert, - fragmentShader: ShaderChunk.distanceRGBA_frag - - }, - - shadow: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.lights, - UniformsLib.fog, - { - color: { value: new Color( 0x00000 ) }, - opacity: { value: 1.0 } - } ] ), - - vertexShader: ShaderChunk.shadow_vert, - fragmentShader: ShaderChunk.shadow_frag - - } - -}; - -ShaderLib.physical = { - - uniforms: UniformsUtils.merge( [ - ShaderLib.standard.uniforms, - { - clearCoat: { value: 0 }, - clearCoatRoughness: { value: 0 } - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - -}; - -/** - * @author bhouston / http://clara.io - */ - -function Box2( min, max ) { - - this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity ); - -} - -Object.assign( Box2.prototype, { - - set: function ( min, max ) { - - this.min.copy( min ); - this.max.copy( max ); - - return this; - - }, - - setFromPoints: function ( points ) { - - this.makeEmpty(); - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - this.expandByPoint( points[ i ] ); - - } - - return this; - - }, - - setFromCenterAndSize: function () { - - var v1 = new Vector2(); - - return function setFromCenterAndSize( center, size ) { - - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); - - return this; - - }, - - makeEmpty: function () { - - this.min.x = this.min.y = + Infinity; - this.max.x = this.max.y = - Infinity; - - return this; - - }, - - isEmpty: function () { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); - - }, - - getSize: function ( optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.subVectors( this.max, this.min ); - - }, - - expandByPoint: function ( point ) { - - this.min.min( point ); - this.max.max( point ); - - return this; - - }, - - expandByVector: function ( vector ) { - - this.min.sub( vector ); - this.max.add( vector ); - - return this; - - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); - - return this; - - }, - - containsPoint: function ( 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: function ( 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: function ( point, optionalTarget ) { - - // This can potentially have a divide by zero if the box - // has a size dimension of 0. - - var result = optionalTarget || new Vector2(); - - return result.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ) - ); - - }, - - intersectsBox: function ( box ) { - - // using 4 splitting planes to rule out intersections - - 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: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return result.copy( point ).clamp( this.min, this.max ); - - }, - - distanceToPoint: function () { - - var v1 = new Vector2(); - - return function distanceToPoint( point ) { - - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); - - }; - - }(), - - intersect: function ( box ) { - - this.min.max( box.min ); - this.max.min( box.max ); - - return this; - - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); - - return this; - - }, - - translate: function ( offset ) { - - this.min.add( offset ); - this.max.add( offset ); - - return this; - - }, - - equals: function ( box ) { - - return box.min.equals( this.min ) && box.max.equals( this.max ); - - } - -} ); - -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - -function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) { - - var vertexBuffer, elementBuffer; - var shader, program, attributes, uniforms; - - var tempTexture, occlusionTexture; - - function init() { - - var vertices = new Float32Array( [ - - 1, - 1, 0, 0, - 1, - 1, 1, 0, - 1, 1, 1, 1, - - 1, 1, 0, 1 - ] ); - - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); - - // buffers - - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); - - // textures - - tempTexture = gl.createTexture(); - occlusionTexture = gl.createTexture(); - - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - - shader = { - - vertexShader: [ - - 'uniform lowp int renderType;', - - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', - 'uniform float rotation;', - - 'uniform sampler2D occlusionMap;', - - 'attribute vec2 position;', - 'attribute vec2 uv;', - - 'varying vec2 vUV;', - 'varying float vVisibility;', - - 'void main() {', - - ' vUV = uv;', - - ' vec2 pos = position;', - - ' if ( renderType == 2 ) {', - - ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', - - ' vVisibility = visibility.r / 9.0;', - ' vVisibility *= 1.0 - visibility.g / 9.0;', - ' vVisibility *= visibility.b / 9.0;', - ' vVisibility *= 1.0 - visibility.a / 9.0;', - - ' pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;', - ' pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;', - - ' }', - - ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', - - '}' - - ].join( '\n' ), - - fragmentShader: [ - - 'uniform lowp int renderType;', - - 'uniform sampler2D map;', - 'uniform float opacity;', - 'uniform vec3 color;', - - 'varying vec2 vUV;', - 'varying float vVisibility;', - - 'void main() {', - - // pink square - - ' if ( renderType == 0 ) {', - - ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );', - - // restore - - ' } else if ( renderType == 1 ) {', - - ' gl_FragColor = texture2D( map, vUV );', - - // flare - - ' } else {', - - ' vec4 texture = texture2D( map, vUV );', - ' texture.a *= opacity * vVisibility;', - ' gl_FragColor = texture;', - ' gl_FragColor.rgb *= color;', - - ' }', - - '}' - - ].join( '\n' ) - - }; - - program = createProgram( shader ); - - attributes = { - vertex: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; - - uniforms = { - renderType: gl.getUniformLocation( program, 'renderType' ), - map: gl.getUniformLocation( program, 'map' ), - occlusionMap: gl.getUniformLocation( program, 'occlusionMap' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - color: gl.getUniformLocation( program, 'color' ), - scale: gl.getUniformLocation( program, 'scale' ), - rotation: gl.getUniformLocation( program, 'rotation' ), - screenPosition: gl.getUniformLocation( program, 'screenPosition' ) - }; - - } - - /* - * Render lens flares - * Method: renders 16x16 0xff00ff-colored points scattered over the light source area, - * reads these back and calculates occlusion. - */ - - this.render = function ( flares, scene, camera, viewport ) { - - if ( flares.length === 0 ) { return; } - - var tempPosition = new Vector3(); - - var invAspect = viewport.w / viewport.z, - halfViewportWidth = viewport.z * 0.5, - halfViewportHeight = viewport.w * 0.5; - - var size = 16 / viewport.w, - scale = new Vector2( size * invAspect, size ); - - var screenPosition = new Vector3( 1, 1, 0 ), - screenPositionPixels = new Vector2( 1, 1 ); - - var validArea = new Box2(); - - validArea.min.set( viewport.x, viewport.y ); - validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); - - if ( program === undefined ) { - - init(); - - } - - state.useProgram( program ); - - state.initAttributes(); - state.enableAttribute( attributes.vertex ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); - - // loop through all lens flares to update their occlusion and positions - // setup gl and common used attribs/uniforms - - gl.uniform1i( uniforms.occlusionMap, 0 ); - gl.uniform1i( uniforms.map, 1 ); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - - state.disable( gl.CULL_FACE ); - state.buffers.depth.setMask( false ); - - for ( var i = 0, l = flares.length; i < l; i ++ ) { - - size = 16 / viewport.w; - scale.set( size * invAspect, size ); - - // calc object screen position - - var flare = flares[ i ]; - - tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] ); - - tempPosition.applyMatrix4( camera.matrixWorldInverse ); - tempPosition.applyMatrix4( camera.projectionMatrix ); - - // setup arrays for gl programs - - screenPosition.copy( tempPosition ); - - // horizontal and vertical coordinate of the lower left corner of the pixels to copy - - screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8; - screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8; - - // screen cull - - if ( validArea.containsPoint( screenPositionPixels ) === true ) { - - // save current RGB to temp texture - - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, null ); - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); - - - // render pink quad - - gl.uniform1i( uniforms.renderType, 0 ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - - state.disable( gl.BLEND ); - state.enable( gl.DEPTH_TEST ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - - // copy result to occlusionMap - - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); - - - // restore graphics - - gl.uniform1i( uniforms.renderType, 1 ); - state.disable( gl.DEPTH_TEST ); - - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - - // update object positions - - flare.positionScreen.copy( screenPosition ); - - if ( flare.customUpdateCallback ) { - - flare.customUpdateCallback( flare ); - - } else { - - flare.updateLensFlares(); - - } - - // render flares - - gl.uniform1i( uniforms.renderType, 2 ); - state.enable( gl.BLEND ); - - for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) { - - var sprite = flare.lensFlares[ j ]; - - if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) { - - screenPosition.x = sprite.x; - screenPosition.y = sprite.y; - screenPosition.z = sprite.z; - - size = sprite.size * sprite.scale / viewport.w; - - scale.x = size * invAspect; - scale.y = size; - - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform1f( uniforms.rotation, sprite.rotation ); - - gl.uniform1f( uniforms.opacity, sprite.opacity ); - gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); - - state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); - - textures.setTexture2D( sprite.texture, 1 ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - } - - } - - } - - } - - // restore gl - - state.enable( gl.CULL_FACE ); - state.enable( gl.DEPTH_TEST ); - state.buffers.depth.setMask( true ); - - state.reset(); - - }; - - function createProgram( shader ) { - - var program = gl.createProgram(); - - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - - var prefix = 'precision ' + capabilities.precision + ' float;\n'; - - gl.shaderSource( fragmentShader, prefix + shader.fragmentShader ); - gl.shaderSource( vertexShader, prefix + shader.vertexShader ); - - gl.compileShader( fragmentShader ); - gl.compileShader( vertexShader ); - - gl.attachShader( program, fragmentShader ); - gl.attachShader( program, vertexShader ); - - gl.linkProgram( program ); - - return program; - - } - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { - - Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - - this.needsUpdate = true; - -} - -CanvasTexture.prototype = Object.create( Texture.prototype ); -CanvasTexture.prototype.constructor = CanvasTexture; - -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - -function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { - - var vertexBuffer, elementBuffer; - var program, attributes, uniforms; - - var texture; - - // decompose matrixWorld - - var spritePosition = new Vector3(); - var spriteRotation = new Quaternion(); - var spriteScale = new Vector3(); - - function init() { - - var vertices = new Float32Array( [ - - 0.5, - 0.5, 0, 0, - 0.5, - 0.5, 1, 0, - 0.5, 0.5, 1, 1, - - 0.5, 0.5, 0, 1 - ] ); - - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); - - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); - - program = createProgram(); - - attributes = { - position: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; - - uniforms = { - uvOffset: gl.getUniformLocation( program, 'uvOffset' ), - uvScale: gl.getUniformLocation( program, 'uvScale' ), - - rotation: gl.getUniformLocation( program, 'rotation' ), - scale: gl.getUniformLocation( program, 'scale' ), - - color: gl.getUniformLocation( program, 'color' ), - map: gl.getUniformLocation( program, 'map' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - - modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ), - projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ), - - fogType: gl.getUniformLocation( program, 'fogType' ), - fogDensity: gl.getUniformLocation( program, 'fogDensity' ), - fogNear: gl.getUniformLocation( program, 'fogNear' ), - fogFar: gl.getUniformLocation( program, 'fogFar' ), - fogColor: gl.getUniformLocation( program, 'fogColor' ), - fogDepth: gl.getUniformLocation( program, 'fogDepth' ), - - alphaTest: gl.getUniformLocation( program, 'alphaTest' ) - }; - - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = 8; - canvas.height = 8; - - var context = canvas.getContext( '2d' ); - context.fillStyle = 'white'; - context.fillRect( 0, 0, 8, 8 ); - - texture = new CanvasTexture( canvas ); - - } - - this.render = function ( sprites, scene, camera ) { - - if ( sprites.length === 0 ) { return; } - - // setup gl - - if ( program === undefined ) { - - init(); - - } - - state.useProgram( program ); - - state.initAttributes(); - state.enableAttribute( attributes.position ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); - - state.disable( gl.CULL_FACE ); - state.enable( gl.BLEND ); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - - gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements ); - - state.activeTexture( gl.TEXTURE0 ); - gl.uniform1i( uniforms.map, 0 ); - - var oldFogType = 0; - var sceneFogType = 0; - var fog = scene.fog; - - if ( fog ) { - - gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b ); - - if ( fog.isFog ) { - - gl.uniform1f( uniforms.fogNear, fog.near ); - gl.uniform1f( uniforms.fogFar, fog.far ); - - gl.uniform1i( uniforms.fogType, 1 ); - oldFogType = 1; - sceneFogType = 1; - - } else if ( fog.isFogExp2 ) { - - gl.uniform1f( uniforms.fogDensity, fog.density ); - - gl.uniform1i( uniforms.fogType, 2 ); - oldFogType = 2; - sceneFogType = 2; - - } - - } else { - - gl.uniform1i( uniforms.fogType, 0 ); - oldFogType = 0; - sceneFogType = 0; - - } - - - // update positions and sort - - for ( var i = 0, l = sprites.length; i < l; i ++ ) { - - var sprite = sprites[ i ]; - - sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); - sprite.z = - sprite.modelViewMatrix.elements[ 14 ]; - - } - - sprites.sort( painterSortStable ); - - // render all sprites - - var scale = []; - - for ( var i = 0, l = sprites.length; i < l; i ++ ) { - - var sprite = sprites[ i ]; - var material = sprite.material; - - if ( material.visible === false ) { continue; } - - sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); - - gl.uniform1f( uniforms.alphaTest, material.alphaTest ); - gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); - - sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale ); - - scale[ 0 ] = spriteScale.x; - scale[ 1 ] = spriteScale.y; - - var fogType = 0; - - if ( scene.fog && material.fog ) { - - fogType = sceneFogType; - - } - - if ( oldFogType !== fogType ) { - - gl.uniform1i( uniforms.fogType, fogType ); - oldFogType = fogType; - - } - - if ( material.map !== null ) { - - gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y ); - gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y ); - - } else { - - gl.uniform2f( uniforms.uvOffset, 0, 0 ); - gl.uniform2f( uniforms.uvScale, 1, 1 ); - - } - - gl.uniform1f( uniforms.opacity, material.opacity ); - gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b ); - - gl.uniform1f( uniforms.rotation, material.rotation ); - gl.uniform2fv( uniforms.scale, scale ); - - state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); - state.buffers.depth.setTest( material.depthTest ); - state.buffers.depth.setMask( material.depthWrite ); - state.buffers.color.setMask( material.colorWrite ); - - textures.setTexture2D( material.map || texture, 0 ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); - - } - - // restore gl - - state.enable( gl.CULL_FACE ); - - state.reset(); - - }; - - function createProgram() { - - var program = gl.createProgram(); - - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - - gl.shaderSource( vertexShader, [ - - 'precision ' + capabilities.precision + ' float;', - - '#define SHADER_NAME ' + 'SpriteMaterial', - - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform float rotation;', - 'uniform vec2 scale;', - 'uniform vec2 uvOffset;', - 'uniform vec2 uvScale;', - - 'attribute vec2 position;', - 'attribute vec2 uv;', - - 'varying vec2 vUV;', - 'varying float fogDepth;', - - 'void main() {', - - ' vUV = uvOffset + uv * uvScale;', - - ' vec2 alignedPosition = position * scale;', - - ' vec2 rotatedPosition;', - ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', - ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', - - ' vec4 mvPosition;', - - ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', - ' mvPosition.xy += rotatedPosition;', - - ' gl_Position = projectionMatrix * mvPosition;', - - ' fogDepth = - mvPosition.z;', - - '}' - - ].join( '\n' ) ); - - gl.shaderSource( fragmentShader, [ - - 'precision ' + capabilities.precision + ' float;', - - '#define SHADER_NAME ' + 'SpriteMaterial', - - 'uniform vec3 color;', - 'uniform sampler2D map;', - 'uniform float opacity;', - - 'uniform int fogType;', - 'uniform vec3 fogColor;', - 'uniform float fogDensity;', - 'uniform float fogNear;', - 'uniform float fogFar;', - 'uniform float alphaTest;', - - 'varying vec2 vUV;', - 'varying float fogDepth;', - - 'void main() {', - - ' vec4 texture = texture2D( map, vUV );', - - ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', - - ' if ( gl_FragColor.a < alphaTest ) discard;', - - ' if ( fogType > 0 ) {', - - ' float fogFactor = 0.0;', - - ' if ( fogType == 1 ) {', - - ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );', - - ' } else {', - - ' const float LOG2 = 1.442695;', - ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', - ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', - - ' }', - - ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', - - ' }', - - '}' - - ].join( '\n' ) ); - - gl.compileShader( vertexShader ); - gl.compileShader( fragmentShader ); - - gl.attachShader( program, vertexShader ); - gl.attachShader( program, fragmentShader ); - - gl.linkProgram( program ); - - return program; - - } - - function painterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } else if ( a.z !== b.z ) { - - return b.z - a.z; - - } else { - - return b.id - a.id; - - } - - } - -} - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -var materialId = 0; - -function Material() { - - Object.defineProperty( this, 'id', { value: materialId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Material'; - - this.fog = true; - this.lights = true; - - this.blending = NormalBlending; - this.side = FrontSide; - this.flatShading = false; - this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors - - 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.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; - - this.colorWrite = true; - - this.precision = null; // override the renderer's default precision for this material - - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; - - this.dithering = false; - - this.alphaTest = 0; - this.premultipliedAlpha = false; - - this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer - - this.visible = true; - - this.userData = {}; - - this.needsUpdate = true; - -} - -Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: Material, - - isMaterial: true, - - onBeforeCompile: function () {}, - - setValues: function ( values ) { - - if ( values === undefined ) { return; } - - for ( var key in values ) { - - var newValue = values[ key ]; - - if ( newValue === undefined ) { - - console.warn( "THREE.Material: '" + key + "' parameter is undefined." ); - continue; - - } - - // for backward compatability if shading is set in the constructor - if ( key === 'shading' ) { - - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( newValue === FlatShading ) ? true : false; - continue; - - } - - var currentValue = this[ key ]; - - if ( currentValue === undefined ) { - - 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 if ( key === 'overdraw' ) { - - // ensure overdraw is backwards-compatible with legacy boolean type - this[ key ] = Number( newValue ); - - } else { - - this[ key ] = newValue; - - } - - } - - }, - - toJSON: function ( meta ) { - - var isRoot = ( meta === undefined || typeof meta === 'string' ); - - if ( isRoot ) { - - meta = { - textures: {}, - images: {} - }; - - } - - var data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; - - // standard Material serialization - 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 !== undefined ) { data.roughness = this.roughness; } - if ( this.metalness !== undefined ) { data.metalness = this.metalness; } - - if ( this.emissive && this.emissive.isColor ) { data.emissive = this.emissive.getHex(); } - if ( this.emissiveIntensity !== 1 ) { data.emissiveIntensity = this.emissiveIntensity; } - - if ( this.specular && this.specular.isColor ) { data.specular = this.specular.getHex(); } - if ( this.shininess !== undefined ) { data.shininess = this.shininess; } - if ( this.clearCoat !== undefined ) { data.clearCoat = this.clearCoat; } - if ( this.clearCoatRoughness !== undefined ) { data.clearCoatRoughness = this.clearCoatRoughness; } - - if ( this.map && this.map.isTexture ) { data.map = this.map.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; } - 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.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.envMap && this.envMap.isTexture ) { - - data.envMap = this.envMap.toJSON( meta ).uuid; - data.reflectivity = this.reflectivity; // Scale behind envMap - - } - - if ( this.gradientMap && this.gradientMap.isTexture ) { - - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; - - } - - if ( this.size !== undefined ) { data.size = this.size; } - if ( this.sizeAttenuation !== undefined ) { data.sizeAttenuation = this.sizeAttenuation; } - - if ( this.blending !== NormalBlending ) { data.blending = this.blending; } - if ( this.flatShading === true ) { data.flatShading = this.flatShading; } - if ( this.side !== FrontSide ) { data.side = this.side; } - if ( this.vertexColors !== NoColors ) { data.vertexColors = this.vertexColors; } - - 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; - - // rotation (SpriteMaterial) - if ( this.rotation !== 0 ) { data.rotation = this.rotation; } - - if ( this.linewidth !== 1 ) { data.linewidth = this.linewidth; } - if ( this.dashSize !== undefined ) { data.dashSize = this.dashSize; } - if ( this.gapSize !== undefined ) { data.gapSize = this.gapSize; } - if ( this.scale !== undefined ) { data.scale = this.scale; } - - if ( this.dithering === true ) { data.dithering = true; } - - if ( this.alphaTest > 0 ) { data.alphaTest = this.alphaTest; } - 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.morphTargets === true ) { data.morphTargets = true; } - if ( this.skinning === true ) { data.skinning = true; } - - if ( this.visible === false ) { data.visible = false; } - if ( JSON.stringify( this.userData ) !== '{}' ) { data.userData = this.userData; } - - // TODO: Copied from Object3D.toJSON - - function extractFromCache( cache ) { - - var values = []; - - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - - return values; - - } - - if ( isRoot ) { - - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - - if ( textures.length > 0 ) { data.textures = textures; } - if ( images.length > 0 ) { data.images = images; } - - } - - return data; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.name = source.name; - - this.fog = source.fog; - this.lights = source.lights; - - this.blending = source.blending; - this.side = source.side; - this.flatShading = source.flatShading; - 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.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.premultipliedAlpha = source.premultipliedAlpha; - - this.overdraw = source.overdraw; - - this.visible = source.visible; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); - - this.clipShadows = source.clipShadows; - this.clipIntersection = source.clipIntersection; - - var srcPlanes = source.clippingPlanes, - dstPlanes = null; - - if ( srcPlanes !== null ) { - - var n = srcPlanes.length; - dstPlanes = new Array( n ); - - for ( var i = 0; i !== n; ++ i ) - { dstPlanes[ i ] = srcPlanes[ i ].clone(); } - - } - - this.clippingPlanes = dstPlanes; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author bhouston / https://clara.io - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * - * opacity: , - * - * map: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * wireframe: , - * wireframeLinewidth: - * } - */ - -function MeshDepthMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshDepthMaterial'; - - this.depthPacking = BasicDepthPacking; - - this.skinning = false; - this.morphTargets = false; - - this.map = null; - - this.alphaMap = null; - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - -} - -MeshDepthMaterial.prototype = Object.create( Material.prototype ); -MeshDepthMaterial.prototype.constructor = MeshDepthMaterial; - -MeshDepthMaterial.prototype.isMeshDepthMaterial = true; - -MeshDepthMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.depthPacking = source.depthPacking; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - 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; - -}; - -/** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * - * referencePosition: , - * nearDistance: , - * farDistance: , - * - * skinning: , - * morphTargets: , - * - * map: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: - * - * } - */ - -function MeshDistanceMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshDistanceMaterial'; - - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - - this.skinning = false; - this.morphTargets = false; - - this.map = null; - - this.alphaMap = null; - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - -} - -MeshDistanceMaterial.prototype = Object.create( Material.prototype ); -MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; - -MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; - -MeshDistanceMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - this.map = source.map; - - this.alphaMap = source.alphaMap; - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - return this; - -}; - -/** - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - */ - -function Box3( min, max ) { - - this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity ); - -} - -Object.assign( Box3.prototype, { - - isBox3: true, - - set: function ( min, max ) { - - this.min.copy( min ); - this.max.copy( max ); - - return this; - - }, - - setFromArray: function ( array ) { - - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; - - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; - - for ( var i = 0, l = array.length; i < l; i += 3 ) { - - var x = array[ i ]; - var y = array[ i + 1 ]; - var z = array[ i + 2 ]; - - if ( x < minX ) { minX = x; } - if ( y < minY ) { minY = y; } - if ( z < minZ ) { minZ = z; } - - if ( x > maxX ) { maxX = x; } - if ( y > maxY ) { maxY = y; } - if ( z > maxZ ) { maxZ = z; } - - } - - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - - return this; - - }, - - setFromBufferAttribute: function ( attribute ) { - - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; - - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - var x = attribute.getX( i ); - var y = attribute.getY( i ); - var z = attribute.getZ( i ); - - if ( x < minX ) { minX = x; } - if ( y < minY ) { minY = y; } - if ( z < minZ ) { minZ = z; } - - if ( x > maxX ) { maxX = x; } - if ( y > maxY ) { maxY = y; } - if ( z > maxZ ) { maxZ = z; } - - } - - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - - return this; - - }, - - setFromPoints: function ( points ) { - - this.makeEmpty(); - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - this.expandByPoint( points[ i ] ); - - } - - return this; - - }, - - setFromCenterAndSize: function () { - - var v1 = new Vector3(); - - return function setFromCenterAndSize( center, size ) { - - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); - - return this; - - }; - - }(), - - setFromObject: function ( object ) { - - this.makeEmpty(); - - return this.expandByObject( object ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); - - return this; - - }, - - makeEmpty: function () { - - this.min.x = this.min.y = this.min.z = + Infinity; - this.max.x = this.max.y = this.max.z = - Infinity; - - return this; - - }, - - isEmpty: function () { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); - - }, - - getSize: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.subVectors( this.max, this.min ); - - }, - - expandByPoint: function ( point ) { - - this.min.min( point ); - this.max.max( point ); - - return this; - - }, - - expandByVector: function ( vector ) { - - this.min.sub( vector ); - this.max.add( vector ); - - return this; - - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); - - return this; - - }, - - expandByObject: function () { - - // Computes the world-axis-aligned bounding box of an object (including its children), - // accounting for both the object's, and children's, world transforms - - var scope, i, l; - - var v1 = new Vector3(); - - function traverse( node ) { - - var geometry = node.geometry; - - if ( geometry !== undefined ) { - - if ( geometry.isGeometry ) { - - var vertices = geometry.vertices; - - for ( i = 0, l = vertices.length; i < l; i ++ ) { - - v1.copy( vertices[ i ] ); - v1.applyMatrix4( node.matrixWorld ); - - scope.expandByPoint( v1 ); - - } - - } else if ( geometry.isBufferGeometry ) { - - var attribute = geometry.attributes.position; - - if ( attribute !== undefined ) { - - for ( i = 0, l = attribute.count; i < l; i ++ ) { - - v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); - - scope.expandByPoint( v1 ); - - } - - } - - } - - } - - } - - return function expandByObject( object ) { - - scope = this; - - object.updateMatrixWorld( true ); - - object.traverse( traverse ); - - return this; - - }; - - }(), - - containsPoint: function ( 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: function ( 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: function ( point, optionalTarget ) { - - // This can potentially have a divide by zero if the box - // has a size dimension of 0. - - var result = optionalTarget || new Vector3(); - - return result.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: function ( box ) { - - // using 6 splitting planes to rule out intersections. - 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: ( function () { - - var closestPoint = new Vector3(); - - return function intersectsSphere( sphere ) { - - // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, closestPoint ); - - // If that point is inside the sphere, the AABB and sphere intersect. - return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); - - }; - - } )(), - - intersectsPlane: function ( plane ) { - - // We compute the minimum and maximum dot product values. If those values - // are on the same side (back or front) of the plane, then there is no intersection. - - var min, max; - - if ( plane.normal.x > 0 ) { - - min = plane.normal.x * this.min.x; - max = plane.normal.x * this.max.x; - - } else { - - min = plane.normal.x * this.max.x; - max = plane.normal.x * this.min.x; - - } - - if ( plane.normal.y > 0 ) { - - min += plane.normal.y * this.min.y; - max += plane.normal.y * this.max.y; - - } else { - - min += plane.normal.y * this.max.y; - max += plane.normal.y * this.min.y; - - } - - if ( plane.normal.z > 0 ) { - - min += plane.normal.z * this.min.z; - max += plane.normal.z * this.max.z; - - } else { - - min += plane.normal.z * this.max.z; - max += plane.normal.z * this.min.z; - - } - - return ( min <= plane.constant && max >= plane.constant ); - - }, - - clampPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.copy( point ).clamp( this.min, this.max ); - - }, - - distanceToPoint: function () { - - var v1 = new Vector3(); - - return function distanceToPoint( point ) { - - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); - - }; - - }(), - - getBoundingSphere: function () { - - var v1 = new Vector3(); - - return function getBoundingSphere( optionalTarget ) { - - var result = optionalTarget || new Sphere(); - - this.getCenter( result.center ); - - result.radius = this.getSize( v1 ).length() * 0.5; - - return result; - - }; - - }(), - - intersect: function ( box ) { - - this.min.max( box.min ); - this.max.min( box.max ); - - // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. - if ( this.isEmpty() ) { this.makeEmpty(); } - - return this; - - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); - - return this; - - }, - - applyMatrix4: function () { - - var points = [ - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3() - ]; - - return function applyMatrix4( matrix ) { - - // transform of empty box is an empty box. - if ( this.isEmpty() ) { return this; } - - // NOTE: I am using a binary pattern to specify all 2^3 combinations below - points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 - points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 - points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 - points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 - points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 - points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 - points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 - points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 - - this.setFromPoints( points ); - - return this; - - }; - - }(), - - translate: function ( offset ) { - - this.min.add( offset ); - this.max.add( offset ); - - return this; - - }, - - equals: function ( box ) { - - return box.min.equals( this.min ) && box.max.equals( this.max ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ - -function Sphere( center, radius ) { - - this.center = ( center !== undefined ) ? center : new Vector3(); - this.radius = ( radius !== undefined ) ? radius : 0; - -} - -Object.assign( Sphere.prototype, { - - set: function ( center, radius ) { - - this.center.copy( center ); - this.radius = radius; - - return this; - - }, - - setFromPoints: function () { - - var box = new Box3(); - - return function setFromPoints( points, optionalCenter ) { - - var center = this.center; - - if ( optionalCenter !== undefined ) { - - center.copy( optionalCenter ); - - } else { - - box.setFromPoints( points ).getCenter( center ); - - } - - var maxRadiusSq = 0; - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); - - } - - this.radius = Math.sqrt( maxRadiusSq ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( sphere ) { - - this.center.copy( sphere.center ); - this.radius = sphere.radius; - - return this; - - }, - - empty: function () { - - return ( this.radius <= 0 ); - - }, - - containsPoint: function ( point ) { - - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - - }, - - distanceToPoint: function ( point ) { - - return ( point.distanceTo( this.center ) - this.radius ); - - }, - - intersectsSphere: function ( sphere ) { - - var radiusSum = this.radius + sphere.radius; - - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsSphere( this ); - - }, - - intersectsPlane: function ( plane ) { - - return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - - }, - - clampPoint: function ( point, optionalTarget ) { - - var deltaLengthSq = this.center.distanceToSquared( point ); - - var result = optionalTarget || new Vector3(); - - result.copy( point ); - - if ( deltaLengthSq > ( this.radius * this.radius ) ) { - - result.sub( this.center ).normalize(); - result.multiplyScalar( this.radius ).add( this.center ); - - } - - return result; - - }, - - getBoundingBox: function ( optionalTarget ) { - - var box = optionalTarget || new Box3(); - - box.set( this.center, this.center ); - box.expandByScalar( this.radius ); - - return box; - - }, - - applyMatrix4: function ( matrix ) { - - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); - - return this; - - }, - - translate: function ( offset ) { - - this.center.add( offset ); - - return this; - - }, - - equals: function ( sphere ) { - - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - */ - -function Plane( normal, constant ) { - - // normal is assumed to be normalized - - this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); - this.constant = ( constant !== undefined ) ? constant : 0; - -} - -Object.assign( Plane.prototype, { - - set: function ( normal, constant ) { - - this.normal.copy( normal ); - this.constant = constant; - - return this; - - }, - - setComponents: function ( x, y, z, w ) { - - this.normal.set( x, y, z ); - this.constant = w; - - return this; - - }, - - setFromNormalAndCoplanarPoint: function ( normal, point ) { - - this.normal.copy( normal ); - this.constant = - point.dot( this.normal ); - - return this; - - }, - - setFromCoplanarPoints: function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function setFromCoplanarPoints( a, b, c ) { - - var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize(); - - // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? - - this.setFromNormalAndCoplanarPoint( normal, a ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( plane ) { - - this.normal.copy( plane.normal ); - this.constant = plane.constant; - - return this; - - }, - - normalize: function () { - - // Note: will lead to a divide by zero if the plane is invalid. - - var inverseNormalLength = 1.0 / this.normal.length(); - this.normal.multiplyScalar( inverseNormalLength ); - this.constant *= inverseNormalLength; - - return this; - - }, - - negate: function () { - - this.constant *= - 1; - this.normal.negate(); - - return this; - - }, - - distanceToPoint: function ( point ) { - - return this.normal.dot( point ) + this.constant; - - }, - - distanceToSphere: function ( sphere ) { - - return this.distanceToPoint( sphere.center ) - sphere.radius; - - }, - - projectPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); - - }, - - intersectLine: function () { - - var v1 = new Vector3(); - - return function intersectLine( line, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - var direction = line.delta( v1 ); - - var denominator = this.normal.dot( direction ); - - if ( denominator === 0 ) { - - // line is coplanar, return origin - if ( this.distanceToPoint( line.start ) === 0 ) { - - return result.copy( line.start ); - - } - - // Unsure if this is the correct method to handle this case. - return undefined; - - } - - var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - - if ( t < 0 || t > 1 ) { - - return undefined; - - } - - return result.copy( direction ).multiplyScalar( t ).add( line.start ); - - }; - - }(), - - intersectsLine: function ( line ) { - - // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. - - var startSign = this.distanceToPoint( line.start ); - var endSign = this.distanceToPoint( line.end ); - - return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsPlane( this ); - - }, - - intersectsSphere: function ( sphere ) { - - return sphere.intersectsPlane( this ); - - }, - - coplanarPoint: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.normal ).multiplyScalar( - this.constant ); - - }, - - applyMatrix4: function () { - - var v1 = new Vector3(); - var m1 = new Matrix3(); - - return function applyMatrix4( matrix, optionalNormalMatrix ) { - - var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); - - var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); - - var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - - this.constant = - referencePoint.dot( normal ); - - return this; - - }; - - }(), - - translate: function ( offset ) { - - this.constant -= offset.dot( this.normal ); - - return this; - - }, - - equals: function ( plane ) { - - return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author bhouston / http://clara.io - */ - -function Frustum( p0, p1, p2, p3, p4, p5 ) { - - this.planes = [ - - ( p0 !== undefined ) ? p0 : new Plane(), - ( p1 !== undefined ) ? p1 : new Plane(), - ( p2 !== undefined ) ? p2 : new Plane(), - ( p3 !== undefined ) ? p3 : new Plane(), - ( p4 !== undefined ) ? p4 : new Plane(), - ( p5 !== undefined ) ? p5 : new Plane() - - ]; - -} - -Object.assign( Frustum.prototype, { - - set: function ( p0, p1, p2, p3, p4, p5 ) { - - var 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; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( frustum ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - planes[ i ].copy( frustum.planes[ i ] ); - - } - - return this; - - }, - - setFromMatrix: function ( m ) { - - var planes = this.planes; - var me = m.elements; - var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; - var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; - var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; - var 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: function () { - - var sphere = new Sphere(); - - return function intersectsObject( object ) { - - var geometry = object.geometry; - - if ( geometry.boundingSphere === null ) - { geometry.computeBoundingSphere(); } - - sphere.copy( geometry.boundingSphere ) - .applyMatrix4( object.matrixWorld ); - - return this.intersectsSphere( sphere ); - - }; - - }(), - - intersectsSprite: function () { - - var sphere = new Sphere(); - - return function intersectsSprite( sprite ) { - - sphere.center.set( 0, 0, 0 ); - sphere.radius = 0.7071067811865476; - sphere.applyMatrix4( sprite.matrixWorld ); - - return this.intersectsSphere( sphere ); - - }; - - }(), - - intersectsSphere: function ( sphere ) { - - var planes = this.planes; - var center = sphere.center; - var negRadius = - sphere.radius; - - for ( var i = 0; i < 6; i ++ ) { - - var distance = planes[ i ].distanceToPoint( center ); - - if ( distance < negRadius ) { - - return false; - - } - - } - - return true; - - }, - - intersectsBox: function () { - - var p1 = new Vector3(), - p2 = new Vector3(); - - return function intersectsBox( box ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - var plane = planes[ i ]; - - p1.x = plane.normal.x > 0 ? box.min.x : box.max.x; - p2.x = plane.normal.x > 0 ? box.max.x : box.min.x; - p1.y = plane.normal.y > 0 ? box.min.y : box.max.y; - p2.y = plane.normal.y > 0 ? box.max.y : box.min.y; - p1.z = plane.normal.z > 0 ? box.min.z : box.max.z; - p2.z = plane.normal.z > 0 ? box.max.z : box.min.z; - - var d1 = plane.distanceToPoint( p1 ); - var d2 = plane.distanceToPoint( p2 ); - - // if both outside plane, no intersection - - if ( d1 < 0 && d2 < 0 ) { - - return false; - - } - - } - - return true; - - }; - - }(), - - containsPoint: function ( point ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - if ( planes[ i ].distanceToPoint( point ) < 0 ) { - - return false; - - } - - } - - return true; - - } - -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { - - var _frustum = new Frustum(), - _projScreenMatrix = new Matrix4(), - - _shadowMapSize = new Vector2(), - _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), - - _lookTarget = new Vector3(), - _lightPositionWorld = new Vector3(), - - _MorphingFlag = 1, - _SkinningFlag = 2, - - _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1, - - _depthMaterials = new Array( _NumberOfMaterialVariants ), - _distanceMaterials = new Array( _NumberOfMaterialVariants ), - - _materialCache = {}; - - var cubeDirections = [ - new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), - new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) - ]; - - var cubeUps = [ - new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), - new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) - ]; - - var cube2DViewPorts = [ - new Vector4(), new Vector4(), new Vector4(), - new Vector4(), new Vector4(), new Vector4() - ]; - - // init - - for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { - - var useMorphing = ( i & _MorphingFlag ) !== 0; - var useSkinning = ( i & _SkinningFlag ) !== 0; - - var depthMaterial = new MeshDepthMaterial( { - - depthPacking: RGBADepthPacking, - - morphTargets: useMorphing, - skinning: useSkinning - - } ); - - _depthMaterials[ i ] = depthMaterial; - - // - - var distanceMaterial = new MeshDistanceMaterial( { - - morphTargets: useMorphing, - skinning: useSkinning - - } ); - - _distanceMaterials[ i ] = distanceMaterial; - - } - - // - - var scope = this; - - this.enabled = false; - - this.autoUpdate = true; - this.needsUpdate = false; - - this.type = PCFShadowMap; - - this.renderReverseSided = true; - this.renderSingleSided = true; - - this.render = function ( lights, scene, camera ) { - - if ( scope.enabled === false ) { return; } - if ( scope.autoUpdate === false && scope.needsUpdate === false ) { return; } - - if ( lights.length === 0 ) { return; } - - // TODO Clean up (needed in case of contextlost) - var _gl = _renderer.context; - var _state = _renderer.state; - - // Set GL state for depth map. - _state.disable( _gl.BLEND ); - _state.buffers.color.setClear( 1, 1, 1, 1 ); - _state.buffers.depth.setTest( true ); - _state.setScissorTest( false ); - - // render depth map - - var faceCount; - - for ( var i = 0, il = lights.length; i < il; i ++ ) { - - var light = lights[ i ]; - var shadow = light.shadow; - var isPointLight = light && light.isPointLight; - - if ( shadow === undefined ) { - - console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); - continue; - - } - - var shadowCamera = shadow.camera; - - _shadowMapSize.copy( shadow.mapSize ); - _shadowMapSize.min( _maxShadowMapSize ); - - if ( isPointLight ) { - - var vpWidth = _shadowMapSize.x; - var vpHeight = _shadowMapSize.y; - - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction - - // positive X - cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); - // negative X - cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); - // positive Z - cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); - // negative Z - cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); - // positive Y - cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); - // negative Y - cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - - _shadowMapSize.x *= 4.0; - _shadowMapSize.y *= 2.0; - - } - - if ( shadow.map === null ) { - - var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + ".shadowMap"; - - shadowCamera.updateProjectionMatrix(); - - } - - if ( shadow.isSpotLightShadow ) { - - shadow.update( light ); - - } - - var shadowMap = shadow.map; - var shadowMatrix = shadow.matrix; - - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld ); - - if ( isPointLight ) { - - faceCount = 6; - - // for point lights we set the shadow matrix to be a translation-only matrix - // equal to inverse of the light's position - - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - - } else { - - faceCount = 1; - - _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - - // compute shadow matrix - - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - - shadowMatrix.multiply( shadowCamera.projectionMatrix ); - shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - - } - - _renderer.setRenderTarget( shadowMap ); - _renderer.clear(); - - // render shadow map for each cube face (if omni-directional) or - // run a single pass if not - - for ( var face = 0; face < faceCount; face ++ ) { - - if ( isPointLight ) { - - _lookTarget.copy( shadowCamera.position ); - _lookTarget.add( cubeDirections[ face ] ); - shadowCamera.up.copy( cubeUps[ face ] ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - - var vpDimensions = cube2DViewPorts[ face ]; - _state.viewport( vpDimensions ); - - } - - // update camera matrices and frustum - - _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); - - // set object matrices & frustum culling - - renderObject( scene, camera, shadowCamera, isPointLight ); - - } - - } - - scope.needsUpdate = false; - - }; - - function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { - - var geometry = object.geometry; - - var result = null; - - var materialVariants = _depthMaterials; - var customMaterial = object.customDepthMaterial; - - if ( isPointLight ) { - - materialVariants = _distanceMaterials; - customMaterial = object.customDistanceMaterial; - - } - - if ( ! customMaterial ) { - - var useMorphing = false; - - if ( material.morphTargets ) { - - if ( geometry && geometry.isBufferGeometry ) { - - useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - - } else if ( geometry && geometry.isGeometry ) { - - useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - - } - - } - - if ( object.isSkinnedMesh && material.skinning === false ) { - - console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); - - } - - var useSkinning = object.isSkinnedMesh && material.skinning; - - var variantIndex = 0; - - if ( useMorphing ) { variantIndex |= _MorphingFlag; } - if ( useSkinning ) { variantIndex |= _SkinningFlag; } - - result = materialVariants[ variantIndex ]; - - } else { - - result = customMaterial; - - } - - if ( _renderer.localClippingEnabled && - material.clipShadows === true && - material.clippingPlanes.length !== 0 ) { - - // in this case we need a unique material instance reflecting the - // appropriate state - - var keyA = result.uuid, keyB = material.uuid; - - var materialsForVariant = _materialCache[ keyA ]; - - if ( materialsForVariant === undefined ) { - - materialsForVariant = {}; - _materialCache[ keyA ] = materialsForVariant; - - } - - var cachedMaterial = materialsForVariant[ keyB ]; - - if ( cachedMaterial === undefined ) { - - cachedMaterial = result.clone(); - materialsForVariant[ keyB ] = cachedMaterial; - - } - - result = cachedMaterial; - - } - - result.visible = material.visible; - result.wireframe = material.wireframe; - - var side = material.side; - - if ( scope.renderSingleSided && side == DoubleSide ) { - - side = FrontSide; - - } - - if ( scope.renderReverseSided ) { - - if ( side === FrontSide ) { side = BackSide; } - else if ( side === BackSide ) { side = FrontSide; } - - } - - result.side = side; - - result.clipShadows = material.clipShadows; - result.clippingPlanes = material.clippingPlanes; - result.clipIntersection = material.clipIntersection; - - result.wireframeLinewidth = material.wireframeLinewidth; - result.linewidth = material.linewidth; - - if ( isPointLight && result.isMeshDistanceMaterial ) { - - result.referencePosition.copy( lightPositionWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; - - } - - return result; - - } - - function renderObject( object, camera, shadowCamera, isPointLight ) { - - if ( object.visible === false ) { return; } - - var visible = object.layers.test( camera.layers ); - - if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - - if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - - object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - - var geometry = _objects.update( object ); - var material = object.material; - - if ( Array.isArray( material ) ) { - - var groups = geometry.groups; - - for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - - var group = groups[ k ]; - var groupMaterial = material[ group.materialIndex ]; - - if ( groupMaterial && groupMaterial.visible ) { - - var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - - } - - } - - } else if ( material.visible ) { - - var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - - } - - } - - } - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - renderObject( children[ i ], camera, shadowCamera, isPointLight ); - - } - - } - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLAttributes( gl ) { - - var buffers = {}; - - function createBuffer( attribute, bufferType ) { - - var array = attribute.array; - var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; - - var buffer = gl.createBuffer(); - - gl.bindBuffer( bufferType, buffer ); - gl.bufferData( bufferType, array, usage ); - - attribute.onUploadCallback(); - - var type = gl.FLOAT; - - if ( array instanceof Float32Array ) { - - type = gl.FLOAT; - - } else if ( array instanceof Float64Array ) { - - console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); - - } else if ( array instanceof Uint16Array ) { - - type = gl.UNSIGNED_SHORT; - - } else if ( array instanceof Int16Array ) { - - type = gl.SHORT; - - } else if ( array instanceof Uint32Array ) { - - type = gl.UNSIGNED_INT; - - } else if ( array instanceof Int32Array ) { - - type = gl.INT; - - } else if ( array instanceof Int8Array ) { - - type = gl.BYTE; - - } else if ( array instanceof Uint8Array ) { - - type = gl.UNSIGNED_BYTE; - - } - - return { - buffer: buffer, - type: type, - bytesPerElement: array.BYTES_PER_ELEMENT, - version: attribute.version - }; - - } - - function updateBuffer( buffer, attribute, bufferType ) { - - var array = attribute.array; - var updateRange = attribute.updateRange; - - gl.bindBuffer( bufferType, buffer ); - - if ( attribute.dynamic === false ) { - - gl.bufferData( bufferType, array, gl.STATIC_DRAW ); - - } else if ( updateRange.count === - 1 ) { - - // Not using update ranges - - gl.bufferSubData( bufferType, 0, array ); - - } else if ( updateRange.count === 0 ) { - - console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); - - } else { - - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); - - updateRange.count = - 1; // reset range - - } - - } - - // - - function get( attribute ) { - - if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; } - - return buffers[ attribute.uuid ]; - - } - - function remove( attribute ) { - - if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; } - - var data = buffers[ attribute.uuid ]; - - if ( data ) { - - gl.deleteBuffer( data.buffer ); - - delete buffers[ attribute.uuid ]; - - } - - } - - function update( attribute, bufferType ) { - - if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; } - - var data = buffers[ attribute.uuid ]; - - if ( data === undefined ) { - - buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); - - } else if ( data.version < attribute.version ) { - - updateBuffer( data.buffer, attribute, bufferType ); - - data.version = attribute.version; - - } - - } - - return { - - get: get, - remove: remove, - update: update - - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - */ - -function Euler( x, y, z, order ) { - - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._order = order || Euler.DefaultOrder; - -} - -Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]; - -Euler.DefaultOrder = 'XYZ'; - -Object.defineProperties( Euler.prototype, { - - x: { - - get: function () { - - return this._x; - - }, - - set: function ( value ) { - - this._x = value; - this.onChangeCallback(); - - } - - }, - - y: { - - get: function () { - - return this._y; - - }, - - set: function ( value ) { - - this._y = value; - this.onChangeCallback(); - - } - - }, - - z: { - - get: function () { - - return this._z; - - }, - - set: function ( value ) { - - this._z = value; - this.onChangeCallback(); - - } - - }, - - order: { - - get: function () { - - return this._order; - - }, - - set: function ( value ) { - - this._order = value; - this.onChangeCallback(); - - } - - } - -} ); - -Object.assign( Euler.prototype, { - - isEuler: true, - - set: function ( x, y, z, order ) { - - this._x = x; - this._y = y; - this._z = z; - this._order = order || this._order; - - this.onChangeCallback(); - - return this; - - }, - - clone: function () { - - return new this.constructor( this._x, this._y, this._z, this._order ); - - }, - - copy: function ( euler ) { - - this._x = euler._x; - this._y = euler._y; - this._z = euler._z; - this._order = euler._order; - - this.onChangeCallback(); - - return this; - - }, - - setFromRotationMatrix: function ( m, order, update ) { - - var clamp = _Math.clamp; - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - var te = m.elements; - var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; - var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; - var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - - order = order || this._order; - - if ( order === 'XYZ' ) { - - this._y = Math.asin( clamp( m13, - 1, 1 ) ); - - if ( Math.abs( m13 ) < 0.99999 ) { - - this._x = Math.atan2( - m23, m33 ); - this._z = Math.atan2( - m12, m11 ); - - } else { - - this._x = Math.atan2( m32, m22 ); - this._z = 0; - - } - - } else if ( order === 'YXZ' ) { - - this._x = Math.asin( - clamp( m23, - 1, 1 ) ); - - if ( Math.abs( m23 ) < 0.99999 ) { - - this._y = Math.atan2( m13, m33 ); - this._z = Math.atan2( m21, m22 ); - - } else { - - this._y = Math.atan2( - m31, m11 ); - this._z = 0; - - } - - } else if ( order === 'ZXY' ) { - - this._x = Math.asin( clamp( m32, - 1, 1 ) ); - - if ( Math.abs( m32 ) < 0.99999 ) { - - this._y = Math.atan2( - m31, m33 ); - this._z = Math.atan2( - m12, m22 ); - - } else { - - this._y = 0; - this._z = Math.atan2( m21, m11 ); - - } - - } else if ( order === 'ZYX' ) { - - this._y = Math.asin( - clamp( m31, - 1, 1 ) ); - - if ( Math.abs( m31 ) < 0.99999 ) { - - this._x = Math.atan2( m32, m33 ); - this._z = Math.atan2( m21, m11 ); - - } else { - - this._x = 0; - this._z = Math.atan2( - m12, m22 ); - - } - - } else if ( order === 'YZX' ) { - - this._z = Math.asin( clamp( m21, - 1, 1 ) ); - - if ( Math.abs( m21 ) < 0.99999 ) { - - this._x = Math.atan2( - m23, m22 ); - this._y = Math.atan2( - m31, m11 ); - - } else { - - this._x = 0; - this._y = Math.atan2( m13, m33 ); - - } - - } else if ( order === 'XZY' ) { - - this._z = Math.asin( - clamp( m12, - 1, 1 ) ); - - if ( Math.abs( m12 ) < 0.99999 ) { - - this._x = Math.atan2( m32, m22 ); - this._y = Math.atan2( m13, m11 ); - - } else { - - this._x = Math.atan2( - m23, m33 ); - this._y = 0; - - } - - } else { - - console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ); - - } - - this._order = order; - - if ( update !== false ) { this.onChangeCallback(); } - - return this; - - }, - - setFromQuaternion: function () { - - var matrix = new Matrix4(); - - return function setFromQuaternion( q, order, update ) { - - matrix.makeRotationFromQuaternion( q ); - - return this.setFromRotationMatrix( matrix, order, update ); - - }; - - }(), - - setFromVector3: function ( v, order ) { - - return this.set( v.x, v.y, v.z, order || this._order ); - - }, - - reorder: function () { - - // WARNING: this discards revolution information -bhouston - - var q = new Quaternion(); - - return function reorder( newOrder ) { - - q.setFromEuler( this ); - - return this.setFromQuaternion( q, newOrder ); - - }; - - }(), - - equals: function ( euler ) { - - return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); - - }, - - fromArray: function ( array ) { - - this._x = array[ 0 ]; - this._y = array[ 1 ]; - this._z = array[ 2 ]; - if ( array[ 3 ] !== undefined ) { this._order = array[ 3 ]; } - - this.onChangeCallback(); - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) { array = []; } - if ( offset === undefined ) { offset = 0; } - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._order; - - return array; - - }, - - toVector3: function ( optionalResult ) { - - if ( optionalResult ) { - - return optionalResult.set( this._x, this._y, this._z ); - - } else { - - return new Vector3( this._x, this._y, this._z ); - - } - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; - - }, - - onChangeCallback: function () {} - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function Layers() { - - this.mask = 1 | 0; - -} - -Object.assign( Layers.prototype, { - - set: function ( channel ) { - - this.mask = 1 << channel | 0; - - }, - - enable: function ( channel ) { - - this.mask |= 1 << channel | 0; - - }, - - toggle: function ( channel ) { - - this.mask ^= 1 << channel | 0; - - }, - - disable: function ( channel ) { - - this.mask &= ~ ( 1 << channel | 0 ); - - }, - - test: function ( layers ) { - - return ( this.mask & layers.mask ) !== 0; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author elephantatwork / www.elephantatwork.ch - */ - -var object3DId = 0; - -function Object3D() { - - Object.defineProperty( this, 'id', { value: object3DId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Object3D'; - - this.parent = null; - this.children = []; - - this.up = Object3D.DefaultUp.clone(); - - var position = new Vector3(); - var rotation = new Euler(); - var quaternion = new Quaternion(); - var scale = new Vector3( 1, 1, 1 ); - - function onRotationChange() { - - quaternion.setFromEuler( rotation, false ); - - } - - function onQuaternionChange() { - - rotation.setFromQuaternion( quaternion, undefined, false ); - - } - - rotation.onChange( onRotationChange ); - quaternion.onChange( onQuaternionChange ); - - Object.defineProperties( this, { - position: { - enumerable: true, - value: position - }, - rotation: { - enumerable: true, - value: rotation - }, - quaternion: { - enumerable: true, - value: quaternion - }, - scale: { - 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.userData = {}; - -} - -Object3D.DefaultUp = new Vector3( 0, 1, 0 ); -Object3D.DefaultMatrixAutoUpdate = true; - -Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: Object3D, - - isObject3D: true, - - onBeforeRender: function () {}, - onAfterRender: function () {}, - - applyMatrix: function ( matrix ) { - - this.matrix.multiplyMatrices( matrix, this.matrix ); - - this.matrix.decompose( this.position, this.quaternion, this.scale ); - - }, - - applyQuaternion: function ( q ) { - - this.quaternion.premultiply( q ); - - return this; - - }, - - setRotationFromAxisAngle: function ( axis, angle ) { - - // assumes axis is normalized - - this.quaternion.setFromAxisAngle( axis, angle ); - - }, - - setRotationFromEuler: function ( euler ) { - - this.quaternion.setFromEuler( euler, true ); - - }, - - setRotationFromMatrix: function ( m ) { - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - this.quaternion.setFromRotationMatrix( m ); - - }, - - setRotationFromQuaternion: function ( q ) { - - // assumes q is normalized - - this.quaternion.copy( q ); - - }, - - rotateOnAxis: function () { - - // rotate object on axis in object space - // axis is assumed to be normalized - - var q1 = new Quaternion(); - - return function rotateOnAxis( axis, angle ) { - - q1.setFromAxisAngle( axis, angle ); - - this.quaternion.multiply( q1 ); - - return this; - - }; - - }(), - - rotateOnWorldAxis: function () { - - // rotate object on axis in world space - // axis is assumed to be normalized - // method assumes no rotated parent - - var q1 = new Quaternion(); - - return function rotateOnWorldAxis( axis, angle ) { - - q1.setFromAxisAngle( axis, angle ); - - this.quaternion.premultiply( q1 ); - - return this; - - }; - - }(), - - rotateX: function () { - - var v1 = new Vector3( 1, 0, 0 ); - - return function rotateX( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - rotateY: function () { - - var v1 = new Vector3( 0, 1, 0 ); - - return function rotateY( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - rotateZ: function () { - - var v1 = new Vector3( 0, 0, 1 ); - - return function rotateZ( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - translateOnAxis: function () { - - // translate object by distance along axis in object space - // axis is assumed to be normalized - - var v1 = new Vector3(); - - return function translateOnAxis( axis, distance ) { - - v1.copy( axis ).applyQuaternion( this.quaternion ); - - this.position.add( v1.multiplyScalar( distance ) ); - - return this; - - }; - - }(), - - translateX: function () { - - var v1 = new Vector3( 1, 0, 0 ); - - return function translateX( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - translateY: function () { - - var v1 = new Vector3( 0, 1, 0 ); - - return function translateY( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - translateZ: function () { - - var v1 = new Vector3( 0, 0, 1 ); - - return function translateZ( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - localToWorld: function ( vector ) { - - return vector.applyMatrix4( this.matrixWorld ); - - }, - - worldToLocal: function () { - - var m1 = new Matrix4(); - - return function worldToLocal( vector ) { - - return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) ); - - }; - - }(), - - lookAt: function () { - - // This method does not support objects with rotated and/or translated parent(s) - - var m1 = new Matrix4(); - var vector = new Vector3(); - - return function lookAt( x, y, z ) { - - if ( x.isVector3 ) { - - vector.copy( x ); - - } else { - - vector.set( x, y, z ); - - } - - if ( this.isCamera ) { - - m1.lookAt( this.position, vector, this.up ); - - } else { - - m1.lookAt( vector, this.position, this.up ); - - } - - this.quaternion.setFromRotationMatrix( m1 ); - - }; - - }(), - - add: function ( object ) { - var arguments$1 = arguments; - - - if ( arguments.length > 1 ) { - - for ( var i = 0; i < arguments.length; i ++ ) { - - this.add( arguments$1[ 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; - object.dispatchEvent( { type: 'added' } ); - - this.children.push( object ); - - } else { - - console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); - - } - - return this; - - }, - - remove: function ( object ) { - var arguments$1 = arguments; - - - if ( arguments.length > 1 ) { - - for ( var i = 0; i < arguments.length; i ++ ) { - - this.remove( arguments$1[ i ] ); - - } - - return this; - - } - - var index = this.children.indexOf( object ); - - if ( index !== - 1 ) { - - object.parent = null; - - object.dispatchEvent( { type: 'removed' } ); - - this.children.splice( index, 1 ); - - } - - return this; - - }, - - getObjectById: function ( id ) { - - return this.getObjectByProperty( 'id', id ); - - }, - - getObjectByName: function ( name ) { - - return this.getObjectByProperty( 'name', name ); - - }, - - getObjectByProperty: function ( name, value ) { - - if ( this[ name ] === value ) { return this; } - - for ( var i = 0, l = this.children.length; i < l; i ++ ) { - - var child = this.children[ i ]; - var object = child.getObjectByProperty( name, value ); - - if ( object !== undefined ) { - - return object; - - } - - } - - return undefined; - - }, - - getWorldPosition: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); - - return result.setFromMatrixPosition( this.matrixWorld ); - - }, - - getWorldQuaternion: function () { - - var position = new Vector3(); - var scale = new Vector3(); - - return function getWorldQuaternion( optionalTarget ) { - - var result = optionalTarget || new Quaternion(); - - this.updateMatrixWorld( true ); - - this.matrixWorld.decompose( position, result, scale ); - - return result; - - }; - - }(), - - getWorldRotation: function () { - - var quaternion = new Quaternion(); - - return function getWorldRotation( optionalTarget ) { - - var result = optionalTarget || new Euler(); - - this.getWorldQuaternion( quaternion ); - - return result.setFromQuaternion( quaternion, this.rotation.order, false ); - - }; - - }(), - - getWorldScale: function () { - - var position = new Vector3(); - var quaternion = new Quaternion(); - - return function getWorldScale( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); - - this.matrixWorld.decompose( position, quaternion, result ); - - return result; - - }; - - }(), - - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.getWorldQuaternion( quaternion ); - - return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); - - }; - - }(), - - raycast: function () {}, - - traverse: function ( callback ) { - - callback( this ); - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverse( callback ); - - } - - }, - - traverseVisible: function ( callback ) { - - if ( this.visible === false ) { return; } - - callback( this ); - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverseVisible( callback ); - - } - - }, - - traverseAncestors: function ( callback ) { - - var parent = this.parent; - - if ( parent !== null ) { - - callback( parent ); - - parent.traverseAncestors( callback ); - - } - - }, - - updateMatrix: function () { - - this.matrix.compose( this.position, this.quaternion, this.scale ); - - this.matrixWorldNeedsUpdate = true; - - }, - - updateMatrixWorld: function ( 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; - - } - - // update children - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].updateMatrixWorld( force ); - - } - - }, - - toJSON: function ( meta ) { - - // meta is a string when called from JSON.stringify - var isRootObject = ( meta === undefined || typeof meta === 'string' ); - - var output = {}; - - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { - - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {}, - shapes: {} - }; - - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; - - } - - // standard Object3D serialization - - var 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 ( JSON.stringify( this.userData ) !== '{}' ) { object.userData = this.userData; } - - object.matrix = this.matrix.toArray(); - - // - - function serialize( library, element ) { - - if ( library[ element.uuid ] === undefined ) { - - library[ element.uuid ] = element.toJSON( meta ); - - } - - return element.uuid; - - } - - if ( this.geometry !== undefined ) { - - object.geometry = serialize( meta.geometries, this.geometry ); - - var parameters = this.geometry.parameters; - - if ( parameters !== undefined && parameters.shapes !== undefined ) { - - var shapes = parameters.shapes; - - if ( Array.isArray( shapes ) ) { - - for ( var i = 0, l = shapes.length; i < l; i ++ ) { - - var shape = shapes[ i ]; - - serialize( meta.shapes, shape ); - - } - - } else { - - serialize( meta.shapes, shapes ); - - } - - } - - } - - if ( this.material !== undefined ) { - - if ( Array.isArray( this.material ) ) { - - var uuids = []; - - for ( var 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 ( var i = 0; i < this.children.length; i ++ ) { - - object.children.push( this.children[ i ].toJSON( meta ).object ); - - } - - } - - if ( isRootObject ) { - - var geometries = extractFromCache( meta.geometries ); - var materials = extractFromCache( meta.materials ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - var shapes = extractFromCache( meta.shapes ); - - 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; } - - } - - output.object = object; - - return output; - - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { - - var values = []; - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - return values; - - } - - }, - - clone: function ( recursive ) { - - return new this.constructor().copy( this, recursive ); - - }, - - copy: function ( source, recursive ) { - - if ( recursive === undefined ) { recursive = true; } - - this.name = source.name; - - this.up.copy( source.up ); - - this.position.copy( source.position ); - 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 ( var i = 0; i < source.children.length; i ++ ) { - - var child = source.children[ i ]; - this.add( child.clone() ); - - } - - } - - return this; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author WestLangley / http://github.com/WestLangley -*/ - -function Camera() { - - Object3D.call( this ); - - this.type = 'Camera'; - - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); - -} - -Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Camera, - - isCamera: true, - - copy: function ( source, recursive ) { - - Object3D.prototype.copy.call( this, source, recursive ); - - this.matrixWorldInverse.copy( source.matrixWorldInverse ); - this.projectionMatrix.copy( source.projectionMatrix ); - - return this; - - }, - - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.getWorldQuaternion( quaternion ); - - return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - - }; - - }(), - - updateMatrixWorld: function ( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - this.matrixWorldInverse.getInverse( this.matrixWorld ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - } - -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - * @author arose / http://github.com/arose - */ - -function OrthographicCamera( left, right, top, bottom, near, far ) { - - Camera.call( this ); - - this.type = 'OrthographicCamera'; - - this.zoom = 1; - this.view = null; - - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; - - this.near = ( near !== undefined ) ? near : 0.1; - this.far = ( far !== undefined ) ? far : 2000; - - this.updateProjectionMatrix(); - -} - -OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - - constructor: OrthographicCamera, - - isOrthographicCamera: true, - - copy: function ( source, recursive ) { - - Camera.prototype.copy.call( this, 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: function ( fullWidth, fullHeight, x, y, 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 = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; - - this.updateProjectionMatrix(); - - }, - - clearViewOffset: function () { - - if ( this.view !== null ) { - - this.view.enabled = false; - - } - - this.updateProjectionMatrix(); - - }, - - updateProjectionMatrix: function () { - - var dx = ( this.right - this.left ) / ( 2 * this.zoom ); - var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - var cx = ( this.right + this.left ) / 2; - var cy = ( this.top + this.bottom ) / 2; - - var left = cx - dx; - var right = cx + dx; - var top = cy + dy; - var bottom = cy - dy; - - if ( this.view !== null && this.view.enabled ) { - - var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); - var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); - var scaleW = ( this.right - this.left ) / this.view.width; - var scaleH = ( this.top - this.bottom ) / this.view.height; - - left += scaleW * ( this.view.offsetX / zoomW ); - right = left + scaleW * ( this.view.width / zoomW ); - top -= scaleH * ( this.view.offsetY / zoomH ); - bottom = top - scaleH * ( this.view.height / zoomH ); - - } - - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); - - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, 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; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -function Face3( a, b, c, normal, color, materialIndex ) { - - this.a = a; - this.b = b; - this.c = c; - - this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); - this.vertexNormals = Array.isArray( normal ) ? normal : []; - - this.color = ( color && color.isColor ) ? color : new Color(); - this.vertexColors = Array.isArray( color ) ? color : []; - - this.materialIndex = materialIndex !== undefined ? materialIndex : 0; - -} - -Object.assign( Face3.prototype, { - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.a = source.a; - this.b = source.b; - this.c = source.c; - - this.normal.copy( source.normal ); - this.color.copy( source.color ); - - this.materialIndex = source.materialIndex; - - for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { - - this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); - - } - - for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { - - this.vertexColors[ i ] = source.vertexColors[ i ].clone(); - - } - - return this; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author bhouston / http://clara.io - */ - -var geometryId = 0; // Geometry uses even numbers as Id - -function Geometry() { - - Object.defineProperty( this, 'id', { value: geometryId += 2 } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Geometry'; - - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - - this.morphTargets = []; - this.morphNormals = []; - - this.skinWeights = []; - this.skinIndices = []; - - this.lineDistances = []; - - this.boundingBox = null; - this.boundingSphere = null; - - // update flags - - this.elementsNeedUpdate = false; - this.verticesNeedUpdate = false; - this.uvsNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.lineDistancesNeedUpdate = false; - this.groupsNeedUpdate = false; - -} - -Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: Geometry, - - isGeometry: true, - - applyMatrix: function ( matrix ) { - - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { - - var vertex = this.vertices[ i ]; - vertex.applyMatrix4( matrix ); - - } - - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { - - var face = this.faces[ i ]; - face.normal.applyMatrix3( normalMatrix ).normalize(); - - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - - face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); - - } - - } - - if ( this.boundingBox !== null ) { - - this.computeBoundingBox(); - - } - - if ( this.boundingSphere !== null ) { - - this.computeBoundingSphere(); - - } - - this.verticesNeedUpdate = true; - this.normalsNeedUpdate = true; - - return this; - - }, - - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); - - return function rotateX( angle ) { - - m1.makeRotationX( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateY: function () { - - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateZ: function () { - - // rotate geometry around world z-axis - - var m1 = new Matrix4(); - - return function rotateZ( angle ) { - - m1.makeRotationZ( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - translate: function () { - - // translate geometry - - var m1 = new Matrix4(); - - return function translate( x, y, z ) { - - m1.makeTranslation( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - scale: function () { - - // scale geometry - - var m1 = new Matrix4(); - - return function scale( x, y, z ) { - - m1.makeScale( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - lookAt: function () { - - var obj = new Object3D(); - - return function lookAt( vector ) { - - obj.lookAt( vector ); - - obj.updateMatrix(); - - this.applyMatrix( obj.matrix ); - - }; - - }(), - - fromBufferGeometry: function ( geometry ) { - - var scope = this; - - var indices = geometry.index !== null ? geometry.index.array : undefined; - var attributes = geometry.attributes; - - var positions = attributes.position.array; - var normals = attributes.normal !== undefined ? attributes.normal.array : undefined; - var colors = attributes.color !== undefined ? attributes.color.array : undefined; - var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined; - var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined; - - if ( uvs2 !== undefined ) { this.faceVertexUvs[ 1 ] = []; } - - var tempNormals = []; - var tempUVs = []; - var tempUVs2 = []; - - for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { - - scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); - - if ( normals !== undefined ) { - - tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); - - } - - if ( colors !== undefined ) { - - scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); - - } - - if ( uvs !== undefined ) { - - tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); - - } - - if ( uvs2 !== undefined ) { - - tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); - - } - - } - - function addFace( a, b, c, materialIndex ) { - - var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; - var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; - - var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); - - scope.faces.push( face ); - - if ( uvs !== undefined ) { - - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); - - } - - if ( uvs2 !== undefined ) { - - scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); - - } - - } - - var groups = geometry.groups; - - if ( groups.length > 0 ) { - - for ( var i = 0; i < groups.length; i ++ ) { - - var group = groups[ i ]; - - var start = group.start; - var count = group.count; - - for ( var j = start, jl = start + count; j < jl; j += 3 ) { - - if ( indices !== undefined ) { - - addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); - - } else { - - addFace( j, j + 1, j + 2, group.materialIndex ); - - } - - } - - } - - } else { - - if ( indices !== undefined ) { - - for ( var i = 0; i < indices.length; i += 3 ) { - - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); - - } - - } else { - - for ( var i = 0; i < positions.length / 3; i += 3 ) { - - addFace( i, i + 1, i + 2 ); - - } - - } - - } - - this.computeFaceNormals(); - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - return this; - - }, - - center: function () { - - this.computeBoundingBox(); - - var offset = this.boundingBox.getCenter().negate(); - - this.translate( offset.x, offset.y, offset.z ); - - return offset; - - }, - - normalize: function () { - - this.computeBoundingSphere(); - - var center = this.boundingSphere.center; - var radius = this.boundingSphere.radius; - - var s = radius === 0 ? 1 : 1.0 / radius; - - var matrix = new Matrix4(); - matrix.set( - s, 0, 0, - s * center.x, - 0, s, 0, - s * center.y, - 0, 0, s, - s * center.z, - 0, 0, 0, 1 - ); - - this.applyMatrix( matrix ); - - return this; - - }, - - computeFaceNormals: function () { - - var cb = new Vector3(), ab = new Vector3(); - - for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { - - var face = this.faces[ f ]; - - var vA = this.vertices[ face.a ]; - var vB = this.vertices[ face.b ]; - var vC = this.vertices[ face.c ]; - - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); - - cb.normalize(); - - face.normal.copy( cb ); - - } - - }, - - computeVertexNormals: function ( areaWeighted ) { - - if ( areaWeighted === undefined ) { areaWeighted = true; } - - var v, vl, f, fl, face, vertices; - - vertices = new Array( this.vertices.length ); - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ] = new Vector3(); - - } - - if ( areaWeighted ) { - - // vertex normals weighted by triangle areas - // http://www.iquilezles.org/www/articles/normals/normals.htm - - var vA, vB, vC; - var cb = new Vector3(), ab = new Vector3(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; - - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); - - vertices[ face.a ].add( cb ); - vertices[ face.b ].add( cb ); - vertices[ face.c ].add( cb ); - - } - - } else { - - this.computeFaceNormals(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - vertices[ face.a ].add( face.normal ); - vertices[ face.b ].add( face.normal ); - vertices[ face.c ].add( face.normal ); - - } - - } - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ].normalize(); - - } - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - vertexNormals[ 0 ].copy( vertices[ face.a ] ); - vertexNormals[ 1 ].copy( vertices[ face.b ] ); - vertexNormals[ 2 ].copy( vertices[ face.c ] ); - - } else { - - vertexNormals[ 0 ] = vertices[ face.a ].clone(); - vertexNormals[ 1 ] = vertices[ face.b ].clone(); - vertexNormals[ 2 ] = vertices[ face.c ].clone(); - - } - - } - - if ( this.faces.length > 0 ) { - - this.normalsNeedUpdate = true; - - } - - }, - - computeFlatVertexNormals: function () { - - var f, fl, face; - - this.computeFaceNormals(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - vertexNormals[ 0 ].copy( face.normal ); - vertexNormals[ 1 ].copy( face.normal ); - vertexNormals[ 2 ].copy( face.normal ); - - } else { - - vertexNormals[ 0 ] = face.normal.clone(); - vertexNormals[ 1 ] = face.normal.clone(); - vertexNormals[ 2 ] = face.normal.clone(); - - } - - } - - if ( this.faces.length > 0 ) { - - this.normalsNeedUpdate = true; - - } - - }, - - computeMorphNormals: function () { - - var i, il, f, fl, face; - - // save original normals - // - create temp variables on first access - // otherwise just copy (for faster repeated calls) - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( ! face.__originalFaceNormal ) { - - face.__originalFaceNormal = face.normal.clone(); - - } else { - - face.__originalFaceNormal.copy( face.normal ); - - } - - if ( ! face.__originalVertexNormals ) { face.__originalVertexNormals = []; } - - for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { - - if ( ! face.__originalVertexNormals[ i ] ) { - - face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); - - } else { - - face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); - - } - - } - - } - - // use temp geometry to compute face and vertex normals for each morph - - var tmpGeo = new Geometry(); - tmpGeo.faces = this.faces; - - for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { - - // create on first access - - if ( ! this.morphNormals[ i ] ) { - - this.morphNormals[ i ] = {}; - this.morphNormals[ i ].faceNormals = []; - this.morphNormals[ i ].vertexNormals = []; - - var dstNormalsFace = this.morphNormals[ i ].faceNormals; - var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; - - var faceNormal, vertexNormals; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - faceNormal = new Vector3(); - vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; - - dstNormalsFace.push( faceNormal ); - dstNormalsVertex.push( vertexNormals ); - - } - - } - - var morphNormals = this.morphNormals[ i ]; - - // set vertices to morph target - - tmpGeo.vertices = this.morphTargets[ i ].vertices; - - // compute morph normals - - tmpGeo.computeFaceNormals(); - tmpGeo.computeVertexNormals(); - - // store morph normals - - var faceNormal, vertexNormals; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - faceNormal = morphNormals.faceNormals[ f ]; - vertexNormals = morphNormals.vertexNormals[ f ]; - - faceNormal.copy( face.normal ); - - vertexNormals.a.copy( face.vertexNormals[ 0 ] ); - vertexNormals.b.copy( face.vertexNormals[ 1 ] ); - vertexNormals.c.copy( face.vertexNormals[ 2 ] ); - - } - - } - - // restore original normals - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - face.normal = face.__originalFaceNormal; - face.vertexNormals = face.__originalVertexNormals; - - } - - }, - - computeLineDistances: function () { - - var d = 0; - var vertices = this.vertices; - - for ( var i = 0, il = vertices.length; i < il; i ++ ) { - - if ( i > 0 ) { - - d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); - - } - - this.lineDistances[ i ] = d; - - } - - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } - - this.boundingBox.setFromPoints( this.vertices ); - - }, - - computeBoundingSphere: function () { - - if ( this.boundingSphere === null ) { - - this.boundingSphere = new Sphere(); - - } - - this.boundingSphere.setFromPoints( this.vertices ); - - }, - - merge: function ( geometry, matrix, materialIndexOffset ) { - - if ( ! ( geometry && geometry.isGeometry ) ) { - - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); - return; - - } - - var normalMatrix, - vertexOffset = this.vertices.length, - vertices1 = this.vertices, - vertices2 = geometry.vertices, - faces1 = this.faces, - faces2 = geometry.faces, - uvs1 = this.faceVertexUvs[ 0 ], - uvs2 = geometry.faceVertexUvs[ 0 ], - colors1 = this.colors, - colors2 = geometry.colors; - - if ( materialIndexOffset === undefined ) { materialIndexOffset = 0; } - - if ( matrix !== undefined ) { - - normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - } - - // vertices - - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { - - var vertex = vertices2[ i ]; - - var vertexCopy = vertex.clone(); - - if ( matrix !== undefined ) { vertexCopy.applyMatrix4( matrix ); } - - vertices1.push( vertexCopy ); - - } - - // colors - - for ( var i = 0, il = colors2.length; i < il; i ++ ) { - - colors1.push( colors2[ i ].clone() ); - - } - - // faces - - for ( i = 0, il = faces2.length; i < il; i ++ ) { - - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; - - faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - faceCopy.normal.copy( face.normal ); - - if ( normalMatrix !== undefined ) { - - faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); - - } - - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { - - normal = faceVertexNormals[ j ].clone(); - - if ( normalMatrix !== undefined ) { - - normal.applyMatrix3( normalMatrix ).normalize(); - - } - - faceCopy.vertexNormals.push( normal ); - - } - - faceCopy.color.copy( face.color ); - - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { - - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); - - } - - faceCopy.materialIndex = face.materialIndex + materialIndexOffset; - - faces1.push( faceCopy ); - - } - - // uvs - - for ( i = 0, il = uvs2.length; i < il; i ++ ) { - - var uv = uvs2[ i ], uvCopy = []; - - if ( uv === undefined ) { - - continue; - - } - - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - - uvCopy.push( uv[ j ].clone() ); - - } - - uvs1.push( uvCopy ); - - } - - }, - - mergeMesh: function ( mesh ) { - - if ( ! ( mesh && mesh.isMesh ) ) { - - console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); - return; - - } - - mesh.matrixAutoUpdate && mesh.updateMatrix(); - - this.merge( mesh.geometry, mesh.matrix ); - - }, - - /* - * Checks for duplicate vertices with hashmap. - * Duplicated vertices are removed - * and faces' vertices are updated. - */ - - mergeVertices: function () { - - var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], changes = []; - - var v, key; - var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001 - var precision = Math.pow( 10, precisionPoints ); - var i, il, face; - var indices, j, jl; - - for ( i = 0, il = this.vertices.length; i < il; i ++ ) { - - v = this.vertices[ i ]; - key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); - - if ( verticesMap[ key ] === undefined ) { - - verticesMap[ key ] = i; - unique.push( this.vertices[ i ] ); - changes[ i ] = unique.length - 1; - - } else { - - //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); - changes[ i ] = changes[ verticesMap[ key ] ]; - - } - - } - - - // if faces are completely degenerate after merging vertices, we - // have to remove them from the geometry. - var faceIndicesToRemove = []; - - for ( i = 0, il = this.faces.length; i < il; i ++ ) { - - face = this.faces[ i ]; - - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; - - indices = [ face.a, face.b, face.c ]; - - // if any duplicate vertices are found in a Face3 - // we have to remove the face as nothing can be saved - for ( var n = 0; n < 3; n ++ ) { - - if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { - - faceIndicesToRemove.push( i ); - break; - - } - - } - - } - - for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - - var idx = faceIndicesToRemove[ i ]; - - this.faces.splice( idx, 1 ); - - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { - - this.faceVertexUvs[ j ].splice( idx, 1 ); - - } - - } - - // Use unique set of vertices - - var diff = this.vertices.length - unique.length; - this.vertices = unique; - return diff; - - }, - - setFromPoints: function ( points ) { - - this.vertices = []; - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); - - } - - return this; - - }, - - sortFacesByMaterialIndex: function () { - - var faces = this.faces; - var length = faces.length; - - // tag faces - - for ( var i = 0; i < length; i ++ ) { - - faces[ i ]._id = i; - - } - - // sort faces - - function materialIndexSort( a, b ) { - - return a.materialIndex - b.materialIndex; - - } - - faces.sort( materialIndexSort ); - - // sort uvs - - var uvs1 = this.faceVertexUvs[ 0 ]; - var uvs2 = this.faceVertexUvs[ 1 ]; - - var newUvs1, newUvs2; - - if ( uvs1 && uvs1.length === length ) { newUvs1 = []; } - if ( uvs2 && uvs2.length === length ) { newUvs2 = []; } - - for ( var i = 0; i < length; i ++ ) { - - var id = faces[ i ]._id; - - if ( newUvs1 ) { newUvs1.push( uvs1[ id ] ); } - if ( newUvs2 ) { newUvs2.push( uvs2[ id ] ); } - - } - - if ( newUvs1 ) { this.faceVertexUvs[ 0 ] = newUvs1; } - if ( newUvs2 ) { this.faceVertexUvs[ 1 ] = newUvs2; } - - }, - - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON' - } - }; - - // standard Geometry serialization - - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) { data.name = this.name; } - - if ( this.parameters !== undefined ) { - - var parameters = this.parameters; - - for ( var key in parameters ) { - - if ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; } - - } - - return data; - - } - - var vertices = []; - - for ( var i = 0; i < this.vertices.length; i ++ ) { - - var vertex = this.vertices[ i ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - var faces = []; - var normals = []; - var normalsHash = {}; - var colors = []; - var colorsHash = {}; - var uvs = []; - var uvsHash = {}; - - for ( var i = 0; i < this.faces.length; i ++ ) { - - var face = this.faces[ i ]; - - var hasMaterial = true; - var hasFaceUv = false; // deprecated - var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined; - var hasFaceNormal = face.normal.length() > 0; - var hasFaceVertexNormal = face.vertexNormals.length > 0; - var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1; - var hasFaceVertexColor = face.vertexColors.length > 0; - - var faceType = 0; - - faceType = setBit( faceType, 0, 0 ); // isQuad - faceType = setBit( faceType, 1, hasMaterial ); - faceType = setBit( faceType, 2, hasFaceUv ); - faceType = setBit( faceType, 3, hasFaceVertexUv ); - faceType = setBit( faceType, 4, hasFaceNormal ); - faceType = setBit( faceType, 5, hasFaceVertexNormal ); - faceType = setBit( faceType, 6, hasFaceColor ); - faceType = setBit( faceType, 7, hasFaceVertexColor ); - - faces.push( faceType ); - faces.push( face.a, face.b, face.c ); - faces.push( face.materialIndex ); - - if ( hasFaceVertexUv ) { - - var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; - - faces.push( - getUvIndex( faceVertexUvs[ 0 ] ), - getUvIndex( faceVertexUvs[ 1 ] ), - getUvIndex( faceVertexUvs[ 2 ] ) - ); - - } - - if ( hasFaceNormal ) { - - faces.push( getNormalIndex( face.normal ) ); - - } - - if ( hasFaceVertexNormal ) { - - var vertexNormals = face.vertexNormals; - - faces.push( - getNormalIndex( vertexNormals[ 0 ] ), - getNormalIndex( vertexNormals[ 1 ] ), - getNormalIndex( vertexNormals[ 2 ] ) - ); - - } - - if ( hasFaceColor ) { - - faces.push( getColorIndex( face.color ) ); - - } - - if ( hasFaceVertexColor ) { - - var vertexColors = face.vertexColors; - - faces.push( - getColorIndex( vertexColors[ 0 ] ), - getColorIndex( vertexColors[ 1 ] ), - getColorIndex( vertexColors[ 2 ] ) - ); - - } - - } - - function setBit( value, position, enabled ) { - - return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); - - } - - function getNormalIndex( normal ) { - - var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); - - if ( normalsHash[ hash ] !== undefined ) { - - return normalsHash[ hash ]; - - } - - normalsHash[ hash ] = normals.length / 3; - normals.push( normal.x, normal.y, normal.z ); - - return normalsHash[ hash ]; - - } - - function getColorIndex( color ) { - - var hash = color.r.toString() + color.g.toString() + color.b.toString(); - - if ( colorsHash[ hash ] !== undefined ) { - - return colorsHash[ hash ]; - - } - - colorsHash[ hash ] = colors.length; - colors.push( color.getHex() ); - - return colorsHash[ hash ]; - - } - - function getUvIndex( uv ) { - - var hash = uv.x.toString() + uv.y.toString(); - - if ( uvsHash[ hash ] !== undefined ) { - - return uvsHash[ hash ]; - - } - - uvsHash[ hash ] = uvs.length / 2; - uvs.push( uv.x, uv.y ); - - return uvsHash[ hash ]; - - } - - data.data = {}; - - data.data.vertices = vertices; - data.data.normals = normals; - if ( colors.length > 0 ) { data.data.colors = colors; } - if ( uvs.length > 0 ) { data.data.uvs = [ uvs ]; } // temporal backward compatibility - data.data.faces = faces; - - return data; - - }, - - clone: function () { - - /* - // Handle primitives - - var parameters = this.parameters; - - if ( parameters !== undefined ) { - - var values = []; - - for ( var key in parameters ) { - - values.push( parameters[ key ] ); - - } - - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; - - } - - return new this.constructor().copy( this ); - */ - - return new Geometry().copy( this ); - - }, - - copy: function ( source ) { - - var i, il, j, jl, k, kl; - - // reset - - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - this.morphTargets = []; - this.morphNormals = []; - this.skinWeights = []; - this.skinIndices = []; - this.lineDistances = []; - this.boundingBox = null; - this.boundingSphere = null; - - // name - - this.name = source.name; - - // vertices - - var vertices = source.vertices; - - for ( i = 0, il = vertices.length; i < il; i ++ ) { - - this.vertices.push( vertices[ i ].clone() ); - - } - - // colors - - var colors = source.colors; - - for ( i = 0, il = colors.length; i < il; i ++ ) { - - this.colors.push( colors[ i ].clone() ); - - } - - // faces - - var faces = source.faces; - - for ( i = 0, il = faces.length; i < il; i ++ ) { - - this.faces.push( faces[ i ].clone() ); - - } - - // face vertex uvs - - for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { - - var faceVertexUvs = source.faceVertexUvs[ i ]; - - if ( this.faceVertexUvs[ i ] === undefined ) { - - this.faceVertexUvs[ i ] = []; - - } - - for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { - - var uvs = faceVertexUvs[ j ], uvsCopy = []; - - for ( k = 0, kl = uvs.length; k < kl; k ++ ) { - - var uv = uvs[ k ]; - - uvsCopy.push( uv.clone() ); - - } - - this.faceVertexUvs[ i ].push( uvsCopy ); - - } - - } - - // morph targets - - var morphTargets = source.morphTargets; - - for ( i = 0, il = morphTargets.length; i < il; i ++ ) { - - var morphTarget = {}; - morphTarget.name = morphTargets[ i ].name; - - // vertices - - if ( morphTargets[ i ].vertices !== undefined ) { - - morphTarget.vertices = []; - - for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { - - morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); - - } - - } - - // normals - - if ( morphTargets[ i ].normals !== undefined ) { - - morphTarget.normals = []; - - for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { - - morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); - - } - - } - - this.morphTargets.push( morphTarget ); - - } - - // morph normals - - var morphNormals = source.morphNormals; - - for ( i = 0, il = morphNormals.length; i < il; i ++ ) { - - var morphNormal = {}; - - // vertex normals - - if ( morphNormals[ i ].vertexNormals !== undefined ) { - - morphNormal.vertexNormals = []; - - for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { - - var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; - var destVertexNormal = {}; - - destVertexNormal.a = srcVertexNormal.a.clone(); - destVertexNormal.b = srcVertexNormal.b.clone(); - destVertexNormal.c = srcVertexNormal.c.clone(); - - morphNormal.vertexNormals.push( destVertexNormal ); - - } - - } - - // face normals - - if ( morphNormals[ i ].faceNormals !== undefined ) { - - morphNormal.faceNormals = []; - - for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { - - morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); - - } - - } - - this.morphNormals.push( morphNormal ); - - } - - // skin weights - - var skinWeights = source.skinWeights; - - for ( i = 0, il = skinWeights.length; i < il; i ++ ) { - - this.skinWeights.push( skinWeights[ i ].clone() ); - - } - - // skin indices - - var skinIndices = source.skinIndices; - - for ( i = 0, il = skinIndices.length; i < il; i ++ ) { - - this.skinIndices.push( skinIndices[ i ].clone() ); - - } - - // line distances - - var lineDistances = source.lineDistances; - - for ( i = 0, il = lineDistances.length; i < il; i ++ ) { - - this.lineDistances.push( lineDistances[ i ] ); - - } - - // bounding box - - var boundingBox = source.boundingBox; - - if ( boundingBox !== null ) { - - this.boundingBox = boundingBox.clone(); - - } - - // bounding sphere - - var boundingSphere = source.boundingSphere; - - if ( boundingSphere !== null ) { - - this.boundingSphere = boundingSphere.clone(); - - } - - // update flags - - this.elementsNeedUpdate = source.elementsNeedUpdate; - this.verticesNeedUpdate = source.verticesNeedUpdate; - this.uvsNeedUpdate = source.uvsNeedUpdate; - this.normalsNeedUpdate = source.normalsNeedUpdate; - this.colorsNeedUpdate = source.colorsNeedUpdate; - this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate; - this.groupsNeedUpdate = source.groupsNeedUpdate; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function BufferAttribute( array, itemSize, normalized ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.uuid = _Math.generateUUID(); - this.name = ''; - - this.array = array; - this.itemSize = itemSize; - this.count = array !== undefined ? array.length / itemSize : 0; - this.normalized = normalized === true; - - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; - - this.onUploadCallback = function () {}; - - this.version = 0; - -} - -Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { - - set: function ( value ) { - - if ( value === true ) { this.version ++; } - - } - -} ); - -Object.assign( BufferAttribute.prototype, { - - isBufferAttribute: true, - - setArray: function ( array ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.count = array !== undefined ? array.length / this.itemSize : 0; - this.array = array; - - }, - - setDynamic: function ( value ) { - - this.dynamic = value; - - return this; - - }, - - copy: function ( source ) { - - this.array = new source.array.constructor( source.array ); - this.itemSize = source.itemSize; - this.count = source.count; - this.normalized = source.normalized; - - this.dynamic = source.dynamic; - - return this; - - }, - - copyAt: function ( index1, attribute, index2 ) { - - index1 *= this.itemSize; - index2 *= attribute.itemSize; - - for ( var i = 0, l = this.itemSize; i < l; i ++ ) { - - this.array[ index1 + i ] = attribute.array[ index2 + i ]; - - } - - return this; - - }, - - copyArray: function ( array ) { - - this.array.set( array ); - - return this; - - }, - - copyColorsArray: function ( colors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = colors.length; i < l; i ++ ) { - - var color = colors[ i ]; - - if ( color === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); - color = new Color(); - - } - - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; - - } - - return this; - - }, - - copyIndicesArray: function ( indices ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = indices.length; i < l; i ++ ) { - - var index = indices[ i ]; - - array[ offset ++ ] = index.a; - array[ offset ++ ] = index.b; - array[ offset ++ ] = index.c; - - } - - return this; - - }, - - copyVector2sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); - vector = new Vector2(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - - } - - return this; - - }, - - copyVector3sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); - vector = new Vector3(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - - } - - return this; - - }, - - copyVector4sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); - vector = new Vector4(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; - - } - - return this; - - }, - - set: function ( value, offset ) { - - if ( offset === undefined ) { offset = 0; } - - this.array.set( value, offset ); - - return this; - - }, - - getX: function ( index ) { - - return this.array[ index * this.itemSize ]; - - }, - - setX: function ( index, x ) { - - this.array[ index * this.itemSize ] = x; - - return this; - - }, - - getY: function ( index ) { - - return this.array[ index * this.itemSize + 1 ]; - - }, - - setY: function ( index, y ) { - - this.array[ index * this.itemSize + 1 ] = y; - - return this; - - }, - - getZ: function ( index ) { - - return this.array[ index * this.itemSize + 2 ]; - - }, - - setZ: function ( index, z ) { - - this.array[ index * this.itemSize + 2 ] = z; - - return this; - - }, - - getW: function ( index ) { - - return this.array[ index * this.itemSize + 3 ]; - - }, - - setW: function ( index, w ) { - - this.array[ index * this.itemSize + 3 ] = w; - - return this; - - }, - - setXY: function ( index, x, y ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - - return this; - - }, - - setXYZ: function ( index, x, y, z ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - - return this; - - }, - - setXYZW: function ( index, x, y, z, w ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - this.array[ index + 3 ] = w; - - return this; - - }, - - onUpload: function ( callback ) { - - this.onUploadCallback = callback; - - return this; - - }, - - clone: function () { - - return new this.constructor( this.array, this.itemSize ).copy( this ); - - } - -} ); - -// - -function Int8BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized ); - -} - -Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; - - -function Uint8BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized ); - -} - -Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; - - -function Uint8ClampedBufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized ); - -} - -Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; - - -function Int16BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized ); - -} - -Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; - - -function Uint16BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); - -} - -Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; - - -function Int32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized ); - -} - -Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; - - -function Uint32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized ); - -} - -Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; - - -function Float32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized ); - -} - -Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; - - -function Float64BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized ); - -} - -Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function DirectGeometry() { - - this.indices = []; - this.vertices = []; - this.normals = []; - this.colors = []; - this.uvs = []; - this.uvs2 = []; - - this.groups = []; - - this.morphTargets = {}; - - this.skinWeights = []; - this.skinIndices = []; - - // this.lineDistances = []; - - this.boundingBox = null; - this.boundingSphere = null; - - // update flags - - this.verticesNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.uvsNeedUpdate = false; - this.groupsNeedUpdate = false; - -} - -Object.assign( DirectGeometry.prototype, { - - computeGroups: function ( geometry ) { - - var group; - var groups = []; - var materialIndex = undefined; - - var faces = geometry.faces; - - for ( var i = 0; i < faces.length; i ++ ) { - - var face = faces[ i ]; - - // materials - - if ( face.materialIndex !== materialIndex ) { - - materialIndex = face.materialIndex; - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - group = { - start: i * 3, - materialIndex: materialIndex - }; - - } - - } - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - this.groups = groups; - - }, - - fromGeometry: function ( geometry ) { - - var faces = geometry.faces; - var vertices = geometry.vertices; - var faceVertexUvs = geometry.faceVertexUvs; - - var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; - - // morphs - - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; - - var morphTargetsPosition; - - if ( morphTargetsLength > 0 ) { - - morphTargetsPosition = []; - - for ( var i = 0; i < morphTargetsLength; i ++ ) { - - morphTargetsPosition[ i ] = []; - - } - - this.morphTargets.position = morphTargetsPosition; - - } - - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; - - var morphTargetsNormal; - - if ( morphNormalsLength > 0 ) { - - morphTargetsNormal = []; - - for ( var i = 0; i < morphNormalsLength; i ++ ) { - - morphTargetsNormal[ i ] = []; - - } - - this.morphTargets.normal = morphTargetsNormal; - - } - - // skins - - var skinIndices = geometry.skinIndices; - var skinWeights = geometry.skinWeights; - - var hasSkinIndices = skinIndices.length === vertices.length; - var hasSkinWeights = skinWeights.length === vertices.length; - - // - - for ( var i = 0; i < faces.length; i ++ ) { - - var face = faces[ i ]; - - this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); - - } else { - - var normal = face.normal; - - this.normals.push( normal, normal, normal ); - - } - - var vertexColors = face.vertexColors; - - if ( vertexColors.length === 3 ) { - - this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - - } else { - - var color = face.color; - - this.colors.push( color, color, color ); - - } - - if ( hasFaceVertexUv === true ) { - - var vertexUvs = faceVertexUvs[ 0 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); - - this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - if ( hasFaceVertexUv2 === true ) { - - var vertexUvs = faceVertexUvs[ 1 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); - - this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - // morphs - - for ( var j = 0; j < morphTargetsLength; j ++ ) { - - var morphTarget = morphTargets[ j ].vertices; - - morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); - - } - - for ( var j = 0; j < morphNormalsLength; j ++ ) { - - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; - - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); - - } - - // skins - - if ( hasSkinIndices ) { - - this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); - - } - - if ( hasSkinWeights ) { - - this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); - - } - - } - - this.computeGroups( geometry ); - - this.verticesNeedUpdate = geometry.verticesNeedUpdate; - this.normalsNeedUpdate = geometry.normalsNeedUpdate; - this.colorsNeedUpdate = geometry.colorsNeedUpdate; - this.uvsNeedUpdate = geometry.uvsNeedUpdate; - this.groupsNeedUpdate = geometry.groupsNeedUpdate; - - return this; - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function arrayMax( array ) { - - if ( array.length === 0 ) { return - Infinity; } - - var max = array[ 0 ]; - - for ( var i = 1, l = array.length; i < l; ++ i ) { - - if ( array[ i ] > max ) { max = array[ i ]; } - - } - - return max; - -} - -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - -var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id - -function BufferGeometry() { - - Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'BufferGeometry'; - - this.index = null; - this.attributes = {}; - - this.morphAttributes = {}; - - this.groups = []; - - this.boundingBox = null; - this.boundingSphere = null; - - this.drawRange = { start: 0, count: Infinity }; - -} - -BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: BufferGeometry, - - isBufferGeometry: true, - - getIndex: function () { - - return this.index; - - }, - - setIndex: function ( index ) { - - if ( Array.isArray( index ) ) { - - this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - - } else { - - this.index = index; - - } - - }, - - addAttribute: function ( name, attribute ) { - - if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { - - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); - - this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); - - return; - - } - - if ( name === 'index' ) { - - console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); - this.setIndex( attribute ); - - return; - - } - - this.attributes[ name ] = attribute; - - return this; - - }, - - getAttribute: function ( name ) { - - return this.attributes[ name ]; - - }, - - removeAttribute: function ( name ) { - - delete this.attributes[ name ]; - - return this; - - }, - - addGroup: function ( start, count, materialIndex ) { - - this.groups.push( { - - start: start, - count: count, - materialIndex: materialIndex !== undefined ? materialIndex : 0 - - } ); - - }, - - clearGroups: function () { - - this.groups = []; - - }, - - setDrawRange: function ( start, count ) { - - this.drawRange.start = start; - this.drawRange.count = count; - - }, - - applyMatrix: function ( matrix ) { - - var position = this.attributes.position; - - if ( position !== undefined ) { - - matrix.applyToBufferAttribute( position ); - position.needsUpdate = true; - - } - - var normal = this.attributes.normal; - - if ( normal !== undefined ) { - - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - normalMatrix.applyToBufferAttribute( normal ); - normal.needsUpdate = true; - - } - - if ( this.boundingBox !== null ) { - - this.computeBoundingBox(); - - } - - if ( this.boundingSphere !== null ) { - - this.computeBoundingSphere(); - - } - - return this; - - }, - - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); - - return function rotateX( angle ) { - - m1.makeRotationX( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateY: function () { - - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateZ: function () { - - // rotate geometry around world z-axis - - var m1 = new Matrix4(); - - return function rotateZ( angle ) { - - m1.makeRotationZ( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - translate: function () { - - // translate geometry - - var m1 = new Matrix4(); - - return function translate( x, y, z ) { - - m1.makeTranslation( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - scale: function () { - - // scale geometry - - var m1 = new Matrix4(); - - return function scale( x, y, z ) { - - m1.makeScale( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - lookAt: function () { - - var obj = new Object3D(); - - return function lookAt( vector ) { - - obj.lookAt( vector ); - - obj.updateMatrix(); - - this.applyMatrix( obj.matrix ); - - }; - - }(), - - center: function () { - - this.computeBoundingBox(); - - var offset = this.boundingBox.getCenter().negate(); - - this.translate( offset.x, offset.y, offset.z ); - - return offset; - - }, - - setFromObject: function ( object ) { - - // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); - - var geometry = object.geometry; - - if ( object.isPoints || object.isLine ) { - - var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); - var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); - - this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); - this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); - - if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { - - var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); - - this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); - - } - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - } else if ( object.isMesh ) { - - if ( geometry && geometry.isGeometry ) { - - this.fromGeometry( geometry ); - - } - - } - - return this; - - }, - - setFromPoints: function ( points ) { - - var position = []; - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - position.push( point.x, point.y, point.z || 0 ); - - } - - this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - - return this; - - }, - - updateFromObject: function ( object ) { - - var geometry = object.geometry; - - if ( object.isMesh ) { - - var direct = geometry.__directGeometry; - - if ( geometry.elementsNeedUpdate === true ) { - - direct = undefined; - geometry.elementsNeedUpdate = false; - - } - - if ( direct === undefined ) { - - return this.fromGeometry( geometry ); - - } - - direct.verticesNeedUpdate = geometry.verticesNeedUpdate; - direct.normalsNeedUpdate = geometry.normalsNeedUpdate; - direct.colorsNeedUpdate = geometry.colorsNeedUpdate; - direct.uvsNeedUpdate = geometry.uvsNeedUpdate; - direct.groupsNeedUpdate = geometry.groupsNeedUpdate; - - geometry.verticesNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.groupsNeedUpdate = false; - - geometry = direct; - - } - - var attribute; - - if ( geometry.verticesNeedUpdate === true ) { - - attribute = this.attributes.position; - - if ( attribute !== undefined ) { - - attribute.copyVector3sArray( geometry.vertices ); - attribute.needsUpdate = true; - - } - - geometry.verticesNeedUpdate = false; - - } - - if ( geometry.normalsNeedUpdate === true ) { - - attribute = this.attributes.normal; - - if ( attribute !== undefined ) { - - attribute.copyVector3sArray( geometry.normals ); - attribute.needsUpdate = true; - - } - - geometry.normalsNeedUpdate = false; - - } - - if ( geometry.colorsNeedUpdate === true ) { - - attribute = this.attributes.color; - - if ( attribute !== undefined ) { - - attribute.copyColorsArray( geometry.colors ); - attribute.needsUpdate = true; - - } - - geometry.colorsNeedUpdate = false; - - } - - if ( geometry.uvsNeedUpdate ) { - - attribute = this.attributes.uv; - - if ( attribute !== undefined ) { - - attribute.copyVector2sArray( geometry.uvs ); - attribute.needsUpdate = true; - - } - - geometry.uvsNeedUpdate = false; - - } - - if ( geometry.lineDistancesNeedUpdate ) { - - attribute = this.attributes.lineDistance; - - if ( attribute !== undefined ) { - - attribute.copyArray( geometry.lineDistances ); - attribute.needsUpdate = true; - - } - - geometry.lineDistancesNeedUpdate = false; - - } - - if ( geometry.groupsNeedUpdate ) { - - geometry.computeGroups( object.geometry ); - this.groups = geometry.groups; - - geometry.groupsNeedUpdate = false; - - } - - return this; - - }, - - fromGeometry: function ( geometry ) { - - geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); - - return this.fromDirectGeometry( geometry.__directGeometry ); - - }, - - fromDirectGeometry: function ( geometry ) { - - var positions = new Float32Array( geometry.vertices.length * 3 ); - this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); - - if ( geometry.normals.length > 0 ) { - - var normals = new Float32Array( geometry.normals.length * 3 ); - this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); - - } - - if ( geometry.colors.length > 0 ) { - - var colors = new Float32Array( geometry.colors.length * 3 ); - this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); - - } - - if ( geometry.uvs.length > 0 ) { - - var uvs = new Float32Array( geometry.uvs.length * 2 ); - this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); - - } - - if ( geometry.uvs2.length > 0 ) { - - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); - - } - - if ( geometry.indices.length > 0 ) { - - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); - - } - - // groups - - this.groups = geometry.groups; - - // morphs - - for ( var name in geometry.morphTargets ) { - - var array = []; - var morphTargets = geometry.morphTargets[ name ]; - - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { - - var morphTarget = morphTargets[ i ]; - - var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); - - array.push( attribute.copyVector3sArray( morphTarget ) ); - - } - - this.morphAttributes[ name ] = array; - - } - - // skinning - - if ( geometry.skinIndices.length > 0 ) { - - var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); - - } - - if ( geometry.skinWeights.length > 0 ) { - - var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); - - } - - // - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - return this; - - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } - - var position = this.attributes.position; - - if ( position !== undefined ) { - - this.boundingBox.setFromBufferAttribute( position ); - - } 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: function () { - - var box = new Box3(); - var vector = new Vector3(); - - return function computeBoundingSphere() { - - if ( this.boundingSphere === null ) { - - this.boundingSphere = new Sphere(); - - } - - var position = this.attributes.position; - - if ( position ) { - - var center = this.boundingSphere.center; - - box.setFromBufferAttribute( position ); - box.getCenter( center ); - - // hoping to find a boundingSphere with a radius smaller than the - // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - - var maxRadiusSq = 0; - - for ( var i = 0, il = position.count; i < il; i ++ ) { - - vector.x = position.getX( i ); - vector.y = position.getY( i ); - vector.z = position.getZ( i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); - - } - - 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 ); - - } - - } - - }; - - }(), - - computeFaceNormals: function () { - - // backwards compatibility - - }, - - computeVertexNormals: function () { - - var index = this.index; - var attributes = this.attributes; - var groups = this.groups; - - if ( attributes.position ) { - - var positions = attributes.position.array; - - if ( attributes.normal === undefined ) { - - this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); - - } else { - - // reset existing normals to zero - - var array = attributes.normal.array; - - for ( var i = 0, il = array.length; i < il; i ++ ) { - - array[ i ] = 0; - - } - - } - - var normals = attributes.normal.array; - - var vA, vB, vC; - var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); - var cb = new Vector3(), ab = new Vector3(); - - // indexed elements - - if ( index ) { - - var indices = index.array; - - if ( groups.length === 0 ) { - - this.addGroup( 0, indices.length ); - - } - - for ( var j = 0, jl = groups.length; j < jl; ++ j ) { - - var group = groups[ j ]; - - var start = group.start; - var count = group.count; - - for ( var i = start, il = start + count; i < il; i += 3 ) { - - vA = indices[ i + 0 ] * 3; - vB = indices[ i + 1 ] * 3; - vC = indices[ i + 2 ] * 3; - - pA.fromArray( positions, vA ); - pB.fromArray( positions, vB ); - pC.fromArray( positions, vC ); - - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); - - normals[ vA ] += cb.x; - normals[ vA + 1 ] += cb.y; - normals[ vA + 2 ] += cb.z; - - normals[ vB ] += cb.x; - normals[ vB + 1 ] += cb.y; - normals[ vB + 2 ] += cb.z; - - normals[ vC ] += cb.x; - normals[ vC + 1 ] += cb.y; - normals[ vC + 2 ] += cb.z; - - } - - } - - } else { - - // non-indexed elements (unconnected triangle soup) - - for ( var i = 0, il = positions.length; i < il; i += 9 ) { - - pA.fromArray( positions, i ); - pB.fromArray( positions, i + 3 ); - pC.fromArray( positions, i + 6 ); - - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); - - normals[ i ] = cb.x; - normals[ i + 1 ] = cb.y; - normals[ i + 2 ] = cb.z; - - normals[ i + 3 ] = cb.x; - normals[ i + 4 ] = cb.y; - normals[ i + 5 ] = cb.z; - - normals[ i + 6 ] = cb.x; - normals[ i + 7 ] = cb.y; - normals[ i + 8 ] = cb.z; - - } - - } - - this.normalizeNormals(); - - attributes.normal.needsUpdate = true; - - } - - }, - - merge: function ( geometry, offset ) { - - if ( ! ( geometry && geometry.isBufferGeometry ) ) { - - console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); - return; - - } - - if ( offset === undefined ) { offset = 0; } - - var attributes = this.attributes; - - for ( var key in attributes ) { - - if ( geometry.attributes[ key ] === undefined ) { continue; } - - var attribute1 = attributes[ key ]; - var attributeArray1 = attribute1.array; - - var attribute2 = geometry.attributes[ key ]; - var attributeArray2 = attribute2.array; - - var attributeSize = attribute2.itemSize; - - for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { - - attributeArray1[ j ] = attributeArray2[ i ]; - - } - - } - - return this; - - }, - - normalizeNormals: function () { - - var vector = new Vector3(); - - return function normalizeNormals() { - - var normals = this.attributes.normal; - - for ( var i = 0, il = normals.count; i < il; i ++ ) { - - vector.x = normals.getX( i ); - vector.y = normals.getY( i ); - vector.z = normals.getZ( i ); - - vector.normalize(); - - normals.setXYZ( i, vector.x, vector.y, vector.z ); - - } - - }; - - }(), - - toNonIndexed: function () { - - if ( this.index === null ) { - - console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); - return this; - - } - - var geometry2 = new BufferGeometry(); - - var indices = this.index.array; - var attributes = this.attributes; - - for ( var name in attributes ) { - - var attribute = attributes[ name ]; - - var array = attribute.array; - var itemSize = attribute.itemSize; - - var array2 = new array.constructor( indices.length * itemSize ); - - var index = 0, index2 = 0; - - for ( var i = 0, l = indices.length; i < l; i ++ ) { - - index = indices[ i ] * itemSize; - - for ( var j = 0; j < itemSize; j ++ ) { - - array2[ index2 ++ ] = array[ index ++ ]; - - } - - } - - geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); - - } - - return geometry2; - - }, - - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'BufferGeometry', - generator: 'BufferGeometry.toJSON' - } - }; - - // standard BufferGeometry serialization - - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) { data.name = this.name; } - - if ( this.parameters !== undefined ) { - - var parameters = this.parameters; - - for ( var key in parameters ) { - - if ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; } - - } - - return data; - - } - - data.data = { attributes: {} }; - - var index = this.index; - - if ( index !== null ) { - - var array = Array.prototype.slice.call( index.array ); - - data.data.index = { - type: index.array.constructor.name, - array: array - }; - - } - - var attributes = this.attributes; - - for ( var key in attributes ) { - - var attribute = attributes[ key ]; - - var array = Array.prototype.slice.call( attribute.array ); - - data.data.attributes[ key ] = { - itemSize: attribute.itemSize, - type: attribute.array.constructor.name, - array: array, - normalized: attribute.normalized - }; - - } - - var groups = this.groups; - - if ( groups.length > 0 ) { - - data.data.groups = JSON.parse( JSON.stringify( groups ) ); - - } - - var boundingSphere = this.boundingSphere; - - if ( boundingSphere !== null ) { - - data.data.boundingSphere = { - center: boundingSphere.center.toArray(), - radius: boundingSphere.radius - }; - - } - - return data; - - }, - - clone: function () { - - /* - // Handle primitives - - var parameters = this.parameters; - - if ( parameters !== undefined ) { - - var values = []; - - for ( var key in parameters ) { - - values.push( parameters[ key ] ); - - } - - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; - - } - - return new this.constructor().copy( this ); - */ - - return new BufferGeometry().copy( this ); - - }, - - copy: function ( source ) { - - var name, i, l; - - // reset - - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; - - // name - - this.name = source.name; - - // index - - var index = source.index; - - if ( index !== null ) { - - this.setIndex( index.clone() ); - - } - - // attributes - - var attributes = source.attributes; - - for ( name in attributes ) { - - var attribute = attributes[ name ]; - this.addAttribute( name, attribute.clone() ); - - } - - // morph attributes - - var morphAttributes = source.morphAttributes; - - for ( name in morphAttributes ) { - - var array = []; - var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - - for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { - - array.push( morphAttribute[ i ].clone() ); - - } - - this.morphAttributes[ name ] = array; - - } - - // groups - - var groups = source.groups; - - for ( i = 0, l = groups.length; i < l; i ++ ) { - - var group = groups[ i ]; - this.addGroup( group.start, group.count, group.materialIndex ); - - } - - // bounding box - - var boundingBox = source.boundingBox; - - if ( boundingBox !== null ) { - - this.boundingBox = boundingBox.clone(); - - } - - // bounding sphere - - var boundingSphere = source.boundingSphere; - - if ( boundingSphere !== null ) { - - this.boundingSphere = boundingSphere.clone(); - - } - - // draw range - - this.drawRange.start = source.drawRange.start; - this.drawRange.count = source.drawRange.count; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - -// BoxGeometry - -function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - Geometry.call( this ); - - this.type = 'BoxGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; - - this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); - this.mergeVertices(); - -} - -BoxGeometry.prototype = Object.create( Geometry.prototype ); -BoxGeometry.prototype.constructor = BoxGeometry; - -// BoxBufferGeometry - -function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - BufferGeometry.call( this ); - - this.type = 'BoxBufferGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; - - var scope = this; - - width = width || 1; - height = height || 1; - depth = depth || 1; - - // segments - - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var numberOfVertices = 0; - var groupStart = 0; - - // build each side of the box geometry - - buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px - buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx - buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py - buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny - buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz - buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { - - var segmentWidth = width / gridX; - var segmentHeight = height / gridY; - - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; - - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; - - var vertexCounter = 0; - var groupCount = 0; - - var ix, iy; - - var vector = new Vector3(); - - // generate vertices, normals and uvs - - for ( iy = 0; iy < gridY1; iy ++ ) { - - var y = iy * segmentHeight - heightHalf; - - for ( ix = 0; ix < gridX1; ix ++ ) { - - var x = ix * segmentWidth - widthHalf; - - // set values to correct vector component - - vector[ u ] = x * udir; - vector[ v ] = y * vdir; - vector[ w ] = depthHalf; - - // now apply vector to vertex buffer - - vertices.push( vector.x, vector.y, vector.z ); - - // set values to correct vector component - - vector[ u ] = 0; - vector[ v ] = 0; - vector[ w ] = depth > 0 ? 1 : - 1; - - // now apply vector to normal buffer - - normals.push( vector.x, vector.y, vector.z ); - - // uvs - - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); - - // counters - - vertexCounter += 1; - - } - - } - - // indices - - // 1. you need three indices to draw a single face - // 2. a single segment consists of two faces - // 3. so we need to generate six (2*3) indices per segment - - for ( iy = 0; iy < gridY; iy ++ ) { - - for ( ix = 0; ix < gridX; ix ++ ) { - - var a = numberOfVertices + ix + gridX1 * iy; - var b = numberOfVertices + ix + gridX1 * ( iy + 1 ); - var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - // increase counter - - groupCount += 6; - - } - - } - - // add a group to the geometry. this will ensure multi material support - - scope.addGroup( groupStart, groupCount, materialIndex ); - - // calculate new start value for groups - - groupStart += groupCount; - - // update total number of vertices - - numberOfVertices += vertexCounter; - - } - -} - -BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; - -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - -// PlaneGeometry - -function PlaneGeometry( width, height, widthSegments, heightSegments ) { - - Geometry.call( this ); - - this.type = 'PlaneGeometry'; - - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; - - this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); - this.mergeVertices(); - -} - -PlaneGeometry.prototype = Object.create( Geometry.prototype ); -PlaneGeometry.prototype.constructor = PlaneGeometry; - -// PlaneBufferGeometry - -function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { - - BufferGeometry.call( this ); - - this.type = 'PlaneBufferGeometry'; - - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; - - width = width || 1; - height = height || 1; - - var width_half = width / 2; - var height_half = height / 2; - - var gridX = Math.floor( widthSegments ) || 1; - var gridY = Math.floor( heightSegments ) || 1; - - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; - - var segment_width = width / gridX; - var segment_height = height / gridY; - - var ix, iy; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // generate vertices, normals and uvs - - for ( iy = 0; iy < gridY1; iy ++ ) { - - var y = iy * segment_height - height_half; - - for ( ix = 0; ix < gridX1; ix ++ ) { - - var x = ix * segment_width - width_half; - - vertices.push( x, - y, 0 ); - - normals.push( 0, 0, 1 ); - - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); - - } - - } - - // indices - - for ( iy = 0; iy < gridY; iy ++ ) { - - for ( ix = 0; ix < gridX; ix ++ ) { - - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - -} - -PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * depthTest: , - * depthWrite: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: - * } - */ - -function MeshBasicMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshBasicMaterial'; - - this.color = new Color( 0xffffff ); // emissive - - this.map = null; - - this.lightMap = null; - this.lightMapIntensity = 1.0; - - this.aoMap = null; - this.aoMapIntensity = 1.0; - - 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.skinning = false; - this.morphTargets = false; - - this.lights = false; - - this.setValues( parameters ); - -} - -MeshBasicMaterial.prototype = Object.create( Material.prototype ); -MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; - -MeshBasicMaterial.prototype.isMeshBasicMaterial = true; - -MeshBasicMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, 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.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - return this; - -}; - -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * defines: { "label" : "value" }, - * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } }, - * - * fragmentShader: , - * vertexShader: , - * - * wireframe: , - * wireframeLinewidth: , - * - * lights: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ - -function ShaderMaterial( parameters ) { - - Material.call( this ); - - this.type = 'ShaderMaterial'; - - this.defines = {}; - this.uniforms = {}; - - this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'; - this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'; - - this.linewidth = 1; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; // set to use scene fog - this.lights = false; // set to use scene lights - this.clipping = false; // set to use user-defined clipping planes - - this.skinning = false; // set to use skinning attribute streams - this.morphTargets = false; // set to use morph targets - this.morphNormals = false; // set to use morph normals - - this.extensions = { - derivatives: false, // set to use derivatives - fragDepth: false, // set to use fragment depth values - drawBuffers: false, // set to use draw buffers - shaderTextureLOD: false // set to use shader texture LOD - }; - - // When rendered geometry doesn't include these attributes but the material does, - // use these default values in WebGL. This avoids errors when buffer data is missing. - this.defaultAttributeValues = { - 'color': [ 1, 1, 1 ], - 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] - }; - - this.index0AttributeName = undefined; - - if ( parameters !== undefined ) { - - if ( parameters.attributes !== undefined ) { - - console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); - - } - - this.setValues( parameters ); - - } - -} - -ShaderMaterial.prototype = Object.create( Material.prototype ); -ShaderMaterial.prototype.constructor = ShaderMaterial; - -ShaderMaterial.prototype.isShaderMaterial = true; - -ShaderMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.fragmentShader = source.fragmentShader; - this.vertexShader = source.vertexShader; - - this.uniforms = UniformsUtils.clone( source.uniforms ); - - this.defines = source.defines; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - - this.lights = source.lights; - this.clipping = source.clipping; - - this.skinning = source.skinning; - - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - this.extensions = source.extensions; - - return this; - -}; - -ShaderMaterial.prototype.toJSON = function ( meta ) { - - var data = Material.prototype.toJSON.call( this, meta ); - - data.uniforms = this.uniforms; - data.vertexShader = this.vertexShader; - data.fragmentShader = this.fragmentShader; - - return data; - -}; - -/** - * @author bhouston / http://clara.io - */ - -function Ray( origin, direction ) { - - this.origin = ( origin !== undefined ) ? origin : new Vector3(); - this.direction = ( direction !== undefined ) ? direction : new Vector3(); - -} - -Object.assign( Ray.prototype, { - - set: function ( origin, direction ) { - - this.origin.copy( origin ); - this.direction.copy( direction ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( ray ) { - - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); - - return this; - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - - }, - - lookAt: function ( v ) { - - this.direction.copy( v ).sub( this.origin ).normalize(); - - return this; - - }, - - recast: function () { - - var v1 = new Vector3(); - - return function recast( t ) { - - this.origin.copy( this.at( t, v1 ) ); - - return this; - - }; - - }(), - - closestPointToPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - result.subVectors( point, this.origin ); - var directionDistance = result.dot( this.direction ); - - if ( directionDistance < 0 ) { - - return result.copy( this.origin ); - - } - - return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - }, - - distanceToPoint: function ( point ) { - - return Math.sqrt( this.distanceSqToPoint( point ) ); - - }, - - distanceSqToPoint: function () { - - var v1 = new Vector3(); - - return function distanceSqToPoint( point ) { - - var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); - - // point behind the ray - - if ( directionDistance < 0 ) { - - return this.origin.distanceToSquared( point ); - - } - - v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - return v1.distanceToSquared( point ); - - }; - - }(), - - distanceSqToSegment: function () { - - var segCenter = new Vector3(); - var segDir = new Vector3(); - var diff = new Vector3(); - - return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h - // It returns the min distance between the ray and the segment - // defined by v0 and v1 - // It can also set two optional targets : - // - The closest point on the ray - // - The closest point on the segment - - segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - segDir.copy( v1 ).sub( v0 ).normalize(); - diff.copy( this.origin ).sub( segCenter ); - - var segExtent = v0.distanceTo( v1 ) * 0.5; - var a01 = - this.direction.dot( segDir ); - var b0 = diff.dot( this.direction ); - var b1 = - diff.dot( segDir ); - var c = diff.lengthSq(); - var det = Math.abs( 1 - a01 * a01 ); - var s0, s1, sqrDist, extDet; - - if ( det > 0 ) { - - // The ray and segment are not parallel. - - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; - - if ( s0 >= 0 ) { - - if ( s1 >= - extDet ) { - - if ( s1 <= extDet ) { - - // region 0 - // Minimum at interior points of ray and segment. - - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - - } else { - - // region 1 - - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } else { - - // region 5 - - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } else { - - if ( s1 <= - extDet ) { - - // region 4 - - 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 ) + c; - - } else if ( s1 <= extDet ) { - - // region 3 - - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; - - } else { - - // region 2 - - 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 ) + c; - - } - - } - - } else { - - // Ray and segment are parallel. - - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - if ( optionalPointOnRay ) { - - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); - - } - - if ( optionalPointOnSegment ) { - - optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); - - } - - return sqrDist; - - }; - - }(), - - intersectSphere: function () { - - var v1 = new Vector3(); - - return function intersectSphere( sphere, optionalTarget ) { - - v1.subVectors( sphere.center, this.origin ); - var tca = v1.dot( this.direction ); - var d2 = v1.dot( v1 ) - tca * tca; - var radius2 = sphere.radius * sphere.radius; - - if ( d2 > radius2 ) { return null; } - - var thc = Math.sqrt( radius2 - d2 ); - - // t0 = first intersect point - entrance on front of sphere - var t0 = tca - thc; - - // t1 = second intersect point - exit point on back of sphere - var t1 = tca + thc; - - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) { return null; } - - // test to see if t0 is behind the ray: - // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, - // in order to always return an intersect point that is in front of the ray. - if ( t0 < 0 ) { return this.at( t1, optionalTarget ); } - - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, optionalTarget ); - - }; - - }(), - - intersectsSphere: function ( sphere ) { - - return this.distanceToPoint( sphere.center ) <= sphere.radius; - - }, - - distanceToPlane: function ( plane ) { - - var denominator = plane.normal.dot( this.direction ); - - if ( denominator === 0 ) { - - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { - - return 0; - - } - - // Null is preferable to undefined since undefined means.... it is undefined - - return null; - - } - - var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - - // Return if the ray never intersects the plane - - return t >= 0 ? t : null; - - }, - - intersectPlane: function ( plane, optionalTarget ) { - - var t = this.distanceToPlane( plane ); - - if ( t === null ) { - - return null; - - } - - return this.at( t, optionalTarget ); - - }, - - intersectsPlane: function ( plane ) { - - // check if the ray lies on the plane first - - var distToPoint = plane.distanceToPoint( this.origin ); - - if ( distToPoint === 0 ) { - - return true; - - } - - var denominator = plane.normal.dot( this.direction ); - - if ( denominator * distToPoint < 0 ) { - - return true; - - } - - // ray origin is behind the plane (and is pointing behind it) - - return false; - - }, - - intersectBox: function ( box, optionalTarget ) { - - var tmin, tmax, tymin, tymax, tzmin, tzmax; - - var invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; - - var 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; } - - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN - - 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; } - - //return point closest to the ray (positive side) - - if ( tmax < 0 ) { return null; } - - return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); - - }, - - intersectsBox: ( function () { - - var v = new Vector3(); - - return function intersectsBox( box ) { - - return this.intersectBox( box, v ) !== null; - - }; - - } )(), - - intersectTriangle: function () { - - // Compute the offset origin, edges, and normal. - var diff = new Vector3(); - var edge1 = new Vector3(); - var edge2 = new Vector3(); - var normal = new Vector3(); - - return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { - - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - - edge1.subVectors( b, a ); - edge2.subVectors( c, a ); - normal.crossVectors( edge1, edge2 ); - - // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, - // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by - // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) - // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) - // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) - var DdN = this.direction.dot( normal ); - var 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, a ); - var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); - - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { - - return null; - - } - - var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); - - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { - - return null; - - } - - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { - - return null; - - } - - // Line intersects triangle, check if ray does. - var QdN = - sign * diff.dot( normal ); - - // t < 0, no intersection - if ( QdN < 0 ) { - - return null; - - } - - // Ray intersects triangle. - return this.at( QdN / DdN, optionalTarget ); - - }; - - }(), - - applyMatrix4: function ( matrix4 ) { - - this.origin.applyMatrix4( matrix4 ); - this.direction.transformDirection( matrix4 ); - - return this; - - }, - - equals: function ( ray ) { - - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - */ - -function Line3( start, end ) { - - this.start = ( start !== undefined ) ? start : new Vector3(); - this.end = ( end !== undefined ) ? end : new Vector3(); - -} - -Object.assign( Line3.prototype, { - - set: function ( start, end ) { - - this.start.copy( start ); - this.end.copy( end ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( line ) { - - this.start.copy( line.start ); - this.end.copy( line.end ); - - return this; - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); - - }, - - delta: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.subVectors( this.end, this.start ); - - }, - - distanceSq: function () { - - return this.start.distanceToSquared( this.end ); - - }, - - distance: function () { - - return this.start.distanceTo( this.end ); - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return this.delta( result ).multiplyScalar( t ).add( this.start ); - - }, - - closestPointToPointParameter: function () { - - var startP = new Vector3(); - var startEnd = new Vector3(); - - return function closestPointToPointParameter( point, clampToLine ) { - - startP.subVectors( point, this.start ); - startEnd.subVectors( this.end, this.start ); - - var startEnd2 = startEnd.dot( startEnd ); - var startEnd_startP = startEnd.dot( startP ); - - var t = startEnd_startP / startEnd2; - - if ( clampToLine ) { - - t = _Math.clamp( t, 0, 1 ); - - } - - return t; - - }; - - }(), - - closestPointToPoint: function ( point, clampToLine, optionalTarget ) { - - var t = this.closestPointToPointParameter( point, clampToLine ); - - var result = optionalTarget || new Vector3(); - - return this.delta( result ).multiplyScalar( t ).add( this.start ); - - }, - - applyMatrix4: function ( matrix ) { - - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); - - return this; - - }, - - equals: function ( line ) { - - return line.start.equals( this.start ) && line.end.equals( this.end ); - - } - -} ); - -/** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ - -function Triangle( a, b, c ) { - - this.a = ( a !== undefined ) ? a : new Vector3(); - this.b = ( b !== undefined ) ? b : new Vector3(); - this.c = ( c !== undefined ) ? c : new Vector3(); - -} - -Object.assign( Triangle, { - - normal: function () { - - var v0 = new Vector3(); - - return function normal( a, b, c, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - result.subVectors( c, b ); - v0.subVectors( a, b ); - result.cross( v0 ); - - var resultLengthSq = result.lengthSq(); - if ( resultLengthSq > 0 ) { - - return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); - - } - - return result.set( 0, 0, 0 ); - - }; - - }(), - - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - barycoordFromPoint: function () { - - var v0 = new Vector3(); - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function barycoordFromPoint( point, a, b, c, optionalTarget ) { - - v0.subVectors( c, a ); - v1.subVectors( b, a ); - v2.subVectors( point, a ); - - var dot00 = v0.dot( v0 ); - var dot01 = v0.dot( v1 ); - var dot02 = v0.dot( v2 ); - var dot11 = v1.dot( v1 ); - var dot12 = v1.dot( v2 ); - - var denom = ( dot00 * dot11 - dot01 * dot01 ); - - var result = optionalTarget || new Vector3(); - - // collinear or singular triangle - if ( denom === 0 ) { - - // arbitrary location outside of triangle? - // not sure if this is the best idea, maybe should be returning undefined - return result.set( - 2, - 1, - 1 ); - - } - - var invDenom = 1 / denom; - var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - - // barycentric coordinates must always sum to 1 - return result.set( 1 - u - v, v, u ); - - }; - - }(), - - containsPoint: function () { - - var v1 = new Vector3(); - - return function containsPoint( point, a, b, c ) { - - var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); - - return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); - - }; - - }() - -} ); - -Object.assign( Triangle.prototype, { - - set: function ( a, b, c ) { - - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); - - return this; - - }, - - setFromPointsAndIndices: function ( points, i0, i1, i2 ) { - - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( triangle ) { - - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); - - return this; - - }, - - area: function () { - - var v0 = new Vector3(); - var v1 = new Vector3(); - - return function area() { - - v0.subVectors( this.c, this.b ); - v1.subVectors( this.a, this.b ); - - return v0.cross( v1 ).length() * 0.5; - - }; - - }(), - - midpoint: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - - }, - - normal: function ( optionalTarget ) { - - return Triangle.normal( this.a, this.b, this.c, optionalTarget ); - - }, - - plane: function ( optionalTarget ) { - - var result = optionalTarget || new Plane(); - - return result.setFromCoplanarPoints( this.a, this.b, this.c ); - - }, - - barycoordFromPoint: function ( point, optionalTarget ) { - - return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); - - }, - - containsPoint: function ( point ) { - - return Triangle.containsPoint( point, this.a, this.b, this.c ); - - }, - - closestPointToPoint: function () { - - var plane = new Plane(); - var edgeList = [ new Line3(), new Line3(), new Line3() ]; - var projectedPoint = new Vector3(); - var closestPoint = new Vector3(); - - return function closestPointToPoint( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - var minDistance = Infinity; - - // project the point onto the plane of the triangle - - plane.setFromCoplanarPoints( this.a, this.b, this.c ); - plane.projectPoint( point, projectedPoint ); - - // check if the projection lies within the triangle - - if ( this.containsPoint( projectedPoint ) === true ) { - - // if so, this is the closest point - - result.copy( projectedPoint ); - - } else { - - // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices - - edgeList[ 0 ].set( this.a, this.b ); - edgeList[ 1 ].set( this.b, this.c ); - edgeList[ 2 ].set( this.c, this.a ); - - for ( var i = 0; i < edgeList.length; i ++ ) { - - edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); - - var distance = projectedPoint.distanceToSquared( closestPoint ); - - if ( distance < minDistance ) { - - minDistance = distance; - - result.copy( closestPoint ); - - } - - } - - } - - return result; - - }; - - }(), - - equals: function ( triangle ) { - - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author jonobr1 / http://jonobr1.com/ - */ - -function Mesh( geometry, material ) { - - Object3D.call( this ); - - this.type = 'Mesh'; - - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); - - this.drawMode = TrianglesDrawMode; - - this.updateMorphTargets(); - -} - -Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Mesh, - - isMesh: true, - - setDrawMode: function ( value ) { - - this.drawMode = value; - - }, - - copy: function ( source ) { - - Object3D.prototype.copy.call( this, source ); - - this.drawMode = source.drawMode; - - if ( source.morphTargetInfluences !== undefined ) { - - this.morphTargetInfluences = source.morphTargetInfluences.slice(); - - } - - if ( source.morphTargetDictionary !== undefined ) { - - this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); - - } - - return this; - - }, - - updateMorphTargets: function () { - - var geometry = this.geometry; - var m, ml, name; - - if ( geometry.isBufferGeometry ) { - - var morphAttributes = geometry.morphAttributes; - var keys = Object.keys( morphAttributes ); - - if ( keys.length > 0 ) { - - var morphAttribute = morphAttributes[ keys[ 0 ] ]; - - if ( morphAttribute !== undefined ) { - - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - - name = morphAttribute[ m ].name || String( m ); - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; - - } - - } - - } - - } else { - - var morphTargets = geometry.morphTargets; - - if ( morphTargets !== undefined && morphTargets.length > 0 ) { - - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { - - name = morphTargets[ m ].name || String( m ); - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; - - } - - } - - } - - }, - - raycast: ( function () { - - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); - - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); - - var tempA = new Vector3(); - var tempB = new Vector3(); - var tempC = new Vector3(); - - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); - - var barycoord = new Vector3(); - - var intersectionPoint = new Vector3(); - var intersectionPointWorld = new Vector3(); - - function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { - - Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); - - uv1.multiplyScalar( barycoord.x ); - uv2.multiplyScalar( barycoord.y ); - uv3.multiplyScalar( barycoord.z ); - - uv1.add( uv2 ).add( uv3 ); - - return uv1.clone(); - - } - - function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { - - var 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 ); - - var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); - - if ( distance < raycaster.near || distance > raycaster.far ) { return null; } - - return { - distance: distance, - point: intersectionPointWorld.clone(), - object: object - }; - - } - - function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { - - vA.fromBufferAttribute( position, a ); - vB.fromBufferAttribute( position, b ); - vC.fromBufferAttribute( position, c ); - - var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); - - if ( intersection ) { - - if ( uv ) { - - uvA.fromBufferAttribute( uv, a ); - uvB.fromBufferAttribute( uv, b ); - uvC.fromBufferAttribute( uv, c ); - - intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); - - } - - intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); - intersection.faceIndex = a; - - } - - return intersection; - - } - - return function raycast( raycaster, intersects ) { - - var geometry = this.geometry; - var material = this.material; - var matrixWorld = this.matrixWorld; - - if ( material === undefined ) { return; } - - // Checking boundingSphere distance to ray - - if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); } - - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - - if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; } - - // - - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - - // Check boundingBox before continuing - - if ( geometry.boundingBox !== null ) { - - if ( ray.intersectsBox( geometry.boundingBox ) === false ) { return; } - - } - - var intersection; - - if ( geometry.isBufferGeometry ) { - - var a, b, c; - var index = geometry.index; - var position = geometry.attributes.position; - var uv = geometry.attributes.uv; - var i, l; - - if ( index !== null ) { - - // indexed buffer geometry - - for ( i = 0, l = index.count; i < l; i += 3 ) { - - a = index.getX( i ); - b = index.getX( i + 1 ); - c = index.getX( i + 2 ); - - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { - - intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics - intersects.push( intersection ); - - } - - } - - } else if ( position !== undefined ) { - - // non-indexed buffer geometry - - for ( i = 0, l = position.count; i < l; i += 3 ) { - - a = i; - b = i + 1; - c = i + 2; - - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { - - intersection.index = a; // triangle number in positions buffer semantics - intersects.push( intersection ); - - } - - } - - } - - } else if ( geometry.isGeometry ) { - - var fvA, fvB, fvC; - var isMultiMaterial = Array.isArray( material ); - - var vertices = geometry.vertices; - var faces = geometry.faces; - var uvs; - - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - if ( faceVertexUvs.length > 0 ) { uvs = faceVertexUvs; } - - for ( var f = 0, fl = faces.length; f < fl; f ++ ) { - - var face = faces[ f ]; - var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; - - if ( faceMaterial === undefined ) { continue; } - - fvA = vertices[ face.a ]; - fvB = vertices[ face.b ]; - fvC = vertices[ face.c ]; - - if ( faceMaterial.morphTargets === true ) { - - var morphTargets = geometry.morphTargets; - var morphInfluences = this.morphTargetInfluences; - - vA.set( 0, 0, 0 ); - vB.set( 0, 0, 0 ); - vC.set( 0, 0, 0 ); - - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { - - var influence = morphInfluences[ t ]; - - if ( influence === 0 ) { continue; } - - var targets = morphTargets[ t ].vertices; - - vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); - vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); - vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); - - } - - vA.add( fvA ); - vB.add( fvB ); - vC.add( fvC ); - - fvA = vA; - fvB = vB; - fvC = vC; - - } - - intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); - - if ( intersection ) { - - if ( uvs && uvs[ f ] ) { - - var uvs_f = uvs[ f ]; - uvA.copy( uvs_f[ 0 ] ); - uvB.copy( uvs_f[ 1 ] ); - uvC.copy( uvs_f[ 2 ] ); - - intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); - - } - - intersection.face = face; - intersection.faceIndex = f; - intersects.push( intersection ); - - } - - } - - } - - }; - - }() ), - - clone: function () { - - return new this.constructor( this.geometry, this.material ).copy( this ); - - } - -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) { - - var clearColor = new Color( 0x000000 ); - var clearAlpha = 0; - - var planeCamera, planeMesh; - var boxMesh; - - function render( renderList, scene, camera, forceClear ) { - - var background = scene.background; - - 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 ) { - - if ( boxMesh === undefined ) { - - boxMesh = new Mesh( - new BoxBufferGeometry( 1, 1, 1 ), - new ShaderMaterial( { - uniforms: ShaderLib.cube.uniforms, - vertexShader: ShaderLib.cube.vertexShader, - fragmentShader: ShaderLib.cube.fragmentShader, - side: BackSide, - depthTest: true, - depthWrite: false, - fog: false - } ) - ); - - boxMesh.geometry.removeAttribute( 'normal' ); - boxMesh.geometry.removeAttribute( 'uv' ); - - boxMesh.onBeforeRender = function ( renderer, scene, camera ) { - - this.matrixWorld.copyPosition( camera.matrixWorld ); - - }; - - geometries.update( boxMesh.geometry ); - - } - - boxMesh.material.uniforms.tCube.value = background; - - renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); - - } else if ( background && background.isTexture ) { - - if ( planeCamera === undefined ) { - - planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - planeMesh = new Mesh( - new PlaneBufferGeometry( 2, 2 ), - new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) - ); - - geometries.update( planeMesh.geometry ); - - } - - planeMesh.material.map = background; - - // TODO Push this to renderList - - renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); - - } - - } - - function setClear( color, alpha ) { - - state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); - - } - - return { - - getClearColor: function () { - - return clearColor; - - }, - setClearColor: function ( color, alpha ) { - - clearColor.set( color ); - clearAlpha = alpha !== undefined ? alpha : 1; - setClear( clearColor, clearAlpha ); - - }, - getClearAlpha: function () { - - return clearAlpha; - - }, - setClearAlpha: function ( alpha ) { - - clearAlpha = alpha; - setClear( clearColor, clearAlpha ); - - }, - render: render - - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function painterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } else if ( a.program && b.program && a.program !== b.program ) { - - return a.program.id - b.program.id; - - } else if ( a.material.id !== b.material.id ) { - - return a.material.id - b.material.id; - - } else if ( a.z !== b.z ) { - - return a.z - b.z; - - } else { - - return a.id - b.id; - - } - -} - -function reversePainterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } if ( a.z !== b.z ) { - - return b.z - a.z; - - } else { - - return a.id - b.id; - - } - -} - -function WebGLRenderList() { - - var renderItems = []; - var renderItemsIndex = 0; - - var opaque = []; - var transparent = []; - - function init() { - - renderItemsIndex = 0; - - opaque.length = 0; - transparent.length = 0; - - } - - function push( object, geometry, material, z, group ) { - - var renderItem = renderItems[ renderItemsIndex ]; - - if ( renderItem === undefined ) { - - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - program: material.program, - renderOrder: object.renderOrder, - z: z, - group: group - }; - - renderItems[ renderItemsIndex ] = renderItem; - - } else { - - renderItem.id = object.id; - renderItem.object = object; - renderItem.geometry = geometry; - renderItem.material = material; - renderItem.program = material.program; - renderItem.renderOrder = object.renderOrder; - renderItem.z = z; - renderItem.group = group; - - } - - ( material.transparent === true ? transparent : opaque ).push( renderItem ); - - renderItemsIndex ++; - - } - - function sort() { - - if ( opaque.length > 1 ) { opaque.sort( painterSortStable ); } - if ( transparent.length > 1 ) { transparent.sort( reversePainterSortStable ); } - - } - - return { - opaque: opaque, - transparent: transparent, - - init: init, - push: push, - - sort: sort - }; - -} - -function WebGLRenderLists() { - - var lists = {}; - - function get( scene, camera ) { - - var hash = scene.id + ',' + camera.id; - var list = lists[ hash ]; - - if ( list === undefined ) { - - // console.log( 'THREE.WebGLRenderLists:', hash ); - - list = new WebGLRenderList(); - lists[ hash ] = list; - - } - - return list; - - } - - function dispose() { - - lists = {}; - - } - - return { - get: get, - dispose: dispose - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function absNumericalSort( a, b ) { - - return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); - -} - -function WebGLMorphtargets( gl ) { - - var influencesList = {}; - var morphInfluences = new Float32Array( 8 ); - - function update( object, geometry, material, program ) { - - var objectInfluences = object.morphTargetInfluences; - - var length = objectInfluences.length; - - var influences = influencesList[ geometry.id ]; - - if ( influences === undefined ) { - - // initialise list - - influences = []; - - for ( var i = 0; i < length; i ++ ) { - - influences[ i ] = [ i, 0 ]; - - } - - influencesList[ geometry.id ] = influences; - - } - - var morphTargets = material.morphTargets && geometry.morphAttributes.position; - var morphNormals = material.morphNormals && geometry.morphAttributes.normal; - - // Remove current morphAttributes - - for ( var i = 0; i < length; i ++ ) { - - var influence = influences[ i ]; - - if ( influence[ 1 ] !== 0 ) { - - if ( morphTargets ) { geometry.removeAttribute( 'morphTarget' + i ); } - if ( morphNormals ) { geometry.removeAttribute( 'morphNormal' + i ); } - - } - - } - - // Collect influences - - for ( var i = 0; i < length; i ++ ) { - - var influence = influences[ i ]; - - influence[ 0 ] = i; - influence[ 1 ] = objectInfluences[ i ]; - - } - - influences.sort( absNumericalSort ); - - // Add morphAttributes - - for ( var i = 0; i < 8; i ++ ) { - - var influence = influences[ i ]; - - if ( influence ) { - - var index = influence[ 0 ]; - var value = influence[ 1 ]; - - if ( value ) { - - if ( morphTargets ) { geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); } - if ( morphNormals ) { geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); } - - morphInfluences[ i ] = value; - continue; - - } - - } - - morphInfluences[ i ] = 0; - - } - - program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); - - } - - return { - - update: update - - }; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { - - var mode; - - function setMode( value ) { - - mode = value; - - } - - var type, bytesPerElement; - - function setIndex( value ) { - - type = value.type; - bytesPerElement = value.bytesPerElement; - - } - - function render( start, count ) { - - gl.drawElements( mode, count, type, start * bytesPerElement ); - - infoRender.calls ++; - infoRender.vertices += count; - - if ( mode === gl.TRIANGLES ) { infoRender.faces += count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += count; } - - } - - function renderInstances( geometry, start, count ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); - - if ( extension === null ) { - - console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; - - } - - extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); - - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; - - if ( mode === gl.TRIANGLES ) { infoRender.faces += geometry.maxInstancedCount * count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += geometry.maxInstancedCount * count; } + return this.multiplyMatrices( m, this ); } - // + multiplyMatrices( a, b ) { - this.setMode = setMode; - this.setIndex = setIndex; - this.render = render; - this.renderInstances = renderInstances; + const ae = a.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 ]; -/** - * @author mrdoob / http://mrdoob.com/ - */ + 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 ]; -function WebGLBufferRenderer( gl, extensions, infoRender ) { + 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; - var mode; + 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; - function setMode( value ) { + 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; - mode = value; + return this; } - function render( start, count ) { + multiplyScalar( s ) { - gl.drawArrays( mode, start, count ); + const te = this.elements; - infoRender.calls ++; - infoRender.vertices += count; + 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; - if ( mode === gl.TRIANGLES ) { infoRender.faces += count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += count; } + return this; } - function renderInstances( geometry, start, count ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + determinant() { - if ( extension === null ) { - - console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + 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 ]; - var position = geometry.attributes.position; + //TODO: make this more efficient + //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) - if ( position.isInterleavedBufferAttribute ) { + 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 + ) - count = position.data.count; + ); - extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount ); + } - } else { + transpose() { - extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount ); + 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; - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; + 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; - if ( mode === gl.TRIANGLES ) { infoRender.faces += geometry.maxInstancedCount * count / 3; } - else if ( mode === gl.POINTS ) { infoRender.points += geometry.maxInstancedCount * count; } + return this; } - // - - this.setMode = setMode; - this.render = render; - this.renderInstances = renderInstances; - -} - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function WebGLGeometries( gl, attributes, infoMemory ) { + setPosition( x, y, z ) { - var geometries = {}; - var wireframeAttributes = {}; + const te = this.elements; - function onGeometryDispose( event ) { + if ( x.isVector3 ) { - var geometry = event.target; - var buffergeometry = geometries[ geometry.id ]; + te[ 12 ] = x.x; + te[ 13 ] = x.y; + te[ 14 ] = x.z; - if ( buffergeometry.index !== null ) { + } else { - attributes.remove( buffergeometry.index ); + te[ 12 ] = x; + te[ 13 ] = y; + te[ 14 ] = z; } - for ( var name in buffergeometry.attributes ) { - - attributes.remove( buffergeometry.attributes[ name ] ); - - } + return this; - geometry.removeEventListener( 'dispose', onGeometryDispose ); + } - delete geometries[ geometry.id ]; + invert() { - // TODO Remove duplicate code + // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + const te = this.elements, - var attribute = wireframeAttributes[ geometry.id ]; + 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 ], - if ( attribute ) { + 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; - attributes.remove( attribute ); - delete wireframeAttributes[ geometry.id ]; + 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 ); - attribute = wireframeAttributes[ buffergeometry.id ]; + const detInv = 1 / det; - if ( attribute ) { + 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; - attributes.remove( attribute ); - delete wireframeAttributes[ buffergeometry.id ]; + 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; - infoMemory.geometries --; + return this; } - function get( object, geometry ) { - - var buffergeometry = geometries[ geometry.id ]; - - if ( buffergeometry ) { return buffergeometry; } - - geometry.addEventListener( 'dispose', onGeometryDispose ); - - if ( geometry.isBufferGeometry ) { - - buffergeometry = geometry; - - } else if ( geometry.isGeometry ) { - - if ( geometry._bufferGeometry === undefined ) { + scale( v ) { - geometry._bufferGeometry = new BufferGeometry().setFromObject( object ); + const te = this.elements; + const x = v.x, y = v.y, z = v.z; - } - - buffergeometry = geometry._bufferGeometry; - - } - - geometries[ geometry.id ] = buffergeometry; - - infoMemory.geometries ++; + te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; + te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; + te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; + te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; - return buffergeometry; + return this; } - function update( geometry ) { - - var index = geometry.index; - var geometryAttributes = geometry.attributes; + getMaxScaleOnAxis() { - if ( index !== null ) { + const te = this.elements; - attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); + 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 ) ); - for ( var name in geometryAttributes ) { + } - attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); + makeTranslation( x, y, z ) { - } + if ( x.isVector3 ) { - // morph targets + this.set( - var morphAttributes = geometry.morphAttributes; + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 - for ( var name in morphAttributes ) { + ); - var array = morphAttributes[ name ]; + } else { - for ( var i = 0, l = array.length; i < l; i ++ ) { + this.set( - attributes.update( array[ i ], gl.ARRAY_BUFFER ); + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 - } + ); } - } - - function getWireframeAttribute( geometry ) { - - var attribute = wireframeAttributes[ geometry.id ]; - - if ( attribute ) { return attribute; } - - var indices = []; - - var geometryIndex = geometry.index; - var geometryAttributes = geometry.attributes; - - // console.time( 'wireframe' ); - - if ( geometryIndex !== null ) { - - var array = geometryIndex.array; - - for ( var i = 0, l = array.length; i < l; i += 3 ) { - - var a = array[ i + 0 ]; - var b = array[ i + 1 ]; - var c = array[ i + 2 ]; + return this; - indices.push( a, b, b, c, c, a ); + } - } + makeRotationX( theta ) { - } else { + const c = Math.cos( theta ), s = Math.sin( theta ); - var array = geometryAttributes.position.array; + this.set( - for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { + 1, 0, 0, 0, + 0, c, - s, 0, + 0, s, c, 0, + 0, 0, 0, 1 - var a = i + 0; - var b = i + 1; - var c = i + 2; + ); - indices.push( a, b, b, c, c, a ); + return this; - } + } - } + makeRotationY( theta ) { - // console.timeEnd( 'wireframe' ); + const c = Math.cos( theta ), s = Math.sin( theta ); - attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + this.set( - attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER ); + c, 0, s, 0, + 0, 1, 0, 0, + - s, 0, c, 0, + 0, 0, 0, 1 - wireframeAttributes[ geometry.id ] = attribute; + ); - return attribute; + return this; } - return { - - get: get, - update: update, - - getWireframeAttribute: getWireframeAttribute - - }; - -} + makeRotationZ( theta ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + const c = Math.cos( theta ), s = Math.sin( theta ); -function UniformsCache() { + this.set( - var lights = {}; + c, - s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - return { + ); - get: function ( light ) { + return this; - if ( lights[ light.id ] !== undefined ) { + } - return lights[ light.id ]; + makeRotationAxis( axis, angle ) { - } + // Based on http://www.gamedev.net/reference/articles/article1199.asp - var uniforms; + const c = Math.cos( angle ); + const s = Math.sin( angle ); + const t = 1 - c; + const x = axis.x, y = axis.y, z = axis.z; + const tx = t * x, ty = t * y; - switch ( light.type ) { + this.set( - case 'DirectionalLight': - uniforms = { - direction: new Vector3(), - color: new Color(), + tx * x + c, tx * y - s * z, tx * z + s * y, 0, + tx * y + s * z, ty * y + c, ty * z - s * x, 0, + tx * z - s * y, ty * z + s * x, t * z * z + c, 0, + 0, 0, 0, 1 - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; + ); - case 'SpotLight': - uniforms = { - position: new Vector3(), - direction: new Vector3(), - color: new Color(), - distance: 0, - coneCos: 0, - penumbraCos: 0, - decay: 0, + return this; - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; + } - case 'PointLight': - uniforms = { - position: new Vector3(), - color: new Color(), - distance: 0, - decay: 0, + makeScale( x, y, z ) { - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2(), - shadowCameraNear: 1, - shadowCameraFar: 1000 - }; - break; + this.set( - case 'HemisphereLight': - uniforms = { - direction: new Vector3(), - skyColor: new Color(), - groundColor: new Color() - }; - break; + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 - case 'RectAreaLight': - uniforms = { - color: new Color(), - position: new Vector3(), - halfWidth: new Vector3(), - halfHeight: new Vector3() - // TODO (abelnation): set RectAreaLight shadow uniforms - }; - break; + ); - } + return this; - lights[ light.id ] = uniforms; + } - return uniforms; + 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 -} + ); -function WebGLLights() { + return this; - var cache = new UniformsCache(); + } - var state = { + compose( position, quaternion, scale ) { - hash: '', + const te = this.elements; - ambient: [ 0, 0, 0 ], - directional: [], - directionalShadowMap: [], - directionalShadowMatrix: [], - spot: [], - spotShadowMap: [], - spotShadowMatrix: [], - rectArea: [], - point: [], - pointShadowMap: [], - pointShadowMatrix: [], - hemi: [] + const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; + const x2 = x + x, y2 = y + y, z2 = z + z; + const xx = x * x2, xy = x * y2, xz = x * z2; + const yy = y * y2, yz = y * z2, zz = z * z2; + const wx = w * x2, wy = w * y2, wz = w * z2; - }; + const sx = scale.x, sy = scale.y, sz = scale.z; - var vector3 = new Vector3(); - var matrix4 = new Matrix4(); - var matrix42 = new Matrix4(); + te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; + te[ 1 ] = ( xy + wz ) * sx; + te[ 2 ] = ( xz - wy ) * sx; + te[ 3 ] = 0; - function setup( lights, shadows, camera ) { + te[ 4 ] = ( xy - wz ) * sy; + te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; + te[ 6 ] = ( yz + wx ) * sy; + te[ 7 ] = 0; - var r = 0, g = 0, b = 0; + te[ 8 ] = ( xz + wy ) * sz; + te[ 9 ] = ( yz - wx ) * sz; + te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; + te[ 11 ] = 0; - var directionalLength = 0; - var pointLength = 0; - var spotLength = 0; - var rectAreaLength = 0; - var hemiLength = 0; + te[ 12 ] = position.x; + te[ 13 ] = position.y; + te[ 14 ] = position.z; + te[ 15 ] = 1; - var viewMatrix = camera.matrixWorldInverse; + return this; - for ( var i = 0, l = lights.length; i < l; i ++ ) { + } - var light = lights[ i ]; + decompose( position, quaternion, scale ) { - var color = light.color; - var intensity = light.intensity; - var distance = light.distance; + const te = this.elements; - var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; + 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(); - if ( light.isAmbientLight ) { + // if determine is negative, we need to invert one scale + const det = this.determinant(); + if ( det < 0 ) sx = - sx; - r += color.r * intensity; - g += color.g * intensity; - b += color.b * intensity; + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; - } else if ( light.isDirectionalLight ) { + // scale the rotation part + _m1$4.copy( this ); - var uniforms = cache.get( light ); + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); + _m1$4.elements[ 0 ] *= invSX; + _m1$4.elements[ 1 ] *= invSX; + _m1$4.elements[ 2 ] *= invSX; - uniforms.shadow = light.castShadow; + _m1$4.elements[ 4 ] *= invSY; + _m1$4.elements[ 5 ] *= invSY; + _m1$4.elements[ 6 ] *= invSY; - if ( light.castShadow ) { + _m1$4.elements[ 8 ] *= invSZ; + _m1$4.elements[ 9 ] *= invSZ; + _m1$4.elements[ 10 ] *= invSZ; - var shadow = light.shadow; + quaternion.setFromRotationMatrix( _m1$4 ); - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; + scale.x = sx; + scale.y = sy; + scale.z = sz; - } + return this; - state.directionalShadowMap[ directionalLength ] = shadowMap; - state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - state.directional[ directionalLength ] = uniforms; + } - directionalLength ++; + makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { - } else if ( light.isSpotLight ) { + const te = this.elements; + const x = 2 * near / ( right - left ); + const y = 2 * near / ( top - bottom ); - var uniforms = cache.get( light ); + const a = ( right + left ) / ( right - left ); + const b = ( top + bottom ) / ( top - bottom ); - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + let c, d; - uniforms.color.copy( color ).multiplyScalar( intensity ); - uniforms.distance = distance; + if ( coordinateSystem === WebGLCoordinateSystem ) { - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); + c = - ( far + near ) / ( far - near ); + d = ( - 2 * far * near ) / ( far - near ); - uniforms.coneCos = Math.cos( light.angle ); - uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - uniforms.shadow = light.castShadow; + c = - far / ( far - near ); + d = ( - far * near ) / ( far - near ); - if ( light.castShadow ) { + } else { - var shadow = light.shadow; + throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; + } - } + te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; + te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; - state.spotShadowMap[ spotLength ] = shadowMap; - state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; - state.spot[ spotLength ] = uniforms; + return this; - spotLength ++; + } - } else if ( light.isRectAreaLight ) { + makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { - var uniforms = cache.get( light ); + const te = this.elements; + const w = 1.0 / ( right - left ); + const h = 1.0 / ( top - bottom ); + const p = 1.0 / ( far - near ); - // (a) intensity controls irradiance of entire light - uniforms.color - .copy( color ) - .multiplyScalar( intensity / ( light.width * light.height ) ); + const x = ( right + left ) * w; + const y = ( top + bottom ) * h; - // (b) intensity controls the radiance per light area - // uniforms.color.copy( color ).multiplyScalar( intensity ); + let z, zInv; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + if ( coordinateSystem === WebGLCoordinateSystem ) { - // extract local rotation of light to derive width/height half vectors - matrix42.identity(); - matrix4.copy( light.matrixWorld ); - matrix4.premultiply( viewMatrix ); - matrix42.extractRotation( matrix4 ); + z = ( far + near ) * p; + zInv = - 2 * p; - uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); - uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - uniforms.halfWidth.applyMatrix4( matrix42 ); - uniforms.halfHeight.applyMatrix4( matrix42 ); + z = near * p; + zInv = - 1 * p; - // TODO (abelnation): RectAreaLight distance? - // uniforms.distance = distance; + } else { - state.rectArea[ rectAreaLength ] = uniforms; + throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); - rectAreaLength ++; + } - } else if ( light.isPointLight ) { + te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; + te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; - var uniforms = cache.get( light ); + return this; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + } - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.distance = light.distance; - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + equals( matrix ) { - uniforms.shadow = light.castShadow; + const te = this.elements; + const me = matrix.elements; - if ( light.castShadow ) { + for ( let i = 0; i < 16; i ++ ) { - var shadow = light.shadow; + if ( te[ i ] !== me[ i ] ) return false; - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - uniforms.shadowCameraNear = shadow.camera.near; - uniforms.shadowCameraFar = shadow.camera.far; + } - } + return true; - state.pointShadowMap[ pointLength ] = shadowMap; - state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - state.point[ pointLength ] = uniforms; + } - pointLength ++; + fromArray( array, offset = 0 ) { - } else if ( light.isHemisphereLight ) { + for ( let i = 0; i < 16; i ++ ) { - var uniforms = cache.get( light ); + this.elements[ i ] = array[ i + offset ]; - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - uniforms.direction.transformDirection( viewMatrix ); - uniforms.direction.normalize(); + } - uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); - uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); + return this; - state.hemi[ hemiLength ] = uniforms; + } - hemiLength ++; + toArray( array = [], offset = 0 ) { - } + const te = this.elements; - } + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + array[ offset + 3 ] = te[ 3 ]; - state.ambient[ 0 ] = r; - state.ambient[ 1 ] = g; - state.ambient[ 2 ] = b; + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; - state.directional.length = directionalLength; - state.spot.length = spotLength; - state.rectArea.length = rectAreaLength; - state.point.length = pointLength; - state.hemi.length = hemiLength; + array[ offset + 8 ] = te[ 8 ]; + array[ offset + 9 ] = te[ 9 ]; + array[ offset + 10 ] = te[ 10 ]; + array[ offset + 11 ] = te[ 11 ]; + + array[ offset + 12 ] = te[ 12 ]; + array[ offset + 13 ] = te[ 13 ]; + array[ offset + 14 ] = te[ 14 ]; + array[ offset + 15 ] = te[ 15 ]; - // TODO (sam-g-steel) why aren't we using join - state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; + return array; } - return { - setup: setup, - state: state - }; - } -/** - * @author mrdoob / http://mrdoob.com/ - */ +const _v1$5 = /*@__PURE__*/ new Vector3(); +const _m1$4 = /*@__PURE__*/ new Matrix4(); +const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); +const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); +const _x = /*@__PURE__*/ new Vector3(); +const _y = /*@__PURE__*/ new Vector3(); +const _z = /*@__PURE__*/ new Vector3(); -function WebGLObjects( geometries, infoRender ) { +const _matrix$2 = /*@__PURE__*/ new Matrix4(); +const _quaternion$3 = /*@__PURE__*/ new Quaternion(); - var updateList = {}; +class Euler { - function update( object ) { + constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { - var frame = infoRender.frame; + this.isEuler = true; - var geometry = object.geometry; - var buffergeometry = geometries.get( object, geometry ); + this._x = x; + this._y = y; + this._z = z; + this._order = order; - // Update once per frame + } - if ( updateList[ buffergeometry.id ] !== frame ) { + get x() { - if ( geometry.isGeometry ) { + return this._x; - buffergeometry.updateFromObject( object ); + } - } + set x( value ) { - geometries.update( buffergeometry ); + this._x = value; + this._onChangeCallback(); - updateList[ buffergeometry.id ] = frame; + } - } + get y() { - return buffergeometry; + return this._y; } - function clear() { + set y( value ) { - updateList = {}; + this._y = value; + this._onChangeCallback(); } - return { - - update: update, - clear: clear + get z() { - }; + return this._z; -} + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + set z( value ) { -function addLineNumbers( string ) { + this._z = value; + this._onChangeCallback(); - var lines = string.split( '\n' ); + } - for ( var i = 0; i < lines.length; i ++ ) { + get order() { - lines[ i ] = ( i + 1 ) + ': ' + lines[ i ]; + return this._order; } - return lines.join( '\n' ); + set order( value ) { -} + this._order = value; + this._onChangeCallback(); -function WebGLShader( gl, type, string ) { + } - var shader = gl.createShader( type ); + set( x, y, z, order = this._order ) { - gl.shaderSource( shader, string ); - gl.compileShader( shader ); + this._x = x; + this._y = y; + this._z = z; + this._order = order; - if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { + this._onChangeCallback(); - console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); + return this; } - if ( gl.getShaderInfoLog( shader ) !== '' ) { + clone() { - console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) ); + return new this.constructor( this._x, this._y, this._z, this._order ); } - // --enable-privileged-webgl-extension - // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - - return shader; + copy( euler ) { -} + this._x = euler._x; + this._y = euler._y; + this._z = euler._z; + this._order = euler._order; -/** - * @author mrdoob / http://mrdoob.com/ - */ + this._onChangeCallback(); -var programIdCount = 0; - -function getEncodingComponents( encoding ) { - - switch ( encoding ) { - - case LinearEncoding: - return [ 'Linear', '( value )' ]; - case sRGBEncoding: - return [ 'sRGB', '( value )' ]; - case RGBEEncoding: - return [ 'RGBE', '( value )' ]; - case RGBM7Encoding: - return [ 'RGBM', '( value, 7.0 )' ]; - case RGBM16Encoding: - return [ 'RGBM', '( value, 16.0 )' ]; - case RGBDEncoding: - return [ 'RGBD', '( value, 256.0 )' ]; - case GammaEncoding: - return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; - default: - throw new Error( 'unsupported encoding: ' + encoding ); + return this; } -} + setFromRotationMatrix( m, order = this._order, update = true ) { + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) -function getTexelDecodingFunction( functionName, encoding ) { + const te = m.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 ]; - var components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }'; + switch ( order ) { -} + case 'XYZ': -function getTexelEncodingFunction( functionName, encoding ) { + this._y = Math.asin( clamp( m13, - 1, 1 ) ); - var components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; + if ( Math.abs( m13 ) < 0.9999999 ) { -} + this._x = Math.atan2( - m23, m33 ); + this._z = Math.atan2( - m12, m11 ); -function getToneMappingFunction( functionName, toneMapping ) { + } else { - var toneMappingName; + this._x = Math.atan2( m32, m22 ); + this._z = 0; - switch ( toneMapping ) { + } - case LinearToneMapping: - toneMappingName = 'Linear'; - break; + break; - case ReinhardToneMapping: - toneMappingName = 'Reinhard'; - break; + case 'YXZ': - case Uncharted2ToneMapping: - toneMappingName = 'Uncharted2'; - break; + this._x = Math.asin( - clamp( m23, - 1, 1 ) ); - case CineonToneMapping: - toneMappingName = 'OptimizedCineon'; - break; + if ( Math.abs( m23 ) < 0.9999999 ) { - default: - throw new Error( 'unsupported toneMapping: ' + toneMapping ); + this._y = Math.atan2( m13, m33 ); + this._z = Math.atan2( m21, m22 ); - } + } else { - return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; + this._y = Math.atan2( - m31, m11 ); + this._z = 0; -} + } -function generateExtensions( extensions, parameters, rendererExtensions ) { + break; - extensions = extensions || {}; + case 'ZXY': - var chunks = [ - ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', - ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '', - ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '', - ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '' - ]; + this._x = Math.asin( clamp( m32, - 1, 1 ) ); - return chunks.filter( filterEmptyLine ).join( '\n' ); + if ( Math.abs( m32 ) < 0.9999999 ) { -} + this._y = Math.atan2( - m31, m33 ); + this._z = Math.atan2( - m12, m22 ); -function generateDefines( defines ) { + } else { - var chunks = []; + this._y = 0; + this._z = Math.atan2( m21, m11 ); + + } - for ( var name in defines ) { + break; - var value = defines[ name ]; + case 'ZYX': - if ( value === false ) { continue; } + this._y = Math.asin( - clamp( m31, - 1, 1 ) ); - chunks.push( '#define ' + name + ' ' + value ); + if ( Math.abs( m31 ) < 0.9999999 ) { - } + this._x = Math.atan2( m32, m33 ); + this._z = Math.atan2( m21, m11 ); - return chunks.join( '\n' ); + } else { -} + this._x = 0; + this._z = Math.atan2( - m12, m22 ); -function fetchAttributeLocations( gl, program ) { + } - var attributes = {}; + break; - var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); + case 'YZX': - for ( var i = 0; i < n; i ++ ) { + this._z = Math.asin( clamp( m21, - 1, 1 ) ); - var info = gl.getActiveAttrib( program, i ); - var name = info.name; + if ( Math.abs( m21 ) < 0.9999999 ) { - // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); + this._x = Math.atan2( - m23, m22 ); + this._y = Math.atan2( - m31, m11 ); - attributes[ name ] = gl.getAttribLocation( program, name ); + } else { - } + this._x = 0; + this._y = Math.atan2( m13, m33 ); - return attributes; + } -} + break; -function filterEmptyLine( string ) { + case 'XZY': - return string !== ''; + this._z = Math.asin( - clamp( m12, - 1, 1 ) ); -} + if ( Math.abs( m12 ) < 0.9999999 ) { -function replaceLightNums( string, parameters ) { + this._x = Math.atan2( m32, m22 ); + this._y = Math.atan2( m13, m11 ); - 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 ); + } else { -} + this._x = Math.atan2( - m23, m33 ); + this._y = 0; -function parseIncludes( string ) { + } - var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm; + break; - function replace( match, include ) { + default: - var replace = ShaderChunk[ include ]; + console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); - if ( replace === undefined ) { + } - throw new Error( 'Can not resolve #include <' + include + '>' ); + this._order = order; - } + if ( update === true ) this._onChangeCallback(); - return parseIncludes( replace ); + return this; } - return string.replace( pattern, replace ); + setFromQuaternion( q, order, update ) { -} + _matrix$2.makeRotationFromQuaternion( q ); -function unrollLoops( string ) { + return this.setFromRotationMatrix( _matrix$2, order, update ); - var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; + } - function replace( match, start, end, snippet ) { + setFromVector3( v, order = this._order ) { - var unroll = ''; + return this.set( v.x, v.y, v.z, order ); - for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) { + } - unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' ); + reorder( newOrder ) { - } + // WARNING: this discards revolution information -bhouston - return unroll; + _quaternion$3.setFromEuler( this ); + + return this.setFromQuaternion( _quaternion$3, newOrder ); } - return string.replace( pattern, replace ); + equals( euler ) { -} + return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); -function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { + } - var gl = renderer.context; + fromArray( array ) { - var defines = material.defines; + this._x = array[ 0 ]; + this._y = array[ 1 ]; + this._z = array[ 2 ]; + if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; - var vertexShader = shader.vertexShader; - var fragmentShader = shader.fragmentShader; + this._onChangeCallback(); - var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; + return this; - if ( parameters.shadowMapType === PCFShadowMap ) { + } - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; + toArray( array = [], offset = 0 ) { - } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._order; - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; + return array; } - var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; - var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + _onChange( callback ) { - if ( parameters.envMap ) { + this._onChangeCallback = callback; - switch ( material.envMap.mapping ) { + return this; - case CubeReflectionMapping: - case CubeRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - break; + } - case CubeUVReflectionMapping: - case CubeUVRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; - break; + _onChangeCallback() {} - case EquirectangularReflectionMapping: - case EquirectangularRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; - break; + *[ Symbol.iterator ]() { - case SphericalReflectionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; - break; + yield this._x; + yield this._y; + yield this._z; + yield this._order; - } + } - switch ( material.envMap.mapping ) { +} - case CubeRefractionMapping: - case EquirectangularRefractionMapping: - envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; - break; +Euler.DEFAULT_ORDER = 'XYZ'; - } +class Layers { - switch ( material.combine ) { + constructor() { - case MultiplyOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; - break; + this.mask = 1 | 0; - case MixOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; - break; + } - case AddOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; - break; + set( channel ) { - } + this.mask = ( 1 << channel | 0 ) >>> 0; } - var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; + enable( channel ) { - // console.log( 'building new program ' ); - - // - - var customExtensions = generateExtensions( material.extensions, parameters, extensions ); + this.mask |= 1 << channel | 0; - var customDefines = generateDefines( defines ); + } - // + enableAll() { - var program = gl.createProgram(); + this.mask = 0xffffffff | 0; - var prefixVertex, prefixFragment; + } - if ( material.isRawShaderMaterial ) { + toggle( channel ) { - prefixVertex = [ + this.mask ^= 1 << channel | 0; - customDefines + } - ].filter( filterEmptyLine ).join( '\n' ); + disable( channel ) { - if ( prefixVertex.length > 0 ) { + this.mask &= ~ ( 1 << channel | 0 ); - prefixVertex += '\n'; + } - } + disableAll() { - prefixFragment = [ + this.mask = 0; - customExtensions, - customDefines + } - ].filter( filterEmptyLine ).join( '\n' ); + test( layers ) { - if ( prefixFragment.length > 0 ) { + return ( this.mask & layers.mask ) !== 0; - prefixFragment += '\n'; + } - } + isEnabled( channel ) { - } else { + return ( this.mask & ( 1 << channel | 0 ) ) !== 0; - prefixVertex = [ + } - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', +} - '#define SHADER_NAME ' + shader.name, +let _object3DId = 0; - customDefines, +const _v1$4 = /*@__PURE__*/ new Vector3(); +const _q1 = /*@__PURE__*/ new Quaternion(); +const _m1$3 = /*@__PURE__*/ new Matrix4(); +const _target = /*@__PURE__*/ new Vector3(); - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', +const _position$3 = /*@__PURE__*/ new Vector3(); +const _scale$2 = /*@__PURE__*/ new Vector3(); +const _quaternion$2 = /*@__PURE__*/ new Quaternion(); - '#define GAMMA_FACTOR ' + gammaFactorDefine, +const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); +const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); +const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); - '#define MAX_BONES ' + parameters.maxBones, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', +const _addedEvent = { type: 'added' }; +const _removedEvent = { type: 'removed' }; - 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.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', +const _childaddedEvent = { type: 'childadded', child: null }; +const _childremovedEvent = { type: 'childremoved', child: null }; - parameters.flatShading ? '#define FLAT_SHADED' : '', +class Object3D extends EventDispatcher { - parameters.skinning ? '#define USE_SKINNING' : '', - parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', + constructor() { - parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', - parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', + super(); - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, + this.isObject3D = true; - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + Object.defineProperty( this, 'id', { value: _object3DId ++ } ); - parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + this.uuid = generateUUID(); - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + this.name = ''; + this.type = 'Object3D'; - 'uniform mat4 modelMatrix;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform mat4 viewMatrix;', - 'uniform mat3 normalMatrix;', - 'uniform vec3 cameraPosition;', + this.parent = null; + this.children = []; - 'attribute vec3 position;', - 'attribute vec3 normal;', - 'attribute vec2 uv;', + this.up = Object3D.DEFAULT_UP.clone(); - '#ifdef USE_COLOR', + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3( 1, 1, 1 ); - ' attribute vec3 color;', + function onRotationChange() { - '#endif', + quaternion.setFromEuler( rotation, false ); - '#ifdef USE_MORPHTARGETS', + } - ' attribute vec3 morphTarget0;', - ' attribute vec3 morphTarget1;', - ' attribute vec3 morphTarget2;', - ' attribute vec3 morphTarget3;', + function onQuaternionChange() { - ' #ifdef USE_MORPHNORMALS', + rotation.setFromQuaternion( quaternion, undefined, false ); - ' attribute vec3 morphNormal0;', - ' attribute vec3 morphNormal1;', - ' attribute vec3 morphNormal2;', - ' attribute vec3 morphNormal3;', + } - ' #else', + rotation._onChange( onRotationChange ); + quaternion._onChange( onQuaternionChange ); - ' attribute vec3 morphTarget4;', - ' attribute vec3 morphTarget5;', - ' attribute vec3 morphTarget6;', - ' attribute vec3 morphTarget7;', + 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() + } + } ); - ' #endif', + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); - '#endif', + this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; - '#ifdef USE_SKINNING', + this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer + this.matrixWorldNeedsUpdate = false; - ' attribute vec4 skinIndex;', - ' attribute vec4 skinWeight;', + this.layers = new Layers(); + this.visible = true; - '#endif', + this.castShadow = false; + this.receiveShadow = false; - '\n' + this.frustumCulled = true; + this.renderOrder = 0; - ].filter( filterEmptyLine ).join( '\n' ); + this.animations = []; - prefixFragment = [ + this.userData = {}; - customExtensions, + } - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', + onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} - '#define SHADER_NAME ' + shader.name, + onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} - customDefines, + onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} - parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', + onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} - '#define GAMMA_FACTOR ' + gammaFactorDefine, + applyMatrix4( matrix ) { - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', + if ( this.matrixAutoUpdate ) this.updateMatrix(); - parameters.map ? '#define USE_MAP' : '', - parameters.envMap ? '#define USE_ENVMAP' : '', - parameters.envMap ? '#define ' + envMapTypeDefine : '', - parameters.envMap ? '#define ' + envMapModeDefine : '', - parameters.envMap ? '#define ' + envMapBlendingDefine : '', - 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.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', + this.matrix.premultiply( matrix ); - parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', + this.matrix.decompose( this.position, this.quaternion, this.scale ); - parameters.flatShading ? '#define FLAT_SHADED' : '', + } - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', + applyQuaternion( q ) { - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, - '#define UNION_CLIPPING_PLANES ' + ( parameters.numClippingPlanes - parameters.numClipIntersection ), + this.quaternion.premultiply( q ); - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + return this; - parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', + } - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + setRotationFromAxisAngle( axis, angle ) { - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + // assumes axis is normalized - parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', + this.quaternion.setFromAxisAngle( axis, angle ); - 'uniform mat4 viewMatrix;', - 'uniform vec3 cameraPosition;', + } - ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', - ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below - ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', + setRotationFromEuler( euler ) { - parameters.dithering ? '#define DITHERING' : '', + this.quaternion.setFromEuler( euler, true ); - ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below - parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', - parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', - parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', - parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '', + } - parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '', + setRotationFromMatrix( m ) { - '\n' + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - ].filter( filterEmptyLine ).join( '\n' ); + this.quaternion.setFromRotationMatrix( m ); } - vertexShader = parseIncludes( vertexShader ); - vertexShader = replaceLightNums( vertexShader, parameters ); - - fragmentShader = parseIncludes( fragmentShader ); - fragmentShader = replaceLightNums( fragmentShader, parameters ); + setRotationFromQuaternion( q ) { - if ( ! material.isShaderMaterial ) { + // assumes q is normalized - vertexShader = unrollLoops( vertexShader ); - fragmentShader = unrollLoops( fragmentShader ); + this.quaternion.copy( q ); } - var vertexGlsl = prefixVertex + vertexShader; - var fragmentGlsl = prefixFragment + fragmentShader; + rotateOnAxis( axis, angle ) { - // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); - - var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); - var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); + // rotate object on axis in object space + // axis is assumed to be normalized - gl.attachShader( program, glVertexShader ); - gl.attachShader( program, glFragmentShader ); + _q1.setFromAxisAngle( axis, angle ); - // Force a particular attribute to index 0. + this.quaternion.multiply( _q1 ); - if ( material.index0AttributeName !== undefined ) { + return this; - gl.bindAttribLocation( program, 0, material.index0AttributeName ); + } - } else if ( parameters.morphTargets === true ) { + rotateOnWorldAxis( axis, angle ) { - // programs with morphTargets displace position out of attribute 0 - gl.bindAttribLocation( program, 0, 'position' ); + // rotate object on axis in world space + // axis is assumed to be normalized + // method assumes no rotated parent - } + _q1.setFromAxisAngle( axis, angle ); - gl.linkProgram( program ); + this.quaternion.premultiply( _q1 ); - var programLog = gl.getProgramInfoLog( program ); - var vertexLog = gl.getShaderInfoLog( glVertexShader ); - var fragmentLog = gl.getShaderInfoLog( glFragmentShader ); + return this; - var runnable = true; - var haveDiagnostics = true; + } - // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) ); - // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) ); + rotateX( angle ) { - if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { + return this.rotateOnAxis( _xAxis, angle ); - runnable = false; + } - console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog ); + rotateY( angle ) { - } else if ( programLog !== '' ) { + return this.rotateOnAxis( _yAxis, angle ); - console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); + } - } else if ( vertexLog === '' || fragmentLog === '' ) { + rotateZ( angle ) { - haveDiagnostics = false; + return this.rotateOnAxis( _zAxis, angle ); } - if ( haveDiagnostics ) { + translateOnAxis( axis, distance ) { - this.diagnostics = { + // translate object by distance along axis in object space + // axis is assumed to be normalized - runnable: runnable, - material: material, + _v1$4.copy( axis ).applyQuaternion( this.quaternion ); - programLog: programLog, + this.position.add( _v1$4.multiplyScalar( distance ) ); - vertexShader: { + return this; - log: vertexLog, - prefix: prefixVertex + } - }, + translateX( distance ) { - fragmentShader: { + return this.translateOnAxis( _xAxis, distance ); - log: fragmentLog, - prefix: prefixFragment + } - } + translateY( distance ) { - }; + return this.translateOnAxis( _yAxis, distance ); } - // clean up + translateZ( distance ) { - gl.deleteShader( glVertexShader ); - gl.deleteShader( glFragmentShader ); + return this.translateOnAxis( _zAxis, distance ); - // set up caching for uniform locations + } - var cachedUniforms; + localToWorld( vector ) { - this.getUniforms = function () { + this.updateWorldMatrix( true, false ); + + return vector.applyMatrix4( this.matrixWorld ); + + } - if ( cachedUniforms === undefined ) { + worldToLocal( vector ) { - cachedUniforms = new WebGLUniforms( gl, program, renderer ); + this.updateWorldMatrix( true, false ); - } + return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() ); - return cachedUniforms; + } - }; + lookAt( x, y, z ) { - // set up caching for attribute locations + // This method does not support objects having non-uniformly-scaled parent(s) - var cachedAttributes; + if ( x.isVector3 ) { - this.getAttributes = function () { + _target.copy( x ); - if ( cachedAttributes === undefined ) { + } else { - cachedAttributes = fetchAttributeLocations( gl, program ); + _target.set( x, y, z ); } - return cachedAttributes; + const parent = this.parent; - }; + this.updateWorldMatrix( true, false ); - // free resource + _position$3.setFromMatrixPosition( this.matrixWorld ); - this.destroy = function () { + if ( this.isCamera || this.isLight ) { - gl.deleteProgram( program ); - this.program = undefined; + _m1$3.lookAt( _position$3, _target, this.up ); - }; + } else { - // DEPRECATED + _m1$3.lookAt( _target, _position$3, this.up ); - Object.defineProperties( this, { + } - uniforms: { - get: function () { + this.quaternion.setFromRotationMatrix( _m1$3 ); - console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' ); - return this.getUniforms(); + if ( parent ) { - } - }, + _m1$3.extractRotation( parent.matrixWorld ); + _q1.setFromRotationMatrix( _m1$3 ); + this.quaternion.premultiply( _q1.invert() ); - attributes: { - get: function () { + } - console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' ); - return this.getAttributes(); + } - } - } + add( object ) { - } ); + if ( arguments.length > 1 ) { + for ( let i = 0; i < arguments.length; i ++ ) { - // + this.add( arguments[ i ] ); - this.id = programIdCount ++; - this.code = code; - this.usedTimes = 1; - this.program = program; - this.vertexShader = glVertexShader; - this.fragmentShader = glFragmentShader; + } - return this; + return this; -} + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + if ( object === this ) { -function WebGLPrograms( renderer, extensions, capabilities ) { + console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); + return this; - var programs = []; + } - var shaderIDs = { - MeshDepthMaterial: 'depth', - MeshDistanceMaterial: 'distanceRGBA', - MeshNormalMaterial: 'normal', - MeshBasicMaterial: 'basic', - MeshLambertMaterial: 'lambert', - MeshPhongMaterial: 'phong', - MeshToonMaterial: 'phong', - MeshStandardMaterial: 'physical', - MeshPhysicalMaterial: 'physical', - LineBasicMaterial: 'basic', - LineDashedMaterial: 'dashed', - PointsMaterial: 'points', - ShadowMaterial: 'shadow' - }; + if ( object && object.isObject3D ) { - var parameterNames = [ - "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", - "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", - "roughnessMap", "metalnessMap", "gradientMap", - "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", - "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", - "maxBones", "useVertexTexture", "morphTargets", "morphNormals", - "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", - "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", - "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', - "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering" - ]; + object.removeFromParent(); + object.parent = this; + this.children.push( object ); + object.dispatchEvent( _addedEvent ); - function allocateBones( object ) { + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; - var skeleton = object.skeleton; - var bones = skeleton.bones; + } else { - if ( capabilities.floatVertexTextures ) { + console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); - return 1024; + } - } else { + return this; - // default for when object is not specified - // ( for example when prebuilding shader to be used with multiple objects ) - // - // - leave some extra space for other uniforms - // - limit here is ANGLE's 254 max uniform vectors - // (up to 54 should be safe) + } - var nVertexUniforms = capabilities.maxVertexUniforms; - var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 ); + remove( object ) { - var maxBones = Math.min( nVertexMatrices, bones.length ); + if ( arguments.length > 1 ) { - if ( maxBones < bones.length ) { + for ( let i = 0; i < arguments.length; i ++ ) { - console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' ); - return 0; + this.remove( arguments[ i ] ); } - return maxBones; + return this; } - } + const index = this.children.indexOf( object ); - function getTextureEncodingFromMap( map, gammaOverrideLinear ) { + if ( index !== - 1 ) { - var encoding; + object.parent = null; + this.children.splice( index, 1 ); - if ( ! map ) { + object.dispatchEvent( _removedEvent ); - encoding = LinearEncoding; + _childremovedEvent.child = object; + this.dispatchEvent( _childremovedEvent ); + _childremovedEvent.child = null; - } else if ( map.isTexture ) { + } - encoding = map.encoding; + return this; - } else if ( map.isWebGLRenderTarget ) { + } - console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." ); - encoding = map.texture.encoding; + removeFromParent() { - } + const parent = this.parent; - // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point. - if ( encoding === LinearEncoding && gammaOverrideLinear ) { + if ( parent !== null ) { - encoding = GammaEncoding; + parent.remove( this ); } - return encoding; + return this; } - this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { + clear() { - var shaderID = shaderIDs[ material.type ]; + return this.remove( ... this.children ); - // heuristics to create shader parameters according to lights in the scene - // (not to blow over maxLights budget) + } - var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; - var precision = capabilities.precision; + attach( object ) { - if ( material.precision !== null ) { + // adds object as a child of this, while maintaining the object's world transform - precision = capabilities.getMaxPrecision( material.precision ); + // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) - if ( precision !== material.precision ) { + this.updateWorldMatrix( true, false ); - console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); + _m1$3.copy( this.matrixWorld ).invert(); - } + if ( object.parent !== null ) { + + object.parent.updateWorldMatrix( true, false ); + + _m1$3.multiply( object.parent.matrixWorld ); } - var currentRenderTarget = renderer.getRenderTarget(); + object.applyMatrix4( _m1$3 ); - var parameters = { + object.removeFromParent(); + object.parent = this; + this.children.push( object ); - shaderID: shaderID, + object.updateWorldMatrix( false, true ); - precision: precision, - supportsVertexTextures: capabilities.vertexTextures, - outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ), - map: !! material.map, - mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ), - envMap: !! material.envMap, - envMapMode: material.envMap && material.envMap.mapping, - envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ), - envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ), - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ), - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - alphaMap: !! material.alphaMap, - - gradientMap: !! material.gradientMap, + object.dispatchEvent( _addedEvent ); - combine: material.combine, + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; - vertexColors: material.vertexColors, + return this; - fog: !! fog, - useFog: material.fog, - fogExp: ( fog && fog.isFogExp2 ), + } - flatShading: material.flatShading, + getObjectById( id ) { - sizeAttenuation: material.sizeAttenuation, - logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, + return this.getObjectByProperty( 'id', id ); - skinning: material.skinning && maxBones > 0, - maxBones: maxBones, - useVertexTexture: capabilities.floatVertexTextures, + } - morphTargets: material.morphTargets, - morphNormals: material.morphNormals, - maxMorphTargets: renderer.maxMorphTargets, - maxMorphNormals: renderer.maxMorphNormals, + getObjectByName( name ) { - numDirLights: lights.directional.length, - numPointLights: lights.point.length, - numSpotLights: lights.spot.length, - numRectAreaLights: lights.rectArea.length, - numHemiLights: lights.hemi.length, + return this.getObjectByProperty( 'name', name ); - numClippingPlanes: nClipPlanes, - numClipIntersection: nClipIntersection, + } - dithering: material.dithering, + getObjectByProperty( name, value ) { - shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, - shadowMapType: renderer.shadowMap.type, + if ( this[ name ] === value ) return this; - toneMapping: renderer.toneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + for ( let i = 0, l = this.children.length; i < l; i ++ ) { - premultipliedAlpha: material.premultipliedAlpha, + const child = this.children[ i ]; + const object = child.getObjectByProperty( name, value ); - alphaTest: material.alphaTest, - doubleSided: material.side === DoubleSide, - flipSided: material.side === BackSide, + if ( object !== undefined ) { - depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false + return object; - }; + } - return parameters; + } - }; + return undefined; - this.getProgramCode = function ( material, parameters ) { + } - var array = []; + getObjectsByProperty( name, value, result = [] ) { - if ( parameters.shaderID ) { + if ( this[ name ] === value ) result.push( this ); - array.push( parameters.shaderID ); + const children = this.children; - } else { + for ( let i = 0, l = children.length; i < l; i ++ ) { - array.push( material.fragmentShader ); - array.push( material.vertexShader ); + children[ i ].getObjectsByProperty( name, value, result ); } - if ( material.defines !== undefined ) { + return result; - for ( var name in material.defines ) { + } - array.push( name ); - array.push( material.defines[ name ] ); + getWorldPosition( target ) { - } + this.updateWorldMatrix( true, false ); - } + return target.setFromMatrixPosition( this.matrixWorld ); - for ( var i = 0; i < parameterNames.length; i ++ ) { + } - array.push( parameters[ parameterNames[ i ] ] ); + getWorldQuaternion( target ) { - } + this.updateWorldMatrix( true, false ); - array.push( material.onBeforeCompile.toString() ); + this.matrixWorld.decompose( _position$3, target, _scale$2 ); - array.push( renderer.gammaOutput ); + return target; - return array.join(); + } - }; + getWorldScale( target ) { - this.acquireProgram = function ( material, shader, parameters, code ) { + this.updateWorldMatrix( true, false ); - var program; + this.matrixWorld.decompose( _position$3, _quaternion$2, target ); - // Check if code has been already compiled - for ( var p = 0, pl = programs.length; p < pl; p ++ ) { + return target; - var programInfo = programs[ p ]; + } - if ( programInfo.code === code ) { + getWorldDirection( target ) { - program = programInfo; - ++ program.usedTimes; + this.updateWorldMatrix( true, false ); - break; + const e = this.matrixWorld.elements; - } + return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); - } + } - if ( program === undefined ) { + raycast( /* raycaster, intersects */ ) {} - program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); - programs.push( program ); + traverse( callback ) { + + callback( this ); + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverse( callback ); } - return program; + } - }; + traverseVisible( callback ) { - this.releaseProgram = function ( program ) { + if ( this.visible === false ) return; - if ( -- program.usedTimes === 0 ) { + callback( this ); - // Remove from unordered set - var i = programs.indexOf( program ); - programs[ i ] = programs[ programs.length - 1 ]; - programs.pop(); + const children = this.children; - // Free WebGL resources - program.destroy(); + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverseVisible( callback ); } - }; + } - // Exposed for resource monitoring & error feedback via renderer.info: - this.programs = programs; + traverseAncestors( callback ) { -} + const parent = this.parent; -/** - * @author mrdoob / http://mrdoob.com/ - */ + if ( parent !== null ) { -function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) { + callback( parent ); - var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof window.WebGL2RenderingContext ); - var _videoTextures = {}; + parent.traverseAncestors( callback ); - // + } - function clampToMaxSize( image, maxSize ) { + } - if ( image.width > maxSize || image.height > maxSize ) { + updateMatrix() { - // Warning: Scaling through the canvas will only work with images that use - // premultiplied alpha. + this.matrix.compose( this.position, this.quaternion, this.scale ); - var scale = maxSize / Math.max( image.width, image.height ); + this.matrixWorldNeedsUpdate = true; - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = Math.floor( image.width * scale ); - canvas.height = Math.floor( image.height * scale ); + } - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height ); + updateMatrixWorld( force ) { - console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); + if ( this.matrixAutoUpdate ) this.updateMatrix(); - return canvas; + if ( this.matrixWorldNeedsUpdate || force ) { - } + if ( this.matrixWorldAutoUpdate === true ) { - return image; + if ( this.parent === null ) { - } + this.matrixWorld.copy( this.matrix ); - function isPowerOfTwo( image ) { + } else { - return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height ); + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - } + } + + } + + this.matrixWorldNeedsUpdate = false; - function makePowerOfTwo( image ) { + force = true; - if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) { + } - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = _Math.floorPowerOfTwo( image.width ); - canvas.height = _Math.floorPowerOfTwo( image.height ); + // make sure descendants are updated if required - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, canvas.width, canvas.height ); + const children = this.children; - console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - return canvas; + const child = children[ i ]; - } + child.updateMatrixWorld( force ); - return image; + } } - function textureNeedsPowerOfTwo( texture ) { + updateWorldMatrix( updateParents, updateChildren ) { - return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || - ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); + const parent = this.parent; - } + if ( updateParents === true && parent !== null ) { - function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { + parent.updateWorldMatrix( true, false ); - return texture.generateMipmaps && isPowerOfTwo && - texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + } - } + if ( this.matrixAutoUpdate ) this.updateMatrix(); - // Fallback filters for non-power-of-2 textures + if ( this.matrixWorldAutoUpdate === true ) { - function filterFallback( f ) { + if ( this.parent === null ) { - if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) { + this.matrixWorld.copy( this.matrix ); - return _gl.NEAREST; + } else { - } + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - return _gl.LINEAR; + } - } + } - // + // make sure descendants are updated - function onTextureDispose( event ) { + if ( updateChildren === true ) { - var texture = event.target; + const children = this.children; - texture.removeEventListener( 'dispose', onTextureDispose ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - deallocateTexture( texture ); + const child = children[ i ]; - if ( texture.isVideoTexture ) { + child.updateWorldMatrix( false, true ); - delete _videoTextures[ texture.id ]; + } } - infoMemory.textures --; - } - function onRenderTargetDispose( event ) { + toJSON( meta ) { - var renderTarget = event.target; + // meta is a string when called from JSON.stringify + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); + const output = {}; - deallocateRenderTarget( renderTarget ); + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { - infoMemory.textures --; + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {}, + nodes: {} + }; - } + output.metadata = { + version: 4.6, + type: 'Object', + generator: 'Object3D.toJSON' + }; - // + } - function deallocateTexture( texture ) { + // standard Object3D serialization - var textureProperties = properties.get( texture ); + const object = {}; - if ( texture.image && textureProperties.__image__webglTextureCube ) { + object.uuid = this.uuid; + object.type = this.type; - // cube texture + 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 ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; - _gl.deleteTexture( textureProperties.__image__webglTextureCube ); + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); - } else { + if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; - // 2D texture + // object specific properties - if ( textureProperties.__webglInit === undefined ) { return; } + if ( this.isInstancedMesh ) { - _gl.deleteTexture( textureProperties.__webglTexture ); + object.type = 'InstancedMesh'; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); } - // remove all webgl properties - properties.remove( texture ); + if ( this.isBatchedMesh ) { - } + object.type = 'BatchedMesh'; + object.perObjectFrustumCulled = this.perObjectFrustumCulled; + object.sortObjects = this.sortObjects; - function deallocateRenderTarget( renderTarget ) { + object.drawRanges = this._drawRanges; + object.reservedRanges = this._reservedRanges; - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); + object.visibility = this._visibility; + object.active = this._active; + object.bounds = this._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + boxMin: bound.box.min.toArray(), + boxMax: bound.box.max.toArray(), - if ( ! renderTarget ) { return; } + sphereInitialized: bound.sphereInitialized, + sphereRadius: bound.sphere.radius, + sphereCenter: bound.sphere.center.toArray() + } ) ); - if ( textureProperties.__webglTexture !== undefined ) { + object.maxInstanceCount = this._maxInstanceCount; + object.maxVertexCount = this._maxVertexCount; + object.maxIndexCount = this._maxIndexCount; - _gl.deleteTexture( textureProperties.__webglTexture ); + object.geometryInitialized = this._geometryInitialized; + object.geometryCount = this._geometryCount; - } + object.matricesTexture = this._matricesTexture.toJSON( meta ); - if ( renderTarget.depthTexture ) { + if ( this._colorsTexture !== null ) object.colorsTexture = this._colorsTexture.toJSON( meta ); - renderTarget.depthTexture.dispose(); + if ( this.boundingSphere !== null ) { - } + object.boundingSphere = { + center: object.boundingSphere.center.toArray(), + radius: object.boundingSphere.radius + }; - if ( renderTarget.isWebGLRenderTargetCube ) { + } - for ( var i = 0; i < 6; i ++ ) { + if ( this.boundingBox !== null ) { - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - if ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); } + object.boundingBox = { + min: object.boundingBox.min.toArray(), + max: object.boundingBox.max.toArray() + }; } - } else { + } - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - if ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); } + // - } + function serialize( library, element ) { - properties.remove( renderTarget.texture ); - properties.remove( renderTarget ); + if ( library[ element.uuid ] === undefined ) { - } + library[ element.uuid ] = element.toJSON( meta ); - // + } + return element.uuid; + } - function setTexture2D( texture, slot ) { + if ( this.isScene ) { - var textureProperties = properties.get( texture ); + if ( this.background ) { - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + if ( this.background.isColor ) { - var image = texture.image; + object.background = this.background.toJSON(); - if ( image === undefined ) { + } else if ( this.background.isTexture ) { - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture ); + object.background = this.background.toJSON( meta ).uuid; - } else if ( image.complete === false ) { + } - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture ); + } - } else { + if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { - uploadTexture( textureProperties, texture, slot ); - return; + object.environment = this.environment.toJSON( meta ).uuid; } - } + } else if ( this.isMesh || this.isLine || this.isPoints ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); + object.geometry = serialize( meta.geometries, this.geometry ); - } + const parameters = this.geometry.parameters; - function setTextureCube( texture, slot ) { + if ( parameters !== undefined && parameters.shapes !== undefined ) { - var textureProperties = properties.get( texture ); + const shapes = parameters.shapes; - if ( texture.image.length === 6 ) { + if ( Array.isArray( shapes ) ) { + + for ( let i = 0, l = shapes.length; i < l; i ++ ) { - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + const shape = shapes[ i ]; - if ( ! textureProperties.__image__webglTextureCube ) { + serialize( meta.shapes, shape ); - texture.addEventListener( 'dispose', onTextureDispose ); + } - textureProperties.__image__webglTextureCube = _gl.createTexture(); + } else { - infoMemory.textures ++; + serialize( meta.shapes, shapes ); } - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); + } - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + } - var isCompressed = ( texture && texture.isCompressedTexture ); - var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); + if ( this.isSkinnedMesh ) { - var cubeImage = []; + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); - for ( var i = 0; i < 6; i ++ ) { + if ( this.skeleton !== undefined ) { - if ( ! isCompressed && ! isDataTexture ) { + serialize( meta.skeletons, this.skeleton ); - cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize ); + object.skeleton = this.skeleton.uuid; - } else { + } - cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; + } - } + if ( this.material !== undefined ) { - } + if ( Array.isArray( this.material ) ) { - var image = cubeImage[ 0 ], - isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); + const uuids = []; - setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); + for ( let i = 0, l = this.material.length; i < l; i ++ ) { - for ( var i = 0; i < 6; i ++ ) { + uuids.push( serialize( meta.materials, this.material[ i ] ) ); - if ( ! isCompressed ) { + } - if ( isDataTexture ) { + object.material = uuids; - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); + } else { - } else { + object.material = serialize( meta.materials, this.material ); - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] ); + } - } + } - } else { + // - var mipmap, mipmaps = cubeImage[ i ].mipmaps; + if ( this.children.length > 0 ) { - for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) { + object.children = []; - mipmap = mipmaps[ j ]; + for ( let i = 0; i < this.children.length; i ++ ) { - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { + object.children.push( this.children[ i ].toJSON( meta ).object ); - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { + } - state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + } - } else { + // - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); + if ( this.animations.length > 0 ) { - } + object.animations = []; - } else { + for ( let i = 0; i < this.animations.length; i ++ ) { - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + const animation = this.animations[ i ]; - } + object.animations.push( serialize( meta.animations, animation ) ); - } + } - } + } - } + if ( isRootObject ) { - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { + 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 ); - _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); + 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; - } + } - textureProperties.__version = texture.version; + output.object = object; - if ( texture.onUpdate ) { texture.onUpdate( texture ); } + return output; - } else { + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { + + const values = []; + for ( const key in cache ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); + const data = cache[ key ]; + delete data.metadata; + values.push( data ); } + return values; + } } - function setTextureCubeDynamic( texture, slot ) { + clone( recursive ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture ); + return new this.constructor().copy( this, recursive ); } - function setTextureParameters( textureType, texture, isPowerOfTwoImage ) { - - var extension; - - if ( isPowerOfTwoImage ) { - - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); + copy( source, recursive = true ) { - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( 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 ); + this.name = source.name; - if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { + this.up.copy( source.up ); - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture ); + 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 ); - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); + this.matrixAutoUpdate = source.matrixAutoUpdate; - if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { + this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture ); + 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; - extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + this.animations = source.animations.slice(); - if ( extension ) { + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) { return; } - if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) { return; } + if ( recursive === true ) { - if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { + for ( let i = 0; i < source.children.length; i ++ ) { - _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); - properties.get( texture ).__currentAnisotropy = texture.anisotropy; + const child = source.children[ i ]; + this.add( child.clone() ); } } - } - - function uploadTexture( textureProperties, texture, slot ) { - - if ( textureProperties.__webglInit === undefined ) { + return this; - textureProperties.__webglInit = true; + } - texture.addEventListener( 'dispose', onTextureDispose ); +} - textureProperties.__webglTexture = _gl.createTexture(); +Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); +Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; +Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; - if ( texture.isVideoTexture ) { +const _v0$2 = /*@__PURE__*/ new Vector3(); +const _v1$3 = /*@__PURE__*/ new Vector3(); +const _v2$2 = /*@__PURE__*/ new Vector3(); +const _v3$2 = /*@__PURE__*/ new Vector3(); - _videoTextures[ texture.id ] = texture; +const _vab = /*@__PURE__*/ new Vector3(); +const _vac = /*@__PURE__*/ new Vector3(); +const _vbc = /*@__PURE__*/ new Vector3(); +const _vap = /*@__PURE__*/ new Vector3(); +const _vbp = /*@__PURE__*/ new Vector3(); +const _vcp = /*@__PURE__*/ new Vector3(); - } +class Triangle { - infoMemory.textures ++; + constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { - } + this.a = a; + this.b = b; + this.c = c; - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); + } - _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 ); + static getNormal( a, b, c, target ) { - var image = clampToMaxSize( texture.image, capabilities.maxTextureSize ); + target.subVectors( c, b ); + _v0$2.subVectors( a, b ); + target.cross( _v0$2 ); - if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) { + const targetLengthSq = target.lengthSq(); + if ( targetLengthSq > 0 ) { - image = makePowerOfTwo( image ); + return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); } - var isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); + return target.set( 0, 0, 0 ); - setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); + } - var mipmap, mipmaps = texture.mipmaps; + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + static getBarycoord( point, a, b, c, target ) { - if ( texture.isDepthTexture ) { + _v0$2.subVectors( c, a ); + _v1$3.subVectors( b, a ); + _v2$2.subVectors( point, a ); - // populate depth texture with dummy data + const dot00 = _v0$2.dot( _v0$2 ); + const dot01 = _v0$2.dot( _v1$3 ); + const dot02 = _v0$2.dot( _v2$2 ); + const dot11 = _v1$3.dot( _v1$3 ); + const dot12 = _v1$3.dot( _v2$2 ); - var internalFormat = _gl.DEPTH_COMPONENT; + const denom = ( dot00 * dot11 - dot01 * dot01 ); - if ( texture.type === FloatType ) { + // collinear or singular triangle + if ( denom === 0 ) { - if ( ! _isWebGL2 ) { throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); } - internalFormat = _gl.DEPTH_COMPONENT32F; + target.set( 0, 0, 0 ); + return null; - } else if ( _isWebGL2 ) { + } - // WebGL 2.0 requires signed internalformat for glTexImage2D - internalFormat = _gl.DEPTH_COMPONENT16; + const invDenom = 1 / denom; + const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - } + // barycentric coordinates must always sum to 1 + return target.set( 1 - u - v, v, u ); - if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) { + } - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { + static containsPoint( point, a, b, c ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); + // if the triangle is degenerate then we can't contain a point + if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) { - texture.type = UnsignedShortType; - glType = utils.convert( texture.type ); + return false; - } + } - } + return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 ); - // Depth stencil textures need the DEPTH_STENCIL internal format - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.format === DepthStencilFormat ) { + } - internalFormat = _gl.DEPTH_STENCIL; + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedInt248Type ) { + if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); + target.x = 0; + target.y = 0; + if ( 'z' in target ) target.z = 0; + if ( 'w' in target ) target.w = 0; + return null; - texture.type = UnsignedInt248Type; - glType = utils.convert( texture.type ); + } - } + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$2.x ); + target.addScaledVector( v2, _v3$2.y ); + target.addScaledVector( v3, _v3$2.z ); - } + return target; - state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null ); + } - } else if ( texture.isDataTexture ) { + static isFrontFacing( a, b, c, direction ) { - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels + _v0$2.subVectors( c, b ); + _v1$3.subVectors( a, b ); - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { + // strictly front facing + return ( _v0$2.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + } - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + set( a, b, c ) { - } + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); - texture.generateMipmaps = false; + return this; - } else { + } - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data ); + setFromPointsAndIndices( points, i0, i1, i2 ) { - } + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); - } else if ( texture.isCompressedTexture ) { + return this; - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + } - mipmap = mipmaps[ i ]; + setFromAttributeAndIndices( attribute, i0, i1, i2 ) { - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { + this.a.fromBufferAttribute( attribute, i0 ); + this.b.fromBufferAttribute( attribute, i1 ); + this.c.fromBufferAttribute( attribute, i2 ); - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { + return this; - state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + } - } else { + clone() { - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); + return new this.constructor().copy( this ); - } + } - } else { + copy( triangle ) { - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); - } + return this; - } + } - } else { + getArea() { - // regular Texture (image, video, canvas) + _v0$2.subVectors( this.c, this.b ); + _v1$3.subVectors( this.a, this.b ); - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels + return _v0$2.cross( _v1$3 ).length() * 0.5; - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { + } - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + getMidpoint( target ) { - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap ); + return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - } + } - texture.generateMipmaps = false; + getNormal( target ) { - } else { + return Triangle.getNormal( this.a, this.b, this.c, target ); - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image ); + } - } + getPlane( target ) { - } + return target.setFromCoplanarPoints( this.a, this.b, this.c ); - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { _gl.generateMipmap( _gl.TEXTURE_2D ); } + } - textureProperties.__version = texture.version; + getBarycoord( point, target ) { - if ( texture.onUpdate ) { texture.onUpdate( texture ); } + return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); } - // Render targets - - // Setup storage for target texture and bind it to correct framebuffer - function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { + getInterpolation( point, v1, v2, v3, target ) { - var glFormat = utils.convert( renderTarget.texture.format ); - var glType = utils.convert( renderTarget.texture.type ); - state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); } - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer - function setupRenderBufferStorage( renderbuffer, renderTarget ) { - - _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); - - if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { + containsPoint( point ) { - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); + return Triangle.containsPoint( point, this.a, this.b, this.c ); - } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { + } - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); + isFrontFacing( direction ) { - } else { + return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); - // FIXME: We don't support !depth !stencil - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height ); + } - } + intersectsBox( box ) { - _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); + return box.intersectsTriangle( this ); } - // Setup resources for a Depth Texture for a FBO (needs an extension) - function setupDepthTexture( framebuffer, renderTarget ) { + closestPointToPoint( p, target ) { - var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - if ( isCube ) { throw new Error( 'Depth Texture with cube render targets is not supported' ); } + const a = this.a, b = this.b, c = this.c; + let v, w; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + // algorithm thanks to Real-Time Collision Detection by Christer Ericson, + // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., + // under the accompanying license; see chapter 5.1.5 for detailed explanation. + // basically, we're distinguishing which of the voronoi regions of the triangle + // the point lies in with the minimum amount of redundant computation. - if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { + _vab.subVectors( b, a ); + _vac.subVectors( c, a ); + _vap.subVectors( p, a ); + const d1 = _vab.dot( _vap ); + const d2 = _vac.dot( _vap ); + if ( d1 <= 0 && d2 <= 0 ) { - throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); + // vertex region of A; barycentric coords (1, 0, 0) + return target.copy( a ); } - // upload an empty depth texture with framebuffer size - if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || - renderTarget.depthTexture.image.width !== renderTarget.width || - renderTarget.depthTexture.image.height !== renderTarget.height ) { + _vbp.subVectors( p, b ); + const d3 = _vab.dot( _vbp ); + const d4 = _vac.dot( _vbp ); + if ( d3 >= 0 && d4 <= d3 ) { - renderTarget.depthTexture.image.width = renderTarget.width; - renderTarget.depthTexture.image.height = renderTarget.height; - renderTarget.depthTexture.needsUpdate = true; + // vertex region of B; barycentric coords (0, 1, 0) + return target.copy( b ); } - setTexture2D( renderTarget.depthTexture, 0 ); + const vc = d1 * d4 - d3 * d2; + if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { - var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + v = d1 / ( d1 - d3 ); + // edge region of AB; barycentric coords (1-v, v, 0) + return target.copy( a ).addScaledVector( _vab, v ); - if ( renderTarget.depthTexture.format === DepthFormat ) { + } - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + _vcp.subVectors( p, c ); + const d5 = _vab.dot( _vcp ); + const d6 = _vac.dot( _vcp ); + if ( d6 >= 0 && d5 <= d6 ) { - } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { + // vertex region of C; barycentric coords (0, 0, 1) + return target.copy( c ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + } - } else { + const vb = d5 * d2 - d1 * d6; + if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { - throw new Error( 'Unknown depthTexture format' ); + w = d2 / ( d2 - d6 ); + // edge region of AC; barycentric coords (1-w, 0, w) + return target.copy( a ).addScaledVector( _vac, w ); } - } + const va = d3 * d6 - d5 * d4; + if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { - // Setup GL resources for a non-texture depth buffer - function setupDepthRenderbuffer( renderTarget ) { + _vbc.subVectors( c, b ); + w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + // edge region of BC; barycentric coords (0, 1-w, w) + return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC - var renderTargetProperties = properties.get( renderTarget ); + } - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); + // face region + const denom = 1 / ( va + vb + vc ); + // u = va * denom + v = vb * denom; + w = vc * denom; - if ( renderTarget.depthTexture ) { + return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); - if ( isCube ) { throw new Error( 'target.depthTexture not supported in Cube render targets' ); } + } - setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); + equals( triangle ) { - } else { + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - if ( isCube ) { + } - renderTargetProperties.__webglDepthbuffer = []; +} + +const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - for ( var i = 0; i < 6; i ++ ) { +const _hslA = { h: 0, s: 0, l: 0 }; +const _hslB = { h: 0, s: 0, l: 0 }; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); - renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget ); +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; - } else { +} - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget ); +class Color { - } + constructor( r, g, b ) { - } + this.isColor = true; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); + this.r = 1; + this.g = 1; + this.b = 1; - } + return this.set( r, g, b ); - // Set up GL resources for the render target - function setupRenderTarget( renderTarget ) { + } - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); + set( r, g, b ) { - renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); + if ( g === undefined && b === undefined ) { - textureProperties.__webglTexture = _gl.createTexture(); + // r is THREE.Color, hex or string - infoMemory.textures ++; + const value = r; - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); + if ( value && value.isColor ) { - // Setup framebuffer + this.copy( value ); - if ( isCube ) { + } else if ( typeof value === 'number' ) { - renderTargetProperties.__webglFramebuffer = []; + this.setHex( value ); - for ( var i = 0; i < 6; i ++ ) { + } else if ( typeof value === 'string' ) { - renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); + this.setStyle( value ); } } else { - renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); + this.setRGB( r, g, b ); } - // Setup color buffer + return this; - if ( isCube ) { + } - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo ); + setScalar( scalar ) { + + this.r = scalar; + this.g = scalar; + this.b = scalar; - for ( var i = 0; i < 6; i ++ ) { + return this; - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i ); + } - } + setHex( hex, colorSpace = SRGBColorSpace ) { - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) { _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); } - state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); + hex = Math.floor( hex ); - } else { + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) { _gl.generateMipmap( _gl.TEXTURE_2D ); } - state.bindTexture( _gl.TEXTURE_2D, null ); + return this; - } + } - // Setup depth and stencil buffers + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - if ( renderTarget.depthBuffer ) { + this.r = r; + this.g = g; + this.b = b; - setupDepthRenderbuffer( renderTarget ); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - } + return this; } - function updateRenderTargetMipmap( renderTarget ) { - - var texture = renderTarget.texture; - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { - if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); - var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; - var webglTexture = properties.get( texture ).__webglTexture; + if ( s === 0 ) { - state.bindTexture( target, webglTexture ); - _gl.generateMipmap( target ); - state.bindTexture( target, null ); + 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; - function updateVideoTextures() { + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); - for ( var id in _videoTextures ) { + } - _videoTextures[ id ].update(); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - } + return this; } - this.setTexture2D = setTexture2D; - this.setTextureCube = setTextureCube; - this.setTextureCubeDynamic = setTextureCubeDynamic; - this.setupRenderTarget = setupRenderTarget; - this.updateRenderTargetMipmap = updateRenderTargetMipmap; - this.updateVideoTextures = updateVideoTextures; + setStyle( style, colorSpace = SRGBColorSpace ) { -} + function handleAlpha( string ) { -/** - * @author fordacious / fordacious.github.io - */ + if ( string === undefined ) return; -function WebGLProperties() { + if ( parseFloat( string ) < 1 ) { - var properties = {}; + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); - function get( object ) { + } - var uuid = object.uuid; - var map = properties[ uuid ]; + } - if ( map === undefined ) { - map = {}; - properties[ uuid ] = map; + let m; - } + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { - return map; + // rgb / hsl - } + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - function remove( object ) { + switch ( name ) { - delete properties[ object.uuid ]; + case 'rgb': + case 'rgba': - } + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - function clear() { + // rgb(255,0,0) rgba(255,0,0,0.5) - properties = {}; + handleAlpha( color[ 4 ] ); - } + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); - return { - get: get, - remove: remove, - clear: clear - }; + } -} + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) -function WebGLState( gl, extensions, utils ) { + handleAlpha( color[ 4 ] ); - function ColorBuffer() { + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); - var locked = false; + } - var color = new Vector4(); - var currentColorMask = null; - var currentColorClear = new Vector4( 0, 0, 0, 0 ); + break; - return { + case 'hsl': + case 'hsla': - setMask: function ( colorMask ) { + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - if ( currentColorMask !== colorMask && ! locked ) { + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - gl.colorMask( colorMask, colorMask, colorMask, colorMask ); - currentColorMask = colorMask; + handleAlpha( color[ 4 ] ); - } + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); - }, + } - setLocked: function ( lock ) { + break; - locked = lock; + default: - }, + console.warn( 'THREE.Color: Unknown color model ' + style ); - setClear: function ( r, g, b, a, premultipliedAlpha ) { + } - if ( premultipliedAlpha === true ) { + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - r *= a; g *= a; b *= a; + // hex color - } + const hex = m[ 1 ]; + const size = hex.length; - color.set( r, g, b, a ); + if ( size === 3 ) { - if ( currentColorClear.equals( color ) === false ) { + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); - gl.clearColor( r, g, b, a ); - currentColorClear.copy( color ); + } else if ( size === 6 ) { - } + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); - }, + } else { - reset: function () { + console.warn( 'THREE.Color: Invalid hex color ' + style ); - locked = false; + } - currentColorMask = null; - currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state + } else if ( style && style.length > 0 ) { - } + return this.setColorName( style, colorSpace ); - }; + } - } + return this; - function DepthBuffer() { + } - var locked = false; + setColorName( style, colorSpace = SRGBColorSpace ) { - var currentDepthMask = null; - var currentDepthFunc = null; - var currentDepthClear = null; + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - return { + if ( hex !== undefined ) { - setTest: function ( depthTest ) { + // red + this.setHex( hex, colorSpace ); - if ( depthTest ) { + } else { - enable( gl.DEPTH_TEST ); + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - } else { + } - disable( gl.DEPTH_TEST ); + return this; - } + } - }, + clone() { - setMask: function ( depthMask ) { + return new this.constructor( this.r, this.g, this.b ); - if ( currentDepthMask !== depthMask && ! locked ) { + } - gl.depthMask( depthMask ); - currentDepthMask = depthMask; + copy( color ) { - } + this.r = color.r; + this.g = color.g; + this.b = color.b; - }, + return this; - setFunc: function ( depthFunc ) { + } - if ( currentDepthFunc !== depthFunc ) { + copySRGBToLinear( color ) { - if ( depthFunc ) { + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - switch ( depthFunc ) { + return this; - case NeverDepth: + } - gl.depthFunc( gl.NEVER ); - break; + copyLinearToSRGB( color ) { - case AlwaysDepth: + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - gl.depthFunc( gl.ALWAYS ); - break; + return this; - case LessDepth: + } - gl.depthFunc( gl.LESS ); - break; + convertSRGBToLinear() { - case LessEqualDepth: + this.copySRGBToLinear( this ); - gl.depthFunc( gl.LEQUAL ); - break; + return this; - case EqualDepth: + } - gl.depthFunc( gl.EQUAL ); - break; + convertLinearToSRGB() { - case GreaterEqualDepth: + this.copyLinearToSRGB( this ); - gl.depthFunc( gl.GEQUAL ); - break; + return this; - case GreaterDepth: + } - gl.depthFunc( gl.GREATER ); - break; + getHex( colorSpace = SRGBColorSpace ) { - case NotEqualDepth: + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - gl.depthFunc( gl.NOTEQUAL ); - break; + return Math.round( clamp( _color$1.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color$1.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color$1.b * 255, 0, 255 ) ); - default: + } - gl.depthFunc( gl.LEQUAL ); + getHexString( colorSpace = SRGBColorSpace ) { - } + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); - } else { + } - gl.depthFunc( gl.LEQUAL ); + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { - } + // h,s,l ranges are in 0.0 - 1.0 - currentDepthFunc = depthFunc; + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - } + const r = _color$1.r, g = _color$1.g, b = _color$1.b; - }, + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - setLocked: function ( lock ) { + let hue, saturation; + const lightness = ( min + max ) / 2.0; - locked = lock; + if ( min === max ) { - }, + hue = 0; + saturation = 0; - setClear: function ( depth ) { + } else { - if ( currentDepthClear !== depth ) { + const delta = max - min; - gl.clearDepth( depth ); - currentDepthClear = depth; + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - } + switch ( max ) { - }, + 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; - reset: function () { + } - locked = false; + hue /= 6; - currentDepthMask = null; - currentDepthFunc = null; - currentDepthClear = null; + } - } + target.h = hue; + target.s = saturation; + target.l = lightness; - }; + return target; } - function StencilBuffer() { - - var locked = false; + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - var currentStencilMask = null; - var currentStencilFunc = null; - var currentStencilRef = null; - var currentStencilFuncMask = null; - var currentStencilFail = null; - var currentStencilZFail = null; - var currentStencilZPass = null; - var currentStencilClear = null; + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - return { + target.r = _color$1.r; + target.g = _color$1.g; + target.b = _color$1.b; - setTest: function ( stencilTest ) { + return target; - if ( stencilTest ) { + } - enable( gl.STENCIL_TEST ); + getStyle( colorSpace = SRGBColorSpace ) { - } else { + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - disable( gl.STENCIL_TEST ); + const r = _color$1.r, g = _color$1.g, b = _color$1.b; - } + if ( colorSpace !== SRGBColorSpace ) { - }, + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; - setMask: function ( stencilMask ) { + } - if ( currentStencilMask !== stencilMask && ! locked ) { + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; - gl.stencilMask( stencilMask ); - currentStencilMask = stencilMask; + } - } + offsetHSL( h, s, l ) { - }, + this.getHSL( _hslA ); - setFunc: function ( stencilFunc, stencilRef, stencilMask ) { + return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); - if ( currentStencilFunc !== stencilFunc || - currentStencilRef !== stencilRef || - currentStencilFuncMask !== stencilMask ) { + } - gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); + add( color ) { - currentStencilFunc = stencilFunc; - currentStencilRef = stencilRef; - currentStencilFuncMask = stencilMask; + this.r += color.r; + this.g += color.g; + this.b += color.b; - } + return this; - }, + } - setOp: function ( stencilFail, stencilZFail, stencilZPass ) { + addColors( color1, color2 ) { - if ( currentStencilFail !== stencilFail || - currentStencilZFail !== stencilZFail || - currentStencilZPass !== stencilZPass ) { + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); + return this; - currentStencilFail = stencilFail; - currentStencilZFail = stencilZFail; - currentStencilZPass = stencilZPass; + } - } + addScalar( s ) { - }, + this.r += s; + this.g += s; + this.b += s; - setLocked: function ( lock ) { + return this; - locked = lock; + } - }, + sub( color ) { - setClear: function ( stencil ) { + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - if ( currentStencilClear !== stencil ) { + return this; - gl.clearStencil( stencil ); - currentStencilClear = stencil; + } - } + multiply( color ) { - }, + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - reset: function () { + return this; - locked = false; + } - currentStencilMask = null; - currentStencilFunc = null; - currentStencilRef = null; - currentStencilFuncMask = null; - currentStencilFail = null; - currentStencilZFail = null; - currentStencilZPass = null; - currentStencilClear = null; + multiplyScalar( s ) { - } + this.r *= s; + this.g *= s; + this.b *= s; - }; + return this; } - // + lerp( color, alpha ) { - var colorBuffer = new ColorBuffer(); - var depthBuffer = new DepthBuffer(); - var stencilBuffer = new StencilBuffer(); + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; - var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var newAttributes = new Uint8Array( maxVertexAttributes ); - var enabledAttributes = new Uint8Array( maxVertexAttributes ); - var attributeDivisors = new Uint8Array( maxVertexAttributes ); + return this; - var capabilities = {}; + } - var compressedTextureFormats = null; + lerpColors( color1, color2, alpha ) { - var currentProgram = null; + 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; - var currentBlending = null; - var currentBlendEquation = null; - var currentBlendSrc = null; - var currentBlendDst = null; - var currentBlendEquationAlpha = null; - var currentBlendSrcAlpha = null; - var currentBlendDstAlpha = null; - var currentPremultipledAlpha = false; + return this; - var currentFlipSided = null; - var currentCullFace = null; + } - var currentLineWidth = null; + lerpHSL( color, alpha ) { - var currentPolygonOffsetFactor = null; - var currentPolygonOffsetUnits = null; + this.getHSL( _hslA ); + color.getHSL( _hslB ); - var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); - var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] ); - var lineWidthAvailable = parseFloat( version ) >= 1.0; + this.setHSL( h, s, l ); - var currentTextureSlot = null; - var currentBoundTextures = {}; + return this; - var currentScissor = new Vector4(); - var currentViewport = new Vector4(); + } - function createTexture( type, target, count ) { + setFromVector3( v ) { - var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. - var texture = gl.createTexture(); + this.r = v.x; + this.g = v.y; + this.b = v.z; - gl.bindTexture( type, texture ); - gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); + return this; - for ( var i = 0; i < count; i ++ ) { + } - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + applyMatrix3( m ) { - } + const r = this.r, g = this.g, b = this.b; + const e = m.elements; - return texture; + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; - } + return this; - var 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 ); + } - // init + equals( c ) { - colorBuffer.setClear( 0, 0, 0, 1 ); - depthBuffer.setClear( 1 ); - stencilBuffer.setClear( 0 ); + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - enable( gl.DEPTH_TEST ); - depthBuffer.setFunc( LessEqualDepth ); + } - setFlipSided( false ); - setCullFace( CullFaceBack ); - enable( gl.CULL_FACE ); + fromArray( array, offset = 0 ) { - enable( gl.BLEND ); - setBlending( NormalBlending ); + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; - // + return this; - function initAttributes() { + } - for ( var i = 0, l = newAttributes.length; i < l; i ++ ) { + toArray( array = [], offset = 0 ) { - newAttributes[ i ] = 0; + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; - } + return array; } - function enableAttribute( attribute ) { + fromBufferAttribute( attribute, index ) { - newAttributes[ attribute ] = 1; + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); - if ( enabledAttributes[ attribute ] === 0 ) { + return this; - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; + } - } + toJSON() { - if ( attributeDivisors[ attribute ] !== 0 ) { + return this.getHex(); - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + } - extension.vertexAttribDivisorANGLE( attribute, 0 ); - attributeDivisors[ attribute ] = 0; + *[ Symbol.iterator ]() { - } + yield this.r; + yield this.g; + yield this.b; } - function enableAttributeAndDivisor( attribute, meshPerAttribute ) { - - newAttributes[ attribute ] = 1; +} - if ( enabledAttributes[ attribute ] === 0 ) { +const _color$1 = /*@__PURE__*/ new Color(); - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; +Color.NAMES = _colorKeywords; - } +let _materialId = 0; - if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { +class Material extends EventDispatcher { - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + constructor() { - extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute ); - attributeDivisors[ attribute ] = meshPerAttribute; + super(); - } + this.isMaterial = true; - } + Object.defineProperty( this, 'id', { value: _materialId ++ } ); - function disableUnusedAttributes() { + this.uuid = generateUUID(); - for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) { + this.name = ''; + this.type = 'Material'; - if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; + this.opacity = 1; + this.transparent = false; + this.alphaHash = false; - } + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + this.blendColor = new Color( 0, 0, 0 ); + this.blendAlpha = 0; - } + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; - } + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; - function enable( id ) { + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; - if ( capabilities[ id ] !== true ) { + this.shadowSide = null; - gl.enable( id ); - capabilities[ id ] = true; + this.colorWrite = true; - } + this.precision = null; // override the renderer's default precision for this material - } + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; - function disable( id ) { + this.dithering = false; - if ( capabilities[ id ] !== false ) { + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; - gl.disable( id ); - capabilities[ id ] = false; + this.visible = true; - } + this.toneMapped = true; - } + this.userData = {}; - function getCompressedTextureFormats() { + this.version = 0; - if ( compressedTextureFormats === null ) { + this._alphaTest = 0; - compressedTextureFormats = []; + } - if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) || - extensions.get( 'WEBGL_compressed_texture_s3tc' ) || - extensions.get( 'WEBGL_compressed_texture_etc1' ) ) { + get alphaTest() { - var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS ); + return this._alphaTest; - for ( var i = 0; i < formats.length; i ++ ) { + } - compressedTextureFormats.push( formats[ i ] ); + set alphaTest( value ) { - } + if ( this._alphaTest > 0 !== value > 0 ) { - } + this.version ++; } - return compressedTextureFormats; + this._alphaTest = value; } - function useProgram( program ) { + onBeforeCompile( /* shaderobject, renderer */ ) {} - if ( currentProgram !== program ) { + customProgramCacheKey() { - gl.useProgram( program ); + return this.onBeforeCompile.toString(); - currentProgram = program; + } - return true; + setValues( values ) { - } + if ( values === undefined ) return; - return false; + for ( const key in values ) { - } + const newValue = values[ key ]; - function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { + if ( newValue === undefined ) { - if ( blending !== NoBlending ) { + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; - enable( gl.BLEND ); + } - } else { + const currentValue = this[ key ]; - disable( gl.BLEND ); + if ( currentValue === undefined ) { - } + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; - if ( blending !== CustomBlending ) { + } - if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { + if ( currentValue && currentValue.isColor ) { - switch ( blending ) { + currentValue.set( newValue ); - case AdditiveBlending: + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { - if ( premultipliedAlpha ) { + currentValue.copy( newValue ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); + } else { - } else { + this[ key ] = newValue; - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + } - } - break; + } + + } - case SubtractiveBlending: + toJSON( meta ) { - if ( premultipliedAlpha ) { + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); + if ( isRootObject ) { - } else { + meta = { + textures: {}, + images: {} + }; - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); + } - } - break; + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; - case MultiplyBlending: + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; - if ( premultipliedAlpha ) { + if ( this.name !== '' ) data.name = this.name; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); - } else { + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; - } - break; + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; - default: + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { - if ( premultipliedAlpha ) { + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + } - } else { + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + 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(); - currentBlendEquation = null; - currentBlendSrc = null; - currentBlendDst = null; - currentBlendEquationAlpha = null; - currentBlendSrcAlpha = null; - currentBlendDstAlpha = null; + } - } else { + if ( this.dispersion !== undefined ) data.dispersion = this.dispersion; - blendEquationAlpha = blendEquationAlpha || blendEquation; - blendSrcAlpha = blendSrcAlpha || blendSrc; - blendDstAlpha = blendDstAlpha || blendDst; + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; - if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { - gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; - currentBlendEquation = blendEquation; - currentBlendEquationAlpha = blendEquationAlpha; + } - } + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { - if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; - gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); + } - currentBlendSrc = blendSrc; - currentBlendDst = blendDst; - currentBlendSrcAlpha = blendSrcAlpha; - currentBlendDstAlpha = blendDstAlpha; + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; - } + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; } - currentBlending = blending; - currentPremultipledAlpha = premultipliedAlpha; + 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 ) { - function setMaterial( material, frontFaceCW ) { + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; - material.side === DoubleSide - ? disable( gl.CULL_FACE ) - : enable( gl.CULL_FACE ); + } - var flipSided = ( material.side === BackSide ); - if ( frontFaceCW ) { flipSided = ! flipSided; } + if ( this.aoMap && this.aoMap.isTexture ) { - setFlipSided( flipSided ); + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; - material.transparent === true - ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ) - : setBlending( NoBlending ); + } - depthBuffer.setFunc( material.depthFunc ); - depthBuffer.setTest( material.depthTest ); - depthBuffer.setMask( material.depthWrite ); - colorBuffer.setMask( material.colorWrite ); + if ( this.bumpMap && this.bumpMap.isTexture ) { - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; - } + } - // + if ( this.normalMap && this.normalMap.isTexture ) { - function setFlipSided( flipSided ) { + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); - if ( currentFlipSided !== flipSided ) { + } - if ( flipSided ) { + if ( this.displacementMap && this.displacementMap.isTexture ) { - gl.frontFace( gl.CW ); + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; - } else { + } - gl.frontFace( gl.CCW ); + 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; - currentFlipSided = flipSided; + if ( this.envMap && this.envMap.isTexture ) { - } + data.envMap = this.envMap.toJSON( meta ).uuid; - } + if ( this.combine !== undefined ) data.combine = this.combine; - function setCullFace( cullFace ) { + } - if ( cullFace !== CullFaceNone ) { + if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray(); + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; - enable( gl.CULL_FACE ); + if ( this.gradientMap && this.gradientMap.isTexture ) { - if ( cullFace !== currentCullFace ) { + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; - if ( cullFace === CullFaceBack ) { + } - gl.cullFace( gl.BACK ); + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors === true ) data.vertexColors = true; + + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = true; + + if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; + if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; + if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; + if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; + if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; + if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; + if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); + if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; + + if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; + if ( this.depthTest === false ) data.depthTest = this.depthTest; + if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; + if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; + + if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; + if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; + if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; + if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask; + if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; + if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; + if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; + if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; - } else if ( cullFace === CullFaceFront ) { + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; - gl.cullFace( gl.FRONT ); + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; - } else { + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; - gl.cullFace( gl.FRONT_AND_BACK ); + if ( this.dithering === true ) data.dithering = true; - } + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaHash === true ) data.alphaHash = true; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; + if ( this.forceSinglePass === true ) data.forceSinglePass = true; - } + if ( this.wireframe === true ) data.wireframe = true; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; - } else { + if ( this.flatShading === true ) data.flatShading = true; - disable( gl.CULL_FACE ); + if ( this.visible === false ) data.visible = false; - } + if ( this.toneMapped === false ) data.toneMapped = false; - currentCullFace = cullFace; + if ( this.fog === false ) data.fog = false; - } + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; - function setLineWidth( width ) { + // TODO: Copied from Object3D.toJSON - if ( width !== currentLineWidth ) { + function extractFromCache( cache ) { - if ( lineWidthAvailable ) { gl.lineWidth( width ); } + const values = []; - currentLineWidth = width; + for ( const key in cache ) { - } + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - } + } - function setPolygonOffset( polygonOffset, factor, units ) { + return values; - if ( polygonOffset ) { + } - enable( gl.POLYGON_OFFSET_FILL ); + if ( isRootObject ) { - if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); - gl.polygonOffset( factor, units ); + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; - currentPolygonOffsetFactor = factor; - currentPolygonOffsetUnits = units; + } - } + return data; - } else { + } - disable( gl.POLYGON_OFFSET_FILL ); + clone() { - } + return new this.constructor().copy( this ); } - function setScissorTest( scissorTest ) { + copy( source ) { - if ( scissorTest ) { + this.name = source.name; - enable( gl.SCISSOR_TEST ); + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; - } else { + this.opacity = source.opacity; + this.transparent = source.transparent; - disable( gl.SCISSOR_TEST ); + 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.blendColor.copy( source.blendColor ); + this.blendAlpha = source.blendAlpha; - } + 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; - // texture + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; - function activeTexture( webglSlot ) { + if ( srcPlanes !== null ) { + + const n = srcPlanes.length; + dstPlanes = new Array( n ); - if ( webglSlot === undefined ) { webglSlot = gl.TEXTURE0 + maxTextures - 1; } + for ( let i = 0; i !== n; ++ i ) { - if ( currentTextureSlot !== webglSlot ) { + dstPlanes[ i ] = srcPlanes[ i ].clone(); - gl.activeTexture( webglSlot ); - currentTextureSlot = webglSlot; + } } - } + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; - function bindTexture( webglType, webglTexture ) { + this.shadowSide = source.shadowSide; - if ( currentTextureSlot === null ) { + this.colorWrite = source.colorWrite; - activeTexture(); + this.precision = source.precision; - } + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; - var boundTexture = currentBoundTextures[ currentTextureSlot ]; + this.dithering = source.dithering; - if ( boundTexture === undefined ) { + this.alphaTest = source.alphaTest; + this.alphaHash = source.alphaHash; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; - boundTexture = { type: undefined, texture: undefined }; - currentBoundTextures[ currentTextureSlot ] = boundTexture; + this.visible = source.visible; - } + this.toneMapped = source.toneMapped; - if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); + return this; - boundTexture.type = webglType; - boundTexture.texture = webglTexture; + } - } + dispose() { - } + this.dispatchEvent( { type: 'dispose' } ); - function compressedTexImage2D() { + } - try { + set needsUpdate( value ) { - gl.compressedTexImage2D.apply( gl, arguments ); + if ( value === true ) this.version ++; - } catch ( error ) { + } - console.error( 'THREE.WebGLState:', error ); + onBuild( /* shaderobject, renderer */ ) { - } + console.warn( 'Material: onBuild() has been removed.' ); // @deprecated, r166 } - function texImage2D() { + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) { - try { + console.warn( 'Material: onBeforeRender() has been removed.' ); // @deprecated, r166 - gl.texImage2D.apply( gl, arguments ); + } - } catch ( error ) { - console.error( 'THREE.WebGLState:', error ); +} - } +class MeshBasicMaterial extends Material { - } + constructor( parameters ) { - // + super(); - function scissor( scissor ) { + this.isMeshBasicMaterial = true; - if ( currentScissor.equals( scissor ) === false ) { + this.type = 'MeshBasicMaterial'; - gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); - currentScissor.copy( scissor ); + this.color = new Color( 0xffffff ); // emissive - } + this.map = null; - } + this.lightMap = null; + this.lightMapIntensity = 1.0; - function viewport( viewport ) { + this.aoMap = null; + this.aoMapIntensity = 1.0; - if ( currentViewport.equals( viewport ) === false ) { + this.specularMap = null; - gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); - currentViewport.copy( viewport ); + this.alphaMap = null; - } + this.envMap = null; + this.envMapRotation = new Euler(); + 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; - function reset() { + this.setValues( parameters ); - for ( var i = 0; i < enabledAttributes.length; i ++ ) { + } - if ( enabledAttributes[ i ] === 1 ) { + copy( source ) { - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; + super.copy( source ); - } + this.color.copy( source.color ); - } + this.map = source.map; - capabilities = {}; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - compressedTextureFormats = null; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - currentTextureSlot = null; - currentBoundTextures = {}; + this.specularMap = source.specularMap; - currentProgram = null; + this.alphaMap = source.alphaMap; - currentBlending = null; + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; - currentFlipSided = null; - currentCullFace = null; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - colorBuffer.reset(); - depthBuffer.reset(); - stencilBuffer.reset(); + this.fog = source.fog; + + return this; } - return { +} - buffers: { - color: colorBuffer, - depth: depthBuffer, - stencil: stencilBuffer - }, +const _vector$9 = /*@__PURE__*/ new Vector3(); +const _vector2$1 = /*@__PURE__*/ new Vector2(); - initAttributes: initAttributes, - enableAttribute: enableAttribute, - enableAttributeAndDivisor: enableAttributeAndDivisor, - disableUnusedAttributes: disableUnusedAttributes, - enable: enable, - disable: disable, - getCompressedTextureFormats: getCompressedTextureFormats, +class BufferAttribute { - useProgram: useProgram, + constructor( array, itemSize, normalized = false ) { - setBlending: setBlending, - setMaterial: setMaterial, + if ( Array.isArray( array ) ) { - setFlipSided: setFlipSided, - setCullFace: setCullFace, + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - setLineWidth: setLineWidth, - setPolygonOffset: setPolygonOffset, + } - setScissorTest: setScissorTest, + this.isBufferAttribute = true; - activeTexture: activeTexture, - bindTexture: bindTexture, - compressedTexImage2D: compressedTexImage2D, - texImage2D: texImage2D, + this.name = ''; - scissor: scissor, - viewport: viewport, + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized; - reset: reset + this.usage = StaticDrawUsage; + this._updateRange = { offset: 0, count: - 1 }; + this.updateRanges = []; + this.gpuType = FloatType; - }; + this.version = 0; -} + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + onUploadCallback() {} -function WebGLCapabilities( gl, extensions, parameters ) { + set needsUpdate( value ) { - var maxAnisotropy; + if ( value === true ) this.version ++; - function getMaxAnisotropy() { + } - if ( maxAnisotropy !== undefined ) { return maxAnisotropy; } + get updateRange() { - var extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 + return this._updateRange; - if ( extension !== null ) { + } - maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); + setUsage( value ) { - } else { + this.usage = value; - maxAnisotropy = 0; + return this; - } + } - return maxAnisotropy; + addUpdateRange( start, count ) { + + this.updateRanges.push( { start, count } ); } - function getMaxPrecision( precision ) { + clearUpdateRanges() { - if ( precision === 'highp' ) { + this.updateRanges.length = 0; - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { + } - return 'highp'; + 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; - precision = 'mediump'; + this.usage = source.usage; + this.gpuType = source.gpuType; - } + return this; - if ( precision === 'mediump' ) { + } - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { + copyAt( index1, attribute, index2 ) { - return 'mediump'; + 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 'lowp'; + return this; } - var precision = parameters.precision !== undefined ? parameters.precision : 'highp'; - var maxPrecision = getMaxPrecision( precision ); + copyArray( array ) { - if ( maxPrecision !== precision ) { + this.array.set( array ); - console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); - precision = maxPrecision; + return this; } - var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; + applyMatrix3( m ) { - var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); - var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); - var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); - var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); + if ( this.itemSize === 2 ) { - var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); - var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); - var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); + for ( let i = 0, l = this.count; i < l; i ++ ) { - var vertexTextures = maxVertexTextures > 0; - var floatFragmentTextures = !! extensions.get( 'OES_texture_float' ); - var floatVertexTextures = vertexTextures && floatFragmentTextures; + _vector2$1.fromBufferAttribute( this, i ); + _vector2$1.applyMatrix3( m ); - return { + this.setXY( i, _vector2$1.x, _vector2$1.y ); - getMaxAnisotropy: getMaxAnisotropy, - getMaxPrecision: getMaxPrecision, + } - precision: precision, - logarithmicDepthBuffer: logarithmicDepthBuffer, + } else if ( this.itemSize === 3 ) { - maxTextures: maxTextures, - maxVertexTextures: maxVertexTextures, - maxTextureSize: maxTextureSize, - maxCubemapSize: maxCubemapSize, + for ( let i = 0, l = this.count; i < l; i ++ ) { - maxAttributes: maxAttributes, - maxVertexUniforms: maxVertexUniforms, - maxVaryings: maxVaryings, - maxFragmentUniforms: maxFragmentUniforms, + _vector$9.fromBufferAttribute( this, i ); + _vector$9.applyMatrix3( m ); - vertexTextures: vertexTextures, - floatFragmentTextures: floatFragmentTextures, - floatVertexTextures: floatVertexTextures + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - }; + } -} + } -/** - * @author mrdoob / http://mrdoob.com/ - * @author greggman / http://games.greggman.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author tschw - */ + return this; -function PerspectiveCamera( fov, aspect, near, far ) { + } - Camera.call( this ); + applyMatrix4( m ) { - this.type = 'PerspectiveCamera'; + for ( let i = 0, l = this.count; i < l; i ++ ) { - this.fov = fov !== undefined ? fov : 50; - this.zoom = 1; + _vector$9.fromBufferAttribute( this, i ); - this.near = near !== undefined ? near : 0.1; - this.far = far !== undefined ? far : 2000; - this.focus = 10; + _vector$9.applyMatrix4( m ); - this.aspect = aspect !== undefined ? aspect : 1; - this.view = null; + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + } - this.updateProjectionMatrix(); + return this; -} + } -PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + applyNormalMatrix( m ) { - constructor: PerspectiveCamera, + for ( let i = 0, l = this.count; i < l; i ++ ) { - isPerspectiveCamera: true, + _vector$9.fromBufferAttribute( this, i ); - copy: function ( source, recursive ) { + _vector$9.applyNormalMatrix( m ); - Camera.prototype.copy.call( this, source, recursive ); + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.fov = source.fov; - this.zoom = source.zoom; + } - this.near = source.near; - this.far = source.far; - this.focus = source.focus; + return this; - this.aspect = source.aspect; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + } - this.filmGauge = source.filmGauge; - this.filmOffset = source.filmOffset; + transformDirection( m ) { - return this; + for ( let i = 0, l = this.count; i < l; i ++ ) { - }, + _vector$9.fromBufferAttribute( this, i ); - /** - * Sets the FOV by focal length in respect to the current .filmGauge. - * - * The default film gauge is 35, so that the focal length can be specified for - * a 35mm (full frame) camera. - * - * Values for focal length and film gauge must have the same unit. - */ - setFocalLength: function ( focalLength ) { + _vector$9.transformDirection( m ); - // see http://www.bobatkins.com/photography/technical/field_of_view.html - var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); - this.updateProjectionMatrix(); + } - }, + return this; - /** - * Calculates the focal length from the current .fov and .filmGauge. - */ - getFocalLength: function () { + } - var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); + set( value, offset = 0 ) { - return 0.5 * this.getFilmHeight() / vExtentSlope; + // Matching BufferAttribute constructor, do not normalize the array. + this.array.set( value, offset ); - }, + return this; - getEffectiveFOV: function () { + } - return _Math.RAD2DEG * 2 * Math.atan( - Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); + getComponent( index, component ) { - }, + let value = this.array[ index * this.itemSize + component ]; - getFilmWidth: function () { + if ( this.normalized ) value = denormalize( value, this.array ); - // film not completely covered in portrait format (aspect < 1) - return this.filmGauge * Math.min( this.aspect, 1 ); + return value; - }, + } - getFilmHeight: function () { + setComponent( index, component, value ) { - // film not completely covered in landscape format (aspect > 1) - return this.filmGauge / Math.max( this.aspect, 1 ); + if ( this.normalized ) value = normalize( value, this.array ); - }, + this.array[ index * this.itemSize + component ] = value; - /** - * Sets an offset in a larger frustum. This is useful for multi-window or - * multi-monitor/multi-machine setups. - * - * For example, if you have 3x2 monitors and each monitor is 1920x1080 and - * the monitors are in grid like this - * - * +---+---+---+ - * | A | B | C | - * +---+---+---+ - * | D | E | F | - * +---+---+---+ - * - * then for each monitor you would call it like this - * - * var w = 1920; - * var h = 1080; - * var fullWidth = w * 3; - * var fullHeight = h * 2; - * - * --A-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); - * - * Note there is no reason monitors have to be the same size or in a grid. - */ - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { + return this; - this.aspect = fullWidth / fullHeight; + } - if ( this.view === null ) { + getX( index ) { - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; + let x = this.array[ index * this.itemSize ]; - } + if ( this.normalized ) x = denormalize( x, this.array ); - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; + return x; - this.updateProjectionMatrix(); + } - }, + setX( index, x ) { - clearViewOffset: function () { + if ( this.normalized ) x = normalize( x, this.array ); - if ( this.view !== null ) { + this.array[ index * this.itemSize ] = x; - this.view.enabled = false; + return this; - } + } - this.updateProjectionMatrix(); + getY( index ) { - }, + let y = this.array[ index * this.itemSize + 1 ]; - updateProjectionMatrix: function () { + if ( this.normalized ) y = denormalize( y, this.array ); - var near = this.near, - top = near * Math.tan( - _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom, - height = 2 * top, - width = this.aspect * height, - left = - 0.5 * width, - view = this.view; + return y; - if ( this.view !== null && this.view.enabled ) { + } - var fullWidth = view.fullWidth, - fullHeight = view.fullHeight; + setY( index, y ) { - left += view.offsetX * width / fullWidth; - top -= view.offsetY * height / fullHeight; - width *= view.width / fullWidth; - height *= view.height / fullHeight; + if ( this.normalized ) y = normalize( y, this.array ); - } + this.array[ index * this.itemSize + 1 ] = y; - var skew = this.filmOffset; - if ( skew !== 0 ) { left += near * skew / this.getFilmWidth(); } + return this; - this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + } - }, + getZ( index ) { - toJSON: function ( meta ) { + let z = this.array[ index * this.itemSize + 2 ]; - var data = Object3D.prototype.toJSON.call( this, meta ); + if ( this.normalized ) z = denormalize( z, this.array ); - data.object.fov = this.fov; - data.object.zoom = this.zoom; + return z; - data.object.near = this.near; - data.object.far = this.far; - data.object.focus = this.focus; + } - data.object.aspect = this.aspect; + setZ( index, z ) { - if ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); } + if ( this.normalized ) z = normalize( z, this.array ); - data.object.filmGauge = this.filmGauge; - data.object.filmOffset = this.filmOffset; + this.array[ index * this.itemSize + 2 ] = z; - return data; + return this; } -} ); + getW( index ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + let w = this.array[ index * this.itemSize + 3 ]; -function ArrayCamera( array ) { + if ( this.normalized ) w = denormalize( w, this.array ); - PerspectiveCamera.call( this ); + return w; - this.cameras = array || []; + } -} + setW( index, w ) { -ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + if ( this.normalized ) w = normalize( w, this.array ); - constructor: ArrayCamera, + this.array[ index * this.itemSize + 3 ] = w; - isArrayCamera: true + return this; -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + setXY( index, x, y ) { -function WebVRManager( renderer ) { + index *= this.itemSize; - var scope = this; + if ( this.normalized ) { - var device = null; - var frameData = null; + x = normalize( x, this.array ); + y = normalize( y, this.array ); - var poseTarget = null; + } - if ( typeof window !== 'undefined' && 'VRFrameData' in window ) { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; - frameData = new window.VRFrameData(); + return this; } - var matrixWorldInverse = new Matrix4(); + setXYZ( index, x, y, z ) { - var cameraL = new PerspectiveCamera(); - cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); - cameraL.layers.enable( 1 ); - - var cameraR = new PerspectiveCamera(); - cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); - cameraR.layers.enable( 2 ); + index *= this.itemSize; - var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + if ( this.normalized ) { - // + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); - var currentSize, currentPixelRatio; + } - function onVRDisplayPresentChange() { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; - if ( device !== null && device.isPresenting ) { + return this; - var eyeParameters = device.getEyeParameters( 'left' ); - var renderWidth = eyeParameters.renderWidth; - var renderHeight = eyeParameters.renderHeight; + } - currentPixelRatio = renderer.getPixelRatio(); - currentSize = renderer.getSize(); + setXYZW( index, x, y, z, w ) { - renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); + index *= this.itemSize; - } else if ( scope.enabled ) { + if ( this.normalized ) { - renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); } + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + this.array[ index + 3 ] = w; + + return this; + } - if ( typeof window !== 'undefined' ) { + onUpload( callback ) { + + this.onUploadCallback = callback; - window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); + return this; } - // + clone() { - this.enabled = false; + return new this.constructor( this.array, this.itemSize ).copy( this ); - this.getDevice = function () { + } - return device; + toJSON() { - }; + const data = { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: Array.from( this.array ), + normalized: this.normalized + }; - this.setDevice = function ( value ) { + if ( this.name !== '' ) data.name = this.name; + if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; - if ( value !== undefined ) { device = value; } + return data; - }; + } - this.setPoseTarget = function ( object ) { +} - if ( object !== undefined ) { poseTarget = object; } +class Uint16BufferAttribute extends BufferAttribute { - }; + constructor( array, itemSize, normalized ) { - this.getCamera = function ( camera ) { + super( new Uint16Array( array ), itemSize, normalized ); - if ( device === null ) { return camera; } + } - device.depthNear = camera.near; - device.depthFar = camera.far; +} - device.getFrameData( frameData ); +class Uint32BufferAttribute extends BufferAttribute { - // + constructor( array, itemSize, normalized ) { - var pose = frameData.pose; - var poseObject = poseTarget !== null ? poseTarget : camera; + super( new Uint32Array( array ), itemSize, normalized ); - if ( pose.position !== null ) { + } - poseObject.position.fromArray( pose.position ); +} - } else { - poseObject.position.set( 0, 0, 0 ); +class Float32BufferAttribute extends BufferAttribute { - } + constructor( array, itemSize, normalized ) { - if ( pose.orientation !== null ) { + super( new Float32Array( array ), itemSize, normalized ); - poseObject.quaternion.fromArray( pose.orientation ); + } - } +} - poseObject.updateMatrixWorld(); +let _id$2 = 0; - if ( device.isPresenting === false ) { return camera; } +const _m1$2 = /*@__PURE__*/ new Matrix4(); +const _obj = /*@__PURE__*/ new Object3D(); +const _offset = /*@__PURE__*/ new Vector3(); +const _box$2 = /*@__PURE__*/ new Box3(); +const _boxMorphTargets = /*@__PURE__*/ new Box3(); +const _vector$8 = /*@__PURE__*/ new Vector3(); - // +class BufferGeometry extends EventDispatcher { - cameraL.near = camera.near; - cameraR.near = camera.near; + constructor() { - cameraL.far = camera.far; - cameraR.far = camera.far; + super(); - cameraVR.matrixWorld.copy( camera.matrixWorld ); - cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); + this.isBufferGeometry = true; - cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); - cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); + Object.defineProperty( this, 'id', { value: _id$2 ++ } ); - var parent = poseObject.parent; + this.uuid = generateUUID(); - if ( parent !== null ) { + this.name = ''; + this.type = 'BufferGeometry'; - matrixWorldInverse.getInverse( parent.matrixWorld ); + this.index = null; + this.attributes = {}; - cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); - cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); + this.morphAttributes = {}; + this.morphTargetsRelative = false; - } + this.groups = []; - // envMap and Mirror needs camera.matrixWorld + this.boundingBox = null; + this.boundingSphere = null; - cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); - cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); + this.drawRange = { start: 0, count: Infinity }; - cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); - cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); + this.userData = {}; - // HACK @mrdoob - // https://github.com/w3c/webvr/issues/203 + } - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + getIndex() { - // + return this.index; - var layers = device.getLayers(); + } - if ( layers.length ) { + setIndex( index ) { - var layer = layers[ 0 ]; + if ( Array.isArray( index ) ) { - if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { + this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - cameraL.bounds.fromArray( layer.leftBounds ); + } else { - } + this.index = index; - if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { + } - cameraR.bounds.fromArray( layer.rightBounds ); + return this; - } + } - } + getAttribute( name ) { - return cameraVR; + return this.attributes[ name ]; - }; + } - this.submitFrame = function () { + setAttribute( name, attribute ) { - if ( device && device.isPresenting ) { device.submitFrame(); } + this.attributes[ name ] = attribute; - }; + return this; - this.dispose = function () { + } - if ( typeof window !== 'undefined' ) { + deleteAttribute( name ) { - window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); + delete this.attributes[ name ]; - } + return this; - }; + } -} + hasAttribute( name ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + return this.attributes[ name ] !== undefined; -function WebGLExtensions( gl ) { + } - var extensions = {}; + addGroup( start, count, materialIndex = 0 ) { - return { + this.groups.push( { - get: function ( name ) { + start: start, + count: count, + materialIndex: materialIndex - if ( extensions[ name ] !== undefined ) { + } ); - return extensions[ name ]; + } - } + clearGroups() { - var extension; + this.groups = []; - 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; + setDrawRange( start, count ) { - 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; + this.drawRange.start = start; + this.drawRange.count = count; - 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; + applyMatrix4( matrix ) { - case 'WEBGL_compressed_texture_etc1': - extension = gl.getExtension( 'WEBGL_compressed_texture_etc1' ); - break; + const position = this.attributes.position; - default: - extension = gl.getExtension( name ); + if ( position !== undefined ) { - } + position.applyMatrix4( matrix ); - if ( extension === null ) { + position.needsUpdate = true; - console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); + } - } + const normal = this.attributes.normal; - extensions[ name ] = extension; + if ( normal !== undefined ) { - return extension; + const normalMatrix = new Matrix3().getNormalMatrix( matrix ); - } + normal.applyNormalMatrix( normalMatrix ); - }; + normal.needsUpdate = true; -} + } -/** - * @author tschw - */ + const tangent = this.attributes.tangent; -function WebGLClipping() { + if ( tangent !== undefined ) { - var scope = this, + tangent.transformDirection( matrix ); - globalState = null, - numGlobalPlanes = 0, - localClippingEnabled = false, - renderingShadows = false, + tangent.needsUpdate = true; - plane = new Plane(), - viewNormalMatrix = new Matrix3(), + } - uniform = { value: null, needsUpdate: false }; + if ( this.boundingBox !== null ) { - this.uniform = uniform; - this.numPlanes = 0; - this.numIntersection = 0; + this.computeBoundingBox(); - this.init = function ( planes, enableLocalClipping, camera ) { + } - var enabled = - planes.length !== 0 || - enableLocalClipping || - // enable state of previous frame - the clipping code has to - // run another frame in order to reset the state: - numGlobalPlanes !== 0 || - localClippingEnabled; + if ( this.boundingSphere !== null ) { - localClippingEnabled = enableLocalClipping; + this.computeBoundingSphere(); - globalState = projectPlanes( planes, camera, 0 ); - numGlobalPlanes = planes.length; + } - return enabled; + return this; - }; + } - this.beginShadows = function () { + applyQuaternion( q ) { - renderingShadows = true; - projectPlanes( null ); + _m1$2.makeRotationFromQuaternion( q ); - }; + this.applyMatrix4( _m1$2 ); - this.endShadows = function () { + return this; - renderingShadows = false; - resetGlobalState(); + } - }; + rotateX( angle ) { - this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) { + // rotate geometry around world x-axis - if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { + _m1$2.makeRotationX( angle ); - // there's no local clipping + this.applyMatrix4( _m1$2 ); - if ( renderingShadows ) { + return this; - // there's no global clipping + } - projectPlanes( null ); + rotateY( angle ) { - } else { + // rotate geometry around world y-axis - resetGlobalState(); + _m1$2.makeRotationY( angle ); - } + this.applyMatrix4( _m1$2 ); - } else { + return this; - var nGlobal = renderingShadows ? 0 : numGlobalPlanes, - lGlobal = nGlobal * 4, + } - dstArray = cache.clippingState || null; + rotateZ( angle ) { - uniform.value = dstArray; // ensure unique state + // rotate geometry around world z-axis - dstArray = projectPlanes( planes, camera, lGlobal, fromCache ); + _m1$2.makeRotationZ( angle ); - for ( var i = 0; i !== lGlobal; ++ i ) { + this.applyMatrix4( _m1$2 ); - dstArray[ i ] = globalState[ i ]; + return this; - } + } - cache.clippingState = dstArray; - this.numIntersection = clipIntersection ? this.numPlanes : 0; - this.numPlanes += nGlobal; + translate( x, y, z ) { - } + // translate geometry + _m1$2.makeTranslation( x, y, z ); - }; + this.applyMatrix4( _m1$2 ); - function resetGlobalState() { + return this; - if ( uniform.value !== globalState ) { + } - uniform.value = globalState; - uniform.needsUpdate = numGlobalPlanes > 0; + scale( x, y, z ) { - } + // scale geometry - scope.numPlanes = numGlobalPlanes; - scope.numIntersection = 0; + _m1$2.makeScale( x, y, z ); + + this.applyMatrix4( _m1$2 ); + + return this; } - function projectPlanes( planes, camera, dstOffset, skipTransform ) { + lookAt( vector ) { - var nPlanes = planes !== null ? planes.length : 0, - dstArray = null; + _obj.lookAt( vector ); - if ( nPlanes !== 0 ) { + _obj.updateMatrix(); - dstArray = uniform.value; + this.applyMatrix4( _obj.matrix ); - if ( skipTransform !== true || dstArray === null ) { + return this; - var flatSize = dstOffset + nPlanes * 4, - viewMatrix = camera.matrixWorldInverse; + } - viewNormalMatrix.getNormalMatrix( viewMatrix ); + center() { - if ( dstArray === null || dstArray.length < flatSize ) { + this.computeBoundingBox(); - dstArray = new Float32Array( flatSize ); + this.boundingBox.getCenter( _offset ).negate(); - } + this.translate( _offset.x, _offset.y, _offset.z ); - for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { + return this; - plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); + } - plane.normal.toArray( dstArray, i4 ); - dstArray[ i4 + 3 ] = plane.constant; + setFromPoints( points ) { - } + const position = []; - } + for ( let i = 0, l = points.length; i < l; i ++ ) { - uniform.value = dstArray; - uniform.needsUpdate = true; + const point = points[ i ]; + position.push( point.x, point.y, point.z || 0 ); } - scope.numPlanes = nPlanes; + this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - return dstArray; + return this; } -} + computeBoundingBox() { -/** - * @author thespite / http://www.twitter.com/thespite - */ + if ( this.boundingBox === null ) { -function WebGLUtils( gl, extensions ) { + this.boundingBox = new Box3(); + + } - function convert( p ) { + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; - var extension; + if ( position && position.isGLBufferAttribute ) { - if ( p === RepeatWrapping ) { return gl.REPEAT; } - if ( p === ClampToEdgeWrapping ) { return gl.CLAMP_TO_EDGE; } - if ( p === MirroredRepeatWrapping ) { return gl.MIRRORED_REPEAT; } + console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); - if ( p === NearestFilter ) { return gl.NEAREST; } - if ( p === NearestMipMapNearestFilter ) { return gl.NEAREST_MIPMAP_NEAREST; } - if ( p === NearestMipMapLinearFilter ) { return gl.NEAREST_MIPMAP_LINEAR; } + this.boundingBox.set( + new Vector3( - Infinity, - Infinity, - Infinity ), + new Vector3( + Infinity, + Infinity, + Infinity ) + ); - if ( p === LinearFilter ) { return gl.LINEAR; } - if ( p === LinearMipMapNearestFilter ) { return gl.LINEAR_MIPMAP_NEAREST; } - if ( p === LinearMipMapLinearFilter ) { return gl.LINEAR_MIPMAP_LINEAR; } + return; - if ( p === UnsignedByteType ) { return gl.UNSIGNED_BYTE; } - if ( p === UnsignedShort4444Type ) { return gl.UNSIGNED_SHORT_4_4_4_4; } - if ( p === UnsignedShort5551Type ) { return gl.UNSIGNED_SHORT_5_5_5_1; } - if ( p === UnsignedShort565Type ) { return gl.UNSIGNED_SHORT_5_6_5; } + } - if ( p === ByteType ) { return gl.BYTE; } - if ( p === ShortType ) { return gl.SHORT; } - if ( p === UnsignedShortType ) { return gl.UNSIGNED_SHORT; } - if ( p === IntType ) { return gl.INT; } - if ( p === UnsignedIntType ) { return gl.UNSIGNED_INT; } - if ( p === FloatType ) { return gl.FLOAT; } + if ( position !== undefined ) { - if ( p === HalfFloatType ) { + this.boundingBox.setFromBufferAttribute( position ); - extension = extensions.get( 'OES_texture_half_float' ); + // process morph attributes if present - if ( extension !== null ) { return extension.HALF_FLOAT_OES; } + if ( morphAttributesPosition ) { - } + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { - if ( p === AlphaFormat ) { return gl.ALPHA; } - if ( p === RGBFormat ) { return gl.RGB; } - if ( p === RGBAFormat ) { return gl.RGBA; } - if ( p === LuminanceFormat ) { return gl.LUMINANCE; } - if ( p === LuminanceAlphaFormat ) { return gl.LUMINANCE_ALPHA; } - if ( p === DepthFormat ) { return gl.DEPTH_COMPONENT; } - if ( p === DepthStencilFormat ) { return gl.DEPTH_STENCIL; } + const morphAttribute = morphAttributesPosition[ i ]; + _box$2.setFromBufferAttribute( morphAttribute ); - if ( p === AddEquation ) { return gl.FUNC_ADD; } - if ( p === SubtractEquation ) { return gl.FUNC_SUBTRACT; } - if ( p === ReverseSubtractEquation ) { return gl.FUNC_REVERSE_SUBTRACT; } + if ( this.morphTargetsRelative ) { - if ( p === ZeroFactor ) { return gl.ZERO; } - if ( p === OneFactor ) { return gl.ONE; } - if ( p === SrcColorFactor ) { return gl.SRC_COLOR; } - if ( p === OneMinusSrcColorFactor ) { return gl.ONE_MINUS_SRC_COLOR; } - if ( p === SrcAlphaFactor ) { return gl.SRC_ALPHA; } - if ( p === OneMinusSrcAlphaFactor ) { return gl.ONE_MINUS_SRC_ALPHA; } - if ( p === DstAlphaFactor ) { return gl.DST_ALPHA; } - if ( p === OneMinusDstAlphaFactor ) { return gl.ONE_MINUS_DST_ALPHA; } + _vector$8.addVectors( this.boundingBox.min, _box$2.min ); + this.boundingBox.expandByPoint( _vector$8 ); - if ( p === DstColorFactor ) { return gl.DST_COLOR; } - if ( p === OneMinusDstColorFactor ) { return gl.ONE_MINUS_DST_COLOR; } - if ( p === SrcAlphaSaturateFactor ) { return gl.SRC_ALPHA_SATURATE; } + _vector$8.addVectors( this.boundingBox.max, _box$2.max ); + this.boundingBox.expandByPoint( _vector$8 ); - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + } else { - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + this.boundingBox.expandByPoint( _box$2.min ); + this.boundingBox.expandByPoint( _box$2.max ); - 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; } + } } - } - - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + } else { - extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + this.boundingBox.makeEmpty(); - 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; } + 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 ); } - if ( p === RGB_ETC1_Format ) { + } + + computeBoundingSphere() { - extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); + if ( this.boundingSphere === null ) { - if ( extension !== null ) { return extension.COMPRESSED_RGB_ETC1_WEBGL; } + this.boundingSphere = new Sphere(); } - if ( p === MinEquation || p === MaxEquation ) { + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; - extension = extensions.get( 'EXT_blend_minmax' ); + if ( position && position.isGLBufferAttribute ) { - if ( extension !== null ) { + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); - if ( p === MinEquation ) { return extension.MIN_EXT; } - if ( p === MaxEquation ) { return extension.MAX_EXT; } + this.boundingSphere.set( new Vector3(), Infinity ); - } + return; } - if ( p === UnsignedInt248Type ) { + if ( position ) { - extension = extensions.get( 'WEBGL_depth_texture' ); + // first, find the center of the bounding sphere - if ( extension !== null ) { return extension.UNSIGNED_INT_24_8_WEBGL; } + const center = this.boundingSphere.center; - } + _box$2.setFromBufferAttribute( position ); - return 0; + // process morph attributes if present - } + if ( morphAttributesPosition ) { - return { convert: convert }; + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { -} + const morphAttribute = morphAttributesPosition[ i ]; + _boxMorphTargets.setFromBufferAttribute( morphAttribute ); -/** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - * @author tschw - */ + if ( this.morphTargetsRelative ) { + + _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); + _box$2.expandByPoint( _vector$8 ); + + _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); + _box$2.expandByPoint( _vector$8 ); + + } else { + + _box$2.expandByPoint( _boxMorphTargets.min ); + _box$2.expandByPoint( _boxMorphTargets.max ); -function WebGLRenderer( parameters ) { + } + + } - console.log( 'THREE.WebGLRenderer', REVISION ); + } - parameters = parameters || {}; + _box$2.getCenter( center ); - var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ), - _context = parameters.context !== undefined ? parameters.context : null, + // second, try to find a boundingSphere with a radius smaller than the + // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - _alpha = parameters.alpha !== undefined ? parameters.alpha : false, - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default'; + let maxRadiusSq = 0; - var lightsArray = []; - var shadowsArray = []; + for ( let i = 0, il = position.count; i < il; i ++ ) { - var currentRenderList = null; + _vector$8.fromBufferAttribute( position, i ); - var spritesArray = []; - var flaresArray = []; + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); - // public properties + } - this.domElement = _canvas; - this.context = null; + // process morph attributes if present - // clearing + if ( morphAttributesPosition ) { - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { - // scene graph + const morphAttribute = morphAttributesPosition[ i ]; + const morphTargetsRelative = this.morphTargetsRelative; - this.sortObjects = true; + for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { - // user-defined clipping + _vector$8.fromBufferAttribute( morphAttribute, j ); - this.clippingPlanes = []; - this.localClippingEnabled = false; + if ( morphTargetsRelative ) { - // physically based shading + _offset.fromBufferAttribute( position, j ); + _vector$8.add( _offset ); - this.gammaFactor = 2.0; // for backwards compatibility - this.gammaInput = false; - this.gammaOutput = false; + } - // physical lights + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); - this.physicallyCorrectLights = false; + } - // tone mapping + } - this.toneMapping = LinearToneMapping; - this.toneMappingExposure = 1.0; - this.toneMappingWhitePoint = 1.0; + } - // morphs + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - this.maxMorphTargets = 8; - this.maxMorphNormals = 4; + if ( isNaN( this.boundingSphere.radius ) ) { - // internal properties + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); - var _this = this, + } - _isContextLost = false, + } - // internal state cache + } - _currentRenderTarget = null, - _currentFramebuffer = null, - _currentMaterialId = - 1, - _currentGeometryProgram = '', + computeTangents() { - _currentCamera = null, - _currentArrayCamera = null, + const index = this.index; + const attributes = this.attributes; - _currentViewport = new Vector4(), - _currentScissor = new Vector4(), - _currentScissorTest = null, + // based on http://www.terathon.com/code/tangent.html + // (per vertex tangents) - // + if ( index === null || + attributes.position === undefined || + attributes.normal === undefined || + attributes.uv === undefined ) { - _usedTextureUnits = 0, + console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); + return; - // + } - _width = _canvas.width, - _height = _canvas.height, + const positionAttribute = attributes.position; + const normalAttribute = attributes.normal; + const uvAttribute = attributes.uv; - _pixelRatio = 1, + if ( this.hasAttribute( 'tangent' ) === false ) { - _viewport = new Vector4( 0, 0, _width, _height ), - _scissor = new Vector4( 0, 0, _width, _height ), - _scissorTest = false, + this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) ); - // frustum + } - _frustum = new Frustum(), + const tangentAttribute = this.getAttribute( 'tangent' ); - // clipping + const tan1 = [], tan2 = []; - _clipping = new WebGLClipping(), - _clippingEnabled = false, - _localClippingEnabled = false, + for ( let i = 0; i < positionAttribute.count; i ++ ) { - // camera matrices cache + tan1[ i ] = new Vector3(); + tan2[ i ] = new Vector3(); - _projScreenMatrix = new Matrix4(), + } - _vector3 = new Vector3(), + const vA = new Vector3(), + vB = new Vector3(), + vC = new Vector3(), - // info + uvA = new Vector2(), + uvB = new Vector2(), + uvC = new Vector2(), - _infoMemory = { - geometries: 0, - textures: 0 - }, + sdir = new Vector3(), + tdir = new Vector3(); - _infoRender = { + function handleTriangle( a, b, c ) { - frame: 0, - calls: 0, - vertices: 0, - faces: 0, - points: 0 + vA.fromBufferAttribute( positionAttribute, a ); + vB.fromBufferAttribute( positionAttribute, b ); + vC.fromBufferAttribute( positionAttribute, c ); - }; + uvA.fromBufferAttribute( uvAttribute, a ); + uvB.fromBufferAttribute( uvAttribute, b ); + uvC.fromBufferAttribute( uvAttribute, c ); - this.info = { + vB.sub( vA ); + vC.sub( vA ); - render: _infoRender, - memory: _infoMemory, - programs: null + uvB.sub( uvA ); + uvC.sub( uvA ); - }; + const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); - function getTargetPixelRatio() { + // silently ignore degenerate uv triangles having coincident or colinear vertices - return _currentRenderTarget === null ? _pixelRatio : 1; + 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 ); - // initialize + tan1[ a ].add( sdir ); + tan1[ b ].add( sdir ); + tan1[ c ].add( sdir ); - var _gl; + tan2[ a ].add( tdir ); + tan2[ b ].add( tdir ); + tan2[ c ].add( tdir ); - try { + } - var contextAttributes = { - alpha: _alpha, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference - }; + let groups = this.groups; - // event listeners must be registered before WebGL context is created, see #12753 + if ( groups.length === 0 ) { - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + groups = [ { + start: 0, + count: index.count + } ]; - _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes ); + } - if ( _gl === null ) { + for ( let i = 0, il = groups.length; i < il; ++ i ) { - if ( _canvas.getContext( 'webgl' ) !== null ) { + const group = groups[ i ]; - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + const start = group.start; + const count = group.count; - } else { + for ( let j = start, jl = start + count; j < jl; j += 3 ) { - throw new Error( 'Error creating WebGL context.' ); + handleTriangle( + index.getX( j + 0 ), + index.getX( j + 1 ), + index.getX( j + 2 ) + ); } } - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + const tmp = new Vector3(), tmp2 = new Vector3(); + const n = new Vector3(), n2 = new Vector3(); - if ( _gl.getShaderPrecisionFormat === undefined ) { + function handleVertex( v ) { - _gl.getShaderPrecisionFormat = function () { + n.fromBufferAttribute( normalAttribute, v ); + n2.copy( n ); - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + const t = tan1[ v ]; - }; + // Gram-Schmidt orthogonalize - } + tmp.copy( t ); + tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); - } catch ( error ) { + // Calculate handedness - console.error( 'THREE.WebGLRenderer: ' + error.message ); + tmp2.crossVectors( n2, t ); + const test = tmp2.dot( tan2[ v ] ); + const w = ( test < 0.0 ) ? - 1.0 : 1.0; - } + tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w ); - var extensions, capabilities, state; - var properties, textures, attributes, geometries, objects, lights; - var programCache, renderLists; + } - var background, morphtargets, bufferRenderer, indexedBufferRenderer; - var flareRenderer, spriteRenderer; + for ( let i = 0, il = groups.length; i < il; ++ i ) { - var utils; + const group = groups[ i ]; - function initGLContext() { + const start = group.start; + const count = group.count; - extensions = new WebGLExtensions( _gl ); - extensions.get( 'WEBGL_depth_texture' ); - extensions.get( 'OES_texture_float' ); - extensions.get( 'OES_texture_float_linear' ); - extensions.get( 'OES_texture_half_float' ); - extensions.get( 'OES_texture_half_float_linear' ); - extensions.get( 'OES_standard_derivatives' ); - extensions.get( 'OES_element_index_uint' ); - extensions.get( 'ANGLE_instanced_arrays' ); + for ( let j = start, jl = start + count; j < jl; j += 3 ) { - utils = new WebGLUtils( _gl, extensions ); + handleVertex( index.getX( j + 0 ) ); + handleVertex( index.getX( j + 1 ) ); + handleVertex( index.getX( j + 2 ) ); - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + } - state = new WebGLState( _gl, extensions, utils ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); + } - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory ); - attributes = new WebGLAttributes( _gl ); - geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); - objects = new WebGLObjects( geometries, _infoRender ); - morphtargets = new WebGLMorphtargets( _gl ); - programCache = new WebGLPrograms( _this, extensions, capabilities ); - lights = new WebGLLights(); - renderLists = new WebGLRenderLists(); + } - background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha ); + computeVertexNormals() { - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); + const index = this.index; + const positionAttribute = this.getAttribute( 'position' ); - flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities ); - spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); + if ( positionAttribute !== undefined ) { - _this.info.programs = programCache.programs; + let normalAttribute = this.getAttribute( 'normal' ); - _this.context = _gl; - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.state = state; + if ( normalAttribute === undefined ) { - } + normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); + this.setAttribute( 'normal', normalAttribute ); - initGLContext(); + } else { - // vr + // reset existing normals to zero - var vr = new WebVRManager( _this ); + for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { - this.vr = vr; + normalAttribute.setXYZ( i, 0, 0, 0 ); - // shadow map + } - var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); + } - this.shadowMap = shadowMap; + 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(); - // API + // indexed elements - this.getContext = function () { + if ( index ) { - return _gl; + for ( let i = 0, il = index.count; i < il; i += 3 ) { - }; + const vA = index.getX( i + 0 ); + const vB = index.getX( i + 1 ); + const vC = index.getX( i + 2 ); - this.getContextAttributes = function () { + pA.fromBufferAttribute( positionAttribute, vA ); + pB.fromBufferAttribute( positionAttribute, vB ); + pC.fromBufferAttribute( positionAttribute, vC ); - return _gl.getContextAttributes(); + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - }; + nA.fromBufferAttribute( normalAttribute, vA ); + nB.fromBufferAttribute( normalAttribute, vB ); + nC.fromBufferAttribute( normalAttribute, vC ); - this.forceContextLoss = function () { + nA.add( cb ); + nB.add( cb ); + nC.add( cb ); - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) { extension.loseContext(); } + 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 ); - }; + } - this.forceContextRestore = function () { + } else { - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) { extension.restoreContext(); } + // non-indexed elements (unconnected triangle soup) - }; + for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { - this.getPixelRatio = function () { + pA.fromBufferAttribute( positionAttribute, i + 0 ); + pB.fromBufferAttribute( positionAttribute, i + 1 ); + pC.fromBufferAttribute( positionAttribute, i + 2 ); - return _pixelRatio; + 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.setPixelRatio = function ( value ) { + } - if ( value === undefined ) { return; } + } - _pixelRatio = value; + this.normalizeNormals(); - this.setSize( _width, _height, false ); + normalAttribute.needsUpdate = true; - }; + } - this.getSize = function () { + } - return { - width: _width, - height: _height - }; + normalizeNormals() { - }; + const normals = this.attributes.normal; - this.setSize = function ( width, height, updateStyle ) { + for ( let i = 0, il = normals.count; i < il; i ++ ) { - var device = vr.getDevice(); + _vector$8.fromBufferAttribute( normals, i ); - if ( device && device.isPresenting ) { + _vector$8.normalize(); - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } - _width = width; - _height = height; + } - _canvas.width = width * _pixelRatio; - _canvas.height = height * _pixelRatio; + toNonIndexed() { - if ( updateStyle !== false ) { + function convertBufferAttribute( attribute, indices ) { - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + const array = attribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; - } + const array2 = new array.constructor( indices.length * itemSize ); - this.setViewport( 0, 0, width, height ); + let index = 0, index2 = 0; - }; + for ( let i = 0, l = indices.length; i < l; i ++ ) { - this.getDrawingBufferSize = function () { + if ( attribute.isInterleavedBufferAttribute ) { - return { - width: _width * _pixelRatio, - height: _height * _pixelRatio - }; + index = indices[ i ] * attribute.data.stride + attribute.offset; - }; + } else { - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + index = indices[ i ] * itemSize; - _width = width; - _height = height; + } - _pixelRatio = pixelRatio; + for ( let j = 0; j < itemSize; j ++ ) { - _canvas.width = width * pixelRatio; - _canvas.height = height * pixelRatio; + array2[ index2 ++ ] = array[ index ++ ]; - this.setViewport( 0, 0, width, height ); + } - }; + } - this.setViewport = function ( x, y, width, height ) { + return new BufferAttribute( array2, itemSize, normalized ); - _viewport.set( x, _height - y - height, width, height ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); + } - }; + // - this.setScissor = function ( x, y, width, height ) { + if ( this.index === null ) { - _scissor.set( x, _height - y - height, width, height ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); + console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); + return this; - }; + } - this.setScissorTest = function ( boolean ) { + const geometry2 = new BufferGeometry(); - state.setScissorTest( _scissorTest = boolean ); + const indices = this.index.array; + const attributes = this.attributes; - }; + // attributes - // Clearing + for ( const name in attributes ) { - this.getClearColor = function () { + const attribute = attributes[ name ]; - return background.getClearColor(); + const newAttribute = convertBufferAttribute( attribute, indices ); - }; + geometry2.setAttribute( name, newAttribute ); - this.setClearColor = function () { + } - background.setClearColor.apply( background, arguments ); + // morph attributes - }; + const morphAttributes = this.morphAttributes; - this.getClearAlpha = function () { + for ( const name in morphAttributes ) { - return background.getClearAlpha(); + const morphArray = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - }; + for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { - this.setClearAlpha = function () { + const attribute = morphAttribute[ i ]; - background.setClearAlpha.apply( background, arguments ); + const newAttribute = convertBufferAttribute( attribute, indices ); - }; + morphArray.push( newAttribute ); - this.clear = function ( color, depth, stencil ) { + } - var bits = 0; + geometry2.morphAttributes[ name ] = morphArray; - if ( color === undefined || color ) { bits |= _gl.COLOR_BUFFER_BIT; } - if ( depth === undefined || depth ) { bits |= _gl.DEPTH_BUFFER_BIT; } - if ( stencil === undefined || stencil ) { bits |= _gl.STENCIL_BUFFER_BIT; } + } - _gl.clear( bits ); + geometry2.morphTargetsRelative = this.morphTargetsRelative; - }; + // groups - this.clearColor = function () { + const groups = this.groups; - this.clear( true, false, false ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - }; + const group = groups[ i ]; + geometry2.addGroup( group.start, group.count, group.materialIndex ); - this.clearDepth = function () { + } - this.clear( false, true, false ); + return geometry2; - }; + } - this.clearStencil = function () { + toJSON() { - this.clear( false, false, true ); + const data = { + metadata: { + version: 4.6, + type: 'BufferGeometry', + generator: 'BufferGeometry.toJSON' + } + }; - }; + // standard BufferGeometry serialization + + 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; - this.clearTarget = function ( renderTarget, color, depth, stencil ) { + if ( this.parameters !== undefined ) { - this.setRenderTarget( renderTarget ); - this.clear( color, depth, stencil ); + const parameters = this.parameters; - }; + for ( const key in parameters ) { - // + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + + } + + return data; + + } + + // for simplicity the code assumes attributes are not shared across geometries, see #15811 + + data.data = { attributes: {} }; - this.dispose = function () { + const index = this.index; - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + if ( index !== null ) { - renderLists.dispose(); + data.data.index = { + type: index.array.constructor.name, + array: Array.prototype.slice.call( index.array ) + }; - vr.dispose(); + } - }; + const attributes = this.attributes; - // Events + for ( const key in attributes ) { - function onContextLost( event ) { + const attribute = attributes[ key ]; - event.preventDefault(); + data.data.attributes[ key ] = attribute.toJSON( data.data ); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + } - _isContextLost = true; + const morphAttributes = {}; + let hasMorphAttributes = false; - } + for ( const key in this.morphAttributes ) { - function onContextRestore( /* event */ ) { + const attributeArray = this.morphAttributes[ key ]; - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + const array = []; - _isContextLost = false; + for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { - initGLContext(); + const attribute = attributeArray[ i ]; - } + array.push( attribute.toJSON( data.data ) ); - function onMaterialDispose( event ) { + } - var material = event.target; + if ( array.length > 0 ) { - material.removeEventListener( 'dispose', onMaterialDispose ); + morphAttributes[ key ] = array; - deallocateMaterial( material ); + hasMorphAttributes = true; - } + } - // Buffer deallocation + } - function deallocateMaterial( material ) { + if ( hasMorphAttributes ) { - releaseMaterialProgramReference( material ); + data.data.morphAttributes = morphAttributes; + data.data.morphTargetsRelative = this.morphTargetsRelative; - properties.remove( material ); + } - } + const groups = this.groups; + if ( groups.length > 0 ) { - function releaseMaterialProgramReference( material ) { + data.data.groups = JSON.parse( JSON.stringify( groups ) ); - var programInfo = properties.get( material ).program; + } - material.program = undefined; + const boundingSphere = this.boundingSphere; - if ( programInfo !== undefined ) { + if ( boundingSphere !== null ) { - programCache.releaseProgram( programInfo ); + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; } + return data; + } - // Buffer rendering + clone() { - function renderObjectImmediate( object, program, material ) { + return new this.constructor().copy( this ); - object.render( function ( object ) { + } - _this.renderBufferImmediate( object, program, material ); + copy( source ) { - } ); + // reset - } + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; - this.renderBufferImmediate = function ( object, program, material ) { + // used for storing cloned, shared data - state.initAttributes(); + const data = {}; - var buffers = properties.get( object ); + // name - if ( object.hasPositions && ! buffers.position ) { buffers.position = _gl.createBuffer(); } - if ( object.hasNormals && ! buffers.normal ) { buffers.normal = _gl.createBuffer(); } - if ( object.hasUvs && ! buffers.uv ) { buffers.uv = _gl.createBuffer(); } - if ( object.hasColors && ! buffers.color ) { buffers.color = _gl.createBuffer(); } + this.name = source.name; - var programAttributes = program.getAttributes(); + // index - if ( object.hasPositions ) { + const index = source.index; - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); + if ( index !== null ) { - state.enableAttribute( programAttributes.position ); - _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 ); + this.setIndex( index.clone( data ) ); } - if ( object.hasNormals ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal ); + // attributes - if ( ! material.isMeshPhongMaterial && - ! material.isMeshStandardMaterial && - ! material.isMeshNormalMaterial && - material.flatShading === true ) { + const attributes = source.attributes; - for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { + for ( const name in attributes ) { - var array = object.normalArray; + const attribute = attributes[ name ]; + this.setAttribute( name, attribute.clone( data ) ); - var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3; - var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3; - var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3; + } - array[ i + 0 ] = nx; - array[ i + 1 ] = ny; - array[ i + 2 ] = nz; + // morph attributes - array[ i + 3 ] = nx; - array[ i + 4 ] = ny; - array[ i + 5 ] = nz; + const morphAttributes = source.morphAttributes; - array[ i + 6 ] = nx; - array[ i + 7 ] = ny; - array[ i + 8 ] = nz; + for ( const name in morphAttributes ) { - } + const array = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - } + for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { - _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); + array.push( morphAttribute[ i ].clone( data ) ); - state.enableAttribute( programAttributes.normal ); + } - _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 ); + this.morphAttributes[ name ] = array; } - if ( object.hasUvs && material.map ) { + this.morphTargetsRelative = source.morphTargetsRelative; + + // groups - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW ); + const groups = source.groups; - state.enableAttribute( programAttributes.uv ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); + const group = groups[ i ]; + this.addGroup( group.start, group.count, group.materialIndex ); } - if ( object.hasColors && material.vertexColors !== NoColors ) { + // bounding box - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW ); + const boundingBox = source.boundingBox; - state.enableAttribute( programAttributes.color ); + if ( boundingBox !== null ) { - _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 ); + this.boundingBox = boundingBox.clone(); } - state.disableUnusedAttributes(); - - _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); - - object.count = 0; + // bounding sphere - }; + const boundingSphere = source.boundingSphere; - this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { + if ( boundingSphere !== null ) { - var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + this.boundingSphere = boundingSphere.clone(); - state.setMaterial( material, frontFaceCW ); + } - var program = setProgram( camera, fog, material, object ); - var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true ); + // draw range - var updateBuffers = false; + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; - if ( geometryProgram !== _currentGeometryProgram ) { + // user data - _currentGeometryProgram = geometryProgram; - updateBuffers = true; + this.userData = source.userData; - } + return this; - if ( object.morphTargetInfluences ) { + } - morphtargets.update( object, geometry, material, program ); + dispose() { - updateBuffers = true; + this.dispatchEvent( { type: 'dispose' } ); - } + } - // +} - var index = geometry.index; - var position = geometry.attributes.position; - var rangeFactor = 1; +const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); +const _ray$3 = /*@__PURE__*/ new Ray(); +const _sphere$6 = /*@__PURE__*/ new Sphere(); +const _sphereHitAt = /*@__PURE__*/ new Vector3(); - if ( material.wireframe === true ) { +const _vA$1 = /*@__PURE__*/ new Vector3(); +const _vB$1 = /*@__PURE__*/ new Vector3(); +const _vC$1 = /*@__PURE__*/ new Vector3(); - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; +const _tempA = /*@__PURE__*/ new Vector3(); +const _morphA = /*@__PURE__*/ new Vector3(); - } +const _uvA$1 = /*@__PURE__*/ new Vector2(); +const _uvB$1 = /*@__PURE__*/ new Vector2(); +const _uvC$1 = /*@__PURE__*/ new Vector2(); - var attribute; - var renderer = bufferRenderer; +const _normalA = /*@__PURE__*/ new Vector3(); +const _normalB = /*@__PURE__*/ new Vector3(); +const _normalC = /*@__PURE__*/ new Vector3(); - if ( index !== null ) { +const _intersectionPoint = /*@__PURE__*/ new Vector3(); +const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); - attribute = attributes.get( index ); +class Mesh extends Object3D { - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { - } + super(); - if ( updateBuffers ) { + this.isMesh = true; - setupVertexAttributes( material, program, geometry ); + this.type = 'Mesh'; - if ( index !== null ) { + this.geometry = geometry; + this.material = material; - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); + this.updateMorphTargets(); - } + } - } + copy( source, recursive ) { - // + super.copy( source, recursive ); - var dataCount = 0; + if ( source.morphTargetInfluences !== undefined ) { - if ( index !== null ) { + this.morphTargetInfluences = source.morphTargetInfluences.slice(); - dataCount = index.count; + } - } else if ( position !== undefined ) { + if ( source.morphTargetDictionary !== undefined ) { - dataCount = position.count; + this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); } - var rangeStart = geometry.drawRange.start * rangeFactor; - var rangeCount = geometry.drawRange.count * rangeFactor; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - var groupStart = group !== null ? group.start * rangeFactor : 0; - var groupCount = group !== null ? group.count * rangeFactor : Infinity; - - var drawStart = Math.max( rangeStart, groupStart ); - var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1; + return this; - var drawCount = Math.max( 0, drawEnd - drawStart + 1 ); + } - if ( drawCount === 0 ) { return; } + updateMorphTargets() { - // + const geometry = this.geometry; - if ( object.isMesh ) { + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - if ( material.wireframe === true ) { + if ( keys.length > 0 ) { - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - } else { + if ( morphAttribute !== undefined ) { - switch ( object.drawMode ) { + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - case TrianglesDrawMode: - renderer.setMode( _gl.TRIANGLES ); - break; + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - case TriangleStripDrawMode: - renderer.setMode( _gl.TRIANGLE_STRIP ); - break; + const name = morphAttribute[ m ].name || String( m ); - case TriangleFanDrawMode: - renderer.setMode( _gl.TRIANGLE_FAN ); - break; + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; } } + } - } else if ( object.isLine ) { - - var lineWidth = material.linewidth; + } - if ( lineWidth === undefined ) { lineWidth = 1; } // Not using Line*Material + getVertexPosition( index, target ) { - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + const geometry = this.geometry; + const position = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; - if ( object.isLineSegments ) { + target.fromBufferAttribute( position, index ); - renderer.setMode( _gl.LINES ); + const morphInfluences = this.morphTargetInfluences; - } else if ( object.isLineLoop ) { + if ( morphPosition && morphInfluences ) { - renderer.setMode( _gl.LINE_LOOP ); + _morphA.set( 0, 0, 0 ); - } else { + for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { - renderer.setMode( _gl.LINE_STRIP ); + const influence = morphInfluences[ i ]; + const morphAttribute = morphPosition[ i ]; - } + if ( influence === 0 ) continue; - } else if ( object.isPoints ) { + _tempA.fromBufferAttribute( morphAttribute, index ); - renderer.setMode( _gl.POINTS ); + if ( morphTargetsRelative ) { - } + _morphA.addScaledVector( _tempA, influence ); - if ( geometry && geometry.isInstancedBufferGeometry ) { + } else { - if ( geometry.maxInstancedCount > 0 ) { + _morphA.addScaledVector( _tempA.sub( target ), influence ); - renderer.renderInstances( geometry, drawStart, drawCount ); + } } - } else { - - renderer.render( drawStart, drawCount ); + target.add( _morphA ); } - }; - - function setupVertexAttributes( material, program, geometry, startIndex ) { - - if ( geometry && geometry.isInstancedBufferGeometry ) { + return target; - if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { - - console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + } - } + raycast( raycaster, intersects ) { - } + const geometry = this.geometry; + const material = this.material; + const matrixWorld = this.matrixWorld; - if ( startIndex === undefined ) { startIndex = 0; } + if ( material === undefined ) return; - state.initAttributes(); + // test with bounding sphere in world space - var geometryAttributes = geometry.attributes; + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - var programAttributes = program.getAttributes(); + _sphere$6.copy( geometry.boundingSphere ); + _sphere$6.applyMatrix4( matrixWorld ); - var materialDefaultAttributeValues = material.defaultAttributeValues; + // check distance from ray origin to bounding sphere - for ( var name in programAttributes ) { + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); - var programAttribute = programAttributes[ name ]; + if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { - if ( programAttribute >= 0 ) { + if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; - var geometryAttribute = geometryAttributes[ name ]; + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; - if ( geometryAttribute !== undefined ) { + } - var normalized = geometryAttribute.normalized; - var size = geometryAttribute.itemSize; + // convert ray to local space of mesh - var attribute = attributes.get( geometryAttribute ); + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); - // TODO Attribute may not be available on context restore + // test with bounding box in local space - if ( attribute === undefined ) { continue; } + if ( geometry.boundingBox !== null ) { - var buffer = attribute.buffer; - var type = attribute.type; - var bytesPerElement = attribute.bytesPerElement; + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; - if ( geometryAttribute.isInterleavedBufferAttribute ) { + } - var data = geometryAttribute.data; - var stride = data.stride; - var offset = geometryAttribute.offset; + // test for intersections with geometry - if ( data && data.isInstancedInterleavedBuffer ) { + this._computeIntersections( raycaster, intersects, _ray$3 ); - state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute ); + } - if ( geometry.maxInstancedCount === undefined ) { + _computeIntersections( raycaster, intersects, rayLocalSpace ) { - geometry.maxInstancedCount = data.meshPerAttribute * data.count; + let intersection; - } + const geometry = this.geometry; + const material = this.material; - } else { + const index = geometry.index; + const position = geometry.attributes.position; + const uv = geometry.attributes.uv; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; + const groups = geometry.groups; + const drawRange = geometry.drawRange; - state.enableAttribute( programAttribute ); + if ( index !== null ) { - } + // indexed buffer geometry - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, ( startIndex * stride + offset ) * bytesPerElement ); + if ( Array.isArray( material ) ) { - } else { + for ( let i = 0, il = groups.length; i < il; i ++ ) { - if ( geometryAttribute.isInstancedBufferAttribute ) { + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute ); + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); - if ( geometry.maxInstancedCount === undefined ) { + for ( let j = start, jl = end; j < jl; j += 3 ) { - geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; + const a = index.getX( j ); + const b = index.getX( j + 1 ); + const c = index.getX( j + 2 ); - } + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - } else { + if ( intersection ) { - state.enableAttribute( programAttribute ); + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); } - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * bytesPerElement ); - } - } else if ( materialDefaultAttributeValues !== undefined ) { - - var value = materialDefaultAttributeValues[ name ]; + } - if ( value !== undefined ) { + } else { - switch ( value.length ) { + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - case 2: - _gl.vertexAttrib2fv( programAttribute, value ); - break; + for ( let i = start, il = end; i < il; i += 3 ) { - case 3: - _gl.vertexAttrib3fv( programAttribute, value ); - break; + const a = index.getX( i ); + const b = index.getX( i + 1 ); + const c = index.getX( i + 2 ); - case 4: - _gl.vertexAttrib4fv( programAttribute, value ); - break; + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - default: - _gl.vertexAttrib1fv( programAttribute, value ); + if ( intersection ) { - } + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics + intersects.push( intersection ); } @@ -22144,29717 +11342,30820 @@ function WebGLRenderer( parameters ) { } - } - - state.disableUnusedAttributes(); + } else if ( position !== undefined ) { - } + // non-indexed buffer geometry - // Compile + if ( Array.isArray( material ) ) { - this.compile = function ( scene, camera ) { + for ( let i = 0, il = groups.length; i < il; i ++ ) { - lightsArray.length = 0; - shadowsArray.length = 0; + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - scene.traverse( function ( object ) { + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); - if ( object.isLight ) { + for ( let j = start, jl = end; j < jl; j += 3 ) { - lightsArray.push( object ); + const a = j; + const b = j + 1; + const c = j + 2; - if ( object.castShadow ) { + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - shadowsArray.push( object ); + if ( intersection ) { - } + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); - } + } - } ); + } - lights.setup( lightsArray, shadowsArray, camera ); + } - scene.traverse( function ( object ) { + } else { - if ( object.material ) { + const start = Math.max( 0, drawRange.start ); + const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); - if ( Array.isArray( object.material ) ) { + for ( let i = start, il = end; i < il; i += 3 ) { - for ( var i = 0; i < object.material.length; i ++ ) { + const a = i; + const b = i + 1; + const c = i + 2; - initMaterial( object.material[ i ], scene.fog, object ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - } + if ( intersection ) { - } else { + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics + intersects.push( intersection ); - initMaterial( object.material, scene.fog, object ); + } } } - } ); - - }; - - // Animation Loop - - var isAnimating = false; - var onAnimationFrame = null; - - function start() { + } - if ( isAnimating ) { return; } + } - var device = vr.getDevice(); +} - if ( device && device.isPresenting ) { +function checkIntersection$1( object, material, raycaster, ray, pA, pB, pC, point ) { - device.requestAnimationFrame( loop ); + let intersect; - } else { + if ( material.side === BackSide ) { - window.requestAnimationFrame( loop ); + intersect = ray.intersectTriangle( pC, pB, pA, true, point ); - } + } else { - isAnimating = true; + intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); } - function loop( time ) { + if ( intersect === null ) return null; - if ( onAnimationFrame !== null ) { onAnimationFrame( time ); } + _intersectionPointWorld.copy( point ); + _intersectionPointWorld.applyMatrix4( object.matrixWorld ); - var device = vr.getDevice(); + const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); - if ( device && device.isPresenting ) { + if ( distance < raycaster.near || distance > raycaster.far ) return null; - device.requestAnimationFrame( loop ); + return { + distance: distance, + point: _intersectionPointWorld.clone(), + object: object + }; - } else { +} - window.requestAnimationFrame( loop ); +function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { - } + object.getVertexPosition( a, _vA$1 ); + object.getVertexPosition( b, _vB$1 ); + object.getVertexPosition( c, _vC$1 ); - } + const intersection = checkIntersection$1( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); - this.animate = function ( callback ) { + if ( intersection ) { - onAnimationFrame = callback; - start(); + if ( uv ) { - }; + _uvA$1.fromBufferAttribute( uv, a ); + _uvB$1.fromBufferAttribute( uv, b ); + _uvC$1.fromBufferAttribute( uv, c ); - // Rendering + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); - this.render = function ( scene, camera, renderTarget, forceClear ) { + } - if ( ! ( camera && camera.isCamera ) ) { + if ( uv1 ) { - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + _uvA$1.fromBufferAttribute( uv1, a ); + _uvB$1.fromBufferAttribute( uv1, b ); + _uvC$1.fromBufferAttribute( uv1, c ); - } + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); - if ( _isContextLost ) { return; } + } - // reset caching for this frame + if ( normal ) { - _currentGeometryProgram = ''; - _currentMaterialId = - 1; - _currentCamera = null; + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); - // update scene graph + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); - if ( scene.autoUpdate === true ) { scene.updateMatrixWorld(); } + if ( intersection.normal.dot( ray.direction ) > 0 ) { - // update camera matrices and frustum + intersection.normal.multiplyScalar( - 1 ); - if ( camera.parent === null ) { camera.updateMatrixWorld(); } + } - if ( vr.enabled ) { + } - camera = vr.getCamera( camera ); + const face = { + a: a, + b: b, + c: c, + normal: new Vector3(), + materialIndex: 0 + }; - } + Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); + intersection.face = face; - lightsArray.length = 0; - shadowsArray.length = 0; + } - spritesArray.length = 0; - flaresArray.length = 0; + return intersection; - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); +} - currentRenderList = renderLists.get( scene, camera ); - currentRenderList.init(); +class BoxGeometry extends BufferGeometry { - projectObject( scene, camera, _this.sortObjects ); + constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { - if ( _this.sortObjects === true ) { + super(); - currentRenderList.sort(); + this.type = 'BoxGeometry'; - } + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - // + const scope = this; - textures.updateVideoTextures(); + // segments - // + widthSegments = Math.floor( widthSegments ); + heightSegments = Math.floor( heightSegments ); + depthSegments = Math.floor( depthSegments ); - if ( _clippingEnabled ) { _clipping.beginShadows(); } + // buffers - shadowMap.render( shadowsArray, scene, camera ); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - lights.setup( lightsArray, shadowsArray, camera ); + // helper variables - if ( _clippingEnabled ) { _clipping.endShadows(); } + let numberOfVertices = 0; + let groupStart = 0; - // + // build each side of the box geometry - _infoRender.frame ++; - _infoRender.calls = 0; - _infoRender.vertices = 0; - _infoRender.faces = 0; - _infoRender.points = 0; + buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px + buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx + buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py + buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny + buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz + buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz - if ( renderTarget === undefined ) { + // build geometry - renderTarget = null; + 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, width, height, depth, gridX, gridY, materialIndex ) { - this.setRenderTarget( renderTarget ); + const segmentWidth = width / gridX; + const segmentHeight = height / gridY; - // + const widthHalf = width / 2; + const heightHalf = height / 2; + const depthHalf = depth / 2; - background.render( currentRenderList, scene, camera, forceClear ); + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; - // render scene + let vertexCounter = 0; + let groupCount = 0; - var opaqueObjects = currentRenderList.opaque; - var transparentObjects = currentRenderList.transparent; + const vector = new Vector3(); - if ( scene.overrideMaterial ) { + // generate vertices, normals and uvs - var overrideMaterial = scene.overrideMaterial; + for ( let iy = 0; iy < gridY1; iy ++ ) { - if ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera, overrideMaterial ); } - if ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera, overrideMaterial ); } + const y = iy * segmentHeight - heightHalf; - } else { + for ( let ix = 0; ix < gridX1; ix ++ ) { - // opaque pass (front-to-back order) + const x = ix * segmentWidth - widthHalf; - if ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera ); } + // set values to correct vector component - // transparent pass (back-to-front order) + vector[ u ] = x * udir; + vector[ v ] = y * vdir; + vector[ w ] = depthHalf; - if ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera ); } + // now apply vector to vertex buffer - } + vertices.push( vector.x, vector.y, vector.z ); - // custom renderers + // set values to correct vector component - spriteRenderer.render( spritesArray, scene, camera ); - flareRenderer.render( flaresArray, scene, camera, _currentViewport ); + vector[ u ] = 0; + vector[ v ] = 0; + vector[ w ] = depth > 0 ? 1 : - 1; - // Generate mipmap if we're using any kind of mipmap filtering + // now apply vector to normal buffer - if ( renderTarget ) { + normals.push( vector.x, vector.y, vector.z ); - textures.updateRenderTargetMipmap( renderTarget ); + // uvs - } + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - // Ensure depth buffer writing is enabled so it can be cleared on next render + // counters - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + vertexCounter += 1; - state.setPolygonOffset( false ); + } - if ( vr.enabled ) { + } - vr.submitFrame(); + // indices - } + // 1. you need three indices to draw a single face + // 2. a single segment consists of two faces + // 3. so we need to generate six (2*3) indices per segment - // _gl.finish(); + for ( let iy = 0; iy < gridY; iy ++ ) { - }; + for ( let ix = 0; ix < gridX; ix ++ ) { - /* - // TODO Duplicated code (Frustum) + const a = numberOfVertices + ix + gridX1 * iy; + const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); + const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; - var _sphere = new Sphere(); + // faces - function isObjectViewable( object ) { + indices.push( a, b, d ); + indices.push( b, c, d ); - var geometry = object.geometry; + // increase counter - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); + groupCount += 6; - _sphere.copy( geometry.boundingSphere ). - applyMatrix4( object.matrixWorld ); + } - return isSphereViewable( _sphere ); + } - } + // add a group to the geometry. this will ensure multi material support - function isSpriteViewable( sprite ) { + scope.addGroup( groupStart, groupCount, materialIndex ); - _sphere.center.set( 0, 0, 0 ); - _sphere.radius = 0.7071067811865476; - _sphere.applyMatrix4( sprite.matrixWorld ); + // calculate new start value for groups - return isSphereViewable( _sphere ); + groupStart += groupCount; - } + // update total number of vertices - function isSphereViewable( sphere ) { + numberOfVertices += vertexCounter; - if ( ! _frustum.intersectsSphere( sphere ) ) return false; + } - var numPlanes = _clipping.numPlanes; + } - if ( numPlanes === 0 ) return true; + copy( source ) { - var planes = _this.clippingPlanes, + super.copy( source ); - center = sphere.center, - negRad = - sphere.radius, - i = 0; + this.parameters = Object.assign( {}, source.parameters ); - do { + return this; - // out when deeper than radius in the negative halfspace - if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; + } - } while ( ++ i !== numPlanes ); + static fromJSON( data ) { - return true; + return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); } - */ - function projectObject( object, camera, sortObjects ) { +} - if ( object.visible === false ) { return; } +/** + * Uniform Utilities + */ - var visible = object.layers.test( camera.layers ); +function cloneUniforms( src ) { - if ( visible ) { + const dst = {}; - if ( object.isLight ) { + for ( const u in src ) { - lightsArray.push( object ); + dst[ u ] = {}; - if ( object.castShadow ) { + for ( const p in src[ u ] ) { - shadowsArray.push( object ); + const property = src[ u ][ p ]; - } + if ( property && ( property.isColor || + property.isMatrix3 || property.isMatrix4 || + property.isVector2 || property.isVector3 || property.isVector4 || + property.isTexture || property.isQuaternion ) ) { - } else if ( object.isSprite ) { + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + } else { - spritesArray.push( object ); + dst[ u ][ p ] = property.clone(); } - } else if ( object.isLensFlare ) { - - flaresArray.push( object ); + } else if ( Array.isArray( property ) ) { - } else if ( object.isImmediateRenderObject ) { + dst[ u ][ p ] = property.slice(); - if ( sortObjects ) { + } else { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + dst[ u ][ p ] = property; - } + } - currentRenderList.push( object, null, object.material, _vector3.z, null ); + } - } else if ( object.isMesh || object.isLine || object.isPoints ) { + } - if ( object.isSkinnedMesh ) { + return dst; - object.skeleton.update(); +} - } +function mergeUniforms( uniforms ) { - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + const merged = {}; - if ( sortObjects ) { + for ( let u = 0; u < uniforms.length; u ++ ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + const tmp = cloneUniforms( uniforms[ u ] ); - } + for ( const p in tmp ) { - var geometry = objects.update( object ); - var material = object.material; + merged[ p ] = tmp[ p ]; - if ( Array.isArray( material ) ) { + } - var groups = geometry.groups; + } - for ( var i = 0, l = groups.length; i < l; i ++ ) { + return merged; - var group = groups[ i ]; - var groupMaterial = material[ group.materialIndex ]; +} - if ( groupMaterial && groupMaterial.visible ) { +function cloneUniformsGroups( src ) { - currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group ); + const dst = []; - } + for ( let u = 0; u < src.length; u ++ ) { - } + dst.push( src[ u ].clone() ); - } else if ( material.visible ) { + } - currentRenderList.push( object, geometry, material, _vector3.z, null ); + return dst; - } +} - } +function getUnlitUniformColorSpace( renderer ) { - } + const currentRenderTarget = renderer.getRenderTarget(); - } + if ( currentRenderTarget === null ) { - var children = object.children; + // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 + return renderer.outputColorSpace; - for ( var i = 0, l = children.length; i < l; i ++ ) { + } - projectObject( children[ i ], camera, sortObjects ); + // https://github.com/mrdoob/three.js/issues/27868 + if ( currentRenderTarget.isXRRenderTarget === true ) { - } + return currentRenderTarget.texture.colorSpace; } - function renderObjects( renderList, scene, camera, overrideMaterial ) { + return ColorManagement.workingColorSpace; - for ( var i = 0, l = renderList.length; i < l; i ++ ) { +} - var renderItem = renderList[ i ]; +// Legacy - var object = renderItem.object; - var geometry = renderItem.geometry; - var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; - var group = renderItem.group; +const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; - if ( camera.isArrayCamera ) { +var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; - _currentArrayCamera = camera; +var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; - var cameras = camera.cameras; +class ShaderMaterial extends Material { - for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { + constructor( parameters ) { - var camera2 = cameras[ j ]; + super(); - if ( object.layers.test( camera2.layers ) ) { + this.isShaderMaterial = true; - var bounds = camera2.bounds; + this.type = 'ShaderMaterial'; - var x = bounds.x * _width; - var y = bounds.y * _height; - var width = bounds.z * _width; - var height = bounds.w * _height; + this.defines = {}; + this.uniforms = {}; + this.uniformsGroups = []; - state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; - renderObject( object, scene, camera2, geometry, material, group ); + this.linewidth = 1; - } + this.wireframe = false; + this.wireframeLinewidth = 1; - } + this.fog = false; // set to use scene fog + this.lights = false; // set to use scene lights + this.clipping = false; // set to use user-defined clipping planes - } else { + this.forceSinglePass = true; - _currentArrayCamera = null; + this.extensions = { + clipCullDistance: false, // set to use vertex shader clipping + multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID + }; - renderObject( object, scene, camera, geometry, material, group ); + // When rendered geometry doesn't include these attributes but the material does, + // use these default values in WebGL. This avoids errors when buffer data is missing. + this.defaultAttributeValues = { + 'color': [ 1, 1, 1 ], + 'uv': [ 0, 0 ], + 'uv1': [ 0, 0 ] + }; - } + this.index0AttributeName = undefined; + this.uniformsNeedUpdate = false; - } + this.glslVersion = null; - } + if ( parameters !== undefined ) { - function renderObject( object, scene, camera, geometry, material, group ) { + this.setValues( parameters ); - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + } - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + } - if ( object.isImmediateRenderObject ) { + copy( source ) { - var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + super.copy( source ); - state.setMaterial( material, frontFaceCW ); + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; - var program = setProgram( camera, scene.fog, material, object ); + this.uniforms = cloneUniforms( source.uniforms ); + this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); - _currentGeometryProgram = ''; + this.defines = Object.assign( {}, source.defines ); - renderObjectImmediate( object, program, material ); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; - } else { + this.fog = source.fog; + this.lights = source.lights; + this.clipping = source.clipping; - _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group ); + this.extensions = Object.assign( {}, source.extensions ); - } + this.glslVersion = source.glslVersion; - object.onAfterRender( _this, scene, camera, geometry, material, group ); + return this; } - function initMaterial( material, fog, object ) { + toJSON( meta ) { - var materialProperties = properties.get( material ); + const data = super.toJSON( meta ); - var parameters = programCache.getParameters( - material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); + data.glslVersion = this.glslVersion; + data.uniforms = {}; - var code = programCache.getProgramCode( material, parameters ); + for ( const name in this.uniforms ) { - var program = materialProperties.program; - var programChange = true; + const uniform = this.uniforms[ name ]; + const value = uniform.value; - if ( program === undefined ) { + if ( value && value.isTexture ) { - // new material - material.addEventListener( 'dispose', onMaterialDispose ); + data.uniforms[ name ] = { + type: 't', + value: value.toJSON( meta ).uuid + }; - } else if ( program.code !== code ) { + } else if ( value && value.isColor ) { - // changed glsl or parameters - releaseMaterialProgramReference( material ); + data.uniforms[ name ] = { + type: 'c', + value: value.getHex() + }; - } else if ( parameters.shaderID !== undefined ) { + } else if ( value && value.isVector2 ) { - // same glsl and uniform list - return; + data.uniforms[ name ] = { + type: 'v2', + value: value.toArray() + }; - } else { + } else if ( value && value.isVector3 ) { - // only rebuild uniform list - programChange = false; + data.uniforms[ name ] = { + type: 'v3', + value: value.toArray() + }; - } + } else if ( value && value.isVector4 ) { - if ( programChange ) { + data.uniforms[ name ] = { + type: 'v4', + value: value.toArray() + }; + + } else if ( value && value.isMatrix3 ) { - if ( parameters.shaderID ) { + data.uniforms[ name ] = { + type: 'm3', + value: value.toArray() + }; - var shader = ShaderLib[ parameters.shaderID ]; + } else if ( value && value.isMatrix4 ) { - materialProperties.shader = { - name: material.type, - uniforms: UniformsUtils.clone( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + data.uniforms[ name ] = { + type: 'm4', + value: value.toArray() }; } else { - materialProperties.shader = { - name: material.type, - uniforms: material.uniforms, - vertexShader: material.vertexShader, - fragmentShader: material.fragmentShader + data.uniforms[ name ] = { + value: value }; - } + // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far - material.onBeforeCompile( materialProperties.shader ); + } - program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); + } - materialProperties.program = program; - material.program = program; + if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; - } + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; - var programAttributes = program.getAttributes(); + data.lights = this.lights; + data.clipping = this.clipping; - if ( material.morphTargets ) { + const extensions = {}; - material.numSupportedMorphTargets = 0; + for ( const key in this.extensions ) { - for ( var i = 0; i < _this.maxMorphTargets; i ++ ) { + if ( this.extensions[ key ] === true ) extensions[ key ] = true; - if ( programAttributes[ 'morphTarget' + i ] >= 0 ) { + } - material.numSupportedMorphTargets ++; + if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; - } + return data; - } + } - } +} - if ( material.morphNormals ) { +class Camera extends Object3D { - material.numSupportedMorphNormals = 0; + constructor() { - for ( var i = 0; i < _this.maxMorphNormals; i ++ ) { + super(); - if ( programAttributes[ 'morphNormal' + i ] >= 0 ) { + this.isCamera = true; - material.numSupportedMorphNormals ++; + this.type = 'Camera'; - } + this.matrixWorldInverse = new Matrix4(); - } + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); - } + this.coordinateSystem = WebGLCoordinateSystem; - var uniforms = materialProperties.shader.uniforms; + } - if ( ! material.isShaderMaterial && - ! material.isRawShaderMaterial || - material.clipping === true ) { + copy( source, recursive ) { - materialProperties.numClippingPlanes = _clipping.numPlanes; - materialProperties.numIntersection = _clipping.numIntersection; - uniforms.clippingPlanes = _clipping.uniform; + super.copy( source, recursive ); - } + this.matrixWorldInverse.copy( source.matrixWorldInverse ); - materialProperties.fog = fog; + this.projectionMatrix.copy( source.projectionMatrix ); + this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); - // store the light setup it was created for + this.coordinateSystem = source.coordinateSystem; - materialProperties.lightsHash = lights.state.hash; + return this; - if ( material.lights ) { + } - // wire up the material to this renderer's lighting state + getWorldDirection( target ) { - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.directionalLights.value = lights.state.directional; - uniforms.spotLights.value = lights.state.spot; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.pointLights.value = lights.state.point; - uniforms.hemisphereLights.value = lights.state.hemi; + return super.getWorldDirection( target ).negate(); - 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; - // TODO (abelnation): add area lights shadow info to uniforms + } - } + updateMatrixWorld( force ) { - var progUniforms = materialProperties.program.getUniforms(), - uniformsList = - WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + super.updateMatrixWorld( force ); - materialProperties.uniformsList = uniformsList; + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); } - function setProgram( camera, fog, material, object ) { + updateWorldMatrix( updateParents, updateChildren ) { + + super.updateWorldMatrix( updateParents, updateChildren ); - _usedTextureUnits = 0; + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); - var materialProperties = properties.get( material ); + } - if ( _clippingEnabled ) { + clone() { - if ( _localClippingEnabled || camera !== _currentCamera ) { + return new this.constructor().copy( this ); - var useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + } - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - _clipping.setState( - material.clippingPlanes, material.clipIntersection, material.clipShadows, - camera, materialProperties, useCache ); +} - } +const _v3$1 = /*@__PURE__*/ new Vector3(); +const _minTarget = /*@__PURE__*/ new Vector2(); +const _maxTarget = /*@__PURE__*/ new Vector2(); - } - if ( material.needsUpdate === false ) { +class PerspectiveCamera extends Camera { - if ( materialProperties.program === undefined ) { + constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { - material.needsUpdate = true; + super(); - } else if ( material.fog && materialProperties.fog !== fog ) { + this.isPerspectiveCamera = true; - material.needsUpdate = true; + this.type = 'PerspectiveCamera'; - } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { + this.fov = fov; + this.zoom = 1; - material.needsUpdate = true; + this.near = near; + this.far = far; + this.focus = 10; - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== _clipping.numPlanes || - materialProperties.numIntersection !== _clipping.numIntersection ) ) { + this.aspect = aspect; + this.view = null; - material.needsUpdate = true; + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - } + this.updateProjectionMatrix(); - } + } - if ( material.needsUpdate ) { + copy( source, recursive ) { - initMaterial( material, fog, object ); - material.needsUpdate = false; + super.copy( source, recursive ); - } + this.fov = source.fov; + this.zoom = source.zoom; - var refreshProgram = false; - var refreshMaterial = false; - var refreshLights = false; + this.near = source.near; + this.far = source.far; + this.focus = source.focus; - var program = materialProperties.program, - p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.shader.uniforms; + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - if ( state.useProgram( program.program ) ) { + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + return this; - } + } - if ( material.id !== _currentMaterialId ) { + /** + * Sets the FOV by focal length in respect to the current .filmGauge. + * + * The default film gauge is 35, so that the focal length can be specified for + * a 35mm (full frame) camera. + * + * Values for focal length and film gauge must have the same unit. + */ + setFocalLength( focalLength ) { - _currentMaterialId = material.id; + /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ + const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - refreshMaterial = true; + this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.updateProjectionMatrix(); - } + } - if ( refreshProgram || camera !== _currentCamera ) { + /** + * Calculates the focal length from the current .fov and .filmGauge. + */ + getFocalLength() { - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); - if ( capabilities.logarithmicDepthBuffer ) { + return 0.5 * this.getFilmHeight() / vExtentSlope; - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } - } + getEffectiveFOV() { - // Avoid unneeded uniform updates per ArrayCamera's sub-camera + return RAD2DEG * 2 * Math.atan( + Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); - if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { + } - _currentCamera = ( _currentArrayCamera || camera ); + getFilmWidth() { - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + // film not completely covered in portrait format (aspect < 1) + return this.filmGauge * Math.min( this.aspect, 1 ); - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + } - } + getFilmHeight() { - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + // film not completely covered in landscape format (aspect > 1) + return this.filmGauge / Math.max( this.aspect, 1 ); - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + } - var uCamPos = p_uniforms.map.cameraPosition; + /** + * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction. + * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle. + */ + getViewBounds( distance, minTarget, maxTarget ) { - if ( uCamPos !== undefined ) { + _v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); - } + _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); - } + maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); - if ( material.isMeshPhongMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.skinning ) { + } - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + /** + * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction. + * Copies the result into the target Vector2, where x is width and y is height. + */ + getViewSize( distance, target ) { - } + this.getViewBounds( distance, _minTarget, _maxTarget ); - } + return target.subVectors( _maxTarget, _minTarget ); - // skinning uniforms must be set even if material didn't change - // auto-setting of texture unit for bone texture must go before other textures - // not sure why, but otherwise weird things happen + } - if ( material.skinning ) { + /** + * Sets an offset in a larger frustum. This is useful for multi-window or + * multi-monitor/multi-machine setups. + * + * For example, if you have 3x2 monitors and each monitor is 1920x1080 and + * the monitors are in grid like this + * + * +---+---+---+ + * | A | B | C | + * +---+---+---+ + * | D | E | F | + * +---+---+---+ + * + * then for each monitor you would call it like this + * + * const w = 1920; + * const h = 1080; + * const fullWidth = w * 3; + * const fullHeight = h * 2; + * + * --A-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); + * --B-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); + * --C-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); + * --D-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); + * --E-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); + * --F-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); + * + * Note there is no reason monitors have to be the same size or in a grid. + */ + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + this.aspect = fullWidth / fullHeight; - var skeleton = object.skeleton; + if ( this.view === null ) { - if ( skeleton ) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - var bones = skeleton.bones; + } - if ( capabilities.floatVertexTextures ) { + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - if ( skeleton.boneTexture === undefined ) { + this.updateProjectionMatrix(); - // layout (1 matrix = 4 pixels) - // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) - // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) - // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) - // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) - // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) + } + clearViewOffset() { - var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix - size = _Math.ceilPowerOfTwo( size ); - size = Math.max( size, 4 ); + if ( this.view !== null ) { - var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel - boneMatrices.set( skeleton.boneMatrices ); // copy current values + this.view.enabled = false; - var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + } - skeleton.boneMatrices = boneMatrices; - skeleton.boneTexture = boneTexture; - skeleton.boneTextureSize = size; + this.updateProjectionMatrix(); - } + } - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + updateProjectionMatrix() { - } else { + 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; - p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' ); + 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; } - if ( refreshMaterial ) { + const skew = this.filmOffset; + if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); + this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); - if ( material.lights ) { + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - // the current material requires lighting info + } - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + toJSON( meta ) { - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); + const data = super.toJSON( meta ); - } + data.object.fov = this.fov; + data.object.zoom = this.zoom; - // refresh uniforms common to several materials + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; - if ( fog && material.fog ) { + data.object.aspect = this.aspect; - refreshUniformsFog( m_uniforms, fog ); + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - } + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; - if ( material.isMeshBasicMaterial ) { + return data; - refreshUniformsCommon( m_uniforms, material ); + } - } else if ( material.isMeshLambertMaterial ) { +} - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsLambert( m_uniforms, material ); +const fov = - 90; // negative fov is not an error +const aspect = 1; - } else if ( material.isMeshPhongMaterial ) { +class CubeCamera extends Object3D { - refreshUniformsCommon( m_uniforms, material ); + constructor( near, far, renderTarget ) { - if ( material.isMeshToonMaterial ) { + super(); - refreshUniformsToon( m_uniforms, material ); + this.type = 'CubeCamera'; - } else { + this.renderTarget = renderTarget; + this.coordinateSystem = null; + this.activeMipmapLevel = 0; - refreshUniformsPhong( m_uniforms, material ); + const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); + cameraPX.layers = this.layers; + this.add( cameraPX ); - } + const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); + cameraNX.layers = this.layers; + this.add( cameraNX ); - } else if ( material.isMeshStandardMaterial ) { + const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); + cameraPY.layers = this.layers; + this.add( cameraPY ); - refreshUniformsCommon( m_uniforms, material ); + const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); + cameraNY.layers = this.layers; + this.add( cameraNY ); - if ( material.isMeshPhysicalMaterial ) { + const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraPZ.layers = this.layers; + this.add( cameraPZ ); - refreshUniformsPhysical( m_uniforms, material ); + const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraNZ.layers = this.layers; + this.add( cameraNZ ); - } else { + } - refreshUniformsStandard( m_uniforms, material ); + updateCoordinateSystem() { - } + const coordinateSystem = this.coordinateSystem; - } else if ( material.isMeshDepthMaterial ) { + const cameras = this.children.concat(); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDepth( m_uniforms, material ); + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; - } else if ( material.isMeshDistanceMaterial ) { + for ( const camera of cameras ) this.remove( camera ); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDistance( m_uniforms, material ); + if ( coordinateSystem === WebGLCoordinateSystem ) { - } else if ( material.isMeshNormalMaterial ) { + cameraPX.up.set( 0, 1, 0 ); + cameraPX.lookAt( 1, 0, 0 ); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsNormal( m_uniforms, material ); + cameraNX.up.set( 0, 1, 0 ); + cameraNX.lookAt( - 1, 0, 0 ); - } else if ( material.isLineBasicMaterial ) { + cameraPY.up.set( 0, 0, - 1 ); + cameraPY.lookAt( 0, 1, 0 ); - refreshUniformsLine( m_uniforms, material ); + cameraNY.up.set( 0, 0, 1 ); + cameraNY.lookAt( 0, - 1, 0 ); - if ( material.isLineDashedMaterial ) { + cameraPZ.up.set( 0, 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); - refreshUniformsDash( m_uniforms, material ); + cameraNZ.up.set( 0, 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); - } + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - } else if ( material.isPointsMaterial ) { + cameraPX.up.set( 0, - 1, 0 ); + cameraPX.lookAt( - 1, 0, 0 ); - refreshUniformsPoints( m_uniforms, material ); + cameraNX.up.set( 0, - 1, 0 ); + cameraNX.lookAt( 1, 0, 0 ); - } else if ( material.isShadowMaterial ) { + cameraPY.up.set( 0, 0, 1 ); + cameraPY.lookAt( 0, 1, 0 ); - m_uniforms.color.value = material.color; - m_uniforms.opacity.value = material.opacity; + cameraNY.up.set( 0, 0, - 1 ); + cameraNY.lookAt( 0, - 1, 0 ); - } + cameraPZ.up.set( 0, - 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); - // RectAreaLight Texture - // TODO (mrdoob): Find a nicer implementation + cameraNZ.up.set( 0, - 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); - if ( m_uniforms.ltcMat !== undefined ) { m_uniforms.ltcMat.value = UniformsLib.LTC_MAT_TEXTURE; } - if ( m_uniforms.ltcMag !== undefined ) { m_uniforms.ltcMag.value = UniformsLib.LTC_MAG_TEXTURE; } + } else { - WebGLUniforms.upload( - _gl, materialProperties.uniformsList, m_uniforms, _this ); + throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); } + for ( const camera of cameras ) { - // common matrices + this.add( camera ); - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + camera.updateMatrixWorld(); - return program; + } } - // Uniforms (refresh uniforms objects) + update( renderer, scene ) { - function refreshUniformsCommon( uniforms, material ) { + if ( this.parent === null ) this.updateMatrixWorld(); - uniforms.opacity.value = material.opacity; + const { renderTarget, activeMipmapLevel } = this; - if ( material.color ) { + if ( this.coordinateSystem !== renderer.coordinateSystem ) { + + this.coordinateSystem = renderer.coordinateSystem; - uniforms.diffuse.value = material.color; + this.updateCoordinateSystem(); } - if ( material.emissive ) { + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; - uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); + const currentRenderTarget = renderer.getRenderTarget(); + const currentActiveCubeFace = renderer.getActiveCubeFace(); + const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); - } + const currentXrEnabled = renderer.xr.enabled; - if ( material.map ) { + renderer.xr.enabled = false; - uniforms.map.value = material.map; + const generateMipmaps = renderTarget.texture.generateMipmaps; - } + renderTarget.texture.generateMipmaps = false; - if ( material.alphaMap ) { + renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); + renderer.render( scene, cameraPX ); - uniforms.alphaMap.value = material.alphaMap; + renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); + renderer.render( scene, cameraNX ); - } + renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); + renderer.render( scene, cameraPY ); - if ( material.specularMap ) { + renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); + renderer.render( scene, cameraNY ); - uniforms.specularMap.value = material.specularMap; + renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); + renderer.render( scene, cameraPZ ); - } + // mipmaps are generated during the last call of render() + // at this point, all sides of the cube render target are defined - if ( material.envMap ) { + renderTarget.texture.generateMipmaps = generateMipmaps; - uniforms.envMap.value = material.envMap; + renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); + renderer.render( scene, cameraNZ ); - // don't flip CubeTexture envMaps, flip everything else: - // WebGLRenderTargetCube will be flipped for backwards compatibility - // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture - // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future - uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; + renderer.xr.enabled = currentXrEnabled; - } + renderTarget.texture.needsPMREMUpdate = true; - if ( material.lightMap ) { + } - uniforms.lightMap.value = material.lightMap; - uniforms.lightMapIntensity.value = material.lightMapIntensity; +} - } +class CubeTexture extends Texture { - if ( material.aoMap ) { + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { - uniforms.aoMap.value = material.aoMap; - uniforms.aoMapIntensity.value = material.aoMapIntensity; + images = images !== undefined ? images : []; + mapping = mapping !== undefined ? mapping : CubeReflectionMapping; + + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + this.isCubeTexture = true; + + this.flipY = false; + + } + + get images() { + + return this.image; + + } + + set images( value ) { + + this.image = value; - } + } - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. normal map - // 4. bump map - // 5. alpha map - // 6. emissive map +} - var uvScaleMap; +class WebGLCubeRenderTarget extends WebGLRenderTarget { - if ( material.map ) { + constructor( size = 1, options = {} ) { - uvScaleMap = material.map; + super( size, size, options ); - } else if ( material.specularMap ) { + this.isWebGLCubeRenderTarget = true; - uvScaleMap = material.specularMap; + const image = { width: size, height: size, depth: 1 }; + const images = [ image, image, image, image, image, image ]; - } else if ( material.displacementMap ) { + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); - uvScaleMap = material.displacementMap; + // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) + // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, + // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. - } else if ( material.normalMap ) { + // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped + // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture + // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). - uvScaleMap = material.normalMap; + this.texture.isRenderTargetTexture = true; - } else if ( material.bumpMap ) { + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - uvScaleMap = material.bumpMap; + } - } else if ( material.roughnessMap ) { + fromEquirectangularTexture( renderer, texture ) { - uvScaleMap = material.roughnessMap; + this.texture.type = texture.type; + this.texture.colorSpace = texture.colorSpace; - } else if ( material.metalnessMap ) { + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; - uvScaleMap = material.metalnessMap; + const shader = { - } else if ( material.alphaMap ) { + uniforms: { + tEquirect: { value: null }, + }, - uvScaleMap = material.alphaMap; + vertexShader: /* glsl */` - } else if ( material.emissiveMap ) { + varying vec3 vWorldDirection; - uvScaleMap = material.emissiveMap; + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { - } + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); - if ( uvScaleMap !== undefined ) { + } - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { + void main() { - uvScaleMap = uvScaleMap.texture; + vWorldDirection = transformDirection( position, modelMatrix ); - } + #include + #include - if ( uvScaleMap.matrixAutoUpdate === true ) { + } + `, - var offset = uvScaleMap.offset; - var repeat = uvScaleMap.repeat; - var rotation = uvScaleMap.rotation; - var center = uvScaleMap.center; + fragmentShader: /* glsl */` - uvScaleMap.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); + uniform sampler2D tEquirect; - } + varying vec3 vWorldDirection; - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); + #include - } + void main() { - } + vec3 direction = normalize( vWorldDirection ); - function refreshUniformsLine( uniforms, material ) { + vec2 sampleUV = equirectUv( direction ); - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; + gl_FragColor = texture2D( tEquirect, sampleUV ); - } + } + ` + }; - function refreshUniformsDash( uniforms, material ) { + const geometry = new BoxGeometry( 5, 5, 5 ); - uniforms.dashSize.value = material.dashSize; - uniforms.totalSize.value = material.dashSize + material.gapSize; - uniforms.scale.value = material.scale; + const material = new ShaderMaterial( { - } + name: 'CubemapFromEquirect', - function refreshUniformsPoints( uniforms, material ) { + uniforms: cloneUniforms( shader.uniforms ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide, + blending: NoBlending - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - uniforms.size.value = material.size * _pixelRatio; - uniforms.scale.value = _height * 0.5; + } ); - uniforms.map.value = material.map; + material.uniforms.tEquirect.value = texture; - if ( material.map !== null ) { + const mesh = new Mesh( geometry, material ); - if ( material.map.matrixAutoUpdate === true ) { + const currentMinFilter = texture.minFilter; - var offset = material.map.offset; - var repeat = material.map.repeat; - var rotation = material.map.rotation; - var center = material.map.center; + // Avoid blurred poles + if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; - material.map.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); + const camera = new CubeCamera( 1, 10, this ); + camera.update( renderer, mesh ); - } + texture.minFilter = currentMinFilter; - uniforms.uvTransform.value.copy( material.map.matrix ); + mesh.geometry.dispose(); + mesh.material.dispose(); - } + return this; } - function refreshUniformsFog( uniforms, fog ) { + clear( renderer, color, depth, stencil ) { - uniforms.fogColor.value = fog.color; + const currentRenderTarget = renderer.getRenderTarget(); - if ( fog.isFog ) { - - uniforms.fogNear.value = fog.near; - uniforms.fogFar.value = fog.far; + for ( let i = 0; i < 6; i ++ ) { - } else if ( fog.isFogExp2 ) { + renderer.setRenderTarget( this, i ); - uniforms.fogDensity.value = fog.density; + renderer.clear( color, depth, stencil ); } + renderer.setRenderTarget( currentRenderTarget ); + } - function refreshUniformsLambert( uniforms, material ) { +} - if ( material.emissiveMap ) { +const _vector1 = /*@__PURE__*/ new Vector3(); +const _vector2 = /*@__PURE__*/ new Vector3(); +const _normalMatrix = /*@__PURE__*/ new Matrix3(); - uniforms.emissiveMap.value = material.emissiveMap; +class Plane { - } + constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { - } + this.isPlane = true; - function refreshUniformsPhong( uniforms, material ) { + // normal is assumed to be normalized - uniforms.specular.value = material.specular; - uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) + this.normal = normal; + this.constant = constant; - if ( material.emissiveMap ) { + } - uniforms.emissiveMap.value = material.emissiveMap; + set( normal, constant ) { - } + this.normal.copy( normal ); + this.constant = constant; - if ( material.bumpMap ) { + return this; - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + } - } + setComponents( x, y, z, w ) { - if ( material.normalMap ) { + this.normal.set( x, y, z ); + this.constant = w; - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + return this; - } + } - if ( material.displacementMap ) { + setFromNormalAndCoplanarPoint( normal, point ) { - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + this.normal.copy( normal ); + this.constant = - point.dot( this.normal ); - } + return this; } - function refreshUniformsToon( uniforms, material ) { + setFromCoplanarPoints( a, b, c ) { - refreshUniformsPhong( uniforms, material ); + const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); - if ( material.gradientMap ) { + // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? - uniforms.gradientMap.value = material.gradientMap; + this.setFromNormalAndCoplanarPoint( normal, a ); - } + return this; } - 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 ) { + copy( plane ) { - uniforms.metalnessMap.value = material.metalnessMap; + this.normal.copy( plane.normal ); + this.constant = plane.constant; - } + return this; - if ( material.emissiveMap ) { + } - uniforms.emissiveMap.value = material.emissiveMap; + normalize() { - } + // Note: will lead to a divide by zero if the plane is invalid. - if ( material.bumpMap ) { + const inverseNormalLength = 1.0 / this.normal.length(); + this.normal.multiplyScalar( inverseNormalLength ); + this.constant *= inverseNormalLength; - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + return this; - } + } - if ( material.normalMap ) { + negate() { - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + this.constant *= - 1; + this.normal.negate(); - } + return this; - if ( material.displacementMap ) { + } - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + distanceToPoint( point ) { - } + return this.normal.dot( point ) + this.constant; - if ( material.envMap ) { + } - //uniforms.envMap.value = material.envMap; // part of uniforms common - uniforms.envMapIntensity.value = material.envMapIntensity; + distanceToSphere( sphere ) { - } + return this.distanceToPoint( sphere.center ) - sphere.radius; } - function refreshUniformsPhysical( uniforms, material ) { - - uniforms.clearCoat.value = material.clearCoat; - uniforms.clearCoatRoughness.value = material.clearCoatRoughness; + projectPoint( point, target ) { - refreshUniformsStandard( uniforms, material ); + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); } - function refreshUniformsDepth( uniforms, material ) { + intersectLine( line, target ) { - if ( material.displacementMap ) { + const direction = line.delta( _vector1 ); - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + const denominator = this.normal.dot( direction ); - } + if ( denominator === 0 ) { - } + // line is coplanar, return origin + if ( this.distanceToPoint( line.start ) === 0 ) { - function refreshUniformsDistance( uniforms, material ) { + return target.copy( line.start ); - if ( material.displacementMap ) { + } - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + // Unsure if this is the correct method to handle this case. + return null; } - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; - - } - - function refreshUniformsNormal( uniforms, material ) { + const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - if ( material.bumpMap ) { + if ( t < 0 || t > 1 ) { - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + return null; } - if ( material.normalMap ) { + return target.copy( line.start ).addScaledVector( direction, t ); - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + } - } + intersectsLine( line ) { - if ( material.displacementMap ) { + // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + const startSign = this.distanceToPoint( line.start ); + const endSign = this.distanceToPoint( line.end ); - } + return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); } - // If uniforms are marked as clean, they don't need to be loaded to the GPU. - - function markUniformsLightsNeedsUpdate( uniforms, value ) { - - uniforms.ambientLightColor.needsUpdate = value; + intersectsBox( box ) { - uniforms.directionalLights.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + return box.intersectsPlane( this ); } - // GL state setting + intersectsSphere( sphere ) { - this.setFaceCulling = function ( cullFace, frontFaceDirection ) { + return sphere.intersectsPlane( this ); - state.setCullFace( cullFace ); - state.setFlipSided( frontFaceDirection === FrontFaceDirectionCW ); + } - }; + coplanarPoint( target ) { - // Textures + return target.copy( this.normal ).multiplyScalar( - this.constant ); - function allocTextureUnit() { + } - var textureUnit = _usedTextureUnits; + applyMatrix4( matrix, optionalNormalMatrix ) { - if ( textureUnit >= capabilities.maxTextures ) { + const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); - console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); + const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); - } + const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - _usedTextureUnits += 1; + this.constant = - referencePoint.dot( normal ); - return textureUnit; + return this; } - this.allocTextureUnit = allocTextureUnit; + translate( offset ) { - // this.setTexture2D = setTexture2D; - this.setTexture2D = ( function () { + this.constant -= offset.dot( this.normal ); - var warned = false; + return this; - // backwards compatibility: peel texture.texture - return function setTexture2D( texture, slot ) { + } - if ( texture && texture.isWebGLRenderTarget ) { + equals( plane ) { - if ( ! warned ) { + return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); - console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." ); - warned = true; + } - } + clone() { - texture = texture.texture; + return new this.constructor().copy( this ); - } + } - textures.setTexture2D( texture, slot ); +} - }; +const _sphere$5 = /*@__PURE__*/ new Sphere(); +const _vector$7 = /*@__PURE__*/ new Vector3(); - }() ); +class Frustum { - this.setTexture = ( function () { + constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { - var warned = false; + this.planes = [ p0, p1, p2, p3, p4, p5 ]; - return function setTexture( texture, slot ) { + } - if ( ! warned ) { + set( p0, p1, p2, p3, p4, p5 ) { - console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." ); - warned = true; + 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 ); - textures.setTexture2D( texture, slot ); + return this; - }; + } - }() ); + copy( frustum ) { - this.setTextureCube = ( function () { + const planes = this.planes; - var warned = false; + for ( let i = 0; i < 6; i ++ ) { - return function setTextureCube( texture, slot ) { + planes[ i ].copy( frustum.planes[ i ] ); - // backwards compatibility: peel texture.texture - if ( texture && texture.isWebGLRenderTargetCube ) { + } - if ( ! warned ) { + return this; - console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." ); - warned = true; + } - } + setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { - texture = texture.texture; + const planes = this.planes; + const me = m.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(); - // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture - // TODO: unify these code paths - if ( ( texture && texture.isCubeTexture ) || - ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) { + if ( coordinateSystem === WebGLCoordinateSystem ) { - // CompressedTexture can have Array in image :/ + planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); - // this function alone should take care of cube textures - textures.setTextureCube( texture, slot ); + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - } else { + planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); + + } else { - // assumed: texture property of THREE.WebGLRenderTargetCube + throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); - textures.setTextureCubeDynamic( texture, slot ); + } - } + return this; - }; + } - }() ); + intersectsObject( object ) { - this.getRenderTarget = function () { + if ( object.boundingSphere !== undefined ) { - return _currentRenderTarget; + if ( object.boundingSphere === null ) object.computeBoundingSphere(); - }; + _sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); - this.setRenderTarget = function ( renderTarget ) { + } else { - _currentRenderTarget = renderTarget; + const geometry = object.geometry; - if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) { + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - textures.setupRenderTarget( renderTarget ); + _sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); } - var framebuffer = null; - var isCube = false; + return this.intersectsSphere( _sphere$5 ); - if ( renderTarget ) { - - var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; + } - if ( renderTarget.isWebGLRenderTargetCube ) { + intersectsSprite( sprite ) { - framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; - isCube = true; + _sphere$5.center.set( 0, 0, 0 ); + _sphere$5.radius = 0.7071067811865476; + _sphere$5.applyMatrix4( sprite.matrixWorld ); - } else { + return this.intersectsSphere( _sphere$5 ); - framebuffer = __webglFramebuffer; + } - } + intersectsSphere( sphere ) { - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + const planes = this.planes; + const center = sphere.center; + const negRadius = - sphere.radius; - } else { + for ( let i = 0; i < 6; i ++ ) { - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); - _currentScissorTest = _scissorTest; + const distance = planes[ i ].distanceToPoint( center ); - } + if ( distance < negRadius ) { - if ( _currentFramebuffer !== framebuffer ) { + return false; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _currentFramebuffer = framebuffer; + } } - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); - - if ( isCube ) { + return true; - var textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel ); + } - } + intersectsBox( box ) { - }; + const planes = this.planes; - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { + for ( let i = 0; i < 6; i ++ ) { - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + const plane = planes[ i ]; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + // corner at max distance - } + _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; - var framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( plane.distanceToPoint( _vector$7 ) < 0 ) { - if ( framebuffer ) { + return false; - var restore = false; + } - if ( framebuffer !== _currentFramebuffer ) { + } - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + return true; - restore = true; + } - } + containsPoint( point ) { - try { + const planes = this.planes; - var texture = renderTarget.texture; - var textureFormat = texture.format; - var textureType = texture.type; + for ( let i = 0; i < 6; i ++ ) { - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + if ( planes[ i ].distanceToPoint( point ) < 0 ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + return false; - } + } - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { + } - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + return true; - } + } - if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) { + clone() { - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + return new this.constructor().copy( this ); - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + } - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); +} - } +function WebGLAnimation() { - } else { + let context = null; + let isAnimating = false; + let animationLoop = null; + let requestId = null; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' ); + function onAnimationFrame( time, frame ) { - } + animationLoop( time, frame ); - } finally { + requestId = context.requestAnimationFrame( onAnimationFrame ); - if ( restore ) { + } - _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer ); + return { - } + start: function () { - } + if ( isAnimating === true ) return; + if ( animationLoop === null ) return; - } + requestId = context.requestAnimationFrame( onAnimationFrame ); - }; + isAnimating = true; -} + }, -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + stop: function () { -function FogExp2( color, density ) { + context.cancelAnimationFrame( requestId ); - this.name = ''; + isAnimating = false; - this.color = new Color( color ); - this.density = ( density !== undefined ) ? density : 0.00025; + }, -} + setAnimationLoop: function ( callback ) { -FogExp2.prototype.isFogExp2 = true; + animationLoop = callback; -FogExp2.prototype.clone = function () { + }, - return new FogExp2( this.color.getHex(), this.density ); + setContext: function ( value ) { -}; + context = value; -FogExp2.prototype.toJSON = function ( /* meta */ ) { + } - return { - type: 'FogExp2', - color: this.color.getHex(), - density: this.density }; -}; +} -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ +function WebGLAttributes( gl ) { -function Fog( color, near, far ) { + const buffers = new WeakMap(); - this.name = ''; + function createBuffer( attribute, bufferType ) { - this.color = new Color( color ); + const array = attribute.array; + const usage = attribute.usage; + const size = array.byteLength; - this.near = ( near !== undefined ) ? near : 1; - this.far = ( far !== undefined ) ? far : 1000; + const buffer = gl.createBuffer(); -} + gl.bindBuffer( bufferType, buffer ); + gl.bufferData( bufferType, array, usage ); -Fog.prototype.isFog = true; + attribute.onUploadCallback(); -Fog.prototype.clone = function () { + let type; - return new Fog( this.color.getHex(), this.near, this.far ); + if ( array instanceof Float32Array ) { -}; + type = gl.FLOAT; -Fog.prototype.toJSON = function ( /* meta */ ) { + } else if ( array instanceof Uint16Array ) { - return { - type: 'Fog', - color: this.color.getHex(), - near: this.near, - far: this.far - }; + if ( attribute.isFloat16BufferAttribute ) { -}; + type = gl.HALF_FLOAT; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } else { -function Scene() { + type = gl.UNSIGNED_SHORT; - Object3D.call( this ); + } - this.type = 'Scene'; + } else if ( array instanceof Int16Array ) { - this.background = null; - this.fog = null; - this.overrideMaterial = null; + type = gl.SHORT; - this.autoUpdate = true; // checked by the renderer + } else if ( array instanceof Uint32Array ) { -} + type = gl.UNSIGNED_INT; -Scene.prototype = Object.assign( Object.create( Object3D.prototype ), { + } else if ( array instanceof Int32Array ) { - constructor: Scene, + type = gl.INT; - copy: function ( source, recursive ) { + } else if ( array instanceof Int8Array ) { - Object3D.prototype.copy.call( this, source, recursive ); + type = gl.BYTE; - if ( source.background !== null ) { this.background = source.background.clone(); } - if ( source.fog !== null ) { this.fog = source.fog.clone(); } - if ( source.overrideMaterial !== null ) { this.overrideMaterial = source.overrideMaterial.clone(); } + } else if ( array instanceof Uint8Array ) { - this.autoUpdate = source.autoUpdate; - this.matrixAutoUpdate = source.matrixAutoUpdate; + type = gl.UNSIGNED_BYTE; - return this; + } else if ( array instanceof Uint8ClampedArray ) { - }, + type = gl.UNSIGNED_BYTE; - toJSON: function ( meta ) { + } else { - var data = Object3D.prototype.toJSON.call( this, meta ); + throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); - if ( this.background !== null ) { data.object.background = this.background.toJSON( meta ); } - if ( this.fog !== null ) { data.object.fog = this.fog.toJSON(); } + } - return data; + return { + buffer: buffer, + type: type, + bytesPerElement: array.BYTES_PER_ELEMENT, + version: attribute.version, + size: size + }; } -} ); + function updateBuffer( buffer, attribute, bufferType ) { -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + const array = attribute.array; + const updateRange = attribute._updateRange; // @deprecated, r159 + const updateRanges = attribute.updateRanges; -function LensFlare( texture, size, distance, blending, color ) { + gl.bindBuffer( bufferType, buffer ); - Object3D.call( this ); + if ( updateRange.count === - 1 && updateRanges.length === 0 ) { - this.lensFlares = []; + // Not using update ranges + gl.bufferSubData( bufferType, 0, array ); - this.positionScreen = new Vector3(); - this.customUpdateCallback = undefined; + } - if ( texture !== undefined ) { + if ( updateRanges.length !== 0 ) { - this.add( texture, size, distance, blending, color ); + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { - } + const range = updateRanges[ i ]; -} + gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, + array, range.start, range.count ); -LensFlare.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: LensFlare, + attribute.clearUpdateRanges(); - isLensFlare: true, + } - copy: function ( source ) { + // @deprecated, r159 + if ( updateRange.count !== - 1 ) { - Object3D.prototype.copy.call( this, source ); + gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, + array, updateRange.offset, updateRange.count ); - this.positionScreen.copy( source.positionScreen ); - this.customUpdateCallback = source.customUpdateCallback; + updateRange.count = - 1; // reset range - for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) { + } - this.lensFlares.push( source.lensFlares[ i ] ); + attribute.onUploadCallback(); - } + } - return this; + // - }, + function get( attribute ) { - add: function ( texture, size, distance, blending, color, opacity ) { - - if ( size === undefined ) { size = - 1; } - if ( distance === undefined ) { distance = 0; } - if ( opacity === undefined ) { opacity = 1; } - if ( color === undefined ) { color = new Color( 0xffffff ); } - if ( blending === undefined ) { blending = NormalBlending; } - - distance = Math.min( distance, Math.max( 0, distance ) ); - - this.lensFlares.push( { - texture: texture, // THREE.Texture - size: size, // size in pixels (-1 = use texture.width) - distance: distance, // distance (0-1) from light source (0=at light source) - x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is in front z = 1 is back - scale: 1, // scale - rotation: 0, // rotation - opacity: opacity, // opacity - color: color, // color - blending: blending // blending - } ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - }, + return buffers.get( attribute ); - /* - * Update lens flares update positions on all flares based on the screen position - * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way. - */ + } - updateLensFlares: function () { + function remove( attribute ) { - var f, fl = this.lensFlares.length; - var flare; - var vecX = - this.positionScreen.x * 2; - var vecY = - this.positionScreen.y * 2; + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - for ( f = 0; f < fl; f ++ ) { + const data = buffers.get( attribute ); - flare = this.lensFlares[ f ]; + if ( data ) { - flare.x = this.positionScreen.x + vecX * flare.distance; - flare.y = this.positionScreen.y + vecY * flare.distance; + gl.deleteBuffer( data.buffer ); - flare.wantedRotation = flare.x * Math.PI * 0.25; - flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25; + buffers.delete( attribute ); } } -} ); + function update( attribute, bufferType ) { -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * uvOffset: new THREE.Vector2(), - * uvScale: new THREE.Vector2() - * } - */ + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; -function SpriteMaterial( parameters ) { + if ( attribute.isGLBufferAttribute ) { - Material.call( this ); + const cached = buffers.get( attribute ); - this.type = 'SpriteMaterial'; + if ( ! cached || cached.version < attribute.version ) { - this.color = new Color( 0xffffff ); - this.map = null; + buffers.set( attribute, { + buffer: attribute.buffer, + type: attribute.type, + bytesPerElement: attribute.elementSize, + version: attribute.version + } ); - this.rotation = 0; + } - this.fog = false; - this.lights = false; + return; - this.setValues( parameters ); + } -} + const data = buffers.get( attribute ); -SpriteMaterial.prototype = Object.create( Material.prototype ); -SpriteMaterial.prototype.constructor = SpriteMaterial; -SpriteMaterial.prototype.isSpriteMaterial = true; + if ( data === undefined ) { -SpriteMaterial.prototype.copy = function ( source ) { + buffers.set( attribute, createBuffer( attribute, bufferType ) ); - Material.prototype.copy.call( this, source ); + } else if ( data.version < attribute.version ) { - this.color.copy( source.color ); - this.map = source.map; + if ( data.size !== attribute.array.byteLength ) { - this.rotation = source.rotation; + throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' ); - return this; + } -}; + updateBuffer( data.buffer, attribute, bufferType ); -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + data.version = attribute.version; -function Sprite( material ) { + } + + } - Object3D.call( this ); + return { - this.type = 'Sprite'; + get: get, + remove: remove, + update: update - this.material = ( material !== undefined ) ? material : new SpriteMaterial(); + }; } -Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { +class PlaneGeometry extends BufferGeometry { - constructor: Sprite, + constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { - isSprite: true, + super(); - raycast: ( function () { + this.type = 'PlaneGeometry'; - var intersectPoint = new Vector3(); - var worldPosition = new Vector3(); - var worldScale = new Vector3(); + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; - return function raycast( raycaster, intersects ) { + const width_half = width / 2; + const height_half = height / 2; - worldPosition.setFromMatrixPosition( this.matrixWorld ); - raycaster.ray.closestPointToPoint( worldPosition, intersectPoint ); + const gridX = Math.floor( widthSegments ); + const gridY = Math.floor( heightSegments ); - worldScale.setFromMatrixScale( this.matrixWorld ); - var guessSizeSq = worldScale.x * worldScale.y / 4; + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; - if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) { return; } + const segment_width = width / gridX; + const segment_height = height / gridY; - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); + // - if ( distance < raycaster.near || distance > raycaster.far ) { return; } + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - intersects.push( { + for ( let iy = 0; iy < gridY1; iy ++ ) { - distance: distance, - point: intersectPoint.clone(), - face: null, - object: this + const y = iy * segment_height - height_half; - } ); + for ( let ix = 0; ix < gridX1; ix ++ ) { - }; + const x = ix * segment_width - width_half; - }() ), + vertices.push( x, - y, 0 ); - clone: function () { + normals.push( 0, 0, 1 ); - return new this.constructor( this.material ).copy( this ); + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - } + } -} ); + } -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + for ( let iy = 0; iy < gridY; iy ++ ) { + + for ( let ix = 0; ix < gridX; ix ++ ) { -function LOD() { + const a = ix + gridX1 * iy; + const b = ix + gridX1 * ( iy + 1 ); + const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = ( ix + 1 ) + gridX1 * iy; - Object3D.call( this ); + indices.push( a, b, d ); + indices.push( b, c, d ); - this.type = 'LOD'; + } - Object.defineProperties( this, { - levels: { - enumerable: true, - value: [] } - } ); -} + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); -LOD.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: LOD, + copy( source ) { - copy: function ( source ) { + super.copy( source ); - Object3D.prototype.copy.call( this, source, false ); + this.parameters = Object.assign( {}, source.parameters ); - var levels = source.levels; + return this; - for ( var i = 0, l = levels.length; i < l; i ++ ) { + } - var level = levels[ i ]; + static fromJSON( data ) { - this.addLevel( level.object.clone(), level.distance ); + return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); - } + } - return this; +} - }, +var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif"; - addLevel: function ( object, distance ) { +var alphahash_pars_fragment = "#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif"; - if ( distance === undefined ) { distance = 0; } +var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; - distance = Math.abs( distance ); +var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - var levels = this.levels; +var alphatest_fragment = "#ifdef USE_ALPHATEST\n\t#ifdef ALPHA_TO_COVERAGE\n\tdiffuseColor.a = smoothstep( alphaTest, alphaTest + fwidth( diffuseColor.a ), diffuseColor.a );\n\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\tif ( diffuseColor.a < alphaTest ) discard;\n\t#endif\n#endif"; - for ( var l = 0; l < levels.length; l ++ ) { +var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; - if ( distance < levels[ l ].distance ) { +var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; - break; +var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; - } +var batching_pars_vertex = "#ifdef USE_BATCHING\n\t#if ! defined( GL_ANGLE_multi_draw )\n\t#define gl_DrawID _gl_DrawID\n\tuniform int _gl_DrawID;\n\t#endif\n\tuniform highp sampler2D batchingTexture;\n\tuniform highp usampler2D batchingIdTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n\tfloat getIndirectIndex( const in int i ) {\n\t\tint size = textureSize( batchingIdTexture, 0 ).x;\n\t\tint x = i % size;\n\t\tint y = i / size;\n\t\treturn float( texelFetch( batchingIdTexture, ivec2( x, y ), 0 ).r );\n\t}\n#endif\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec3 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb;\n\t}\n#endif"; - } +var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( getIndirectIndex( gl_DrawID ) );\n#endif"; - levels.splice( l, 0, { distance: distance, object: object } ); +var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif"; - this.add( object ); +var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; - }, +var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated"; - getObjectForDistance: function ( distance ) { +var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.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\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; - var levels = this.levels; +var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; - for ( var i = 1, l = levels.length; i < l; i ++ ) { +var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif"; - if ( distance < levels[ i ].distance ) { +var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; - break; +var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; - } +var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; - } +var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; - return levels[ i - 1 ].object; +var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; - }, +var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif"; - raycast: ( function () { +var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif"; - var matrixPosition = new Vector3(); +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\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; - return function raycast( raycaster, intersects ) { +var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; - matrixPosition.setFromMatrixPosition( this.matrixWorld ); +var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; - var distance = raycaster.ray.origin.distanceTo( matrixPosition ); +var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; - this.getObjectForDistance( distance ).raycast( raycaster, intersects ); +var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; - }; +var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; - }() ), +var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; - update: function () { +var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; - var v1 = new Vector3(); - var v2 = new Vector3(); +var colorspace_pars_fragment = "\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn 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}"; - return function update( camera ) { +var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; - var levels = this.levels; +var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; - if ( levels.length > 1 ) { +var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif"; - v1.setFromMatrixPosition( camera.matrixWorld ); - v2.setFromMatrixPosition( this.matrixWorld ); +var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif"; - var distance = v1.distanceTo( v2 ); +var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif"; - levels[ 0 ].object.visible = true; +var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; - for ( var i = 1, l = levels.length; i < l; i ++ ) { +var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; - if ( distance >= levels[ i ].distance ) { +var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"; - levels[ i - 1 ].object.visible = false; - levels[ i ].object.visible = true; +var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif"; - } else { +var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; - break; +var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; - } +var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; - } +var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; - for ( ; i < l; i ++ ) { +var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; - levels[ i ].object.visible = false; +var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; - } +var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; - } +var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon"; - }; +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\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; - toJSON: function ( meta ) { +var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; - var data = Object3D.prototype.toJSON.call( this, meta ); +var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; - data.object.levels = []; +var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; - var levels = this.levels; +var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; - for ( var i = 0, l = levels.length; i < l; i ++ ) { +var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif"; - var level = levels[ i ]; +var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; - data.object.levels.push( { - object: level.object.uuid, - distance: level.distance - } ); +var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; - } +var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; - return data; +var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif"; - } +var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = 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\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; -} ); +var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author michael guerrero / http://realitymeltdown.com - * @author ikerr / http://verold.com - */ +var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; -function Skeleton( bones, boneInverses ) { +var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - // copy the bone array +var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; - bones = bones || []; +var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; - this.bones = bones.slice( 0 ); - this.boneMatrices = new Float32Array( this.bones.length * 16 ); +var morphinstance_vertex = "#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif"; - // use the supplied bone inverses or calculate the inverses +var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif"; - if ( boneInverses === undefined ) { +var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; - this.calculateInverses(); +var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif"; - } else { +var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; - if ( this.bones.length === boneInverses.length ) { +var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;"; - this.boneInverses = boneInverses.slice( 0 ); +var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; - } else { +var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; - console.warn( 'THREE.Skeleton boneInverses is the wrong length.' ); +var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; - this.boneInverses = []; +var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { +var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; - this.boneInverses.push( new Matrix4() ); +var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif"; - } +var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; - } +var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; - } +var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; -} +var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; -Object.assign( Skeleton.prototype, { +var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn 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\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; - calculateInverses: function () { +var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; - this.boneInverses = []; +var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { +var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; - var inverse = new Matrix4(); +var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; - if ( this.bones[ i ] ) { +var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; - inverse.getInverse( this.bones[ i ].matrixWorld ); +var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; - } +var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif"; - this.boneInverses.push( inverse ); +var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; - } +var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; - }, +var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}"; - pose: function () { +var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; - var bone, i, il; +var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif"; - // recover the bind-time world matrices +var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif"; - for ( i = 0, il = this.bones.length; i < il; i ++ ) { +var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; - bone = this.bones[ i ]; +var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; - if ( bone ) { +var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; - bone.matrixWorld.getInverse( this.boneInverses[ i ] ); +var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_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\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - } +var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; - // compute the local matrices, positions, rotations and scales +var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; - for ( i = 0, il = this.bones.length; i < il; i ++ ) { +var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - bone = this.bones[ i ]; +var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - if ( bone ) { +var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; - if ( bone.parent && bone.parent.isBone ) { +var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; - bone.matrix.getInverse( bone.parent.matrixWorld ); - bone.matrix.multiply( bone.matrixWorld ); +const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; - } else { +const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; - bone.matrix.copy( bone.matrixWorld ); +const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; - } +const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); +const vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; - } +const fragment$f = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}"; - } +const vertex$e = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}"; - }, +const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}"; - update: ( function () { +const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}"; - var offsetMatrix = new Matrix4(); - var identityMatrix = new Matrix4(); +const 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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; - return function update() { +const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}"; - var bones = this.bones; - var boneInverses = this.boneInverses; - var boneMatrices = this.boneMatrices; - var boneTexture = this.boneTexture; +const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; - // flatten bone matrices to array +const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - for ( var i = 0, il = bones.length; i < il; i ++ ) { +const 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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - // compute the offset between the current and the original transform +const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix; +const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); - offsetMatrix.toArray( boneMatrices, i * 16 ); +const vertex$9 = "#define LAMBERT\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } +const fragment$9 = "#define LAMBERT\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - if ( boneTexture !== undefined ) { +const 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 \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; - boneTexture.needsUpdate = true; +const 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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } +const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; - }; +const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; - } )(), +const 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - clone: function () { +const 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - return new Skeleton( this.bones, this.boneInverses ); +const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; - } +const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -} ); +const 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author ikerr / http://verold.com - */ +const 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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -function Bone() { +const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - Object3D.call( this ); +const fragment$3 = "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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - this.type = 'Bone'; +const vertex$2 = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -} +const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; -Bone.prototype = Object.assign( Object.create( Object3D.prototype ), { +const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"; - constructor: Bone, +const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - isBone: true +const ShaderChunk = { + alphahash_fragment: alphahash_fragment, + alphahash_pars_fragment: alphahash_pars_fragment, + alphamap_fragment: alphamap_fragment, + alphamap_pars_fragment: alphamap_pars_fragment, + alphatest_fragment: alphatest_fragment, + alphatest_pars_fragment: alphatest_pars_fragment, + aomap_fragment: aomap_fragment, + aomap_pars_fragment: aomap_pars_fragment, + batching_pars_vertex: batching_pars_vertex, + batching_vertex: batching_vertex, + begin_vertex: begin_vertex, + beginnormal_vertex: beginnormal_vertex, + bsdfs: bsdfs, + iridescence_fragment: iridescence_fragment, + bumpmap_pars_fragment: bumpmap_pars_fragment, + clipping_planes_fragment: clipping_planes_fragment, + clipping_planes_pars_fragment: clipping_planes_pars_fragment, + clipping_planes_pars_vertex: clipping_planes_pars_vertex, + clipping_planes_vertex: clipping_planes_vertex, + color_fragment: color_fragment, + color_pars_fragment: color_pars_fragment, + color_pars_vertex: color_pars_vertex, + color_vertex: color_vertex, + common: common, + cube_uv_reflection_fragment: cube_uv_reflection_fragment, + defaultnormal_vertex: defaultnormal_vertex, + displacementmap_pars_vertex: displacementmap_pars_vertex, + displacementmap_vertex: displacementmap_vertex, + emissivemap_fragment: emissivemap_fragment, + emissivemap_pars_fragment: emissivemap_pars_fragment, + colorspace_fragment: colorspace_fragment, + colorspace_pars_fragment: colorspace_pars_fragment, + envmap_fragment: envmap_fragment, + envmap_common_pars_fragment: envmap_common_pars_fragment, + envmap_pars_fragment: envmap_pars_fragment, + envmap_pars_vertex: envmap_pars_vertex, + envmap_physical_pars_fragment: envmap_physical_pars_fragment, + envmap_vertex: envmap_vertex, + fog_vertex: fog_vertex, + fog_pars_vertex: fog_pars_vertex, + fog_fragment: fog_fragment, + fog_pars_fragment: fog_pars_fragment, + gradientmap_pars_fragment: gradientmap_pars_fragment, + lightmap_pars_fragment: lightmap_pars_fragment, + lights_lambert_fragment: lights_lambert_fragment, + lights_lambert_pars_fragment: lights_lambert_pars_fragment, + lights_pars_begin: lights_pars_begin, + lights_toon_fragment: lights_toon_fragment, + lights_toon_pars_fragment: lights_toon_pars_fragment, + lights_phong_fragment: lights_phong_fragment, + lights_phong_pars_fragment: lights_phong_pars_fragment, + lights_physical_fragment: lights_physical_fragment, + lights_physical_pars_fragment: lights_physical_pars_fragment, + lights_fragment_begin: lights_fragment_begin, + lights_fragment_maps: lights_fragment_maps, + lights_fragment_end: lights_fragment_end, + logdepthbuf_fragment: logdepthbuf_fragment, + logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, + logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, + logdepthbuf_vertex: logdepthbuf_vertex, + map_fragment: map_fragment, + map_pars_fragment: map_pars_fragment, + map_particle_fragment: map_particle_fragment, + map_particle_pars_fragment: map_particle_pars_fragment, + metalnessmap_fragment: metalnessmap_fragment, + metalnessmap_pars_fragment: metalnessmap_pars_fragment, + morphinstance_vertex: morphinstance_vertex, + morphcolor_vertex: morphcolor_vertex, + morphnormal_vertex: morphnormal_vertex, + morphtarget_pars_vertex: morphtarget_pars_vertex, + morphtarget_vertex: morphtarget_vertex, + normal_fragment_begin: normal_fragment_begin, + normal_fragment_maps: normal_fragment_maps, + normal_pars_fragment: normal_pars_fragment, + normal_pars_vertex: normal_pars_vertex, + normal_vertex: normal_vertex, + normalmap_pars_fragment: normalmap_pars_fragment, + clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, + clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, + clearcoat_pars_fragment: clearcoat_pars_fragment, + iridescence_pars_fragment: iridescence_pars_fragment, + opaque_fragment: opaque_fragment, + packing: packing, + premultiplied_alpha_fragment: premultiplied_alpha_fragment, + project_vertex: project_vertex, + dithering_fragment: dithering_fragment, + dithering_pars_fragment: dithering_pars_fragment, + roughnessmap_fragment: roughnessmap_fragment, + roughnessmap_pars_fragment: roughnessmap_pars_fragment, + shadowmap_pars_fragment: shadowmap_pars_fragment, + shadowmap_pars_vertex: shadowmap_pars_vertex, + shadowmap_vertex: shadowmap_vertex, + shadowmask_pars_fragment: shadowmask_pars_fragment, + skinbase_vertex: skinbase_vertex, + skinning_pars_vertex: skinning_pars_vertex, + skinning_vertex: skinning_vertex, + skinnormal_vertex: skinnormal_vertex, + specularmap_fragment: specularmap_fragment, + specularmap_pars_fragment: specularmap_pars_fragment, + tonemapping_fragment: tonemapping_fragment, + tonemapping_pars_fragment: tonemapping_pars_fragment, + transmission_fragment: transmission_fragment, + transmission_pars_fragment: transmission_pars_fragment, + uv_pars_fragment: uv_pars_fragment, + uv_pars_vertex: uv_pars_vertex, + uv_vertex: uv_vertex, + worldpos_vertex: worldpos_vertex, -} ); + background_vert: vertex$h, + background_frag: fragment$h, + backgroundCube_vert: vertex$g, + backgroundCube_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 +}; /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author ikerr / http://verold.com + * Uniforms library for shared webgl shaders */ -function SkinnedMesh( geometry, material ) { - - Mesh.call( this, geometry, material ); - - this.type = 'SkinnedMesh'; - - this.bindMode = 'attached'; - this.bindMatrix = new Matrix4(); - this.bindMatrixInverse = new Matrix4(); - - var bones = this.initBones(); - var skeleton = new Skeleton( bones ); +const UniformsLib = { - this.bind( skeleton, this.matrixWorld ); - - this.normalizeSkinWeights(); - -} - -SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { - - constructor: SkinnedMesh, - - isSkinnedMesh: true, - - initBones: function () { - - var bones = [], bone, gbone; - var i, il; - - if ( this.geometry && this.geometry.bones !== undefined ) { - - // first, create array of 'Bone' objects from geometry data - - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { - - gbone = this.geometry.bones[ i ]; - - // create new 'Bone' object + common: { - bone = new Bone(); - bones.push( bone ); + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, - // apply values + map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, - bone.name = gbone.name; - bone.position.fromArray( gbone.pos ); - bone.quaternion.fromArray( gbone.rotq ); - if ( gbone.scl !== undefined ) { bone.scale.fromArray( gbone.scl ); } + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, - } + alphaTest: { value: 0 } - // second, create bone hierarchy + }, - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { + specularmap: { - gbone = this.geometry.bones[ i ]; + specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } - if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { + }, - // subsequent bones in the hierarchy + envmap: { - bones[ gbone.parent ].add( bones[ i ] ); + envMap: { value: null }, + envMapRotation: { value: /*@__PURE__*/ new Matrix3() }, + flipEnvMap: { value: - 1 }, + reflectivity: { value: 1.0 }, // basic, lambert, phong + ior: { value: 1.5 }, // physical + refractionRatio: { value: 0.98 }, // basic, lambert, phong - } else { + }, - // topmost bone, immediate child of the skinned mesh + aomap: { - this.add( bones[ i ] ); + aoMap: { value: null }, + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } - } + }, - } + lightmap: { - } + lightMap: { value: null }, + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } - // now the bones are part of the scene graph and children of the skinned mesh. - // let's update the corresponding matrices + }, - this.updateMatrixWorld( true ); + bumpmap: { - return bones; + bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + bumpScale: { value: 1 } }, - bind: function ( skeleton, bindMatrix ) { + normalmap: { - this.skeleton = skeleton; + normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } - if ( bindMatrix === undefined ) { + }, - this.updateMatrixWorld( true ); + displacementmap: { - this.skeleton.calculateInverses(); + displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + displacementScale: { value: 1 }, + displacementBias: { value: 0 } - bindMatrix = this.matrixWorld; + }, - } + emissivemap: { - this.bindMatrix.copy( bindMatrix ); - this.bindMatrixInverse.getInverse( bindMatrix ); + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, - pose: function () { + metalnessmap: { - this.skeleton.pose(); + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, - normalizeSkinWeights: function () { - - var scale, i; - - if ( this.geometry && this.geometry.isGeometry ) { + roughnessmap: { - for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) { + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } - var sw = this.geometry.skinWeights[ i ]; + }, - scale = 1.0 / sw.manhattanLength(); + gradientmap: { - if ( scale !== Infinity ) { + gradientMap: { value: null } - sw.multiplyScalar( scale ); + }, - } else { + fog: { - sw.set( 1, 0, 0, 0 ); // do something reasonable + fogDensity: { value: 0.00025 }, + fogNear: { value: 1 }, + fogFar: { value: 2000 }, + fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } - } + }, - } + lights: { - } else if ( this.geometry && this.geometry.isBufferGeometry ) { + ambientLightColor: { value: [] }, - var vec = new Vector4(); + lightProbe: { value: [] }, - var skinWeight = this.geometry.attributes.skinWeight; + directionalLights: { value: [], properties: { + direction: {}, + color: {} + } }, - for ( i = 0; i < skinWeight.count; i ++ ) { + directionalLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, - vec.x = skinWeight.getX( i ); - vec.y = skinWeight.getY( i ); - vec.z = skinWeight.getZ( i ); - vec.w = skinWeight.getW( i ); + directionalShadowMap: { value: [] }, + directionalShadowMatrix: { value: [] }, - scale = 1.0 / vec.manhattanLength(); + spotLights: { value: [], properties: { + color: {}, + position: {}, + direction: {}, + distance: {}, + coneCos: {}, + penumbraCos: {}, + decay: {} + } }, - if ( scale !== Infinity ) { + spotLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, - vec.multiplyScalar( scale ); + spotLightMap: { value: [] }, + spotShadowMap: { value: [] }, + spotLightMatrix: { value: [] }, - } else { + pointLights: { value: [], properties: { + color: {}, + position: {}, + decay: {}, + distance: {} + } }, - vec.set( 1, 0, 0, 0 ); // do something reasonable + pointLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} + } }, - } + pointShadowMap: { value: [] }, + pointShadowMatrix: { value: [] }, - skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w ); + hemisphereLights: { value: [], properties: { + direction: {}, + skyColor: {}, + groundColor: {} + } }, - } + // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src + rectAreaLights: { value: [], properties: { + color: {}, + position: {}, + width: {}, + height: {} + } }, - } + ltc_1: { value: null }, + ltc_2: { value: null } }, - updateMatrixWorld: function ( force ) { - - Mesh.prototype.updateMatrixWorld.call( this, force ); - - if ( this.bindMode === 'attached' ) { - - this.bindMatrixInverse.getInverse( this.matrixWorld ); - - } else if ( this.bindMode === 'detached' ) { - - this.bindMatrixInverse.getInverse( this.bindMatrix ); - - } else { - - console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); + points: { - } + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, + size: { value: 1.0 }, + scale: { value: 1.0 }, + map: { value: null }, + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 }, + uvTransform: { value: /*@__PURE__*/ new Matrix3() } }, - clone: function () { + sprite: { - return new this.constructor( this.geometry, this.material ).copy( this ); + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, + center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, + rotation: { value: 0.0 }, + map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * linecap: "round", - * linejoin: "round" - * } - */ - -function LineBasicMaterial( parameters ) { +}; - Material.call( this ); +const ShaderLib = { - this.type = 'LineBasicMaterial'; + basic: { - this.color = new Color( 0xffffff ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.fog + ] ), - this.linewidth = 1; - this.linecap = 'round'; - this.linejoin = 'round'; + vertexShader: ShaderChunk.meshbasic_vert, + fragmentShader: ShaderChunk.meshbasic_frag - this.lights = false; + }, - this.setValues( parameters ); + lambert: { -} + 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 Color( 0x000000 ) } + } + ] ), -LineBasicMaterial.prototype = Object.create( Material.prototype ); -LineBasicMaterial.prototype.constructor = LineBasicMaterial; + vertexShader: ShaderChunk.meshlambert_vert, + fragmentShader: ShaderChunk.meshlambert_frag -LineBasicMaterial.prototype.isLineBasicMaterial = true; + }, -LineBasicMaterial.prototype.copy = function ( source ) { + phong: { - Material.prototype.copy.call( this, source ); + 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 Color( 0x000000 ) }, + specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, + shininess: { value: 30 } + } + ] ), - this.color.copy( source.color ); + vertexShader: ShaderChunk.meshphong_vert, + fragmentShader: ShaderChunk.meshphong_frag - this.linewidth = source.linewidth; - this.linecap = source.linecap; - this.linejoin = source.linejoin; + }, - return this; + 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 Color( 0x000000 ) }, + roughness: { value: 1.0 }, + metalness: { value: 0.0 }, + envMapIntensity: { value: 1 } + } + ] ), -/** - * @author mrdoob / http://mrdoob.com/ - */ + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag -function Line( geometry, material, mode ) { + }, - if ( mode === 1 ) { + toon: { - console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' ); - return new LineSegments( geometry, material ); + 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 Color( 0x000000 ) } + } + ] ), - } + vertexShader: ShaderChunk.meshtoon_vert, + fragmentShader: ShaderChunk.meshtoon_frag - Object3D.call( this ); + }, - this.type = 'Line'; + matcap: { - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.fog, + { + matcap: { value: null } + } + ] ), -} + vertexShader: ShaderChunk.meshmatcap_vert, + fragmentShader: ShaderChunk.meshmatcap_frag -Line.prototype = Object.assign( Object.create( Object3D.prototype ), { + }, - constructor: Line, + points: { - isLine: true, + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.points, + UniformsLib.fog + ] ), - raycast: ( function () { + vertexShader: ShaderChunk.points_vert, + fragmentShader: ShaderChunk.points_frag - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + }, - return function raycast( raycaster, intersects ) { + dashed: { - var precision = raycaster.linePrecision; - var precisionSq = precision * precision; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.fog, + { + scale: { value: 1 }, + dashSize: { value: 1 }, + totalSize: { value: 2 } + } + ] ), - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; + vertexShader: ShaderChunk.linedashed_vert, + fragmentShader: ShaderChunk.linedashed_frag - // Checking boundingSphere distance to ray + }, - if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); } + depth: { - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.displacementmap + ] ), - if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; } + vertexShader: ShaderChunk.depth_vert, + fragmentShader: ShaderChunk.depth_frag - // + }, - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + normal: { - var vStart = new Vector3(); - var vEnd = new Vector3(); - var interSegment = new Vector3(); - var interRay = new Vector3(); - var step = ( this && this.isLineSegments ) ? 2 : 1; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + { + opacity: { value: 1.0 } + } + ] ), - if ( geometry.isBufferGeometry ) { + vertexShader: ShaderChunk.meshnormal_vert, + fragmentShader: ShaderChunk.meshnormal_frag - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; + }, - if ( index !== null ) { + sprite: { - var indices = index.array; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.sprite, + UniformsLib.fog + ] ), - for ( var i = 0, l = indices.length - 1; i < l; i += step ) { + vertexShader: ShaderChunk.sprite_vert, + fragmentShader: ShaderChunk.sprite_frag - var a = indices[ i ]; - var b = indices[ i + 1 ]; + }, - vStart.fromArray( positions, a * 3 ); - vEnd.fromArray( positions, b * 3 ); + background: { - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + uniforms: { + uvTransform: { value: /*@__PURE__*/ new Matrix3() }, + t2D: { value: null }, + backgroundIntensity: { value: 1 } + }, - if ( distSq > precisionSq ) { continue; } + vertexShader: ShaderChunk.background_vert, + fragmentShader: ShaderChunk.background_frag - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + }, - var distance = raycaster.ray.origin.distanceTo( interRay ); + backgroundCube: { - if ( distance < raycaster.near || distance > raycaster.far ) { continue; } + uniforms: { + envMap: { value: null }, + flipEnvMap: { value: - 1 }, + backgroundBlurriness: { value: 0 }, + backgroundIntensity: { value: 1 }, + backgroundRotation: { value: /*@__PURE__*/ new Matrix3() } + }, - intersects.push( { + vertexShader: ShaderChunk.backgroundCube_vert, + fragmentShader: ShaderChunk.backgroundCube_frag - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + }, - } ); + cube: { - } + uniforms: { + tCube: { value: null }, + tFlip: { value: - 1 }, + opacity: { value: 1.0 } + }, - } else { + vertexShader: ShaderChunk.cube_vert, + fragmentShader: ShaderChunk.cube_frag - for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) { + }, - vStart.fromArray( positions, 3 * i ); - vEnd.fromArray( positions, 3 * i + 3 ); + equirect: { - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + uniforms: { + tEquirect: { value: null }, + }, - if ( distSq > precisionSq ) { continue; } + vertexShader: ShaderChunk.equirect_vert, + fragmentShader: ShaderChunk.equirect_frag - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + }, - var distance = raycaster.ray.origin.distanceTo( interRay ); + distanceRGBA: { - if ( distance < raycaster.near || distance > raycaster.far ) { continue; } + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.displacementmap, + { + referencePosition: { value: /*@__PURE__*/ new Vector3() }, + nearDistance: { value: 1 }, + farDistance: { value: 1000 } + } + ] ), - intersects.push( { + vertexShader: ShaderChunk.distanceRGBA_vert, + fragmentShader: ShaderChunk.distanceRGBA_frag - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + }, - } ); + shadow: { - } + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.lights, + UniformsLib.fog, + { + color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, + opacity: { value: 1.0 } + }, + ] ), - } + vertexShader: ShaderChunk.shadow_vert, + fragmentShader: ShaderChunk.shadow_frag - } else if ( geometry.isGeometry ) { + } - var vertices = geometry.vertices; - var nbVertices = vertices.length; +}; - for ( var i = 0; i < nbVertices - 1; i += step ) { +ShaderLib.physical = { - var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + ShaderLib.standard.uniforms, + { + clearcoat: { value: 0 }, + clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, + clearcoatRoughness: { value: 0 }, + clearcoatRoughnessMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + dispersion: { value: 0 }, + iridescence: { value: 0 }, + iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + iridescenceIOR: { value: 1.3 }, + iridescenceThicknessMinimum: { value: 100 }, + iridescenceThicknessMaximum: { value: 400 }, + iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + sheen: { value: 0 }, + sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, + sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + sheenRoughness: { value: 1 }, + sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + transmission: { value: 0 }, + transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, + transmissionSamplerMap: { value: null }, + thickness: { value: 0 }, + thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + attenuationDistance: { value: 0 }, + attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, + specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, + specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + } + ] ), - if ( distSq > precisionSq ) { continue; } + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation +}; - var distance = raycaster.ray.origin.distanceTo( interRay ); +const _rgb = { r: 0, b: 0, g: 0 }; +const _e1$1 = /*@__PURE__*/ new Euler(); +const _m1$1 = /*@__PURE__*/ new Matrix4(); - if ( distance < raycaster.near || distance > raycaster.far ) { continue; } +function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { - intersects.push( { + const clearColor = new Color( 0x000000 ); + let clearAlpha = alpha === true ? 0 : 1; - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + let planeMesh; + let boxMesh; - } ); + let currentBackground = null; + let currentBackgroundVersion = 0; + let currentTonemapping = null; - } + function getBackground( scene ) { - } + let background = scene.isScene === true ? scene.background : null; - }; + if ( background && background.isTexture ) { - }() ), + const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background + background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); - clone: function () { + } - return new this.constructor( this.geometry, this.material ).copy( this ); + return background; } -} ); + function render( scene ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function LineSegments( geometry, material ) { - - Line.call( this, geometry, material ); + let forceClear = false; + const background = getBackground( scene ); - this.type = 'LineSegments'; + if ( background === null ) { -} + setClear( clearColor, clearAlpha ); -LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { + } else if ( background && background.isColor ) { - constructor: LineSegments, + setClear( background, 1 ); + forceClear = true; - isLineSegments: true + } -} ); + const environmentBlendMode = renderer.xr.getEnvironmentBlendMode(); -/** - * @author mgreter / http://github.com/mgreter - */ + if ( environmentBlendMode === 'additive' ) { -function LineLoop( geometry, material ) { + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); - Line.call( this, geometry, material ); + } else if ( environmentBlendMode === 'alpha-blend' ) { - this.type = 'LineLoop'; + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); -} + } -LineLoop.prototype = Object.assign( Object.create( Line.prototype ), { + if ( renderer.autoClear || forceClear ) { - constructor: LineLoop, + // buffers might not be writable which is required to ensure a correct clear - isLineLoop: true, + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); -} ); + renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * size: , - * sizeAttenuation: - * } - */ + } -function PointsMaterial( parameters ) { + } - Material.call( this ); + function addToRenderList( renderList, scene ) { - this.type = 'PointsMaterial'; + const background = getBackground( scene ); - this.color = new Color( 0xffffff ); + if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { - this.map = null; + if ( boxMesh === undefined ) { - this.size = 1; - this.sizeAttenuation = true; + boxMesh = new Mesh( + new BoxGeometry( 1, 1, 1 ), + new ShaderMaterial( { + name: 'BackgroundCubeMaterial', + uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), + vertexShader: ShaderLib.backgroundCube.vertexShader, + fragmentShader: ShaderLib.backgroundCube.fragmentShader, + side: BackSide, + depthTest: false, + depthWrite: false, + fog: false + } ) + ); - this.lights = false; + boxMesh.geometry.deleteAttribute( 'normal' ); + boxMesh.geometry.deleteAttribute( 'uv' ); - this.setValues( parameters ); + boxMesh.onBeforeRender = function ( renderer, scene, camera ) { -} + this.matrixWorld.copyPosition( camera.matrixWorld ); -PointsMaterial.prototype = Object.create( Material.prototype ); -PointsMaterial.prototype.constructor = PointsMaterial; + }; -PointsMaterial.prototype.isPointsMaterial = true; + // add "envMap" material property so the renderer can evaluate it like for built-in materials + Object.defineProperty( boxMesh.material, 'envMap', { -PointsMaterial.prototype.copy = function ( source ) { + get: function () { - Material.prototype.copy.call( this, source ); + return this.uniforms.envMap.value; - this.color.copy( source.color ); + } - this.map = source.map; + } ); - this.size = source.size; - this.sizeAttenuation = source.sizeAttenuation; + objects.update( boxMesh ); - return this; + } -}; + _e1$1.copy( scene.backgroundRotation ); -/** - * @author alteredq / http://alteredqualia.com/ - */ + // accommodate left-handed frame + _e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1; -function Points$1( geometry, material ) { + if ( background.isCubeTexture && background.isRenderTargetTexture === false ) { - Object3D.call( this ); + // environment maps which are not cube render targets or PMREMs follow a different convention + _e1$1.y *= - 1; + _e1$1.z *= - 1; - this.type = 'Points'; + } - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } ); + boxMesh.material.uniforms.envMap.value = background; + boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; + boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; + boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; + boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) ); + boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; -} + if ( currentBackground !== background || + currentBackgroundVersion !== background.version || + currentTonemapping !== renderer.toneMapping ) { -Points$1.prototype = Object.assign( Object.create( Object3D.prototype ), { + boxMesh.material.needsUpdate = true; - constructor: Points$1, + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; - isPoints: true, + } - raycast: ( function () { + boxMesh.layers.enableAll(); - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + // push to the pre-sorted opaque render list + renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); - return function raycast( raycaster, intersects ) { + } else if ( background && background.isTexture ) { - var object = this; - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; - var threshold = raycaster.params.Points.threshold; + if ( planeMesh === undefined ) { - // Checking boundingSphere distance to ray + 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 + } ) + ); - if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); } + planeMesh.geometry.deleteAttribute( 'normal' ); - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - sphere.radius += threshold; + // add "map" material property so the renderer can evaluate it like for built-in materials + Object.defineProperty( planeMesh.material, 'map', { - if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; } + get: function () { - // + return this.uniforms.t2D.value; - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + } - var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); - var localThresholdSq = localThreshold * localThreshold; - var position = new Vector3(); + } ); - function testPoint( point, index ) { + objects.update( planeMesh ); - var rayPointDistanceSq = ray.distanceSqToPoint( point ); + } - if ( rayPointDistanceSq < localThresholdSq ) { + planeMesh.material.uniforms.t2D.value = background; + planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; + planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; - var intersectPoint = ray.closestPointToPoint( point ); - intersectPoint.applyMatrix4( matrixWorld ); + if ( background.matrixAutoUpdate === true ) { - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); + background.updateMatrix(); - if ( distance < raycaster.near || distance > raycaster.far ) { return; } + } - intersects.push( { + planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); - distance: distance, - distanceToRay: Math.sqrt( rayPointDistanceSq ), - point: intersectPoint.clone(), - index: index, - face: null, - object: object + if ( currentBackground !== background || + currentBackgroundVersion !== background.version || + currentTonemapping !== renderer.toneMapping ) { - } ); + planeMesh.material.needsUpdate = true; - } + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; } - if ( geometry.isBufferGeometry ) { - - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; + planeMesh.layers.enableAll(); - if ( index !== null ) { + // push to the pre-sorted opaque render list + renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); - var indices = index.array; - - for ( var i = 0, il = indices.length; i < il; i ++ ) { + } - var a = indices[ i ]; + } - position.fromArray( positions, a * 3 ); + function setClear( color, alpha ) { - testPoint( position, a ); + color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); - } + state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); - } else { + } - for ( var i = 0, l = positions.length / 3; i < l; i ++ ) { + return { - position.fromArray( positions, i * 3 ); + getClearColor: function () { - testPoint( position, i ); + return clearColor; - } + }, + setClearColor: function ( color, alpha = 1 ) { - } + clearColor.set( color ); + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); - } else { + }, + getClearAlpha: function () { - var vertices = geometry.vertices; + return clearAlpha; - for ( var i = 0, l = vertices.length; i < l; i ++ ) { + }, + setClearAlpha: function ( alpha ) { - testPoint( vertices[ i ], i ); + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); - } + }, + render: render, + addToRenderList: addToRenderList - } + }; - }; +} - }() ), +function WebGLBindingStates( gl, attributes ) { - clone: function () { + const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - return new this.constructor( this.geometry, this.material ).copy( this ); + const bindingStates = {}; - } + const defaultState = createBindingState( null ); + let currentState = defaultState; + let forceUpdate = false; -} ); + function setup( object, material, program, geometry, index ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + let updateBuffers = false; -function Group() { + const state = getBindingState( geometry, program, material ); - Object3D.call( this ); + if ( currentState !== state ) { - this.type = 'Group'; + currentState = state; + bindVertexArrayObject( currentState.object ); -} + } -Group.prototype = Object.assign( Object.create( Object3D.prototype ), { + updateBuffers = needsUpdate( object, geometry, program, index ); - constructor: Group, + if ( updateBuffers ) saveCache( object, geometry, program, index ); - isGroup: true + if ( index !== null ) { -} ); + attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + if ( updateBuffers || forceUpdate ) { - Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + forceUpdate = false; - this.generateMipmaps = false; + setupVertexAttributes( object, material, program, geometry ); - // Set needsUpdate when first frame is ready + if ( index !== null ) { - var scope = this; + gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); - function onLoaded() { + } - video.removeEventListener( 'loadeddata', onLoaded, false ); - scope.needsUpdate = true; + } } - video.addEventListener( 'loadeddata', onLoaded, false ); - -} - -VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), { + function createVertexArrayObject() { - constructor: VideoTexture, + return gl.createVertexArray(); - isVideoTexture: true, + } - update: function () { + function bindVertexArrayObject( vao ) { - var video = this.image; + return gl.bindVertexArray( vao ); - if ( video.readyState >= video.HAVE_CURRENT_DATA ) { + } - this.needsUpdate = true; + function deleteVertexArrayObject( vao ) { - } + return gl.deleteVertexArray( vao ); } -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - */ - -function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + function getBindingState( geometry, program, material ) { - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + const wireframe = ( material.wireframe === true ); - this.image = { width: width, height: height }; - this.mipmaps = mipmaps; + let programMap = bindingStates[ geometry.id ]; - // no flipping for cube textures - // (also flipping doesn't work for compressed textures ) + if ( programMap === undefined ) { - this.flipY = false; + programMap = {}; + bindingStates[ geometry.id ] = programMap; - // can't generate mipmaps for compressed textures - // mips must be embedded in DDS files + } - this.generateMipmaps = false; + let stateMap = programMap[ program.id ]; -} + if ( stateMap === undefined ) { -CompressedTexture.prototype = Object.create( Texture.prototype ); -CompressedTexture.prototype.constructor = CompressedTexture; + stateMap = {}; + programMap[ program.id ] = stateMap; -CompressedTexture.prototype.isCompressedTexture = true; + } -/** - * @author Matt DesLauriers / @mattdesl - * @author atix / arthursilber.de - */ + let state = stateMap[ wireframe ]; -function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { + if ( state === undefined ) { - format = format !== undefined ? format : DepthFormat; + state = createBindingState( createVertexArrayObject() ); + stateMap[ wireframe ] = state; - if ( format !== DepthFormat && format !== DepthStencilFormat ) { + } - throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); + return state; } - if ( type === undefined && format === DepthFormat ) { type = UnsignedShortType; } - if ( type === undefined && format === DepthStencilFormat ) { type = UnsignedInt248Type; } - - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + function createBindingState( vao ) { - this.image = { width: width, height: height }; + const newAttributes = []; + const enabledAttributes = []; + const attributeDivisors = []; - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + for ( let i = 0; i < maxVertexAttributes; i ++ ) { - this.flipY = false; - this.generateMipmaps = false; - -} + newAttributes[ i ] = 0; + enabledAttributes[ i ] = 0; + attributeDivisors[ i ] = 0; -DepthTexture.prototype = Object.create( Texture.prototype ); -DepthTexture.prototype.constructor = DepthTexture; -DepthTexture.prototype.isDepthTexture = true; + } -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + return { -function WireframeGeometry( geometry ) { + // for backward compatibility on non-VAO support browser + geometry: null, + program: null, + wireframe: false, - BufferGeometry.call( this ); + newAttributes: newAttributes, + enabledAttributes: enabledAttributes, + attributeDivisors: attributeDivisors, + object: vao, + attributes: {}, + index: null - this.type = 'WireframeGeometry'; + }; - // buffer + } - var vertices = []; + function needsUpdate( object, geometry, program, index ) { - // helper variables + const cachedAttributes = currentState.attributes; + const geometryAttributes = geometry.attributes; - var i, j, l, o, ol; - var edge = [ 0, 0 ], edges = {}, e, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; - var vertex; + let attributesNum = 0; - // different logic for Geometry and BufferGeometry + const programAttributes = program.getAttributes(); - if ( geometry && geometry.isGeometry ) { + for ( const name in programAttributes ) { - // create a data structure that contains all edges without duplicates + const programAttribute = programAttributes[ name ]; - var faces = geometry.faces; + if ( programAttribute.location >= 0 ) { - for ( i = 0, l = faces.length; i < l; i ++ ) { + const cachedAttribute = cachedAttributes[ name ]; + let geometryAttribute = geometryAttributes[ name ]; - var face = faces[ i ]; + if ( geometryAttribute === undefined ) { - for ( j = 0; j < 3; j ++ ) { + if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); + } - key = edge[ 0 ] + ',' + edge[ 1 ]; + if ( cachedAttribute === undefined ) return true; - if ( edges[ key ] === undefined ) { + if ( cachedAttribute.attribute !== geometryAttribute ) return true; - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; + if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; - } + attributesNum ++; } } - // generate vertices - - for ( key in edges ) { + if ( currentState.attributesNum !== attributesNum ) return true; - e = edges[ key ]; + if ( currentState.index !== index ) return true; - vertex = geometry.vertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - vertex = geometry.vertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } + return false; - } else if ( geometry && geometry.isBufferGeometry ) { + } - var position, indices, groups; - var group, start, count; - var index1, index2; + function saveCache( object, geometry, program, index ) { - vertex = new Vector3(); + const cache = {}; + const attributes = geometry.attributes; + let attributesNum = 0; - if ( geometry.index !== null ) { + const programAttributes = program.getAttributes(); - // indexed BufferGeometry + for ( const name in programAttributes ) { - position = geometry.attributes.position; - indices = geometry.index; - groups = geometry.groups; + const programAttribute = programAttributes[ name ]; - if ( groups.length === 0 ) { + if ( programAttribute.location >= 0 ) { - groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; + let attribute = attributes[ name ]; - } + if ( attribute === undefined ) { - // create a data structure that contains all eges without duplicates + if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; - for ( o = 0, ol = groups.length; o < ol; ++ o ) { + } - group = groups[ o ]; + const data = {}; + data.attribute = attribute; - start = group.start; - count = group.count; + if ( attribute && attribute.data ) { - for ( i = start, l = ( start + count ); i < l; i += 3 ) { + data.data = attribute.data; - for ( j = 0; j < 3; j ++ ) { + } - edge1 = indices.getX( i + j ); - edge2 = indices.getX( i + ( j + 1 ) % 3 ); - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); + cache[ name ] = data; - key = edge[ 0 ] + ',' + edge[ 1 ]; + attributesNum ++; - if ( edges[ key ] === undefined ) { + } - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; + } - } + currentState.attributes = cache; + currentState.attributesNum = attributesNum; - } + currentState.index = index; - } + } - } + function initAttributes() { - // generate vertices + const newAttributes = currentState.newAttributes; - for ( key in edges ) { + for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { - e = edges[ key ]; + newAttributes[ i ] = 0; - vertex.fromBufferAttribute( position, e.index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - vertex.fromBufferAttribute( position, e.index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - } + function enableAttribute( attribute ) { - } else { + enableAttributeAndDivisor( attribute, 0 ); - // non-indexed BufferGeometry + } - position = geometry.attributes.position; + function enableAttributeAndDivisor( attribute, meshPerAttribute ) { - for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) { + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + const attributeDivisors = currentState.attributeDivisors; - for ( j = 0; j < 3; j ++ ) { + newAttributes[ attribute ] = 1; - // three edges per triangle, an edge is represented as (index1, index2) - // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) + if ( enabledAttributes[ attribute ] === 0 ) { - index1 = 3 * i + j; - vertex.fromBufferAttribute( position, index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + gl.enableVertexAttribArray( attribute ); + enabledAttributes[ attribute ] = 1; - index2 = 3 * i + ( ( j + 1 ) % 3 ); - vertex.fromBufferAttribute( position, index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - } + if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { - } + gl.vertexAttribDivisor( attribute, meshPerAttribute ); + attributeDivisors[ attribute ] = meshPerAttribute; } } - // build geometry - - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - -} + function disableUnusedAttributes() { -WireframeGeometry.prototype = Object.create( BufferGeometry.prototype ); -WireframeGeometry.prototype.constructor = WireframeGeometry; + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; -/** - * @author zz85 / https://github.com/zz85 - * @author Mugen87 / https://github.com/Mugen87 - * - * Parametric Surfaces Geometry - * based on the brilliant article by @prideout http://prideout.net/blog/?p=44 - */ + for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { -// ParametricGeometry + if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { -function ParametricGeometry( func, slices, stacks ) { + gl.disableVertexAttribArray( i ); + enabledAttributes[ i ] = 0; - Geometry.call( this ); + } - this.type = 'ParametricGeometry'; + } - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + } - this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) ); - this.mergeVertices(); + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { -} + if ( integer === true ) { -ParametricGeometry.prototype = Object.create( Geometry.prototype ); -ParametricGeometry.prototype.constructor = ParametricGeometry; + gl.vertexAttribIPointer( index, size, type, stride, offset ); -// ParametricBufferGeometry + } else { -function ParametricBufferGeometry( func, slices, stacks ) { + gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); - BufferGeometry.call( this ); + } - this.type = 'ParametricBufferGeometry'; + } - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + function setupVertexAttributes( object, material, program, geometry ) { - // buffers + initAttributes(); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + const geometryAttributes = geometry.attributes; - var EPS = 0.00001; + const programAttributes = program.getAttributes(); - var normal = new Vector3(); + const materialDefaultAttributeValues = material.defaultAttributeValues; - var p0 = new Vector3(), p1 = new Vector3(); - var pu = new Vector3(), pv = new Vector3(); + for ( const name in programAttributes ) { - var i, j; + const programAttribute = programAttributes[ name ]; - // generate vertices, normals and uvs + if ( programAttribute.location >= 0 ) { - var sliceCount = slices + 1; + let geometryAttribute = geometryAttributes[ name ]; - for ( i = 0; i <= stacks; i ++ ) { + if ( geometryAttribute === undefined ) { - var v = i / stacks; + if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; - for ( j = 0; j <= slices; j ++ ) { + } - var u = j / slices; + if ( geometryAttribute !== undefined ) { - // vertex + const normalized = geometryAttribute.normalized; + const size = geometryAttribute.itemSize; - p0 = func( u, v, p0 ); - vertices.push( p0.x, p0.y, p0.z ); + const attribute = attributes.get( geometryAttribute ); - // normal + // TODO Attribute may not be available on context restore - // approximate tangent vectors via finite differences + if ( attribute === undefined ) continue; - if ( u - EPS >= 0 ) { + const buffer = attribute.buffer; + const type = attribute.type; + const bytesPerElement = attribute.bytesPerElement; - p1 = func( u - EPS, v, p1 ); - pu.subVectors( p0, p1 ); + // check for integer attributes - } else { + const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ); - p1 = func( u + EPS, v, p1 ); - pu.subVectors( p1, p0 ); + if ( geometryAttribute.isInterleavedBufferAttribute ) { - } + const data = geometryAttribute.data; + const stride = data.stride; + const offset = geometryAttribute.offset; - if ( v - EPS >= 0 ) { + if ( data.isInstancedInterleavedBuffer ) { - p1 = func( u, v - EPS, p1 ); - pv.subVectors( p0, p1 ); + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - } else { + enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); - p1 = func( u, v + EPS, p1 ); - pv.subVectors( p1, p0 ); + } - } + if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { - // cross product of tangent vectors returns surface normal + geometry._maxInstanceCount = data.meshPerAttribute * data.count; - normal.crossVectors( pu, pv ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + } - // uv + } else { - uvs.push( u, v ); + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - } + enableAttribute( programAttribute.location + i ); - } + } - // generate indices + } - for ( i = 0; i < stacks; i ++ ) { + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); - for ( j = 0; j < slices; j ++ ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - var a = i * sliceCount + j; - var b = i * sliceCount + j + 1; - var c = ( i + 1 ) * sliceCount + j + 1; - var d = ( i + 1 ) * sliceCount + j; + vertexAttribPointer( + programAttribute.location + i, + size / programAttribute.locationSize, + type, + normalized, + stride * bytesPerElement, + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer + ); - // faces one and two + } - indices.push( a, b, d ); - indices.push( b, c, d ); + } else { - } + if ( geometryAttribute.isInstancedBufferAttribute ) { - } + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - // build geometry + enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + } -} + if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { -ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry; + geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; -/** - * @author clockworkgeek / https://github.com/clockworkgeek - * @author timothypratley / https://github.com/timothypratley - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ + } -// PolyhedronGeometry + } else { -function PolyhedronGeometry( vertices, indices, radius, detail ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - Geometry.call( this ); + enableAttribute( programAttribute.location + i ); - this.type = 'PolyhedronGeometry'; + } - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; + } - this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) ); - this.mergeVertices(); + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); -} + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { -PolyhedronGeometry.prototype = Object.create( Geometry.prototype ); -PolyhedronGeometry.prototype.constructor = PolyhedronGeometry; + vertexAttribPointer( + programAttribute.location + i, + size / programAttribute.locationSize, + type, + normalized, + size * bytesPerElement, + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer + ); -// PolyhedronBufferGeometry + } -function PolyhedronBufferGeometry( vertices, indices, radius, detail ) { + } - BufferGeometry.call( this ); + } else if ( materialDefaultAttributeValues !== undefined ) { - this.type = 'PolyhedronBufferGeometry'; + const value = materialDefaultAttributeValues[ name ]; - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; + if ( value !== undefined ) { - radius = radius || 1; - detail = detail || 0; + switch ( value.length ) { - // default buffer data + case 2: + gl.vertexAttrib2fv( programAttribute.location, value ); + break; - var vertexBuffer = []; - var uvBuffer = []; + case 3: + gl.vertexAttrib3fv( programAttribute.location, value ); + break; - // the subdivision creates the vertex buffer data + case 4: + gl.vertexAttrib4fv( programAttribute.location, value ); + break; - subdivide( detail ); + default: + gl.vertexAttrib1fv( programAttribute.location, value ); - // all vertices should lie on a conceptual sphere with a given radius + } - appplyRadius( radius ); + } - // finally, create the uv data + } - generateUVs(); + } - // build non-indexed geometry + } - this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); + disableUnusedAttributes(); - if ( detail === 0 ) { + } - this.computeVertexNormals(); // flat normals + function dispose() { - } else { + reset(); - this.normalizeNormals(); // smooth normals + for ( const geometryId in bindingStates ) { - } + const programMap = bindingStates[ geometryId ]; - // helper functions + for ( const programId in programMap ) { - function subdivide( detail ) { + const stateMap = programMap[ programId ]; - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); + for ( const wireframe in stateMap ) { - // iterate over all faces and apply a subdivison with the given detail value + deleteVertexArrayObject( stateMap[ wireframe ].object ); - for ( var i = 0; i < indices.length; i += 3 ) { + delete stateMap[ wireframe ]; - // get the vertices of the face + } - getVertexByIndex( indices[ i + 0 ], a ); - getVertexByIndex( indices[ i + 1 ], b ); - getVertexByIndex( indices[ i + 2 ], c ); + delete programMap[ programId ]; - // perform subdivision + } - subdivideFace( a, b, c, detail ); + delete bindingStates[ geometryId ]; } } - function subdivideFace( a, b, c, detail ) { + function releaseStatesOfGeometry( geometry ) { - var cols = Math.pow( 2, detail ); + if ( bindingStates[ geometry.id ] === undefined ) return; - // we use this multidimensional array as a data structure for creating the subdivision + const programMap = bindingStates[ geometry.id ]; - var v = []; + for ( const programId in programMap ) { - var i, j; + const stateMap = programMap[ programId ]; - // construct all of the vertices for this subdivision + for ( const wireframe in stateMap ) { - for ( i = 0; i <= cols; i ++ ) { + deleteVertexArrayObject( stateMap[ wireframe ].object ); - v[ i ] = []; + delete stateMap[ wireframe ]; - var aj = a.clone().lerp( c, i / cols ); - var bj = b.clone().lerp( c, i / cols ); + } - var rows = cols - i; + delete programMap[ programId ]; - for ( j = 0; j <= rows; j ++ ) { + } - if ( j === 0 && i === cols ) { + delete bindingStates[ geometry.id ]; - v[ i ][ j ] = aj; + } - } else { + function releaseStatesOfProgram( program ) { - v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); + for ( const geometryId in bindingStates ) { - } + const programMap = bindingStates[ geometryId ]; - } + if ( programMap[ program.id ] === undefined ) continue; - } + const stateMap = programMap[ program.id ]; - // construct all of the faces + for ( const wireframe in stateMap ) { - for ( i = 0; i < cols; i ++ ) { + deleteVertexArrayObject( stateMap[ wireframe ].object ); - for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { + delete stateMap[ wireframe ]; - var k = Math.floor( j / 2 ); + } - if ( j % 2 === 0 ) { + delete programMap[ program.id ]; - 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 reset() { - } + resetDefaultState(); + forceUpdate = true; - } + if ( currentState === defaultState ) return; - } + currentState = defaultState; + bindVertexArrayObject( currentState.object ); } - function appplyRadius( radius ) { + // for backward-compatibility - var vertex = new Vector3(); + function resetDefaultState() { - // iterate over the entire buffer and apply the radius to each vertex + defaultState.geometry = null; + defaultState.program = null; + defaultState.wireframe = false; - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { + } - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; + return { - vertex.normalize().multiplyScalar( radius ); + setup: setup, + reset: reset, + resetDefaultState: resetDefaultState, + dispose: dispose, + releaseStatesOfGeometry: releaseStatesOfGeometry, + releaseStatesOfProgram: releaseStatesOfProgram, - vertexBuffer[ i + 0 ] = vertex.x; - vertexBuffer[ i + 1 ] = vertex.y; - vertexBuffer[ i + 2 ] = vertex.z; + initAttributes: initAttributes, + enableAttribute: enableAttribute, + disableUnusedAttributes: disableUnusedAttributes - } + }; - } +} - function generateUVs() { +function WebGLBufferRenderer( gl, extensions, info ) { - var vertex = new Vector3(); + let mode; - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { + function setMode( value ) { - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; + mode = value; - var u = azimuth( vertex ) / 2 / Math.PI + 0.5; - var v = inclination( vertex ) / Math.PI + 0.5; - uvBuffer.push( u, 1 - v ); + } - } + function render( start, count ) { - correctUVs(); + gl.drawArrays( mode, start, count ); - correctSeam(); + info.update( count, mode, 1 ); } - function correctSeam() { + function renderInstances( start, count, primcount ) { - // handle case when face straddles the seam, see #3269 + if ( primcount === 0 ) return; - for ( var i = 0; i < uvBuffer.length; i += 6 ) { + gl.drawArraysInstanced( mode, start, count, primcount ); - // uv data of a single face + info.update( count, mode, primcount ); - var x0 = uvBuffer[ i + 0 ]; - var x1 = uvBuffer[ i + 2 ]; - var x2 = uvBuffer[ i + 4 ]; + } - var max = Math.max( x0, x1, x2 ); - var min = Math.min( x0, x1, x2 ); + function renderMultiDraw( starts, counts, drawCount ) { - // 0.9 is somewhat arbitrary + if ( drawCount === 0 ) return; - if ( max > 0.9 && min < 0.1 ) { + const extension = extensions.get( 'WEBGL_multi_draw' ); + extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); - if ( x0 < 0.2 ) { uvBuffer[ i + 0 ] += 1; } - if ( x1 < 0.2 ) { uvBuffer[ i + 2 ] += 1; } - if ( x2 < 0.2 ) { uvBuffer[ i + 4 ] += 1; } + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - } + elementCount += counts[ i ]; } - } - - function pushVertex( vertex ) { - - vertexBuffer.push( vertex.x, vertex.y, vertex.z ); + info.update( elementCount, mode, 1 ); } - function getVertexByIndex( index, vertex ) { + function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { - var stride = index * 3; + if ( drawCount === 0 ) return; - vertex.x = vertices[ stride + 0 ]; - vertex.y = vertices[ stride + 1 ]; - vertex.z = vertices[ stride + 2 ]; + const extension = extensions.get( 'WEBGL_multi_draw' ); - } + if ( extension === null ) { - function correctUVs() { + for ( let i = 0; i < starts.length; i ++ ) { - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); + renderInstances( starts[ i ], counts[ i ], primcount[ i ] ); + + } - var centroid = new Vector3(); + } else { - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount ); - for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); - b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); - c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); + elementCount += counts[ i ]; - 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( a ).add( b ).add( c ).divideScalar( 3 ); + for ( let i = 0; i < primcount.length; i ++ ) { - var azi = azimuth( centroid ); + info.update( elementCount, mode, primcount[ i ] ); - correctUV( uvA, j + 0, a, azi ); - correctUV( uvB, j + 2, b, azi ); - correctUV( uvC, j + 4, c, azi ); + } } } - function correctUV( uv, stride, vector, azimuth ) { + // - if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { + this.setMode = setMode; + this.render = render; + this.renderInstances = renderInstances; + this.renderMultiDraw = renderMultiDraw; + this.renderMultiDrawInstances = renderMultiDrawInstances; - uvBuffer[ stride ] = uv.x - 1; +} - } +function WebGLCapabilities( gl, extensions, parameters, utils ) { - if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { + let maxAnisotropy; - uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; + function getMaxAnisotropy() { - } + if ( maxAnisotropy !== undefined ) return maxAnisotropy; - } + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { - // Angle around the Y axis, counter-clockwise when looking from above. + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); - function azimuth( vector ) { + maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); - return Math.atan2( vector.z, - vector.x ); + } else { - } + maxAnisotropy = 0; + } - // Angle above the XZ plane. + return maxAnisotropy; - function inclination( vector ) { + } - return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); + function textureFormatReadable( textureFormat ) { - } + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { -} + return false; -PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry; + } -/** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + return true; -// TetrahedronGeometry + } -function TetrahedronGeometry( radius, detail ) { + function textureTypeReadable( textureType ) { - Geometry.call( this ); + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ); - this.type = 'TetrahedronGeometry'; + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + textureType !== FloatType && ! halfFloatSupportedByExt ) { - this.parameters = { - radius: radius, - detail: detail - }; + return false; - this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + } -} + return true; -TetrahedronGeometry.prototype = Object.create( Geometry.prototype ); -TetrahedronGeometry.prototype.constructor = TetrahedronGeometry; + } -// TetrahedronBufferGeometry + function getMaxPrecision( precision ) { -function TetrahedronBufferGeometry( radius, detail ) { + if ( precision === 'highp' ) { - var vertices = [ - 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 - ]; + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { - var indices = [ - 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 - ]; + return 'highp'; - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + } - this.type = 'TetrahedronBufferGeometry'; + precision = 'mediump'; - this.parameters = { - radius: radius, - detail: detail - }; + } -} + if ( precision === 'mediump' ) { -TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry; + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { -/** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + return 'mediump'; -// OctahedronGeometry + } -function OctahedronGeometry( radius, detail ) { + } - Geometry.call( this ); + return 'lowp'; - this.type = 'OctahedronGeometry'; + } - this.parameters = { - radius: radius, - detail: detail - }; + let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; + const maxPrecision = getMaxPrecision( precision ); - this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + if ( maxPrecision !== precision ) { -} + console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); + precision = maxPrecision; -OctahedronGeometry.prototype = Object.create( Geometry.prototype ); -OctahedronGeometry.prototype.constructor = OctahedronGeometry; + } -// OctahedronBufferGeometry + const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; -function OctahedronBufferGeometry( radius, detail ) { + 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 ); - var vertices = [ - 1, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, - 1, 0, 0, 0, 1, 0, 0, - 1 - ]; + 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 ); - var 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 - ]; + const vertexTextures = maxVertexTextures > 0; - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + const maxSamples = gl.getParameter( gl.MAX_SAMPLES ); - this.type = 'OctahedronBufferGeometry'; + return { - this.parameters = { - radius: radius, - detail: detail - }; + isWebGL2: true, // keeping this for backwards compatibility -} + getMaxAnisotropy: getMaxAnisotropy, + getMaxPrecision: getMaxPrecision, -OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry; + textureFormatReadable: textureFormatReadable, + textureTypeReadable: textureTypeReadable, -/** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + precision: precision, + logarithmicDepthBuffer: logarithmicDepthBuffer, -// IcosahedronGeometry + maxTextures: maxTextures, + maxVertexTextures: maxVertexTextures, + maxTextureSize: maxTextureSize, + maxCubemapSize: maxCubemapSize, -function IcosahedronGeometry( radius, detail ) { + maxAttributes: maxAttributes, + maxVertexUniforms: maxVertexUniforms, + maxVaryings: maxVaryings, + maxFragmentUniforms: maxFragmentUniforms, - Geometry.call( this ); + vertexTextures: vertexTextures, - this.type = 'IcosahedronGeometry'; + maxSamples: maxSamples - this.parameters = { - radius: radius, - detail: detail }; - this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - } -IcosahedronGeometry.prototype = Object.create( Geometry.prototype ); -IcosahedronGeometry.prototype.constructor = IcosahedronGeometry; +function WebGLClipping( properties ) { -// IcosahedronBufferGeometry + const scope = this; -function IcosahedronBufferGeometry( radius, detail ) { - - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - - var 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 - ]; + let globalState = null, + numGlobalPlanes = 0, + localClippingEnabled = false, + renderingShadows = false; - var 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 - ]; + const plane = new Plane(), + viewNormalMatrix = new Matrix3(), - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + uniform = { value: null, needsUpdate: false }; - this.type = 'IcosahedronBufferGeometry'; + this.uniform = uniform; + this.numPlanes = 0; + this.numIntersection = 0; - this.parameters = { - radius: radius, - detail: detail - }; + this.init = function ( planes, enableLocalClipping ) { -} + const enabled = + planes.length !== 0 || + enableLocalClipping || + // enable state of previous frame - the clipping code has to + // run another frame in order to reset the state: + numGlobalPlanes !== 0 || + localClippingEnabled; -IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry; + localClippingEnabled = enableLocalClipping; -/** - * @author Abe Pazos / https://hamoid.com - * @author Mugen87 / https://github.com/Mugen87 - */ + numGlobalPlanes = planes.length; -// DodecahedronGeometry + return enabled; -function DodecahedronGeometry( radius, detail ) { + }; - Geometry.call( this ); + this.beginShadows = function () { - this.type = 'DodecahedronGeometry'; + renderingShadows = true; + projectPlanes( null ); - this.parameters = { - radius: radius, - detail: detail }; - this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - -} - -DodecahedronGeometry.prototype = Object.create( Geometry.prototype ); -DodecahedronGeometry.prototype.constructor = DodecahedronGeometry; + this.endShadows = function () { -// DodecahedronBufferGeometry + renderingShadows = false; -function DodecahedronBufferGeometry( radius, detail ) { + }; - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - var r = 1 / t; + this.setGlobalState = function ( planes, camera ) { - var vertices = [ + globalState = projectPlanes( planes, camera, 0 ); - // (±1, ±1, ±1) - - 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, ±1/φ, ±φ) - 0, - r, - t, 0, - r, t, - 0, r, - t, 0, r, t, + this.setState = function ( material, camera, useCache ) { - // (±1/φ, ±φ, 0) - - r, - t, 0, - r, t, 0, - r, - t, 0, r, t, 0, + const planes = material.clippingPlanes, + clipIntersection = material.clipIntersection, + clipShadows = material.clipShadows; - // (±φ, 0, ±1/φ) - - t, 0, - r, t, 0, - r, - - t, 0, r, t, 0, r - ]; + const materialProperties = properties.get( material ); - var 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 - ]; + if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + // there's no local clipping - this.type = 'DodecahedronBufferGeometry'; + if ( renderingShadows ) { - this.parameters = { - radius: radius, - detail: detail - }; + // there's no global clipping -} + projectPlanes( null ); -DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); -DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry; + } else { -/** - * @author oosmoxiecode / https://github.com/oosmoxiecode - * @author WestLangley / https://github.com/WestLangley - * @author zz85 / https://github.com/zz85 - * @author miningold / https://github.com/miningold - * @author jonobr1 / https://github.com/jonobr1 - * @author Mugen87 / https://github.com/Mugen87 - * - */ + resetGlobalState(); -// TubeGeometry + } -function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) { + } else { - Geometry.call( this ); + const nGlobal = renderingShadows ? 0 : numGlobalPlanes, + lGlobal = nGlobal * 4; - this.type = 'TubeGeometry'; + let dstArray = materialProperties.clippingState || null; - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; + uniform.value = dstArray; // ensure unique state - if ( taper !== undefined ) { console.warn( 'THREE.TubeGeometry: taper has been removed.' ); } + dstArray = projectPlanes( planes, camera, lGlobal, useCache ); - var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ); + for ( let i = 0; i !== lGlobal; ++ i ) { - // expose internals + dstArray[ i ] = globalState[ i ]; - this.tangents = bufferGeometry.tangents; - this.normals = bufferGeometry.normals; - this.binormals = bufferGeometry.binormals; + } - // create geometry + materialProperties.clippingState = dstArray; + this.numIntersection = clipIntersection ? this.numPlanes : 0; + this.numPlanes += nGlobal; - this.fromBufferGeometry( bufferGeometry ); - this.mergeVertices(); + } -} -TubeGeometry.prototype = Object.create( Geometry.prototype ); -TubeGeometry.prototype.constructor = TubeGeometry; + }; -// TubeBufferGeometry + function resetGlobalState() { -function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) { + if ( uniform.value !== globalState ) { - BufferGeometry.call( this ); + uniform.value = globalState; + uniform.needsUpdate = numGlobalPlanes > 0; - this.type = 'TubeBufferGeometry'; + } - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; + scope.numPlanes = numGlobalPlanes; + scope.numIntersection = 0; - tubularSegments = tubularSegments || 64; - radius = radius || 1; - radialSegments = radialSegments || 8; - closed = closed || false; + } - var frames = path.computeFrenetFrames( tubularSegments, closed ); + function projectPlanes( planes, camera, dstOffset, skipTransform ) { - // expose internals + const nPlanes = planes !== null ? planes.length : 0; + let dstArray = null; - this.tangents = frames.tangents; - this.normals = frames.normals; - this.binormals = frames.binormals; + if ( nPlanes !== 0 ) { - // helper variables + dstArray = uniform.value; - var vertex = new Vector3(); - var normal = new Vector3(); - var uv = new Vector2(); - var P = new Vector3(); + if ( skipTransform !== true || dstArray === null ) { - var i, j; + const flatSize = dstOffset + nPlanes * 4, + viewMatrix = camera.matrixWorldInverse; - // buffer + viewNormalMatrix.getNormalMatrix( viewMatrix ); - var vertices = []; - var normals = []; - var uvs = []; - var indices = []; + if ( dstArray === null || dstArray.length < flatSize ) { - // create buffer data + dstArray = new Float32Array( flatSize ); - generateBufferData(); + } - // build geometry + for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); - // functions + plane.normal.toArray( dstArray, i4 ); + dstArray[ i4 + 3 ] = plane.constant; - function generateBufferData() { + } - for ( i = 0; i < tubularSegments; i ++ ) { + } - generateSegment( i ); + uniform.value = dstArray; + uniform.needsUpdate = true; } - // if the geometry is not closed, generate the last row of vertices and normals - // at the regular position on the given path - // - // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) + scope.numPlanes = nPlanes; + scope.numIntersection = 0; - generateSegment( ( closed === false ) ? tubularSegments : 0 ); + return dstArray; - // uvs are generated in a separate function. - // this makes it easy compute correct values for closed geometries + } - generateUVs(); +} - // finally create faces +function WebGLCubeMaps( renderer ) { - generateIndices(); + let cubemaps = new WeakMap(); - } + function mapTextureMapping( texture, mapping ) { - function generateSegment( i ) { + if ( mapping === EquirectangularReflectionMapping ) { - // we use getPointAt to sample evenly distributed points from the given path + texture.mapping = CubeReflectionMapping; - P = path.getPointAt( i / tubularSegments, P ); + } else if ( mapping === EquirectangularRefractionMapping ) { - // retrieve corresponding normal and binormal + texture.mapping = CubeRefractionMapping; - var N = frames.normals[ i ]; - var B = frames.binormals[ i ]; + } - // generate normals and vertices for the current segment + return texture; - for ( j = 0; j <= radialSegments; j ++ ) { + } - var v = j / radialSegments * Math.PI * 2; + function get( texture ) { - var sin = Math.sin( v ); - var cos = - Math.cos( v ); + if ( texture && texture.isTexture ) { - // normal + const mapping = texture.mapping; - 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(); + if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { - normals.push( normal.x, normal.y, normal.z ); + if ( cubemaps.has( texture ) ) { - // vertex + const cubemap = cubemaps.get( texture ).texture; + return mapTextureMapping( cubemap, texture.mapping ); - vertex.x = P.x + radius * normal.x; - vertex.y = P.y + radius * normal.y; - vertex.z = P.z + radius * normal.z; + } else { - vertices.push( vertex.x, vertex.y, vertex.z ); + const image = texture.image; - } + if ( image && image.height > 0 ) { - } + const renderTarget = new WebGLCubeRenderTarget( image.height ); + renderTarget.fromEquirectangularTexture( renderer, texture ); + cubemaps.set( texture, renderTarget ); - function generateIndices() { + texture.addEventListener( 'dispose', onTextureDispose ); - for ( j = 1; j <= tubularSegments; j ++ ) { + return mapTextureMapping( renderTarget.texture, texture.mapping ); - for ( i = 1; i <= radialSegments; i ++ ) { + } else { - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; + // image not yet ready. try the conversion next frame - // faces + return null; - indices.push( a, b, d ); - indices.push( b, c, d ); + } + + } } } + return texture; + } - function generateUVs() { + function onTextureDispose( event ) { - for ( i = 0; i <= tubularSegments; i ++ ) { + const texture = event.target; - for ( j = 0; j <= radialSegments; j ++ ) { + texture.removeEventListener( 'dispose', onTextureDispose ); - uv.x = i / tubularSegments; - uv.y = j / radialSegments; + const cubemap = cubemaps.get( texture ); - uvs.push( uv.x, uv.y ); + if ( cubemap !== undefined ) { - } + cubemaps.delete( texture ); + cubemap.dispose(); } } -} - -TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -TubeBufferGeometry.prototype.constructor = TubeBufferGeometry; - -/** - * @author oosmoxiecode - * @author Mugen87 / https://github.com/Mugen87 - * - * based on http://www.blackpawn.com/texts/pqtorus/ - */ - -// TorusKnotGeometry - -function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) { + function dispose() { - Geometry.call( this ); + cubemaps = new WeakMap(); - this.type = 'TorusKnotGeometry'; + } - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q + return { + get: get, + dispose: dispose }; - if ( heightScale !== undefined ) { console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); } - - this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) ); - this.mergeVertices(); - } -TorusKnotGeometry.prototype = Object.create( Geometry.prototype ); -TorusKnotGeometry.prototype.constructor = TorusKnotGeometry; +class OrthographicCamera extends Camera { -// TorusKnotBufferGeometry + constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { -function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) { + super(); - BufferGeometry.call( this ); + this.isOrthographicCamera = true; - this.type = 'TorusKnotBufferGeometry'; + this.type = 'OrthographicCamera'; - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q - }; + this.zoom = 1; + this.view = null; - radius = radius || 1; - tube = tube || 0.4; - tubularSegments = Math.floor( tubularSegments ) || 64; - radialSegments = Math.floor( radialSegments ) || 8; - p = p || 2; - q = q || 3; + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; - // buffers + this.near = near; + this.far = far; - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + this.updateProjectionMatrix(); - // helper variables + } - var i, j; + copy( source, recursive ) { - var vertex = new Vector3(); - var normal = new Vector3(); + super.copy( source, recursive ); - var P1 = new Vector3(); - var P2 = new Vector3(); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; - var B = new Vector3(); - var T = new Vector3(); - var N = new Vector3(); + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - // generate vertices, normals and uvs + return this; - for ( i = 0; i <= tubularSegments; ++ i ) { + } - // the radian "u" is used to calculate the position on the torus curve of the current tubular segement + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - var u = i / tubularSegments * p * Math.PI * 2; + if ( this.view === null ) { - // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. - // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - calculatePositionOnCurve( u, p, q, radius, P1 ); - calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); + } - // calculate orthonormal basis + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - T.subVectors( P2, P1 ); - N.addVectors( P2, P1 ); - B.crossVectors( T, N ); - N.crossVectors( B, T ); + this.updateProjectionMatrix(); - // normalize B, N. T can be ignored, we don't use it + } - B.normalize(); - N.normalize(); + clearViewOffset() { - for ( j = 0; j <= radialSegments; ++ j ) { + if ( this.view !== null ) { - // now calculate the vertices. they are nothing more than an extrusion of the torus curve. - // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. + this.view.enabled = false; - var v = j / radialSegments * Math.PI * 2; - var cx = - tube * Math.cos( v ); - var cy = tube * Math.sin( v ); + } - // now calculate the final vertex position. - // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve + this.updateProjectionMatrix(); - vertex.x = P1.x + ( cx * N.x + cy * B.x ); - vertex.y = P1.y + ( cx * N.y + cy * B.y ); - vertex.z = P1.z + ( cx * N.z + cy * B.z ); + } - vertices.push( vertex.x, vertex.y, vertex.z ); + updateProjectionMatrix() { - // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) + 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; - normal.subVectors( vertex, P1 ).normalize(); + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; - normals.push( normal.x, normal.y, normal.z ); + if ( this.view !== null && this.view.enabled ) { - // uv + const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; + const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; } - } - - // generate indices + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); - for ( j = 1; j <= tubularSegments; j ++ ) { + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - for ( i = 1; i <= radialSegments; i ++ ) { + } - // indices + toJSON( meta ) { - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; + const data = super.toJSON( meta ); - // faces + 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; - indices.push( a, b, d ); - indices.push( b, c, d ); + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - } + return data; } - // build geometry +} - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); +const LOD_MIN = 4; + +// The standard deviations (radians) associated with the extra mips. These are +// chosen to approximate a Trowbridge-Reitz distribution function times the +// geometric shadowing function. These sigma values squared must match the +// variance #defines in cube_uv_reflection_fragment.glsl.js. +const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; + +// The maximum length of the blur for loop. Smaller sigmas will use fewer +// samples and exit early, but not recompile the shader. +const MAX_SAMPLES = 20; + +const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); +const _clearColor = /*@__PURE__*/ new Color(); +let _oldTarget = null; +let _oldActiveCubeFace = 0; +let _oldActiveMipmapLevel = 0; +let _oldXrEnabled = false; + +// Golden Ratio +const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; +const INV_PHI = 1 / PHI; + +// Vertices of a dodecahedron (except the opposites, which represent the +// same axis), used as axis directions evenly spread on a sphere. +const _axisDirections = [ + /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), + /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( - 1, 1, 1 ), + /*@__PURE__*/ new Vector3( 1, 1, 1 ) ]; + +/** + * This class generates a Prefiltered, Mipmapped Radiance Environment Map + * (PMREM) from a cubeMap environment texture. This allows different levels of + * blur to be quickly accessed based on material roughness. It is packed into a + * special CubeUV format that allows us to perform custom interpolation so that + * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap + * chain, it only goes down to the LOD_MIN level (above), and then creates extra + * even more filtered 'mips' at the same LOD_MIN resolution, associated with + * higher roughness levels. In this way we maintain resolution to smoothly + * interpolate diffuse lighting while limiting sampling computation. + * + * Paper: Fast, Accurate Image-Based Lighting + * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view +*/ - // this function calculates the current position on the torus curve +class PMREMGenerator { - function calculatePositionOnCurve( u, p, q, radius, position ) { + constructor( renderer ) { - var cu = Math.cos( u ); - var su = Math.sin( u ); - var quOverP = q / p * u; - var cs = Math.cos( quOverP ); + this._renderer = renderer; + this._pingPongRenderTarget = null; - position.x = radius * ( 2 + cs ) * 0.5 * cu; - position.y = radius * ( 2 + cs ) * su * 0.5; - position.z = radius * Math.sin( quOverP ) * 0.5; + 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 ); -TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry; + } -/** - * @author oosmoxiecode - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + /** + * Generates a PMREM from a supplied Scene, which can be faster than using an + * image if networking bandwidth is low. Optional sigma specifies a blur radius + * in radians to be applied to the scene before PMREM generation. Optional near + * and far planes ensure the scene is rendered in its entirety (the cubeCamera + * is placed at the origin). + */ + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { -// TorusGeometry + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + _oldXrEnabled = this._renderer.xr.enabled; -function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) { + this._renderer.xr.enabled = false; - Geometry.call( this ); + this._setSize( 256 ); - this.type = 'TorusGeometry'; + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; + this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); - this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) ); - this.mergeVertices(); + if ( sigma > 0 ) { -} + this._blur( cubeUVRenderTarget, 0, 0, sigma ); -TorusGeometry.prototype = Object.create( Geometry.prototype ); -TorusGeometry.prototype.constructor = TorusGeometry; + } -// TorusBufferGeometry + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); -function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) { + return cubeUVRenderTarget; - BufferGeometry.call( this ); + } - this.type = 'TorusBufferGeometry'; + /** + * Generates a PMREM from an equirectangular texture, which can be either LDR + * or HDR. The ideal input image size is 1k (1024 x 512), + * as this matches best with the 256 x 256 cubemap output. + * The smallest supported equirectangular image size is 64 x 32. + */ + fromEquirectangular( equirectangular, renderTarget = null ) { - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; + return this._fromTexture( equirectangular, renderTarget ); - radius = radius || 1; - tube = tube || 0.4; - radialSegments = Math.floor( radialSegments ) || 8; - tubularSegments = Math.floor( tubularSegments ) || 6; - arc = arc || Math.PI * 2; + } - // buffers + /** + * Generates a PMREM from an cubemap texture, which can be either LDR + * or HDR. The ideal input cube size is 256 x 256, + * as this matches best with the 256 x 256 cubemap output. + * The smallest supported cube size is 16 x 16. + */ + fromCubemap( cubemap, renderTarget = null ) { - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + return this._fromTexture( cubemap, renderTarget ); - // helper variables + } - var center = new Vector3(); - var vertex = new Vector3(); - var normal = new Vector3(); + /** + * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + compileCubemapShader() { - var j, i; + if ( this._cubemapMaterial === null ) { - // generate vertices, normals and uvs + this._cubemapMaterial = _getCubemapMaterial(); + this._compileMaterial( this._cubemapMaterial ); - for ( j = 0; j <= radialSegments; j ++ ) { + } - for ( i = 0; i <= tubularSegments; i ++ ) { + } - var u = i / tubularSegments * arc; - var v = j / radialSegments * Math.PI * 2; + /** + * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + compileEquirectangularShader() { - // vertex + if ( this._equirectMaterial === null ) { - vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); - vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); - vertex.z = tube * Math.sin( v ); + this._equirectMaterial = _getEquirectMaterial(); + this._compileMaterial( this._equirectMaterial ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - // normal + } - center.x = radius * Math.cos( u ); - center.y = radius * Math.sin( u ); - normal.subVectors( vertex, center ).normalize(); + /** + * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, + * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on + * one of them will cause any others to also become unusable. + */ + dispose() { - normals.push( normal.x, normal.y, normal.z ); + this._dispose(); - // uv + if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); + if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); + } - } + // private interface - } + _setSize( cubeSize ) { - // generate indices + this._lodMax = Math.floor( Math.log2( cubeSize ) ); + this._cubeSize = Math.pow( 2, this._lodMax ); - for ( j = 1; j <= radialSegments; j ++ ) { + } - for ( i = 1; i <= tubularSegments; i ++ ) { + _dispose() { - // indices + if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); - var a = ( tubularSegments + 1 ) * j + i - 1; - var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; - var c = ( tubularSegments + 1 ) * ( j - 1 ) + i; - var d = ( tubularSegments + 1 ) * j + i; + if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); - // faces + for ( let i = 0; i < this._lodPlanes.length; i ++ ) { - indices.push( a, b, d ); - indices.push( b, c, d ); + this._lodPlanes[ i ].dispose(); } } - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - -} - -TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -TorusBufferGeometry.prototype.constructor = TorusBufferGeometry; - -/** - * @author Mugen87 / https://github.com/Mugen87 - * Port from https://github.com/mapbox/earcut (v2.1.2) - */ + _cleanup( outputTarget ) { -var Earcut = { + this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); + this._renderer.xr.enabled = _oldXrEnabled; - triangulate: function ( data, holeIndices, dim ) { + outputTarget.scissorTest = false; + _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); - dim = dim || 2; + } - var hasHoles = holeIndices && holeIndices.length, - outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length, - outerNode = linkedList( data, 0, outerLen, dim, true ), - triangles = []; + _fromTexture( texture, renderTarget ) { - if ( ! outerNode ) { return triangles; } + if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { - var minX, minY, maxX, maxY, x, y, invSize; + this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); - if ( hasHoles ) { outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); } + } else { // Equirectangular - // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + this._setSize( texture.image.width / 4 ); - if ( data.length > 80 * dim ) { + } - minX = maxX = data[ 0 ]; - minY = maxY = data[ 1 ]; + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + _oldXrEnabled = this._renderer.xr.enabled; - for ( var i = dim; i < outerLen; i += dim ) { + this._renderer.xr.enabled = false; - x = data[ i ]; - y = data[ i + 1 ]; - if ( x < minX ) { minX = x; } - if ( y < minY ) { minY = y; } - if ( x > maxX ) { maxX = x; } - if ( y > maxY ) { maxY = y; } + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV( texture, cubeUVRenderTarget ); + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); - } + return cubeUVRenderTarget; - // minX, minY and invSize are later used to transform coords into integers for z-order calculation + } - invSize = Math.max( maxX - minX, maxY - minY ); - invSize = invSize !== 0 ? 1 / invSize : 0; + _allocateTargets() { - } + const width = 3 * Math.max( this._cubeSize, 16 * 7 ); + const height = 4 * this._cubeSize; - earcutLinked( outerNode, triangles, dim, minX, minY, invSize ); + const params = { + magFilter: LinearFilter, + minFilter: LinearFilter, + generateMipmaps: false, + type: HalfFloatType, + format: RGBAFormat, + colorSpace: LinearSRGBColorSpace, + depthBuffer: false + }; - return triangles; + const cubeUVRenderTarget = _createRenderTarget( width, height, params ); - } + if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { -}; + if ( this._pingPongRenderTarget !== null ) { -// create a circular doubly linked list from polygon points in the specified winding order + this._dispose(); -function linkedList( data, start, end, dim, clockwise ) { + } - var i, last; + this._pingPongRenderTarget = _createRenderTarget( width, height, params ); - if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { + const { _lodMax } = this; + ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); - for ( i = start; i < end; i += dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); } + this._blurMaterial = _getBlurShader( _lodMax, width, height ); - } else { + } - for ( i = end - dim; i >= start; i -= dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); } + return cubeUVRenderTarget; } - if ( last && equals( last, last.next ) ) { + _compileMaterial( material ) { - removeNode( last ); - last = last.next; + const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); + this._renderer.compile( tmpMesh, _flatCamera ); } - return last; + _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { -} + const fov = 90; + const aspect = 1; + const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); + const upSign = [ 1, - 1, 1, 1, 1, 1 ]; + const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; + const renderer = this._renderer; -// eliminate colinear or duplicate points + const originalAutoClear = renderer.autoClear; + const toneMapping = renderer.toneMapping; + renderer.getClearColor( _clearColor ); -function filterPoints( start, end ) { + renderer.toneMapping = NoToneMapping; + renderer.autoClear = false; + + const backgroundMaterial = new MeshBasicMaterial( { + name: 'PMREM.Background', + side: BackSide, + depthWrite: false, + depthTest: false, + } ); - if ( ! start ) { return start; } - if ( ! end ) { end = start; } + const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); - var p = start, again; + let useSolidColor = false; + const background = scene.background; - do { + if ( background ) { - again = false; + if ( background.isColor ) { - if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { + backgroundMaterial.color.copy( background ); + scene.background = null; + useSolidColor = true; - removeNode( p ); - p = end = p.prev; - if ( p === p.next ) { break; } - again = true; + } } else { - p = p.next; + backgroundMaterial.color.copy( _clearColor ); + useSolidColor = true; } - } while ( again || p !== end ); - - return end; + for ( let i = 0; i < 6; i ++ ) { -} + const col = i % 3; -// main ear slicing loop which triangulates a polygon (given as a linked list) + if ( col === 0 ) { -function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); - if ( ! ear ) { return; } + } else if ( col === 1 ) { - // interlink polygon nodes in z-order + cubeCamera.up.set( 0, 0, upSign[ i ] ); + cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); - if ( ! pass && invSize ) { indexCurve( ear, minX, minY, invSize ); } + } else { - var stop = ear, prev, next; + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); - // iterate through ears, slicing them one by one + } - while ( ear.prev !== ear.next ) { + const size = this._cubeSize; - prev = ear.prev; - next = ear.next; + _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); - if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { + renderer.setRenderTarget( cubeUVRenderTarget ); - // cut off the triangle - triangles.push( prev.i / dim ); - triangles.push( ear.i / dim ); - triangles.push( next.i / dim ); + if ( useSolidColor ) { - removeNode( ear ); + renderer.render( backgroundBox, cubeCamera ); - // skipping the next vertice leads to less sliver triangles - ear = next.next; - stop = next.next; + } - continue; + renderer.render( scene, cubeCamera ); } - ear = next; - - // if we looped through the whole remaining polygon and can't find any more ears - - if ( ear === stop ) { + backgroundBox.geometry.dispose(); + backgroundBox.material.dispose(); - // try filtering points and slicing again + renderer.toneMapping = toneMapping; + renderer.autoClear = originalAutoClear; + scene.background = background; - if ( ! pass ) { - - earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); + } - // if this didn't work, try curing all small self-intersections locally + _textureToCubeUV( texture, cubeUVRenderTarget ) { - } else if ( pass === 1 ) { + const renderer = this._renderer; - ear = cureLocalIntersections( ear, triangles, dim ); - earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); + const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); - // as a last resort, try splitting the remaining polygon into two + if ( isCubeTexture ) { - } else if ( pass === 2 ) { + if ( this._cubemapMaterial === null ) { - splitEarcut( ear, triangles, dim, minX, minY, invSize ); + this._cubemapMaterial = _getCubemapMaterial(); } - break; - - } - - } + this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; -} + } else { -// check whether a polygon node forms a valid ear with adjacent nodes + if ( this._equirectMaterial === null ) { -function isEar( ear ) { + this._equirectMaterial = _getEquirectMaterial(); - var a = ear.prev, - b = ear, - c = ear.next; + } - if ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear + } - // now make sure we don't have other points inside the potential ear - var p = ear.next.next; + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + const mesh = new Mesh( this._lodPlanes[ 0 ], material ); - while ( p !== ear.prev ) { + const uniforms = material.uniforms; - if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) { + uniforms[ 'envMap' ].value = texture; - return false; + const size = this._cubeSize; - } + _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); - p = p.next; + renderer.setRenderTarget( cubeUVRenderTarget ); + renderer.render( mesh, _flatCamera ); } - return true; + _applyPMREM( cubeUVRenderTarget ) { -} + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + const n = this._lodPlanes.length; -function isEarHashed( ear, minX, minY, invSize ) { + for ( let i = 1; i < n; i ++ ) { - var a = ear.prev, - b = ear, - c = ear.next; + const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); - if ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear + const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; - // triangle bbox; min & max are calculated like this for speed + this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); - var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ), - minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ), - maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ), - maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y ); + } - // z-order range for the current triangle bbox; + renderer.autoClear = autoClear; - var minZ = zOrder( minTX, minTY, minX, minY, invSize ), - maxZ = zOrder( maxTX, maxTY, minX, minY, invSize ); + } - // first look for points inside the triangle in increasing z-order + /** + * This is a two-pass Gaussian blur for a cubemap. Normally this is done + * vertically and horizontally, but this breaks down on a cube. Here we apply + * the blur latitudinally (around the poles), and then longitudinally (towards + * the poles) to approximate the orthogonally-separable blur. It is least + * accurate at the poles, but still does a decent job. + */ + _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { - var p = ear.nextZ; + const pingPongRenderTarget = this._pingPongRenderTarget; - while ( p && p.z <= maxZ ) { + this._halfBlur( + cubeUVRenderTarget, + pingPongRenderTarget, + lodIn, + lodOut, + sigma, + 'latitudinal', + poleAxis ); - if ( p !== ear.prev && p !== ear.next && - pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && - area( p.prev, p, p.next ) >= 0 ) { return false; } - p = p.nextZ; + this._halfBlur( + pingPongRenderTarget, + cubeUVRenderTarget, + lodOut, + lodOut, + sigma, + 'longitudinal', + poleAxis ); } - // then look for points in decreasing z-order + _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { + + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; - p = ear.prevZ; + if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { - while ( p && p.z >= minZ ) { + console.error( + 'blur direction must be either latitudinal or longitudinal!' ); - if ( p !== ear.prev && p !== ear.next && - pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && - area( p.prev, p, p.next ) >= 0 ) { return false; } + } - p = p.prevZ; + // Number of standard deviations at which to cut off the discrete approximation. + const STANDARD_DEVIATIONS = 3; - } + const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); + const blurUniforms = blurMaterial.uniforms; - return true; + 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 ) { -// go through all polygon nodes and cure small local self-intersections + console.warn( `sigmaRadians, ${ + sigmaRadians}, is too large and will clip, as it requested ${ + samples} samples when the maximum is set to ${MAX_SAMPLES}` ); -function cureLocalIntersections( start, triangles, dim ) { + } - var p = start; + const weights = []; + let sum = 0; - do { + for ( let i = 0; i < MAX_SAMPLES; ++ i ) { - var a = p.prev, b = p.next.next; + const x = i / sigmaPixels; + const weight = Math.exp( - x * x / 2 ); + weights.push( weight ); - if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { + if ( i === 0 ) { - triangles.push( a.i / dim ); - triangles.push( p.i / dim ); - triangles.push( b.i / dim ); + sum += weight; - // remove two nodes involved + } else if ( i < samples ) { - removeNode( p ); - removeNode( p.next ); + sum += 2 * weight; - p = start = b; + } } - p = p.next; + for ( let i = 0; i < weights.length; i ++ ) { - } while ( p !== start ); + weights[ i ] = weights[ i ] / sum; - return p; + } -} + blurUniforms[ 'envMap' ].value = targetIn.texture; + blurUniforms[ 'samples' ].value = samples; + blurUniforms[ 'weights' ].value = weights; + blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; + + if ( poleAxis ) { -// try splitting polygon into two and triangulate them independently + blurUniforms[ 'poleAxis' ].value = poleAxis; + + } -function splitEarcut( start, triangles, dim, minX, minY, invSize ) { + const { _lodMax } = this; + blurUniforms[ 'dTheta' ].value = radiansPerPixel; + blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; - // look for a valid diagonal that divides the polygon into two + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); - var a = start; + _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( targetOut ); + renderer.render( blurMesh, _flatCamera ); - do { + } - var b = a.next.next; +} - while ( b !== a.prev ) { - if ( a.i !== b.i && isValidDiagonal( a, b ) ) { - // split the polygon in two by the diagonal +function _createPlanes( lodMax ) { - var c = splitPolygon( a, b ); + const lodPlanes = []; + const sizeLods = []; + const sigmas = []; - // filter colinear points around the cuts + let lod = lodMax; - a = filterPoints( a, a.next ); - c = filterPoints( c, c.next ); + const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; - // run earcut on each half + for ( let i = 0; i < totalLods; i ++ ) { - earcutLinked( a, triangles, dim, minX, minY, invSize ); - earcutLinked( c, triangles, dim, minX, minY, invSize ); - return; + const sizeLod = Math.pow( 2, lod ); + sizeLods.push( sizeLod ); + let sigma = 1.0 / sizeLod; - } + if ( i > lodMax - LOD_MIN ) { - b = b.next; + sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; - } + } else if ( i === 0 ) { - a = a.next; + sigma = 0; - } while ( a !== start ); + } -} + sigmas.push( sigma ); -// link every hole into the outer loop, producing a single-ring polygon without holes + const texelSize = 1.0 / ( sizeLod - 2 ); + const min = - texelSize; + const max = 1 + texelSize; + const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; -function eliminateHoles( data, holeIndices, outerNode, dim ) { + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; - var queue = [], i, len, start, end, list; + const position = new Float32Array( positionSize * vertices * cubeFaces ); + const uv = new Float32Array( uvSize * vertices * cubeFaces ); + const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); - for ( i = 0, len = holeIndices.length; i < len; i ++ ) { + for ( let face = 0; face < cubeFaces; face ++ ) { - start = holeIndices[ i ] * dim; - end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; - list = linkedList( data, start, end, dim, false ); - if ( list === list.next ) { list.steiner = true; } - queue.push( getLeftmost( list ) ); + const x = ( face % 3 ) * 2 / 3 - 1; + const y = face > 2 ? 0 : - 1; + const coordinates = [ + x, y, 0, + x + 2 / 3, y, 0, + x + 2 / 3, y + 1, 0, + x, y, 0, + x + 2 / 3, y + 1, 0, + x, y + 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 ); - } + } - queue.sort( compareX ); + 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 ); - // process holes from left to right + if ( lod > LOD_MIN ) { - for ( i = 0; i < queue.length; i ++ ) { + lod --; - eliminateHole( queue[ i ], outerNode ); - outerNode = filterPoints( outerNode, outerNode.next ); + } } - return outerNode; + return { lodPlanes, sizeLods, sigmas }; } -function compareX( a, b ) { +function _createRenderTarget( width, height, params ) { - return a.x - b.x; + const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; + cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; } -// find a bridge between vertices that connects hole with an outer ring and and link it - -function eliminateHole( hole, outerNode ) { - - outerNode = findHoleBridge( hole, outerNode ); - - if ( outerNode ) { - - var b = splitPolygon( outerNode, hole ); - - filterPoints( b, b.next ); +function _setViewport( target, x, y, width, height ) { - } + target.viewport.set( x, y, width, height ); + target.scissor.set( x, y, width, height ); } -// David Eberly's algorithm for finding a bridge between hole and outer polygon +function _getBlurShader( lodMax, width, height ) { + + const weights = new Float32Array( MAX_SAMPLES ); + const poleAxis = new Vector3( 0, 1, 0 ); + const shaderMaterial = new ShaderMaterial( { -function findHoleBridge( hole, outerNode ) { + name: 'SphericalGaussianBlur', - var p = outerNode, - hx = hole.x, - hy = hole.y, - qx = - Infinity, - m; + defines: { + 'n': MAX_SAMPLES, + 'CUBEUV_TEXEL_WIDTH': 1.0 / width, + 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, + 'CUBEUV_MAX_MIP': `${lodMax}.0`, + }, - // find a segment intersected by a ray from the hole's leftmost point to the left; - // segment's endpoint with lesser x will be potential connection point + uniforms: { + 'envMap': { value: null }, + 'samples': { value: 1 }, + 'weights': { value: weights }, + 'latitudinal': { value: false }, + 'dTheta': { value: 0 }, + 'mipInt': { value: 0 }, + 'poleAxis': { value: poleAxis } + }, - do { + vertexShader: _getCommonVertexShader(), - if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { + fragmentShader: /* glsl */` - var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); + precision mediump float; + precision mediump int; - if ( x <= hx && x > qx ) { + varying vec3 vOutputDirection; - qx = x; + uniform sampler2D envMap; + uniform int samples; + uniform float weights[ n ]; + uniform bool latitudinal; + uniform float dTheta; + uniform float mipInt; + uniform vec3 poleAxis; - if ( x === hx ) { + #define ENVMAP_TYPE_CUBE_UV + #include - if ( hy === p.y ) { return p; } - if ( hy === p.next.y ) { return p.next; } + 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 ); - m = p.x < p.next.x ? p : p.next; + return bilinearCubeUV( envMap, sampleDirection, mipInt ); } - } + void main() { - p = p.next; + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); - } while ( p !== outerNode ); + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { - if ( ! m ) { return null; } + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); - if ( hx === qx ) { return m.prev; } // hole touches outer segment; pick lower endpoint + } - // look for points inside the triangle of hole point, segment intersection and endpoint; - // if there are no points found, we have a valid connection; - // otherwise choose the point of the minimum angle with the ray as connection point + axis = normalize( axis ); - var stop = m, - mx = m.x, - my = m.y, - tanMin = Infinity, - tan; + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); - p = m.next; + for ( int i = 1; i < n; i++ ) { - while ( p !== stop ) { + if ( i >= samples ) { - 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 ) ) { + break; - tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential + } - if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) { + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); - m = p; - tanMin = tan; + } } + `, - } - - p = p.next; + blending: NoBlending, + depthTest: false, + depthWrite: false - } + } ); - return m; + return shaderMaterial; } -// interlink polygon nodes in z-order +function _getEquirectMaterial() { + + return new ShaderMaterial( { -function indexCurve( start, minX, minY, invSize ) { + name: 'EquirectangularToCubeUV', - var p = start; + uniforms: { + 'envMap': { value: null } + }, - do { + vertexShader: _getCommonVertexShader(), - 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; + fragmentShader: /* glsl */` - } while ( p !== start ); + precision mediump float; + precision mediump int; - p.prevZ.nextZ = null; - p.prevZ = null; + varying vec3 vOutputDirection; - sortLinked( p ); + uniform sampler2D envMap; -} + #include -// Simon Tatham's linked list merge sort algorithm -// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html + void main() { -function sortLinked( list ) { + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); - var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); - do { + } + `, - p = list; - list = null; - tail = null; - numMerges = 0; + blending: NoBlending, + depthTest: false, + depthWrite: false - while ( p ) { + } ); - numMerges ++; - q = p; - pSize = 0; +} - for ( i = 0; i < inSize; i ++ ) { +function _getCubemapMaterial() { - pSize ++; - q = q.nextZ; - if ( ! q ) { break; } + return new ShaderMaterial( { - } + name: 'CubemapToCubeUV', - qSize = inSize; + uniforms: { + 'envMap': { value: null }, + 'flipEnvMap': { value: - 1 } + }, - while ( pSize > 0 || ( qSize > 0 && q ) ) { + vertexShader: _getCommonVertexShader(), - if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { + fragmentShader: /* glsl */` - e = p; - p = p.nextZ; - pSize --; + precision mediump float; + precision mediump int; - } else { + uniform float flipEnvMap; - e = q; - q = q.nextZ; - qSize --; + varying vec3 vOutputDirection; - } + uniform samplerCube envMap; - if ( tail ) { tail.nextZ = e; } - else { list = e; } + void main() { - e.prevZ = tail; - tail = e; + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); } + `, - p = q; + blending: NoBlending, + depthTest: false, + depthWrite: false - } + } ); - tail.nextZ = null; - inSize *= 2; +} - } while ( numMerges > 1 ); +function _getCommonVertexShader() { - return list; + return /* glsl */` -} + precision mediump float; + precision mediump int; -// z-order of a point given coords and inverse of the longer side of data bbox + attribute float faceIndex; -function zOrder( x, y, minX, minY, invSize ) { + varying vec3 vOutputDirection; - // coords are transformed into non-negative 15-bit integer range + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { - x = 32767 * ( x - minX ) * invSize; - y = 32767 * ( y - minY ) * invSize; + uv = 2.0 * uv - 1.0; - x = ( x | ( x << 8 ) ) & 0x00FF00FF; - x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; - x = ( x | ( x << 2 ) ) & 0x33333333; - x = ( x | ( x << 1 ) ) & 0x55555555; + vec3 direction = vec3( uv, 1.0 ); - y = ( y | ( y << 8 ) ) & 0x00FF00FF; - y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; - y = ( y | ( y << 2 ) ) & 0x33333333; - y = ( y | ( y << 1 ) ) & 0x55555555; + if ( face == 0.0 ) { - return x | ( y << 1 ); + direction = direction.zyx; // ( 1, v, u ) pos x -} + } else if ( face == 1.0 ) { -// find the leftmost node of a polygon ring + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y -function getLeftmost( start ) { + } else if ( face == 2.0 ) { - var p = start, leftmost = start; + direction.x *= -1.0; // ( -u, v, 1 ) pos z - do { + } else if ( face == 3.0 ) { - if ( p.x < leftmost.x ) { leftmost = p; } - p = p.next; + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x - } while ( p !== start ); + } else if ( face == 4.0 ) { - return leftmost; + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y -} + } else if ( face == 5.0 ) { -// check if a point lies within a convex triangle + direction.z *= -1.0; // ( u, v, -1 ) neg z -function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { + } - return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 && - ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 && - ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0; + return direction; -} + } -// check if a diagonal between two polygon nodes is valid (lies in polygon interior) + void main() { -function isValidDiagonal( a, b ) { + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); - return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && - locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ); + } + `; } -// signed area of a triangle +function WebGLCubeUVMaps( renderer ) { -function area( p, q, r ) { + let cubeUVmaps = new WeakMap(); - return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); + let pmremGenerator = null; -} + function get( texture ) { -// check if two points are equal + if ( texture && texture.isTexture ) { -function equals( p1, p2 ) { + const mapping = texture.mapping; - return p1.x === p2.x && p1.y === p2.y; + const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); + const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); -} + // equirect/cube map to cubeUV conversion -// check if two segments intersect + if ( isEquirectMap || isCubeMap ) { -function intersects( p1, q1, p2, q2 ) { + let renderTarget = cubeUVmaps.get( texture ); - if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) || - ( equals( p1, q2 ) && equals( p2, q1 ) ) ) { return true; } + const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0; - return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 && - area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0; + if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) { -} + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); -// check if a polygon diagonal intersects any polygon segments + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); + renderTarget.texture.pmremVersion = texture.pmremVersion; -function intersectsPolygon( a, b ) { + cubeUVmaps.set( texture, renderTarget ); - var p = a; + return renderTarget.texture; - do { + } else { - if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && - intersects( p, p.next, a, b ) ) { + if ( renderTarget !== undefined ) { - return true; + return renderTarget.texture; - } + } else { - p = p.next; + const image = texture.image; - } while ( p !== a ); + if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { - return false; + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); -} + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); + renderTarget.texture.pmremVersion = texture.pmremVersion; -// check if a polygon diagonal is locally inside the polygon + cubeUVmaps.set( texture, renderTarget ); -function locallyInside( a, b ) { + texture.addEventListener( 'dispose', onTextureDispose ); - return area( a.prev, a, a.next ) < 0 ? - area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : - area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; + return renderTarget.texture; -} + } else { -// check if the middle point of a polygon diagonal is inside the polygon + // image not yet ready. try the conversion next frame -function middleInside( a, b ) { + return null; - var p = a, - inside = false, - px = ( a.x + b.x ) / 2, - py = ( a.y + b.y ) / 2; + } - do { + } - if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && - ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) { + } - inside = ! inside; + } } - p = p.next; + return texture; - } while ( p !== a ); + } - return inside; + function isCubeTextureComplete( image ) { -} + let count = 0; + const length = 6; -// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; -// if one belongs to the outer ring and another to a hole, it merges it into a single ring + for ( let i = 0; i < length; i ++ ) { -function splitPolygon( a, b ) { + if ( image[ i ] !== undefined ) count ++; - var a2 = new Node( a.i, a.x, a.y ), - b2 = new Node( b.i, b.x, b.y ), - an = a.next, - bp = b.prev; + } - a.next = b; - b.prev = a; + return count === length; - a2.next = an; - an.prev = a2; - b2.next = a2; - a2.prev = b2; + } - bp.next = b2; - b2.prev = bp; + function onTextureDispose( event ) { - return b2; + const texture = event.target; -} + texture.removeEventListener( 'dispose', onTextureDispose ); -// create a node and optionally link it with previous one (in a circular doubly linked list) + const cubemapUV = cubeUVmaps.get( texture ); -function insertNode( i, x, y, last ) { + if ( cubemapUV !== undefined ) { - var p = new Node( i, x, y ); + cubeUVmaps.delete( texture ); + cubemapUV.dispose(); - if ( ! last ) { + } - p.prev = p; - p.next = p; + } - } else { + function dispose() { - p.next = last.next; - p.prev = last; - last.next.prev = p; - last.next = p; + cubeUVmaps = new WeakMap(); + + if ( pmremGenerator !== null ) { + + pmremGenerator.dispose(); + pmremGenerator = null; + + } } - return p; + return { + get: get, + dispose: dispose + }; } -function removeNode( p ) { +function WebGLExtensions( gl ) { - p.next.prev = p.prev; - p.prev.next = p.next; + const extensions = {}; - if ( p.prevZ ) { p.prevZ.nextZ = p.nextZ; } - if ( p.nextZ ) { p.nextZ.prevZ = p.prevZ; } + function getExtension( name ) { -} + if ( extensions[ name ] !== undefined ) { -function Node( i, x, y ) { + return extensions[ name ]; - // vertice index in coordinates array - this.i = i; + } - // vertex coordinates - this.x = x; - this.y = y; + let extension; - // previous and next vertice nodes in a polygon ring - this.prev = null; - this.next = null; + switch ( name ) { - // z-order curve value - this.z = null; + case 'WEBGL_depth_texture': + extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); + break; - // previous and next nodes in z-order - this.prevZ = null; - this.nextZ = null; + 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; - // indicates whether this is a steiner point - this.steiner = false; + 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; -function signedArea( data, start, end, dim ) { + default: + extension = gl.getExtension( name ); - var sum = 0; + } - for ( var i = start, j = end - dim; i < end; i += dim ) { + extensions[ name ] = extension; - sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); - j = i; + return extension; } - return sum; + return { -} + has: function ( name ) { -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - */ + return getExtension( name ) !== null; + + }, -var ShapeUtils = { + init: function () { - // calculate area of the contour polygon + getExtension( 'EXT_color_buffer_float' ); + getExtension( 'WEBGL_clip_cull_distance' ); + getExtension( 'OES_texture_float_linear' ); + getExtension( 'EXT_color_buffer_half_float' ); + getExtension( 'WEBGL_multisampled_render_to_texture' ); + getExtension( 'WEBGL_render_shared_exponent' ); - area: function ( contour ) { + }, + + get: function ( name ) { + + const extension = getExtension( name ); - var n = contour.length; - var a = 0.0; + if ( extension === null ) { + + warnOnce( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); - for ( var p = n - 1, q = 0; q < n; p = q ++ ) { + } - a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; + return extension; } - return a * 0.5; + }; - }, +} - isClockWise: function ( pts ) { +function WebGLGeometries( gl, attributes, info, bindingStates ) { - return ShapeUtils.area( pts ) < 0; + const geometries = {}; + const wireframeAttributes = new WeakMap(); - }, + function onGeometryDispose( event ) { - triangulateShape: function ( contour, holes ) { + const geometry = event.target; - function removeDupEndPts( points ) { + if ( geometry.index !== null ) { - var l = points.length; + attributes.remove( geometry.index ); - if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { + } - points.pop(); + for ( const name in geometry.attributes ) { - } + attributes.remove( geometry.attributes[ name ] ); } - function addContour( vertices, contour ) { + for ( const name in geometry.morphAttributes ) { - for ( var i = 0; i < contour.length; i ++ ) { + const array = geometry.morphAttributes[ name ]; - vertices.push( contour[ i ].x ); - vertices.push( contour[ i ].y ); + for ( let i = 0, l = array.length; i < l; i ++ ) { + + attributes.remove( array[ i ] ); } } - var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] - var holeIndices = []; // array of hole indices - var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] + geometry.removeEventListener( 'dispose', onGeometryDispose ); - removeDupEndPts( contour ); - addContour( vertices, contour ); + delete geometries[ geometry.id ]; - // + const attribute = wireframeAttributes.get( geometry ); + + if ( attribute ) { + + attributes.remove( attribute ); + wireframeAttributes.delete( geometry ); - var holeIndex = contour.length; - holes.forEach( removeDupEndPts ); + } + + bindingStates.releaseStatesOfGeometry( geometry ); - for ( i = 0; i < holes.length; i ++ ) { + if ( geometry.isInstancedBufferGeometry === true ) { - holeIndices.push( holeIndex ); - holeIndex += holes[ i ].length; - addContour( vertices, holes[ i ] ); + delete geometry._maxInstanceCount; } // - var triangles = Earcut.triangulate( vertices, holeIndices ); + info.memory.geometries --; - // + } - for ( var i = 0; i < triangles.length; i += 3 ) { + function get( object, geometry ) { - faces.push( triangles.slice( i, i + 3 ) ); + if ( geometries[ geometry.id ] === true ) return geometry; - } + geometry.addEventListener( 'dispose', onGeometryDispose ); - return faces; + geometries[ geometry.id ] = true; - } + info.memory.geometries ++; -}; + return geometry; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Creates extruded geometry from a path shape. - * - * parameters = { - * - * curveSegments: , // number of points on the curves - * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too - * amount: , // Depth to extrude the shape - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into the original shape bevel goes - * bevelSize: , // how far from shape outline is bevel - * bevelSegments: , // number of bevel layers - * - * extrudePath: // curve to extrude shape along - * frames: // containing arrays of tangents, normals, binormals - * - * UVGenerator: // object that provides UV generator functions - * - * } - */ + } -// ExtrudeGeometry + function update( geometry ) { -function ExtrudeGeometry( shapes, options ) { + const geometryAttributes = geometry.attributes; - Geometry.call( this ); + // Updating index buffer in VAO now. See WebGLBindingStates. - this.type = 'ExtrudeGeometry'; + for ( const name in geometryAttributes ) { - this.parameters = { - shapes: shapes, - options: options - }; + attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); - this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) ); - this.mergeVertices(); + } -} + // morph targets -ExtrudeGeometry.prototype = Object.create( Geometry.prototype ); -ExtrudeGeometry.prototype.constructor = ExtrudeGeometry; + const morphAttributes = geometry.morphAttributes; -// ExtrudeBufferGeometry + for ( const name in morphAttributes ) { -function ExtrudeBufferGeometry( shapes, options ) { + const array = morphAttributes[ name ]; - if ( typeof ( shapes ) === "undefined" ) { + for ( let i = 0, l = array.length; i < l; i ++ ) { - return; + attributes.update( array[ i ], gl.ARRAY_BUFFER ); - } + } - BufferGeometry.call( this ); + } - this.type = 'ExtrudeBufferGeometry'; + } - shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; + function updateWireframeAttribute( geometry ) { - this.addShapeList( shapes, options ); + const indices = []; - this.computeVertexNormals(); + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; + let version = 0; - // can't really use automatic vertex normals - // as then front and back sides get smoothed too - // should do separate smoothing just for sides + if ( geometryIndex !== null ) { - //this.computeVertexNormals(); + const array = geometryIndex.array; + version = geometryIndex.version; - //console.log( "took", ( Date.now() - startTime ) ); + for ( let i = 0, l = array.length; i < l; i += 3 ) { -} + const a = array[ i + 0 ]; + const b = array[ i + 1 ]; + const c = array[ i + 2 ]; -ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry; + indices.push( a, b, b, c, c, a ); -ExtrudeBufferGeometry.prototype.getArrays = function () { + } - var positionAttribute = this.getAttribute( "position" ); - var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : []; + } else if ( geometryPosition !== undefined ) { - var uvAttribute = this.getAttribute( "uv" ); - var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : []; + const array = geometryPosition.array; + version = geometryPosition.version; - var IndexAttribute = this.index; - var indicesArray = IndexAttribute ? Array.prototype.slice.call( IndexAttribute.array ) : []; + for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { - return { - position: verticesArray, - uv: uvArray, - index: indicesArray - }; + const a = i + 0; + const b = i + 1; + const c = i + 2; -}; + indices.push( a, b, b, c, c, a ); -ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) { + } - var sl = shapes.length; - options.arrays = this.getArrays(); + } else { - for ( var s = 0; s < sl; s ++ ) { + return; - var shape = shapes[ s ]; - this.addShape( shape, options ); + } - } + const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + attribute.version = version; - this.setIndex( options.arrays.index ); - this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) ); + // Updating index buffer in VAO now. See WebGLBindingStates -}; + // -ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) { + const previousAttribute = wireframeAttributes.get( geometry ); - var arrays = options.arrays ? options.arrays : this.getArrays(); - var verticesArray = arrays.position; - var indicesArray = arrays.index; - var uvArray = arrays.uv; + if ( previousAttribute ) attributes.remove( previousAttribute ); - var placeholder = []; + // + wireframeAttributes.set( geometry, attribute ); - var amount = options.amount !== undefined ? options.amount : 100; + } - var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10 - var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8 - var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; + function getWireframeAttribute( geometry ) { - var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false + const currentAttribute = wireframeAttributes.get( geometry ); - var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; + if ( currentAttribute ) { - var steps = options.steps !== undefined ? options.steps : 1; + const geometryIndex = geometry.index; - var extrudePath = options.extrudePath; - var extrudePts, extrudeByPath = false; + if ( geometryIndex !== null ) { - // Use default WorldUVGenerator if no UV generators are specified. - var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator; + // if the attribute is obsolete, create a new one - var splineTube, binormal, normal, position2; - if ( extrudePath ) { + if ( currentAttribute.version < geometryIndex.version ) { - extrudePts = extrudePath.getSpacedPoints( steps ); + updateWireframeAttribute( geometry ); - extrudeByPath = true; - bevelEnabled = false; // bevels not supported for path extrusion + } - // SETUP TNB variables + } - // TODO1 - have a .isClosed in spline? + } else { - splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false ); + updateWireframeAttribute( geometry ); - // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); + } - binormal = new Vector3(); - normal = new Vector3(); - position2 = new Vector3(); + return wireframeAttributes.get( geometry ); } - // Safeguards if bevels are not enabled - - if ( ! bevelEnabled ) { + return { - bevelSegments = 0; - bevelThickness = 0; - bevelSize = 0; + get: get, + update: update, - } + getWireframeAttribute: getWireframeAttribute - // Variables initialization + }; - var ahole, h, hl; // looping of holes - var scope = this; +} - var shapePoints = shape.extractPoints( curveSegments ); +function WebGLIndexedBufferRenderer( gl, extensions, info ) { - var vertices = shapePoints.shape; - var holes = shapePoints.holes; + let mode; - var reverse = ! ShapeUtils.isClockWise( vertices ); + function setMode( value ) { - if ( reverse ) { + mode = value; - vertices = vertices.reverse(); + } - // Maybe we should also check if holes are in the opposite direction, just to be safe ... + let type, bytesPerElement; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + function setIndex( value ) { - ahole = holes[ h ]; + type = value.type; + bytesPerElement = value.bytesPerElement; - if ( ShapeUtils.isClockWise( ahole ) ) { + } - holes[ h ] = ahole.reverse(); + function render( start, count ) { - } + gl.drawElements( mode, count, type, start * bytesPerElement ); - } + info.update( count, mode, 1 ); } + function renderInstances( start, count, primcount ) { - var faces = ShapeUtils.triangulateShape( vertices, holes ); + if ( primcount === 0 ) return; - /* Vertices */ + gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount ); - var contour = vertices; // vertices has all points but contour has only points of circumference + info.update( count, mode, primcount ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + } - ahole = holes[ h ]; + function renderMultiDraw( starts, counts, drawCount ) { - vertices = vertices.concat( ahole ); + if ( drawCount === 0 ) return; - } + const extension = extensions.get( 'WEBGL_multi_draw' ); + extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount ); + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - function scalePt2( pt, vec, size ) { + elementCount += counts[ i ]; + + } - if ( ! vec ) { console.error( "THREE.ExtrudeGeometry: vec does not exist" ); } + info.update( elementCount, mode, 1 ); - return vec.clone().multiplyScalar( size ).add( pt ); } - var b, bs, t, z, - vert, vlen = vertices.length, - face, flen = faces.length; + function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { + if ( drawCount === 0 ) return; - // Find directions for point movement + const extension = extensions.get( 'WEBGL_multi_draw' ); + if ( extension === null ) { - function getBevelVec( inPt, inPrev, inNext ) { + for ( let i = 0; i < starts.length; i ++ ) { - // computes for inPt the corresponding point inPt' on a new contour - // shifted by 1 unit (length of normalized vector) to the left - // if we walk along contour clockwise, this new contour is outside the old one - // - // inPt' is the intersection of the two lines parallel to the two - // adjacent edges of inPt at a distance of 1 unit on the left side. + renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] ); - var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt + } - // good reading for geometry algorithms (here: line-line intersection) - // http://geomalgorithms.com/a05-_intersect-1.html + } else { - var v_prev_x = inPt.x - inPrev.x, - v_prev_y = inPt.y - inPrev.y; - var v_next_x = inNext.x - inPt.x, - v_next_y = inNext.y - inPt.y; + extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount ); - var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - // check for collinear edges - var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); + elementCount += counts[ i ]; - if ( Math.abs( collinear0 ) > Number.EPSILON ) { + } - // not collinear + for ( let i = 0; i < primcount.length; i ++ ) { - // length of vectors for normalizing + info.update( elementCount, mode, primcount[ i ] ); - var v_prev_len = Math.sqrt( v_prev_lensq ); - var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); + } - // shift adjacent points by unit vectors to the left + } - var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); - var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); + } - var ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); - var ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); + // - // scaling factor for v_prev to intersection point + this.setMode = setMode; + this.setIndex = setIndex; + this.render = render; + this.renderInstances = renderInstances; + this.renderMultiDraw = renderMultiDraw; + this.renderMultiDrawInstances = renderMultiDrawInstances; - var 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 ); +} - // vector from inPt to intersection point +function WebGLInfo( gl ) { - v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); - v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); + const memory = { + geometries: 0, + textures: 0 + }; - // Don't normalize!, otherwise sharp corners become ugly - // but prevent crazy spikes - var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); - if ( v_trans_lensq <= 2 ) { + const render = { + frame: 0, + calls: 0, + triangles: 0, + points: 0, + lines: 0 + }; - return new Vector2( v_trans_x, v_trans_y ); + function update( count, mode, instanceCount ) { - } else { + render.calls ++; - shrink_by = Math.sqrt( v_trans_lensq / 2 ); + switch ( mode ) { - } + case gl.TRIANGLES: + render.triangles += instanceCount * ( count / 3 ); + break; - } else { + case gl.LINES: + render.lines += instanceCount * ( count / 2 ); + break; - // handle special case of collinear edges + case gl.LINE_STRIP: + render.lines += instanceCount * ( count - 1 ); + break; - var direction_eq = false; // assumes: opposite - if ( v_prev_x > Number.EPSILON ) { + case gl.LINE_LOOP: + render.lines += instanceCount * count; + break; - if ( v_next_x > Number.EPSILON ) { + case gl.POINTS: + render.points += instanceCount * count; + break; - direction_eq = true; + default: + console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); + break; - } + } - } else { + } - if ( v_prev_x < - Number.EPSILON ) { + function reset() { - if ( v_next_x < - Number.EPSILON ) { + render.calls = 0; + render.triangles = 0; + render.points = 0; + render.lines = 0; - direction_eq = true; + } - } + return { + memory: memory, + render: render, + programs: null, + autoReset: true, + reset: reset, + update: update + }; - } else { +} - if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { +function WebGLMorphtargets( gl, capabilities, textures ) { - direction_eq = true; + const morphTextures = new WeakMap(); + const morph = new Vector4(); - } + function update( object, geometry, program ) { - } + const objectInfluences = object.morphTargetInfluences; - } + // the following encodes morph targets into an array of data textures. Each layer represents a single morph target. - if ( direction_eq ) { + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - // console.log("Warning: lines are a straight sequence"); - v_trans_x = - v_prev_y; - v_trans_y = v_prev_x; - shrink_by = Math.sqrt( v_prev_lensq ); + let entry = morphTextures.get( geometry ); - } else { + if ( entry === undefined || entry.count !== morphTargetsCount ) { - // console.log("Warning: lines are a straight spike"); - v_trans_x = v_prev_x; - v_trans_y = v_prev_y; - shrink_by = Math.sqrt( v_prev_lensq / 2 ); + if ( entry !== undefined ) entry.texture.dispose(); - } + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.morphAttributes.normal !== undefined; + const hasMorphColors = geometry.morphAttributes.color !== undefined; - } + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; - return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); + 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; - var contourMovements = []; + if ( width > capabilities.maxTextureSize ) { - for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + height = Math.ceil( width / capabilities.maxTextureSize ); + width = capabilities.maxTextureSize; - if ( j === il ) { j = 0; } - if ( k === il ) { k = 0; } + } - // (j)---(i)---(k) - // console.log('i,j,k', i, j , k) + const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); - contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); + const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); + texture.type = FloatType; + texture.needsUpdate = true; - } + // fill buffer - var holesMovements = [], - oneHoleMovements, verticesMovements = contourMovements.concat(); + const vertexDataStride = vertexDataCount * 4; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + for ( let i = 0; i < morphTargetsCount; i ++ ) { - ahole = holes[ h ]; + const morphTarget = morphTargets[ i ]; + const morphNormal = morphNormals[ i ]; + const morphColor = morphColors[ i ]; - oneHoleMovements = []; + const offset = width * height * 4 * i; - for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + for ( let j = 0; j < morphTarget.count; j ++ ) { - if ( j === il ) { j = 0; } - if ( k === il ) { k = 0; } + const stride = j * vertexDataStride; - // (j)---(i)---(k) - oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); + if ( hasMorphPosition === true ) { - } + morph.fromBufferAttribute( morphTarget, j ); - holesMovements.push( oneHoleMovements ); - verticesMovements = verticesMovements.concat( oneHoleMovements ); + 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 ) { - // Loop bevelSegments, 1 for the front, 1 for the back + morph.fromBufferAttribute( morphNormal, j ); - for ( b = 0; b < bevelSegments; b ++ ) { + buffer[ offset + stride + 4 ] = morph.x; + buffer[ offset + stride + 5 ] = morph.y; + buffer[ offset + stride + 6 ] = morph.z; + buffer[ offset + stride + 7 ] = 0; - //for ( b = bevelSegments; b > 0; b -- ) { + } - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); + if ( hasMorphColors === true ) { - // contract shape + morph.fromBufferAttribute( morphColor, j ); - for ( i = 0, il = contour.length; i < il; i ++ ) { + 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; - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); + } - v( vert.x, vert.y, - z ); + } - } + } - // expand holes + entry = { + count: morphTargetsCount, + texture: texture, + size: new Vector2( width, height ) + }; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + morphTextures.set( geometry, entry ); - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; + function disposeTexture() { - for ( i = 0, il = ahole.length; i < il; i ++ ) { + texture.dispose(); - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + morphTextures.delete( geometry ); - v( vert.x, vert.y, - z ); + geometry.removeEventListener( 'dispose', disposeTexture ); } - } - - } + geometry.addEventListener( 'dispose', disposeTexture ); - bs = bevelSize; + } - // Back facing vertices + // + if ( object.isInstancedMesh === true && object.morphTexture !== null ) { - for ( i = 0; i < vlen; i ++ ) { + program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures ); - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; + } else { - if ( ! extrudeByPath ) { + let morphInfluencesSum = 0; - v( vert.x, vert.y, 0 ); + for ( let i = 0; i < objectInfluences.length; i ++ ) { - } else { + morphInfluencesSum += objectInfluences[ i ]; - // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); + } - normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); + const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; - position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); - v( position2.x, position2.y, position2.z ); + 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 ); + } - // Add stepped vertices... - // Including front facing vertices + return { - var s; + update: update - for ( s = 1; s <= steps; s ++ ) { + }; - for ( i = 0; i < vlen; i ++ ) { +} - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; +function WebGLObjects( gl, geometries, attributes, info ) { - if ( ! extrudeByPath ) { + let updateMap = new WeakMap(); - v( vert.x, vert.y, amount / steps * s ); + function update( object ) { - } else { + const frame = info.render.frame; - // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); + const geometry = object.geometry; + const buffergeometry = geometries.get( object, geometry ); - normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); + // Update once per frame - position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); + if ( updateMap.get( buffergeometry ) !== frame ) { - v( position2.x, position2.y, position2.z ); + geometries.update( buffergeometry ); - } + updateMap.set( buffergeometry, frame ); } - } - + if ( object.isInstancedMesh ) { - // Add bevel segments planes + if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { - //for ( b = 1; b <= bevelSegments; b ++ ) { - for ( b = bevelSegments - 1; b >= 0; b -- ) { + object.addEventListener( 'dispose', onInstancedMeshDispose ); - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); - - // contract shape + } - for ( i = 0, il = contour.length; i < il; i ++ ) { + if ( updateMap.get( object ) !== frame ) { - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); - v( vert.x, vert.y, amount + z ); + attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); - } + if ( object.instanceColor !== null ) { - // expand holes + attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + } - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; + updateMap.set( object, frame ); - for ( i = 0, il = ahole.length; i < il; i ++ ) { + } - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + } - if ( ! extrudeByPath ) { + if ( object.isSkinnedMesh ) { - v( vert.x, vert.y, amount + z ); + const skeleton = object.skeleton; - } else { + if ( updateMap.get( skeleton ) !== frame ) { - v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); + skeleton.update(); - } + updateMap.set( skeleton, frame ); } } + return buffergeometry; + } - /* Faces */ + function dispose() { - // Top and bottom faces + updateMap = new WeakMap(); - buildLidFaces(); + } - // Sides faces + function onInstancedMeshDispose( event ) { - buildSideFaces(); + const instancedMesh = event.target; + instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); - ///// Internal functions + attributes.remove( instancedMesh.instanceMatrix ); - function buildLidFaces() { + if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); - var start = verticesArray.length / 3; + } - if ( bevelEnabled ) { + return { - var layer = 0; // steps + 1 - var offset = vlen * layer; + update: update, + dispose: dispose - // Bottom faces + }; - for ( i = 0; i < flen; i ++ ) { +} - face = faces[ i ]; - f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); +class DepthTexture extends Texture { - } + constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) { - layer = steps + bevelSegments * 2; - offset = vlen * layer; + if ( format !== DepthFormat && format !== DepthStencilFormat ) { - // Top faces + throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); - for ( i = 0; i < flen; i ++ ) { + } - face = faces[ i ]; - f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); + if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; + if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; - } + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - } else { + this.isDepthTexture = true; - // Bottom faces + this.image = { width: width, height: height }; - for ( i = 0; i < flen; i ++ ) { + this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; + this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; - face = faces[ i ]; - f3( face[ 2 ], face[ 1 ], face[ 0 ] ); + this.flipY = false; + this.generateMipmaps = false; - } + this.compareFunction = null; - // Top faces + } - for ( i = 0; i < flen; i ++ ) { - face = faces[ i ]; - f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); + copy( source ) { - } + super.copy( source ); - } + this.compareFunction = source.compareFunction; - scope.addGroup( start, verticesArray.length / 3 - start, options.material !== undefined ? options.material : 0 ); + return this; } - // Create faces for the z-sides of the shape - - function buildSideFaces() { + toJSON( meta ) { - var start = verticesArray.length / 3; - var layeroffset = 0; - sidewalls( contour, layeroffset ); - layeroffset += contour.length; + const data = super.toJSON( meta ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; - ahole = holes[ h ]; - sidewalls( ahole, layeroffset ); - - //, true - layeroffset += ahole.length; - - } + return data; + } - scope.addGroup( start, verticesArray.length / 3 - start, options.extrudeMaterial !== undefined ? options.extrudeMaterial : 1 ); +} +/** + * Uniforms of a program. + * Those form a tree structure with a special top-level container for the root, + * which you get by calling 'new WebGLUniforms( gl, program )'. + * + * + * Properties of inner nodes including the top-level container: + * + * .seq - array of nested uniforms + * .map - nested uniforms by name + * + * + * Methods of all nodes except the top-level container: + * + * .setValue( gl, value, [textures] ) + * + * uploads a uniform value(s) + * the 'textures' parameter is needed for sampler uniforms + * + * + * Static methods of the top-level container (textures factorizations): + * + * .upload( gl, seq, values, textures ) + * + * sets uniforms in 'seq' to 'values[id].value' + * + * .seqWithValue( seq, values ) : filteredSeq + * + * filters 'seq' entries with corresponding entry in values + * + * + * Methods of the top-level container (textures factorizations): + * + * .setValue( gl, name, value, textures ) + * + * sets uniform with name 'name' to 'value' + * + * .setOptional( gl, obj, prop ) + * + * like .set for an optional property of the object + * + */ - } - function sidewalls( contour, layeroffset ) { +const emptyTexture = /*@__PURE__*/ new Texture(); - var j, k; - i = contour.length; +const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 ); - while ( -- i >= 0 ) { +const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); +const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); +const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); - j = i; - k = i - 1; - if ( k < 0 ) { k = contour.length - 1; } +// --- Utilities --- - //console.log('b', i,j, i-1, k,vertices.length); +// Array Caches (provide typed arrays for temporary by size) - var s = 0, - sl = steps + bevelSegments * 2; +const arrayCacheF32 = []; +const arrayCacheI32 = []; - for ( s = 0; s < sl; s ++ ) { +// Float32Array caches used for uploading Matrix uniforms - var slen1 = vlen * s; - var slen2 = vlen * ( s + 1 ); +const mat4array = new Float32Array( 16 ); +const mat3array = new Float32Array( 9 ); +const mat2array = new Float32Array( 4 ); - var a = layeroffset + j + slen1, - b = layeroffset + k + slen1, - c = layeroffset + k + slen2, - d = layeroffset + j + slen2; +// Flattening for arrays of vectors and matrices - f4( a, b, c, d ); +function flatten( array, nBlocks, blockSize ) { - } + const firstElem = array[ 0 ]; - } + if ( firstElem <= 0 || firstElem > 0 ) return array; + // unoptimized: ! isNaN( firstElem ) + // see http://jacksondunstan.com/articles/983 - } + const n = nBlocks * blockSize; + let r = arrayCacheF32[ n ]; - function v( x, y, z ) { + if ( r === undefined ) { - placeholder.push( x ); - placeholder.push( y ); - placeholder.push( z ); + r = new Float32Array( n ); + arrayCacheF32[ n ] = r; } + if ( nBlocks !== 0 ) { - function f3( a, b, c ) { + firstElem.toArray( r, 0 ); - addVertex( a ); - addVertex( b ); - addVertex( c ); + for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + offset += blockSize; + array[ i ].toArray( r, offset ); - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); + } } - function f4( a, b, c, d ) { - - addVertex( a ); - addVertex( b ); - addVertex( d ); + return r; - addVertex( b ); - addVertex( c ); - addVertex( d ); +} +function arraysEqual( a, b ) { - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + if ( a.length !== b.length ) return false; - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 3 ] ); + for ( let i = 0, l = a.length; i < l; i ++ ) { - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); - addUV( uvs[ 3 ] ); + if ( a[ i ] !== b[ i ] ) return false; } - function addVertex( index ) { - - indicesArray.push( verticesArray.length / 3 ); - verticesArray.push( placeholder[ index * 3 + 0 ] ); - verticesArray.push( placeholder[ index * 3 + 1 ] ); - verticesArray.push( placeholder[ index * 3 + 2 ] ); + return true; - } +} +function copyArray( a, b ) { - function addUV( vector2 ) { + for ( let i = 0, l = b.length; i < l; i ++ ) { - uvArray.push( vector2.x ); - uvArray.push( vector2.y ); + a[ i ] = b[ i ]; } - if ( ! options.arrays ) { - - this.setIndex( indicesArray ); - this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); +} - } +// Texture unit allocation -}; +function allocTexUnits( textures, n ) { -ExtrudeGeometry.WorldUVGenerator = { + let r = arrayCacheI32[ n ]; - generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { + if ( r === undefined ) { - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; + r = new Int32Array( n ); + arrayCacheI32[ n ] = r; - return [ - new Vector2( a_x, a_y ), - new Vector2( b_x, b_y ), - new Vector2( c_x, c_y ) - ]; + } - }, + for ( let i = 0; i !== n; ++ i ) { - generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { - - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var a_z = vertices[ indexA * 3 + 2 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var b_z = vertices[ indexB * 3 + 2 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; - var c_z = vertices[ indexC * 3 + 2 ]; - var d_x = vertices[ indexD * 3 ]; - var d_y = vertices[ indexD * 3 + 1 ]; - var d_z = vertices[ indexD * 3 + 2 ]; - - if ( Math.abs( a_y - b_y ) < 0.01 ) { - - return [ - new Vector2( a_x, 1 - a_z ), - new Vector2( b_x, 1 - b_z ), - new Vector2( c_x, 1 - c_z ), - new Vector2( d_x, 1 - d_z ) - ]; + r[ i ] = textures.allocateTextureUnit(); - } else { + } - return [ - new Vector2( a_y, 1 - a_z ), - new Vector2( b_y, 1 - b_z ), - new Vector2( c_y, 1 - c_z ), - new Vector2( d_y, 1 - d_z ) - ]; + return r; - } +} - } -}; +// --- Setters --- -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author alteredq / http://alteredqualia.com/ - * - * Text = 3D Text - * - * parameters = { - * font: , // font - * - * size: , // size of the text - * height: , // thickness to extrude text - * curveSegments: , // number of points on the curves - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into text bevel goes - * bevelSize: // how far from text outline is bevel - * } - */ +// Note: Defining these methods externally, because they come in a bunch +// and this way their names minify. -// TextGeometry +// Single scalar -function TextGeometry( text, parameters ) { +function setValueV1f( gl, v ) { - Geometry.call( this ); + const cache = this.cache; - this.type = 'TextGeometry'; + if ( cache[ 0 ] === v ) return; - this.parameters = { - text: text, - parameters: parameters - }; + gl.uniform1f( this.addr, v ); - this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) ); - this.mergeVertices(); + cache[ 0 ] = v; } -TextGeometry.prototype = Object.create( Geometry.prototype ); -TextGeometry.prototype.constructor = TextGeometry; - -// TextBufferGeometry - -function TextBufferGeometry( text, parameters ) { +// Single float vector (from flat array or THREE.VectorN) - parameters = parameters || {}; +function setValueV2f( gl, v ) { - var font = parameters.font; + const cache = this.cache; - if ( ! ( font && font.isFont ) ) { + if ( v.x !== undefined ) { - console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); - return new Geometry(); + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - } + gl.uniform2f( this.addr, v.x, v.y ); - var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - // translate parameters to ExtrudeGeometry API + } - parameters.amount = parameters.height !== undefined ? parameters.height : 50; + } else { - // defaults + if ( arraysEqual( cache, v ) ) return; - if ( parameters.bevelThickness === undefined ) { parameters.bevelThickness = 10; } - if ( parameters.bevelSize === undefined ) { parameters.bevelSize = 8; } - if ( parameters.bevelEnabled === undefined ) { parameters.bevelEnabled = false; } + gl.uniform2fv( this.addr, v ); - ExtrudeBufferGeometry.call( this, shapes, parameters ); + copyArray( cache, v ); - this.type = 'TextBufferGeometry'; + } } -TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype ); -TextBufferGeometry.prototype.constructor = TextBufferGeometry; +function setValueV3f( gl, v ) { -/** - * @author mrdoob / http://mrdoob.com/ - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - */ + const cache = this.cache; -// SphereGeometry + if ( v.x !== undefined ) { -function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - Geometry.call( this ); + gl.uniform3f( this.addr, v.x, v.y, v.z ); - this.type = 'SphereGeometry'; + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + } - this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) ); - this.mergeVertices(); + } else if ( v.r !== undefined ) { -} + if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { -SphereGeometry.prototype = Object.create( Geometry.prototype ); -SphereGeometry.prototype.constructor = SphereGeometry; + gl.uniform3f( this.addr, v.r, v.g, v.b ); -// SphereBufferGeometry + cache[ 0 ] = v.r; + cache[ 1 ] = v.g; + cache[ 2 ] = v.b; -function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { + } - BufferGeometry.call( this ); + } else { - this.type = 'SphereBufferGeometry'; + if ( arraysEqual( cache, v ) ) return; - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + gl.uniform3fv( this.addr, v ); - radius = radius || 1; + copyArray( cache, v ); - widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 ); - heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 ); + } - phiStart = phiStart !== undefined ? phiStart : 0; - phiLength = phiLength !== undefined ? phiLength : Math.PI * 2; +} - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI; +function setValueV4f( gl, v ) { - var thetaEnd = thetaStart + thetaLength; + const cache = this.cache; - var ix, iy; + if ( v.x !== undefined ) { - var index = 0; - var grid = []; + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - var vertex = new Vector3(); - var normal = new Vector3(); + gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); - // buffers + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // generate vertices, normals and uvs + } else { - for ( iy = 0; iy <= heightSegments; iy ++ ) { + if ( arraysEqual( cache, v ) ) return; - var verticesRow = []; + gl.uniform4fv( this.addr, v ); - var v = iy / heightSegments; + copyArray( cache, v ); - for ( ix = 0; ix <= widthSegments; ix ++ ) { + } - var u = ix / widthSegments; +} - // vertex +// Single matrix (from flat array or THREE.MatrixN) - vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); - vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); +function setValueM2( gl, v ) { - vertices.push( vertex.x, vertex.y, vertex.z ); + const cache = this.cache; + const elements = v.elements; - // normal + if ( elements === undefined ) { - normal.set( vertex.x, vertex.y, vertex.z ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + if ( arraysEqual( cache, v ) ) return; - // uv + gl.uniformMatrix2fv( this.addr, false, v ); - uvs.push( u, 1 - v ); + copyArray( cache, v ); - verticesRow.push( index ++ ); + } else { - } + if ( arraysEqual( cache, elements ) ) return; - grid.push( verticesRow ); + mat2array.set( elements ); - } + gl.uniformMatrix2fv( this.addr, false, mat2array ); - // indices + copyArray( cache, elements ); - for ( iy = 0; iy < heightSegments; iy ++ ) { + } - for ( ix = 0; ix < widthSegments; ix ++ ) { +} - var a = grid[ iy ][ ix + 1 ]; - var b = grid[ iy ][ ix ]; - var c = grid[ iy + 1 ][ ix ]; - var d = grid[ iy + 1 ][ ix + 1 ]; +function setValueM3( gl, v ) { - if ( iy !== 0 || thetaStart > 0 ) { indices.push( a, b, d ); } - if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) { indices.push( b, c, d ); } + const cache = this.cache; + const elements = v.elements; - } + if ( elements === undefined ) { - } + if ( arraysEqual( cache, v ) ) return; - // build geometry + gl.uniformMatrix3fv( this.addr, false, v ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + copyArray( cache, v ); -} + } else { -SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -SphereBufferGeometry.prototype.constructor = SphereBufferGeometry; + if ( arraysEqual( cache, elements ) ) return; -/** - * @author Kaleb Murphy - * @author Mugen87 / https://github.com/Mugen87 - */ + mat3array.set( elements ); -// RingGeometry + gl.uniformMatrix3fv( this.addr, false, mat3array ); -function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { + copyArray( cache, elements ); - Geometry.call( this ); + } - this.type = 'RingGeometry'; +} - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; +function setValueM4( gl, v ) { - this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) ); - this.mergeVertices(); + const cache = this.cache; + const elements = v.elements; -} + if ( elements === undefined ) { -RingGeometry.prototype = Object.create( Geometry.prototype ); -RingGeometry.prototype.constructor = RingGeometry; + if ( arraysEqual( cache, v ) ) return; -// RingBufferGeometry + gl.uniformMatrix4fv( this.addr, false, v ); -function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { + copyArray( cache, v ); - BufferGeometry.call( this ); + } else { - this.type = 'RingBufferGeometry'; + if ( arraysEqual( cache, elements ) ) return; - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + mat4array.set( elements ); - innerRadius = innerRadius || 0.5; - outerRadius = outerRadius || 1; + gl.uniformMatrix4fv( this.addr, false, mat4array ); - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + copyArray( cache, elements ); - thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8; - phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1; + } - // buffers +} - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; +// Single integer / boolean - // some helper variables +function setValueV1i( gl, v ) { - var segment; - var radius = innerRadius; - var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); - var vertex = new Vector3(); - var uv = new Vector2(); - var j, i; + const cache = this.cache; - // generate vertices, normals and uvs + if ( cache[ 0 ] === v ) return; - for ( j = 0; j <= phiSegments; j ++ ) { + gl.uniform1i( this.addr, v ); - for ( i = 0; i <= thetaSegments; i ++ ) { + cache[ 0 ] = v; - // values are generate from the inside of the ring to the outside +} - segment = thetaStart + i / thetaSegments * thetaLength; +// Single integer / boolean vector (from flat array or THREE.VectorN) - // vertex +function setValueV2i( gl, v ) { - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); + const cache = this.cache; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( v.x !== undefined ) { - // normal + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - normals.push( 0, 0, 1 ); + gl.uniform2i( this.addr, v.x, v.y ); - // uv + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - uv.x = ( vertex.x / outerRadius + 1 ) / 2; - uv.y = ( vertex.y / outerRadius + 1 ) / 2; + } - uvs.push( uv.x, uv.y ); + } else { - } + if ( arraysEqual( cache, v ) ) return; - // increase the radius for next row of vertices + gl.uniform2iv( this.addr, v ); - radius += radiusStep; + copyArray( cache, v ); } - // indices - - for ( j = 0; j < phiSegments; j ++ ) { +} - var thetaSegmentLevel = j * ( thetaSegments + 1 ); +function setValueV3i( gl, v ) { - for ( i = 0; i < thetaSegments; i ++ ) { + const cache = this.cache; - segment = i + thetaSegmentLevel; + if ( v.x !== undefined ) { - var a = segment; - var b = segment + thetaSegments + 1; - var c = segment + thetaSegments + 2; - var d = segment + 1; + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - // faces + gl.uniform3i( this.addr, v.x, v.y, v.z ); - indices.push( a, b, d ); - indices.push( b, c, d ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; } - } + } else { + + if ( arraysEqual( cache, v ) ) return; - // build geometry + gl.uniform3iv( this.addr, v ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + copyArray( cache, v ); + + } } -RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -RingBufferGeometry.prototype.constructor = RingBufferGeometry; +function setValueV4i( gl, v ) { -/** - * @author astrodud / http://astrodud.isgreat.org/ - * @author zz85 / https://github.com/zz85 - * @author bhouston / http://clara.io - * @author Mugen87 / https://github.com/Mugen87 - */ + const cache = this.cache; -// LatheGeometry + if ( v.x !== undefined ) { -function LatheGeometry( points, segments, phiStart, phiLength ) { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - Geometry.call( this ); + gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); - this.type = 'LatheGeometry'; + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; + } - this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) ); - this.mergeVertices(); + } else { -} + if ( arraysEqual( cache, v ) ) return; -LatheGeometry.prototype = Object.create( Geometry.prototype ); -LatheGeometry.prototype.constructor = LatheGeometry; + gl.uniform4iv( this.addr, v ); -// LatheBufferGeometry + copyArray( cache, v ); -function LatheBufferGeometry( points, segments, phiStart, phiLength ) { + } - BufferGeometry.call( this ); +} - this.type = 'LatheBufferGeometry'; +// Single unsigned integer - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; +function setValueV1ui( gl, v ) { - segments = Math.floor( segments ) || 12; - phiStart = phiStart || 0; - phiLength = phiLength || Math.PI * 2; + const cache = this.cache; - // clamp phiLength so it's in range of [ 0, 2PI ] + if ( cache[ 0 ] === v ) return; - phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 ); + gl.uniform1ui( this.addr, v ); + cache[ 0 ] = v; - // buffers +} - var indices = []; - var vertices = []; - var uvs = []; +// Single unsigned integer vector (from flat array or THREE.VectorN) - // helper variables +function setValueV2ui( gl, v ) { - var base; - var inverseSegments = 1.0 / segments; - var vertex = new Vector3(); - var uv = new Vector2(); - var i, j; + const cache = this.cache; - // generate vertices and uvs + if ( v.x !== undefined ) { - for ( i = 0; i <= segments; i ++ ) { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - var phi = phiStart + i * inverseSegments * phiLength; + gl.uniform2ui( this.addr, v.x, v.y ); - var sin = Math.sin( phi ); - var cos = Math.cos( phi ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - for ( j = 0; j <= ( points.length - 1 ); j ++ ) { + } - // vertex + } else { - vertex.x = points[ j ].x * sin; - vertex.y = points[ j ].y; - vertex.z = points[ j ].x * cos; + if ( arraysEqual( cache, v ) ) return; - vertices.push( vertex.x, vertex.y, vertex.z ); + gl.uniform2uiv( this.addr, v ); - // uv + copyArray( cache, v ); - uv.x = i / segments; - uv.y = j / ( points.length - 1 ); + } - uvs.push( uv.x, uv.y ); +} +function setValueV3ui( gl, v ) { - } + const cache = this.cache; - } + if ( v.x !== undefined ) { - // indices + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - for ( i = 0; i < segments; i ++ ) { + gl.uniform3ui( this.addr, v.x, v.y, v.z ); - for ( j = 0; j < ( points.length - 1 ); j ++ ) { + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - base = j + i * points.length; + } - var a = base; - var b = base + points.length; - var c = base + points.length + 1; - var d = base + 1; + } else { - // faces + if ( arraysEqual( cache, v ) ) return; - indices.push( a, b, d ); - indices.push( b, c, d ); + gl.uniform3uiv( this.addr, v ); - } + copyArray( cache, v ); } - // build geometry +} + +function setValueV4ui( gl, v ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + const cache = this.cache; - // generate normals + if ( v.x !== undefined ) { - this.computeVertexNormals(); + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). + gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); - if ( phiLength === Math.PI * 2 ) { + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - var normals = this.attributes.normal.array; - var n1 = new Vector3(); - var n2 = new Vector3(); - var n = new Vector3(); + } - // this is the buffer offset for the last line of vertices + } else { - base = segments * points.length * 3; + if ( arraysEqual( cache, v ) ) return; - for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) { + gl.uniform4uiv( this.addr, v ); - // select the normal of the vertex in the first line + copyArray( cache, v ); - n1.x = normals[ j + 0 ]; - n1.y = normals[ j + 1 ]; - n1.z = normals[ j + 2 ]; + } - // select the normal of the vertex in the last line +} - n2.x = normals[ base + j + 0 ]; - n2.y = normals[ base + j + 1 ]; - n2.z = normals[ base + j + 2 ]; - // average normals +// Single texture (2D / Cube) - n.addVectors( n1, n2 ).normalize(); +function setValueT1( gl, v, textures ) { - // assign the new values to both normals + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; - normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; - normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; + if ( cache[ 0 ] !== unit ) { - } + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; } -} + let emptyTexture2D; -LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -LatheBufferGeometry.prototype.constructor = LatheBufferGeometry; + if ( this.type === gl.SAMPLER_2D_SHADOW ) { -/** - * @author jonobr1 / http://jonobr1.com - * @author Mugen87 / https://github.com/Mugen87 - */ + emptyShadowTexture.compareFunction = LessEqualCompare; // #28670 + emptyTexture2D = emptyShadowTexture; + + } else { -// ShapeGeometry + emptyTexture2D = emptyTexture; -function ShapeGeometry( shapes, curveSegments ) { + } - Geometry.call( this ); + textures.setTexture2D( v || emptyTexture2D, unit ); - this.type = 'ShapeGeometry'; +} - if ( typeof curveSegments === 'object' ) { +function setValueT3D1( gl, v, textures ) { - console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' ); + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - curveSegments = curveSegments.curveSegments; + if ( cache[ 0 ] !== unit ) { - } + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; + } - this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) ); - this.mergeVertices(); + textures.setTexture3D( v || empty3dTexture, unit ); } -ShapeGeometry.prototype = Object.create( Geometry.prototype ); -ShapeGeometry.prototype.constructor = ShapeGeometry; +function setValueT6( gl, v, textures ) { -ShapeGeometry.prototype.toJSON = function () { + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - var data = Geometry.prototype.toJSON.call( this ); + if ( cache[ 0 ] !== unit ) { - var shapes = this.parameters.shapes; + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - return toJSON( shapes, data ); + } -}; + textures.setTextureCube( v || emptyCubeTexture, unit ); -// ShapeBufferGeometry +} -function ShapeBufferGeometry( shapes, curveSegments ) { +function setValueT2DArray1( gl, v, textures ) { - BufferGeometry.call( this ); + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - this.type = 'ShapeBufferGeometry'; + if ( cache[ 0 ] !== unit ) { - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - curveSegments = curveSegments || 12; + } - // buffers + textures.setTexture2DArray( v || emptyArrayTexture, unit ); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; +} - // helper variables +// Helper to pick the right setter for the singular case - var groupStart = 0; - var groupCount = 0; +function getSingularSetter( type ) { - // allow single and array values for "shapes" parameter + switch ( type ) { - if ( Array.isArray( shapes ) === false ) { + case 0x1406: return setValueV1f; // FLOAT + case 0x8b50: return setValueV2f; // _VEC2 + case 0x8b51: return setValueV3f; // _VEC3 + case 0x8b52: return setValueV4f; // _VEC4 - addShape( shapes ); + case 0x8b5a: return setValueM2; // _MAT2 + case 0x8b5b: return setValueM3; // _MAT3 + case 0x8b5c: return setValueM4; // _MAT4 - } else { + case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL + case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 + case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 + case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 - for ( var i = 0; i < shapes.length; i ++ ) { + case 0x1405: return setValueV1ui; // UINT + case 0x8dc6: return setValueV2ui; // _VEC2 + case 0x8dc7: return setValueV3ui; // _VEC3 + case 0x8dc8: return setValueV4ui; // _VEC4 - addShape( shapes[ i ] ); + case 0x8b5e: // SAMPLER_2D + case 0x8d66: // SAMPLER_EXTERNAL_OES + case 0x8dca: // INT_SAMPLER_2D + case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D + case 0x8b62: // SAMPLER_2D_SHADOW + return setValueT1; - this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support + case 0x8b5f: // SAMPLER_3D + case 0x8dcb: // INT_SAMPLER_3D + case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D + return setValueT3D1; - groupStart += groupCount; - groupCount = 0; + case 0x8b60: // SAMPLER_CUBE + case 0x8dcc: // INT_SAMPLER_CUBE + case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE + case 0x8dc5: // SAMPLER_CUBE_SHADOW + return setValueT6; - } + case 0x8dc1: // SAMPLER_2D_ARRAY + case 0x8dcf: // INT_SAMPLER_2D_ARRAY + case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY + case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW + return setValueT2DArray1; } - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); +} - // helper functions +// Array of scalars - function addShape( shape ) { +function setValueV1fArray( gl, v ) { - var i, l, shapeHole; + gl.uniform1fv( this.addr, v ); - var indexOffset = vertices.length / 3; - var points = shape.extractPoints( curveSegments ); +} - var shapeVertices = points.shape; - var shapeHoles = points.holes; +// Array of vectors (from flat array or array of THREE.VectorN) - // check direction of vertices +function setValueV2fArray( gl, v ) { - if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { + const data = flatten( v, this.size, 2 ); - shapeVertices = shapeVertices.reverse(); + gl.uniform2fv( this.addr, data ); - // also check if holes are in the opposite direction +} - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { +function setValueV3fArray( gl, v ) { - shapeHole = shapeHoles[ i ]; + const data = flatten( v, this.size, 3 ); - if ( ShapeUtils.isClockWise( shapeHole ) === true ) { + gl.uniform3fv( this.addr, data ); - shapeHoles[ i ] = shapeHole.reverse(); +} - } +function setValueV4fArray( gl, v ) { - } + const data = flatten( v, this.size, 4 ); - } + gl.uniform4fv( this.addr, data ); - var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); +} - // join vertices of inner and outer paths to a single array +// Array of matrices (from flat array or array of THREE.MatrixN) - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { +function setValueM2Array( gl, v ) { - shapeHole = shapeHoles[ i ]; - shapeVertices = shapeVertices.concat( shapeHole ); + const data = flatten( v, this.size, 4 ); - } + gl.uniformMatrix2fv( this.addr, false, data ); - // vertices, normals, uvs +} - for ( i = 0, l = shapeVertices.length; i < l; i ++ ) { +function setValueM3Array( gl, v ) { - var vertex = shapeVertices[ i ]; + const data = flatten( v, this.size, 9 ); - vertices.push( vertex.x, vertex.y, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( vertex.x, vertex.y ); // world uvs + gl.uniformMatrix3fv( this.addr, false, data ); - } +} - // incides +function setValueM4Array( gl, v ) { - for ( i = 0, l = faces.length; i < l; i ++ ) { + const data = flatten( v, this.size, 16 ); - var face = faces[ i ]; + gl.uniformMatrix4fv( this.addr, false, data ); - var a = face[ 0 ] + indexOffset; - var b = face[ 1 ] + indexOffset; - var c = face[ 2 ] + indexOffset; +} - indices.push( a, b, c ); - groupCount += 3; +// Array of integer / boolean - } +function setValueV1iArray( gl, v ) { - } + gl.uniform1iv( this.addr, v ); } -ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry; +// Array of integer / boolean vectors (from flat array) -ShapeBufferGeometry.prototype.toJSON = function () { +function setValueV2iArray( gl, v ) { - var data = BufferGeometry.prototype.toJSON.call( this ); - - var shapes = this.parameters.shapes; + gl.uniform2iv( this.addr, v ); - return toJSON( shapes, data ); +} -}; +function setValueV3iArray( gl, v ) { -// + gl.uniform3iv( this.addr, v ); -function toJSON( shapes, data ) { +} - data.shapes = []; +function setValueV4iArray( gl, v ) { - if ( Array.isArray( shapes ) ) { + gl.uniform4iv( this.addr, v ); - for ( var i = 0, l = shapes.length; i < l; i ++ ) { +} - var shape = shapes[ i ]; +// Array of unsigned integer - data.shapes.push( shape.uuid ); +function setValueV1uiArray( gl, v ) { - } + gl.uniform1uiv( this.addr, v ); - } else { +} - data.shapes.push( shapes.uuid ); +// Array of unsigned integer vectors (from flat array) - } +function setValueV2uiArray( gl, v ) { - return data; + gl.uniform2uiv( this.addr, v ); } -/** - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ - -function EdgesGeometry( geometry, thresholdAngle ) { +function setValueV3uiArray( gl, v ) { - BufferGeometry.call( this ); + gl.uniform3uiv( this.addr, v ); - this.type = 'EdgesGeometry'; +} - this.parameters = { - thresholdAngle: thresholdAngle - }; +function setValueV4uiArray( gl, v ) { - thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1; + gl.uniform4uiv( this.addr, v ); - // buffer +} - var vertices = []; - // helper variables +// Array of textures (2D / 3D / Cube / 2DArray) - var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle ); - var edge = [ 0, 0 ], edges = {}, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; +function setValueT1Array( gl, v, textures ) { - // prepare source geometry + const cache = this.cache; - var geometry2; + const n = v.length; - if ( geometry.isBufferGeometry ) { + const units = allocTexUnits( textures, n ); - geometry2 = new Geometry(); - geometry2.fromBufferGeometry( geometry ); + if ( ! arraysEqual( cache, units ) ) { - } else { + gl.uniform1iv( this.addr, units ); - geometry2 = geometry.clone(); + copyArray( cache, units ); } - geometry2.mergeVertices(); - geometry2.computeFaceNormals(); + for ( let i = 0; i !== n; ++ i ) { - var sourceVertices = geometry2.vertices; - var faces = geometry2.faces; + textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); - // now create a data structure where each entry represents an edge with its adjoining faces + } - for ( var i = 0, l = faces.length; i < l; i ++ ) { +} - var face = faces[ i ]; +function setValueT3DArray( gl, v, textures ) { - for ( var j = 0; j < 3; j ++ ) { + const cache = this.cache; - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); - edge[ 1 ] = Math.max( edge1, edge2 ); + const n = v.length; - key = edge[ 0 ] + ',' + edge[ 1 ]; + const units = allocTexUnits( textures, n ); - if ( edges[ key ] === undefined ) { + if ( ! arraysEqual( cache, units ) ) { - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined }; + gl.uniform1iv( this.addr, units ); - } else { + copyArray( cache, units ); - edges[ key ].face2 = i; + } - } + for ( let i = 0; i !== n; ++ i ) { - } + textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); } - // generate vertices +} - for ( key in edges ) { +function setValueT6Array( gl, v, textures ) { - var e = edges[ key ]; + const cache = this.cache; - // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree. + const n = v.length; - if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) { + const units = allocTexUnits( textures, n ); - var vertex = sourceVertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( ! arraysEqual( cache, units ) ) { - vertex = sourceVertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + gl.uniform1iv( this.addr, units ); - } + copyArray( cache, units ); } - // build geometry + for ( let i = 0; i !== n; ++ i ) { - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); -} + } -EdgesGeometry.prototype = Object.create( BufferGeometry.prototype ); -EdgesGeometry.prototype.constructor = EdgesGeometry; +} -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ +function setValueT2DArrayArray( gl, v, textures ) { -// CylinderGeometry + const cache = this.cache; -function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + const n = v.length; - Geometry.call( this ); + const units = allocTexUnits( textures, n ); - this.type = 'CylinderGeometry'; + if ( ! arraysEqual( cache, units ) ) { - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + gl.uniform1iv( this.addr, units ); - this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) ); - this.mergeVertices(); + copyArray( cache, units ); -} + } -CylinderGeometry.prototype = Object.create( Geometry.prototype ); -CylinderGeometry.prototype.constructor = CylinderGeometry; + for ( let i = 0; i !== n; ++ i ) { -// CylinderBufferGeometry + textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); -function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + } - BufferGeometry.call( this ); +} - this.type = 'CylinderBufferGeometry'; - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; +// Helper to pick the right setter for a pure (bottom-level) array - var scope = this; +function getPureArraySetter( type ) { - radiusTop = radiusTop !== undefined ? radiusTop : 1; - radiusBottom = radiusBottom !== undefined ? radiusBottom : 1; - height = height || 1; + switch ( type ) { - radialSegments = Math.floor( radialSegments ) || 8; - heightSegments = Math.floor( heightSegments ) || 1; + case 0x1406: return setValueV1fArray; // FLOAT + case 0x8b50: return setValueV2fArray; // _VEC2 + case 0x8b51: return setValueV3fArray; // _VEC3 + case 0x8b52: return setValueV4fArray; // _VEC4 - openEnded = openEnded !== undefined ? openEnded : false; - thetaStart = thetaStart !== undefined ? thetaStart : 0.0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + case 0x8b5a: return setValueM2Array; // _MAT2 + case 0x8b5b: return setValueM3Array; // _MAT3 + case 0x8b5c: return setValueM4Array; // _MAT4 - // buffers + case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL + case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 + case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 + case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + case 0x1405: return setValueV1uiArray; // UINT + case 0x8dc6: return setValueV2uiArray; // _VEC2 + case 0x8dc7: return setValueV3uiArray; // _VEC3 + case 0x8dc8: return setValueV4uiArray; // _VEC4 - // helper variables + case 0x8b5e: // SAMPLER_2D + case 0x8d66: // SAMPLER_EXTERNAL_OES + case 0x8dca: // INT_SAMPLER_2D + case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D + case 0x8b62: // SAMPLER_2D_SHADOW + return setValueT1Array; - var index = 0; - var indexArray = []; - var halfHeight = height / 2; - var groupStart = 0; + case 0x8b5f: // SAMPLER_3D + case 0x8dcb: // INT_SAMPLER_3D + case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D + return setValueT3DArray; - // generate geometry + case 0x8b60: // SAMPLER_CUBE + case 0x8dcc: // INT_SAMPLER_CUBE + case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE + case 0x8dc5: // SAMPLER_CUBE_SHADOW + return setValueT6Array; - generateTorso(); + case 0x8dc1: // SAMPLER_2D_ARRAY + case 0x8dcf: // INT_SAMPLER_2D_ARRAY + case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY + case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW + return setValueT2DArrayArray; - if ( openEnded === false ) { + } - if ( radiusTop > 0 ) { generateCap( true ); } - if ( radiusBottom > 0 ) { generateCap( false ); } +} - } +// --- Uniform Classes --- - // build geometry +class SingleUniform { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + constructor( id, activeInfo, addr ) { - function generateTorso() { + this.id = id; + this.addr = addr; + this.cache = []; + this.type = activeInfo.type; + this.setValue = getSingularSetter( activeInfo.type ); - var x, y; - var normal = new Vector3(); - var vertex = new Vector3(); + // this.path = activeInfo.name; // DEBUG - var groupCount = 0; + } - // this will be used to calculate the normal - var slope = ( radiusBottom - radiusTop ) / height; +} - // generate vertices, normals and uvs +class PureArrayUniform { - for ( y = 0; y <= heightSegments; y ++ ) { + constructor( id, activeInfo, addr ) { - var indexRow = []; + this.id = id; + this.addr = addr; + this.cache = []; + this.type = activeInfo.type; + this.size = activeInfo.size; + this.setValue = getPureArraySetter( activeInfo.type ); - var v = y / heightSegments; + // this.path = activeInfo.name; // DEBUG - // calculate the radius of the current row + } - var radius = v * ( radiusBottom - radiusTop ) + radiusTop; +} - for ( x = 0; x <= radialSegments; x ++ ) { +class StructuredUniform { - var u = x / radialSegments; + constructor( id ) { - var theta = u * thetaLength + thetaStart; + this.id = id; - var sinTheta = Math.sin( theta ); - var cosTheta = Math.cos( theta ); + this.seq = []; + this.map = {}; - // vertex + } - vertex.x = radius * sinTheta; - vertex.y = - v * height + halfHeight; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); + setValue( gl, value, textures ) { - // normal + const seq = this.seq; - normal.set( sinTheta, slope, cosTheta ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - // uv + const u = seq[ i ]; + u.setValue( gl, value[ u.id ], textures ); - uvs.push( u, 1 - v ); + } - // save index of vertex in respective row + } - indexRow.push( index ++ ); +} - } +// --- Top-level --- - // now save vertices of the row in our index array +// Parser - builds up the property tree from the path strings - indexArray.push( indexRow ); +const RePathPart = /(\w+)(\])?(\[|\.)?/g; - } +// extracts +// - the identifier (member name or array index) +// - followed by an optional right bracket (found when array index) +// - followed by an optional left bracket or dot (type of subscript) +// +// Note: These portions can be read in a non-overlapping fashion and +// allow straightforward parsing of the hierarchy that WebGL encodes +// in the uniform names. - // generate indices +function addUniform( container, uniformObject ) { - for ( x = 0; x < radialSegments; x ++ ) { + container.seq.push( uniformObject ); + container.map[ uniformObject.id ] = uniformObject; - for ( y = 0; y < heightSegments; y ++ ) { +} - // we use the index array to access the correct indices +function parseUniform( activeInfo, addr, container ) { - var a = indexArray[ y ][ x ]; - var b = indexArray[ y + 1 ][ x ]; - var c = indexArray[ y + 1 ][ x + 1 ]; - var d = indexArray[ y ][ x + 1 ]; + const path = activeInfo.name, + pathLength = path.length; - // faces + // reset RegExp object, because of the early exit of a previous run + RePathPart.lastIndex = 0; - indices.push( a, b, d ); - indices.push( b, c, d ); + while ( true ) { - // update group counter + const match = RePathPart.exec( path ), + matchEnd = RePathPart.lastIndex; - groupCount += 6; + let id = match[ 1 ]; + const idIsIndex = match[ 2 ] === ']', + subscript = match[ 3 ]; - } + if ( idIsIndex ) id = id | 0; // convert to integer - } + if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { - // add a group to the geometry. this will ensure multi material support + // bare name or "pure" bottom-level array "[0]" suffix - scope.addGroup( groupStart, groupCount, 0 ); + addUniform( container, subscript === undefined ? + new SingleUniform( id, activeInfo, addr ) : + new PureArrayUniform( id, activeInfo, addr ) ); - // calculate new start value for groups + break; - groupStart += groupCount; + } else { - } + // step into inner node / create it in case it doesn't exist - function generateCap( top ) { + const map = container.map; + let next = map[ id ]; - var x, centerIndexStart, centerIndexEnd; + if ( next === undefined ) { - var uv = new Vector2(); - var vertex = new Vector3(); + next = new StructuredUniform( id ); + addUniform( container, next ); - var groupCount = 0; + } - var radius = ( top === true ) ? radiusTop : radiusBottom; - var sign = ( top === true ) ? 1 : - 1; + container = next; - // save the index of the first center vertex - centerIndexStart = index; + } - // first we generate the center vertex data of the cap. - // because the geometry needs one set of uvs per face, - // we must generate a center vertex per face/segment + } - for ( x = 1; x <= radialSegments; x ++ ) { +} - // vertex +// Root Container - vertices.push( 0, halfHeight * sign, 0 ); +class WebGLUniforms { - // normal + constructor( gl, program ) { - normals.push( 0, sign, 0 ); + this.seq = []; + this.map = {}; - // uv + const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); - uvs.push( 0.5, 0.5 ); + for ( let i = 0; i < n; ++ i ) { - // increase index + const info = gl.getActiveUniform( program, i ), + addr = gl.getUniformLocation( program, info.name ); - index ++; + parseUniform( info, addr, this ); } - // save the index of the last center vertex - - centerIndexEnd = index; + } - // now we generate the surrounding vertices, normals and uvs + setValue( gl, name, value, textures ) { - for ( x = 0; x <= radialSegments; x ++ ) { + const u = this.map[ name ]; - var u = x / radialSegments; - var theta = u * thetaLength + thetaStart; + if ( u !== undefined ) u.setValue( gl, value, textures ); - var cosTheta = Math.cos( theta ); - var sinTheta = Math.sin( theta ); + } - // vertex + setOptional( gl, object, name ) { - vertex.x = radius * sinTheta; - vertex.y = halfHeight * sign; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); + const v = object[ name ]; - // normal + if ( v !== undefined ) this.setValue( gl, name, v ); - normals.push( 0, sign, 0 ); + } - // uv + static upload( gl, seq, values, textures ) { - uv.x = ( cosTheta * 0.5 ) + 0.5; - uv.y = ( sinTheta * 0.5 * sign ) + 0.5; - uvs.push( uv.x, uv.y ); + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - // increase index + const u = seq[ i ], + v = values[ u.id ]; - index ++; + if ( v.needsUpdate !== false ) { - } + // note: always updating when .needsUpdate is undefined + u.setValue( gl, v.value, textures ); - // generate indices + } - for ( x = 0; x < radialSegments; x ++ ) { + } - var c = centerIndexStart + x; - var i = centerIndexEnd + x; + } - if ( top === true ) { + static seqWithValue( seq, values ) { - // face top + const r = []; - indices.push( i, i + 1, c ); + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - } else { + const u = seq[ i ]; + if ( u.id in values ) r.push( u ); - // face bottom + } - indices.push( i + 1, i, c ); + return r; - } + } - groupCount += 3; +} - } +function WebGLShader( gl, type, string ) { - // add a group to the geometry. this will ensure multi material support + const shader = gl.createShader( type ); - scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); + gl.shaderSource( shader, string ); + gl.compileShader( shader ); - // calculate new start value for groups + return shader; - groupStart += groupCount; +} - } +// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ +const COMPLETION_STATUS_KHR = 0x91B1; -} +let programIdCount = 0; -CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry; +function handleSource( string, errorLine ) { -/** - * @author abelnation / http://github.com/abelnation - */ + const lines = string.split( '\n' ); + const lines2 = []; -// ConeGeometry + const from = Math.max( errorLine - 6, 0 ); + const to = Math.min( errorLine + 6, lines.length ); -function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + for ( let i = from; i < to; i ++ ) { - CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + const line = i + 1; + lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); - this.type = 'ConeGeometry'; + } - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + return lines2.join( '\n' ); } -ConeGeometry.prototype = Object.create( CylinderGeometry.prototype ); -ConeGeometry.prototype.constructor = ConeGeometry; +function getEncodingComponents( colorSpace ) { -// ConeBufferGeometry + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const encodingPrimaries = ColorManagement.getPrimaries( colorSpace ); -function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + let gamutMapping; - CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + if ( workingPrimaries === encodingPrimaries ) { - this.type = 'ConeBufferGeometry'; + gamutMapping = ''; - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + } else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) { -} + gamutMapping = 'LinearDisplayP3ToLinearSRGB'; -ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype ); -ConeBufferGeometry.prototype.constructor = ConeBufferGeometry; + } else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - * @author hughes - */ + gamutMapping = 'LinearSRGBToLinearDisplayP3'; -// CircleGeometry + } -function CircleGeometry( radius, segments, thetaStart, thetaLength ) { + switch ( colorSpace ) { - Geometry.call( this ); + case LinearSRGBColorSpace: + case LinearDisplayP3ColorSpace: + return [ gamutMapping, 'LinearTransferOETF' ]; - this.type = 'CircleGeometry'; + case SRGBColorSpace: + case DisplayP3ColorSpace: + return [ gamutMapping, 'sRGBTransferOETF' ]; - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + default: + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); + return [ gamutMapping, 'LinearTransferOETF' ]; - this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) ); - this.mergeVertices(); + } } -CircleGeometry.prototype = Object.create( Geometry.prototype ); -CircleGeometry.prototype.constructor = CircleGeometry; +function getShaderErrors( gl, shader, type ) { -// CircleBufferGeometry + const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); + const errors = gl.getShaderInfoLog( shader ).trim(); -function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) { + if ( status && errors === '' ) return ''; - BufferGeometry.call( this ); + const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); + if ( errorMatches ) { - this.type = 'CircleBufferGeometry'; + // --enable-privileged-webgl-extension + // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + const errorLine = parseInt( errorMatches[ 1 ] ); + return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); - radius = radius || 1; - segments = segments !== undefined ? Math.max( 3, segments ) : 8; + } else { - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + return errors; - // buffers + } - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; +} - // helper variables +function getTexelEncodingFunction( functionName, colorSpace ) { - var i, s; - var vertex = new Vector3(); - var uv = new Vector2(); + const components = getEncodingComponents( colorSpace ); + return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`; - // center point +} - vertices.push( 0, 0, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( 0.5, 0.5 ); +function getToneMappingFunction( functionName, toneMapping ) { - for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) { + let toneMappingName; - var segment = thetaStart + s / segments * thetaLength; + switch ( toneMapping ) { - // vertex + case LinearToneMapping: + toneMappingName = 'Linear'; + break; - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); + case ReinhardToneMapping: + toneMappingName = 'Reinhard'; + break; - vertices.push( vertex.x, vertex.y, vertex.z ); + case CineonToneMapping: + toneMappingName = 'OptimizedCineon'; + break; - // normal + case ACESFilmicToneMapping: + toneMappingName = 'ACESFilmic'; + break; - normals.push( 0, 0, 1 ); + case AgXToneMapping: + toneMappingName = 'AgX'; + break; - // uvs + case NeutralToneMapping: + toneMappingName = 'Neutral'; + break; - uv.x = ( vertices[ i ] / radius + 1 ) / 2; - uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; + case CustomToneMapping: + toneMappingName = 'Custom'; + break; - uvs.push( uv.x, uv.y ); + default: + console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); + toneMappingName = 'Linear'; } - // indices + return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; - for ( i = 1; i <= segments; i ++ ) { +} - indices.push( i, i + 1, 0 ); +const _v0$1 = /*@__PURE__*/ new Vector3(); - } +function getLuminanceFunction() { - // build geometry + ColorManagement.getLuminanceCoefficients( _v0$1 ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + const r = _v0$1.x.toFixed( 4 ); + const g = _v0$1.y.toFixed( 4 ); + const b = _v0$1.z.toFixed( 4 ); -} + return [ -CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -CircleBufferGeometry.prototype.constructor = CircleBufferGeometry; + 'float luminance( const in vec3 rgb ) {', + ` const vec3 weights = vec3( ${ r }, ${ g }, ${ b } );`, + ' return dot( weights, rgb );', -var Geometries = Object.freeze({ - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry -}); + '}' -/** - * @author mrdoob / http://mrdoob.com/ - * - * parameters = { - * color: , - * opacity: - * } - */ + ].join( '\n' ); -function ShadowMaterial( parameters ) { +} - Material.call( this ); +function generateVertexExtensions( parameters ) { - this.type = 'ShadowMaterial'; + const chunks = [ + parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '', + parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '', + ]; - this.color = new Color( 0x000000 ); - this.opacity = 1.0; + return chunks.filter( filterEmptyLine ).join( '\n' ); - this.lights = true; - this.transparent = true; +} - this.setValues( parameters ); +function generateDefines( defines ) { -} + const chunks = []; -ShadowMaterial.prototype = Object.create( Material.prototype ); -ShadowMaterial.prototype.constructor = ShadowMaterial; + for ( const name in defines ) { -ShadowMaterial.prototype.isShadowMaterial = true; + const value = defines[ name ]; -/** - * @author mrdoob / http://mrdoob.com/ - */ + if ( value === false ) continue; -function RawShaderMaterial( parameters ) { + chunks.push( '#define ' + name + ' ' + value ); - ShaderMaterial.call( this, parameters ); + } - this.type = 'RawShaderMaterial'; + return chunks.join( '\n' ); } -RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype ); -RawShaderMaterial.prototype.constructor = RawShaderMaterial; +function fetchAttributeLocations( gl, program ) { -RawShaderMaterial.prototype.isRawShaderMaterial = true; + const attributes = {}; -/** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * color: , - * roughness: , - * metalness: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * roughnessMap: new THREE.Texture( ), - * - * metalnessMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), - * envMapIntensity: - * - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); + + for ( let i = 0; i < n; i ++ ) { -function MeshStandardMaterial( parameters ) { + const info = gl.getActiveAttrib( program, i ); + const name = info.name; - Material.call( this ); + 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; - this.defines = { 'STANDARD': '' }; + // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); + + attributes[ name ] = { + type: info.type, + location: gl.getAttribLocation( program, name ), + locationSize: locationSize + }; - this.type = 'MeshStandardMaterial'; + } - this.color = new Color( 0xffffff ); // diffuse - this.roughness = 0.5; - this.metalness = 0.5; + return attributes; - this.map = null; +} - this.lightMap = null; - this.lightMapIntensity = 1.0; +function filterEmptyLine( string ) { - this.aoMap = null; - this.aoMapIntensity = 1.0; + return string !== ''; - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; +} - this.bumpMap = null; - this.bumpScale = 1; +function replaceLightNums( string, parameters ) { - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + return string + .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) + .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) + .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) + .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) + .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_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) + .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) + .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); - this.roughnessMap = null; +} - this.metalnessMap = null; +function replaceClippingPlaneNums( string, parameters ) { - this.alphaMap = null; + return string + .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) + .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); - this.envMap = null; - this.envMapIntensity = 1.0; +} - this.refractionRatio = 0.98; +// Resolve Includes - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; +const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; +function resolveIncludes( string ) { - this.setValues( parameters ); + return string.replace( includePattern, includeReplacer ); } -MeshStandardMaterial.prototype = Object.create( Material.prototype ); -MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; +const shaderChunkMap = new Map(); -MeshStandardMaterial.prototype.isMeshStandardMaterial = true; +function includeReplacer( match, include ) { -MeshStandardMaterial.prototype.copy = function ( source ) { + let string = ShaderChunk[ include ]; - Material.prototype.copy.call( this, source ); + if ( string === undefined ) { - this.defines = { 'STANDARD': '' }; + const newInclude = shaderChunkMap.get( include ); - this.color.copy( source.color ); - this.roughness = source.roughness; - this.metalness = source.metalness; + if ( newInclude !== undefined ) { - this.map = source.map; + string = ShaderChunk[ newInclude ]; + console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + } else { - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + throw new Error( 'Can not resolve #include <' + include + '>' ); - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + } - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + } - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + return resolveIncludes( string ); - this.roughnessMap = source.roughnessMap; +} - this.metalnessMap = source.metalnessMap; +// Unroll Loops - this.alphaMap = source.alphaMap; +const 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; - this.envMap = source.envMap; - this.envMapIntensity = source.envMapIntensity; +function unrollLoops( string ) { - this.refractionRatio = source.refractionRatio; + return string.replace( unrollLoopPattern, loopReplacer ); - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; +} - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; +function loopReplacer( match, start, end, snippet ) { - return this; + let string = ''; -}; + for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { -/** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * reflectivity: - * } - */ + string += snippet + .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) + .replace( /UNROLLED_LOOP_INDEX/g, i ); -function MeshPhysicalMaterial( parameters ) { + } - MeshStandardMaterial.call( this ); + return string; - this.defines = { 'PHYSICAL': '' }; +} - this.type = 'MeshPhysicalMaterial'; +// - this.reflectivity = 0.5; // maps to F0 = 0.04 +function generatePrecision( parameters ) { - this.clearCoat = 0.0; - this.clearCoatRoughness = 0.0; + let precisionstring = `precision ${parameters.precision} float; + precision ${parameters.precision} int; + precision ${parameters.precision} sampler2D; + precision ${parameters.precision} samplerCube; + precision ${parameters.precision} sampler3D; + precision ${parameters.precision} sampler2DArray; + precision ${parameters.precision} sampler2DShadow; + precision ${parameters.precision} samplerCubeShadow; + precision ${parameters.precision} sampler2DArrayShadow; + precision ${parameters.precision} isampler2D; + precision ${parameters.precision} isampler3D; + precision ${parameters.precision} isamplerCube; + precision ${parameters.precision} isampler2DArray; + precision ${parameters.precision} usampler2D; + precision ${parameters.precision} usampler3D; + precision ${parameters.precision} usamplerCube; + precision ${parameters.precision} usampler2DArray; + `; - this.setValues( parameters ); + if ( parameters.precision === 'highp' ) { -} + precisionstring += '\n#define HIGH_PRECISION'; -MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); -MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; + } else if ( parameters.precision === 'mediump' ) { -MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; + precisionstring += '\n#define MEDIUM_PRECISION'; -MeshPhysicalMaterial.prototype.copy = function ( source ) { + } else if ( parameters.precision === 'lowp' ) { - MeshStandardMaterial.prototype.copy.call( this, source ); + precisionstring += '\n#define LOW_PRECISION'; - this.defines = { 'PHYSICAL': '' }; + } - this.reflectivity = source.reflectivity; + return precisionstring; - this.clearCoat = source.clearCoat; - this.clearCoatRoughness = source.clearCoatRoughness; +} - return this; +function generateShadowMapTypeDefine( parameters ) { -}; + let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * specular: , - * shininess: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + if ( parameters.shadowMapType === PCFShadowMap ) { -function MeshPhongMaterial( parameters ) { + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; - Material.call( this ); + } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { - this.type = 'MeshPhongMaterial'; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; - this.color = new Color( 0xffffff ); // diffuse - this.specular = new Color( 0x111111 ); - this.shininess = 30; + } else if ( parameters.shadowMapType === VSMShadowMap ) { - this.map = null; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; - this.lightMap = null; - this.lightMapIntensity = 1.0; + } - this.aoMap = null; - this.aoMapIntensity = 1.0; + return shadowMapTypeDefine; - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; +} - this.bumpMap = null; - this.bumpScale = 1; +function generateEnvMapTypeDefine( parameters ) { - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + if ( parameters.envMap ) { - this.specularMap = null; + switch ( parameters.envMapMode ) { - this.alphaMap = null; + case CubeReflectionMapping: + case CubeRefractionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; + break; - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + case CubeUVReflectionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; + break; - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + } - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + } - this.setValues( parameters ); + return envMapTypeDefine; } -MeshPhongMaterial.prototype = Object.create( Material.prototype ); -MeshPhongMaterial.prototype.constructor = MeshPhongMaterial; +function generateEnvMapModeDefine( parameters ) { -MeshPhongMaterial.prototype.isMeshPhongMaterial = true; + let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; -MeshPhongMaterial.prototype.copy = function ( source ) { + if ( parameters.envMap ) { - Material.prototype.copy.call( this, source ); + switch ( parameters.envMapMode ) { - this.color.copy( source.color ); - this.specular.copy( source.specular ); - this.shininess = source.shininess; + case CubeRefractionMapping: - this.map = source.map; + envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; + break; - 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; + return envMapModeDefine; - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; +} - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); +function generateEnvMapBlendingDefine( parameters ) { - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; - this.specularMap = source.specularMap; + if ( parameters.envMap ) { - this.alphaMap = source.alphaMap; + switch ( parameters.combine ) { - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + case MultiplyOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + break; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + case MixOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; + break; - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + case AddOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; + break; - return this; + } -}; + } -/** - * @author takahirox / http://github.com/takahirox - * - * parameters = { - * gradientMap: new THREE.Texture( ) - * } - */ + return envMapBlendingDefine; -function MeshToonMaterial( parameters ) { +} - MeshPhongMaterial.call( this ); +function generateCubeUVSize( parameters ) { - this.defines = { 'TOON': '' }; + const imageHeight = parameters.envMapCubeUVHeight; - this.type = 'MeshToonMaterial'; + if ( imageHeight === null ) return null; - this.gradientMap = null; + const maxMip = Math.log2( imageHeight ) - 2; - this.setValues( parameters ); + const texelHeight = 1.0 / imageHeight; -} + const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); -MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype ); -MeshToonMaterial.prototype.constructor = MeshToonMaterial; + return { texelWidth, texelHeight, maxMip }; -MeshToonMaterial.prototype.isMeshToonMaterial = true; +} -MeshToonMaterial.prototype.copy = function ( source ) { +function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { - MeshPhongMaterial.prototype.copy.call( this, source ); + // TODO Send this event to Three.js DevTools + // console.log( 'WebGLProgram', cacheKey ); - this.gradientMap = source.gradientMap; + const gl = renderer.getContext(); - return this; + const defines = parameters.defines; -}; + let vertexShader = parameters.vertexShader; + let fragmentShader = parameters.fragmentShader; -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * opacity: , - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * wireframe: , - * wireframeLinewidth: - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); + const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); + const envMapModeDefine = generateEnvMapModeDefine( parameters ); + const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); + const envMapCubeUVSize = generateCubeUVSize( parameters ); -function MeshNormalMaterial( parameters ) { + const customVertexExtensions = generateVertexExtensions( parameters ); - Material.call( this ); + const customDefines = generateDefines( defines ); - this.type = 'MeshNormalMaterial'; + const program = gl.createProgram(); - this.bumpMap = null; - this.bumpScale = 1; + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + if ( parameters.isRawShaderMaterial ) { - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + prefixVertex = [ - this.wireframe = false; - this.wireframeLinewidth = 1; + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - this.fog = false; - this.lights = false; + customDefines - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + ].filter( filterEmptyLine ).join( '\n' ); - this.setValues( parameters ); + if ( prefixVertex.length > 0 ) { -} + prefixVertex += '\n'; -MeshNormalMaterial.prototype = Object.create( Material.prototype ); -MeshNormalMaterial.prototype.constructor = MeshNormalMaterial; + } -MeshNormalMaterial.prototype.isMeshNormalMaterial = true; + prefixFragment = [ -MeshNormalMaterial.prototype.copy = function ( source ) { + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - Material.prototype.copy.call( this, source ); + customDefines - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + ].filter( filterEmptyLine ).join( '\n' ); - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + if ( prefixFragment.length > 0 ) { - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + prefixFragment += '\n'; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; + } - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + } else { - return this; + prefixVertex = [ -}; + generatePrecision( parameters ), -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, -function MeshLambertMaterial( parameters ) { + customDefines, - Material.call( this ); + parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', + parameters.batching ? '#define USE_BATCHING' : '', + parameters.batchingColor ? '#define USE_BATCHING_COLOR' : '', + parameters.instancing ? '#define USE_INSTANCING' : '', + parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', + parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '', - this.type = 'MeshLambertMaterial'; + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', - this.color = new Color( 0xffffff ); // diffuse + 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.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', - this.map = null; + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', - this.lightMap = null; - this.lightMapIntensity = 1.0; + parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', + parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', + parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', - this.aoMap = null; - this.aoMapIntensity = 1.0; + parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', + parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', - this.specularMap = null; + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', + parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.alphaHash ? '#define USE_ALPHAHASH' : '', - this.alphaMap = null; + parameters.transmission ? '#define USE_TRANSMISSION' : '', + parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', + parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + // - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', - this.setValues( parameters ); + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', -} + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', -MeshLambertMaterial.prototype = Object.create( Material.prototype ); -MeshLambertMaterial.prototype.constructor = MeshLambertMaterial; + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', -MeshLambertMaterial.prototype.isMeshLambertMaterial = true; + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', -MeshLambertMaterial.prototype.copy = function ( source ) { + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', - Material.prototype.copy.call( this, source ); + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', - this.color.copy( source.color ); + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', - this.map = source.map; + // - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', + parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + parameters.flatShading ? '#define FLAT_SHADED' : '', - this.specularMap = source.specularMap; + parameters.skinning ? '#define USE_SKINNING' : '', - this.alphaMap = source.alphaMap; + parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', + parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', + ( parameters.morphColors ) ? '#define USE_MORPHCOLORS' : '', + ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', + ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', - return this; + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', -}; + 'uniform mat4 modelMatrix;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'uniform mat4 viewMatrix;', + 'uniform mat3 normalMatrix;', + 'uniform vec3 cameraPosition;', + 'uniform bool isOrthographic;', -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * - * scale: , - * dashSize: , - * gapSize: - * } - */ + '#ifdef USE_INSTANCING', -function LineDashedMaterial( parameters ) { + ' attribute mat4 instanceMatrix;', - LineBasicMaterial.call( this ); + '#endif', - this.type = 'LineDashedMaterial'; + '#ifdef USE_INSTANCING_COLOR', - this.scale = 1; - this.dashSize = 3; - this.gapSize = 1; + ' attribute vec3 instanceColor;', - this.setValues( parameters ); + '#endif', -} + '#ifdef USE_INSTANCING_MORPH', -LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); -LineDashedMaterial.prototype.constructor = LineDashedMaterial; + ' uniform sampler2D morphTexture;', -LineDashedMaterial.prototype.isLineDashedMaterial = true; + '#endif', -LineDashedMaterial.prototype.copy = function ( source ) { + 'attribute vec3 position;', + 'attribute vec3 normal;', + 'attribute vec2 uv;', - LineBasicMaterial.prototype.copy.call( this, source ); + '#ifdef USE_UV1', - this.scale = source.scale; - this.dashSize = source.dashSize; - this.gapSize = source.gapSize; + ' attribute vec2 uv1;', - return this; + '#endif', -}; + '#ifdef USE_UV2', + ' attribute vec2 uv2;', + '#endif', -var Materials = Object.freeze({ - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material -}); + '#ifdef USE_UV3', -/** - * @author mrdoob / http://mrdoob.com/ - */ + ' attribute vec2 uv3;', -var Cache = { + '#endif', - enabled: false, + '#ifdef USE_TANGENT', - files: {}, + ' attribute vec4 tangent;', - add: function ( key, file ) { + '#endif', - if ( this.enabled === false ) { return; } + '#if defined( USE_COLOR_ALPHA )', - // console.log( 'THREE.Cache', 'Adding key:', key ); + ' attribute vec4 color;', - this.files[ key ] = file; + '#elif defined( USE_COLOR )', - }, + ' attribute vec3 color;', - get: function ( key ) { + '#endif', - if ( this.enabled === false ) { return; } + '#ifdef USE_SKINNING', - // console.log( 'THREE.Cache', 'Checking key:', key ); + ' attribute vec4 skinIndex;', + ' attribute vec4 skinWeight;', - return this.files[ key ]; + '#endif', - }, + '\n' - remove: function ( key ) { + ].filter( filterEmptyLine ).join( '\n' ); - delete this.files[ key ]; + prefixFragment = [ - }, + generatePrecision( parameters ), - clear: function () { + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - this.files = {}; + customDefines, - } + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', -}; + parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '', + 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.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', -/** - * @author mrdoob / http://mrdoob.com/ - */ + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', -function LoadingManager( onLoad, onProgress, onError ) { + parameters.clearcoat ? '#define USE_CLEARCOAT' : '', + parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', + parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', + parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', - var scope = this; + parameters.dispersion ? '#define USE_DISPERSION' : '', - var isLoading = false; - var itemsLoaded = 0; - var itemsTotal = 0; - var urlModifier = undefined; + parameters.iridescence ? '#define USE_IRIDESCENCE' : '', + parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', + parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', - this.itemStart = function ( url ) { + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', + parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - itemsTotal ++; + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.alphaTest ? '#define USE_ALPHATEST' : '', + parameters.alphaHash ? '#define USE_ALPHAHASH' : '', - if ( isLoading === false ) { + parameters.sheen ? '#define USE_SHEEN' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', - if ( scope.onStart !== undefined ) { + parameters.transmission ? '#define USE_TRANSMISSION' : '', + parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', + parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - scope.onStart( url, itemsLoaded, itemsTotal ); + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', + parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '', + parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', - } + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', - } + parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', - isLoading = true; + parameters.flatShading ? '#define FLAT_SHADED' : '', - }; + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - this.itemEnd = function ( url ) { + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - itemsLoaded ++; + parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - if ( scope.onProgress !== undefined ) { + parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', - scope.onProgress( url, itemsLoaded, itemsTotal ); + parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - } + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - if ( itemsLoaded === itemsTotal ) { + 'uniform mat4 viewMatrix;', + 'uniform vec3 cameraPosition;', + 'uniform bool isOrthographic;', - isLoading = false; + ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', + ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below + ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', - if ( scope.onLoad !== undefined ) { + parameters.dithering ? '#define DITHERING' : '', + parameters.opaque ? '#define OPAQUE' : '', - scope.onLoad(); + ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), + getLuminanceFunction(), - } + parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', - } + '\n' - }; + ].filter( filterEmptyLine ).join( '\n' ); - this.itemError = function ( url ) { + } - if ( scope.onError !== undefined ) { + vertexShader = resolveIncludes( vertexShader ); + vertexShader = replaceLightNums( vertexShader, parameters ); + vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); - scope.onError( url ); + fragmentShader = resolveIncludes( fragmentShader ); + fragmentShader = replaceLightNums( fragmentShader, parameters ); + fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); - } + vertexShader = unrollLoops( vertexShader ); + fragmentShader = unrollLoops( fragmentShader ); - }; + if ( parameters.isRawShaderMaterial !== true ) { - this.resolveURL = function ( url ) { + // GLSL 3.0 conversion for built-in materials and ShaderMaterial - if ( urlModifier ) { + versionString = '#version 300 es\n'; - return urlModifier( url ); + prefixVertex = [ + customVertexExtensions, + '#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; - return url; + // console.log( '*VERTEX*', vertexGlsl ); + // console.log( '*FRAGMENT*', fragmentGlsl ); - }; + const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); + const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); - this.setURLModifier = function ( transform ) { + gl.attachShader( program, glVertexShader ); + gl.attachShader( program, glFragmentShader ); - urlModifier = transform; - return this; + // Force a particular attribute to index 0. - }; + if ( parameters.index0AttributeName !== undefined ) { -} + gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); -var DefaultLoadingManager = new LoadingManager(); + } else if ( parameters.morphTargets === true ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + // programs with morphTargets displace position out of attribute 0 + gl.bindAttribLocation( program, 0, 'position' ); -var loading = {}; + } -function FileLoader( manager ) { + gl.linkProgram( program ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + function onFirstUse( self ) { -} + // check for link errors + if ( renderer.debug.checkShaderErrors ) { -Object.assign( FileLoader.prototype, { + const programLog = gl.getProgramInfoLog( program ).trim(); + const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); + const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); - load: function ( url, onLoad, onProgress, onError ) { + let runnable = true; + let haveDiagnostics = true; - if ( url === undefined ) { url = ''; } + if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { - if ( this.path !== undefined ) { url = this.path + url; } + runnable = false; - url = this.manager.resolveURL( url ); + if ( typeof renderer.debug.onShaderError === 'function' ) { - var scope = this; + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); - var cached = Cache.get( url ); + } else { - if ( cached !== undefined ) { + // default error reporting - scope.manager.itemStart( url ); + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); - setTimeout( function () { + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Material Name: ' + self.name + '\n' + + 'Material Type: ' + self.type + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); - if ( onLoad ) { onLoad( cached ); } + } - scope.manager.itemEnd( url ); + } else if ( programLog !== '' ) { - }, 0 ); + console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); - return cached; + } else if ( vertexLog === '' || fragmentLog === '' ) { - } + haveDiagnostics = false; - // Check if request is duplicate + } - if ( loading[ url ] !== undefined ) { + if ( haveDiagnostics ) { - loading[ url ].push( { + self.diagnostics = { - onLoad: onLoad, - onProgress: onProgress, - onError: onError + runnable: runnable, - } ); + programLog: programLog, - return; + vertexShader: { - } + log: vertexLog, + prefix: prefixVertex - // Check for data: URI - var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/; - var dataUriRegexResult = url.match( dataUriRegex ); + }, - // Safari can not handle Data URIs through XMLHttpRequest so process manually - if ( dataUriRegexResult ) { + fragmentShader: { - var mimeType = dataUriRegexResult[ 1 ]; - var isBase64 = !! dataUriRegexResult[ 2 ]; - var data = dataUriRegexResult[ 3 ]; + log: fragmentLog, + prefix: prefixFragment - data = window.decodeURIComponent( data ); + } - if ( isBase64 ) { data = window.atob( data ); } + }; - try { + } - var response; - var responseType = ( this.responseType || '' ).toLowerCase(); + } - switch ( responseType ) { + // Clean up - case 'arraybuffer': - case 'blob': + // Crashes in iOS9 and iOS10. #18402 + // gl.detachShader( program, glVertexShader ); + // gl.detachShader( program, glFragmentShader ); - var view = new Uint8Array( data.length ); + gl.deleteShader( glVertexShader ); + gl.deleteShader( glFragmentShader ); - for ( var i = 0; i < data.length; i ++ ) { + cachedUniforms = new WebGLUniforms( gl, program ); + cachedAttributes = fetchAttributeLocations( gl, program ); - view[ i ] = data.charCodeAt( i ); + } - } + // set up caching for uniform locations - if ( responseType === 'blob' ) { + let cachedUniforms; - response = new Blob( [ view.buffer ], { type: mimeType } ); + this.getUniforms = function () { - } else { + if ( cachedUniforms === undefined ) { - response = view.buffer; + // Populates cachedUniforms and cachedAttributes + onFirstUse( this ); - } + } - break; + return cachedUniforms; - case 'document': + }; - var parser = new DOMParser(); - response = parser.parseFromString( data, mimeType ); + // set up caching for attribute locations - break; + let cachedAttributes; - case 'json': + this.getAttributes = function () { - response = JSON.parse( data ); + if ( cachedAttributes === undefined ) { - break; + // Populates cachedAttributes and cachedUniforms + onFirstUse( this ); - default: // 'text' or other + } - response = data; + return cachedAttributes; - break; + }; - } + // indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported, + // flag the program as ready immediately. It may cause a stall when it's first used. - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { + let programReady = ( parameters.rendererExtensionParallelShaderCompile === false ); - if ( onLoad ) { onLoad( response ); } + this.isReady = function () { - scope.manager.itemEnd( url ); + if ( programReady === false ) { - }, 0 ); + programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR ); - } catch ( error ) { + } - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { + return programReady; - if ( onError ) { onError( error ); } + }; - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + // free resource - }, 0 ); + this.destroy = function () { - } + bindingStates.releaseStatesOfProgram( this ); - } else { + gl.deleteProgram( program ); + this.program = undefined; - // Initialise array for duplicate requests + }; - loading[ url ] = []; + // - loading[ url ].push( { + this.type = parameters.shaderType; + this.name = parameters.shaderName; + this.id = programIdCount ++; + this.cacheKey = cacheKey; + this.usedTimes = 1; + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; - onLoad: onLoad, - onProgress: onProgress, - onError: onError + return this; - } ); +} - var request = new XMLHttpRequest(); +let _id$1 = 0; - request.open( 'GET', url, true ); +class WebGLShaderCache { - request.addEventListener( 'load', function ( event ) { + constructor() { - var response = this.response; + this.shaderCache = new Map(); + this.materialCache = new Map(); - Cache.add( url, response ); + } - var callbacks = loading[ url ]; + update( material ) { - delete loading[ url ]; + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; - if ( this.status === 200 ) { + const vertexShaderStage = this._getShaderStage( vertexShader ); + const fragmentShaderStage = this._getShaderStage( fragmentShader ); - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + const materialShaders = this._getShaderCacheForMaterial( material ); - var callback = callbacks[ i ]; - if ( callback.onLoad ) { callback.onLoad( response ); } + if ( materialShaders.has( vertexShaderStage ) === false ) { - } + materialShaders.add( vertexShaderStage ); + vertexShaderStage.usedTimes ++; - scope.manager.itemEnd( url ); + } - } else if ( this.status === 0 ) { + if ( materialShaders.has( fragmentShaderStage ) === false ) { - // Some browsers return HTTP Status 0 when using non-http protocol - // e.g. 'file://' or 'data://'. Handle as success. + materialShaders.add( fragmentShaderStage ); + fragmentShaderStage.usedTimes ++; - console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); + } - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + return this; - var callback = callbacks[ i ]; - if ( callback.onLoad ) { callback.onLoad( response ); } + } - } + remove( material ) { - scope.manager.itemEnd( url ); + const materialShaders = this.materialCache.get( material ); - } else { + for ( const shaderStage of materialShaders ) { - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + shaderStage.usedTimes --; - var callback = callbacks[ i ]; - if ( callback.onError ) { callback.onError( event ); } + if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); - } + } - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + this.materialCache.delete( material ); - } + return this; - }, false ); + } - request.addEventListener( 'progress', function ( event ) { + getVertexShaderID( material ) { - var callbacks = loading[ url ]; + return this._getShaderStage( material.vertexShader ).id; - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + } - var callback = callbacks[ i ]; - if ( callback.onProgress ) { callback.onProgress( event ); } + getFragmentShaderID( material ) { - } + return this._getShaderStage( material.fragmentShader ).id; - }, false ); + } - request.addEventListener( 'error', function ( event ) { + dispose() { - var callbacks = loading[ url ]; + this.shaderCache.clear(); + this.materialCache.clear(); - delete loading[ url ]; + } - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + _getShaderCacheForMaterial( material ) { - var callback = callbacks[ i ]; - if ( callback.onError ) { callback.onError( event ); } + const cache = this.materialCache; + let set = cache.get( material ); - } + if ( set === undefined ) { - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + set = new Set(); + cache.set( material, set ); - }, false ); + } - if ( this.responseType !== undefined ) { request.responseType = this.responseType; } - if ( this.withCredentials !== undefined ) { request.withCredentials = this.withCredentials; } + return set; - if ( request.overrideMimeType ) { request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); } + } - for ( var header in this.requestHeader ) { + _getShaderStage( code ) { - request.setRequestHeader( header, this.requestHeader[ header ] ); + const cache = this.shaderCache; + let stage = cache.get( code ); - } + if ( stage === undefined ) { - request.send( null ); + stage = new WebGLShaderStage( code ); + cache.set( code, stage ); } - scope.manager.itemStart( url ); + return stage; - return request; + } - }, +} - setPath: function ( value ) { +class WebGLShaderStage { - this.path = value; - return this; + constructor( code ) { - }, + this.id = _id$1 ++; - setResponseType: function ( value ) { + this.code = code; + this.usedTimes = 0; - this.responseType = value; - return this; + } - }, +} - setWithCredentials: function ( value ) { +function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { - this.withCredentials = value; - return this; + const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); + const _activeChannels = new Set(); + const programs = []; - }, + const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; - setMimeType: function ( value ) { + let precision = capabilities.precision; - this.mimeType = value; - return this; + 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 getChannel( value ) { - setRequestHeader: function ( value ) { + _activeChannels.add( value ); - this.requestHeader = value; - return this; + if ( value === 0 ) return 'uv'; + + return `uv${ value }`; } -} ); + function getParameters( material, lights, shadows, scene, object ) { -/** - * @author mrdoob / http://mrdoob.com/ - * - * Abstract Base class to block based textures loader (dds, pvr, ...) - */ + 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; -function CompressedTextureLoader( manager ) { + const shaderID = shaderIDs[ material.type ]; - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + // heuristics to create shader parameters according to lights in the scene + // (not to blow over maxLights budget) - // override in sub classes - this._parser = null; + if ( material.precision !== null ) { -} + precision = capabilities.getMaxPrecision( material.precision ); -Object.assign( CompressedTextureLoader.prototype, { + if ( precision !== material.precision ) { - load: function ( url, onLoad, onProgress, onError ) { + console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); - var scope = this; + } - var images = []; + } - var texture = new CompressedTexture(); - texture.image = images; + // - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - function loadTexture( i ) { + let morphTextureStride = 0; - loader.load( url[ i ], function ( buffer ) { + if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; + if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; + if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; - var texDatas = scope._parser( buffer, true ); + // - images[ i ] = { - width: texDatas.width, - height: texDatas.height, - format: texDatas.format, - mipmaps: texDatas.mipmaps - }; + let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; - loaded += 1; + if ( shaderID ) { - if ( loaded === 6 ) { + const shader = ShaderLib[ shaderID ]; - if ( texDatas.mipmapCount === 1 ) - { texture.minFilter = LinearFilter; } + vertexShader = shader.vertexShader; + fragmentShader = shader.fragmentShader; - texture.format = texDatas.format; - texture.needsUpdate = true; + } else { - if ( onLoad ) { onLoad( texture ); } + vertexShader = material.vertexShader; + fragmentShader = material.fragmentShader; - } + _customShaders.update( material ); - }, onProgress, onError ); + customVertexShaderID = _customShaders.getVertexShaderID( material ); + customFragmentShaderID = _customShaders.getFragmentShaderID( material ); } - if ( Array.isArray( url ) ) { + const currentRenderTarget = renderer.getRenderTarget(); - var loaded = 0; + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + const IS_BATCHEDMESH = object.isBatchedMesh === true; - for ( var i = 0, il = url.length; i < il; ++ i ) { + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; - loadTexture( i ); + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; - } + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_DISPERSION = material.dispersion > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; - } else { + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; - // compressed cubemap texture stored in a single DDS file + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; - loader.load( url, function ( buffer ) { + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; - var texDatas = scope._parser( buffer, true ); + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; - if ( texDatas.isCubemap ) { + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; - var faces = texDatas.mipmaps.length / texDatas.mipmapCount; + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; - for ( var f = 0; f < faces; f ++ ) { + const HAS_GRADIENTMAP = !! material.gradientMap; - images[ f ] = { mipmaps: [] }; + const HAS_ALPHAMAP = !! material.alphaMap; - for ( var i = 0; i < texDatas.mipmapCount; i ++ ) { + const HAS_ALPHATEST = material.alphaTest > 0; - 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; + const HAS_ALPHAHASH = !! material.alphaHash; - } + const HAS_EXTENSIONS = !! material.extensions; - } + let toneMapping = NoToneMapping; - } else { + if ( material.toneMapped ) { - texture.image.width = texDatas.width; - texture.image.height = texDatas.height; - texture.mipmaps = texDatas.mipmaps; + if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) { - } + toneMapping = renderer.toneMapping; - if ( texDatas.mipmapCount === 1 ) { + } - texture.minFilter = LinearFilter; + } - } + const parameters = { - texture.format = texDatas.format; - texture.needsUpdate = true; + shaderID: shaderID, + shaderType: material.type, + shaderName: material.name, - if ( onLoad ) { onLoad( texture ); } + vertexShader: vertexShader, + fragmentShader: fragmentShader, + defines: material.defines, - }, onProgress, onError ); + customVertexShaderID: customVertexShaderID, + customFragmentShaderID: customFragmentShaderID, - } + isRawShaderMaterial: material.isRawShaderMaterial === true, + glslVersion: material.glslVersion, - return texture; + precision: precision, - }, + batching: IS_BATCHEDMESH, + batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, + instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, - setPath: function ( value ) { + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), + alphaToCoverage: !! material.alphaToCoverage, - this.path = value; - return this; + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, + envMapCubeUVHeight: envMapCubeUVHeight, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - } + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, -} ); + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, -/** - * @author Nikos M. / https://github.com/foo123/ - * - * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) - */ + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, -function DataTextureLoader( manager ) { + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + dispersion: HAS_DISPERSION, - // override in sub classes - this._parser = null; + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, -} + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, -Object.assign( DataTextureLoader.prototype, { + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, - load: function ( url, onLoad, onProgress, onError ) { + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, - var scope = this; + gradientMap: HAS_GRADIENTMAP, - var texture = new DataTexture(); + opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false, - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, + alphaHash: HAS_ALPHAHASH, - loader.load( url, function ( buffer ) { + combine: material.combine, - var texData = scope._parser( buffer ); + // - if ( ! texData ) { return; } + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), - if ( undefined !== texData.image ) { + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), - texture.image = texData.image; + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), - } else if ( undefined !== texData.data ) { + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), - texture.image.width = texData.width; - texture.image.height = texData.height; - texture.image.data = texData.data; + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), - } + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), - texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping; - texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping; + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), - texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter; - texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter; + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), - texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1; + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), - if ( undefined !== texData.format ) { + // - texture.format = texData.format; + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), + vertexColors: material.vertexColors, + vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - } - if ( undefined !== texData.type ) { + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), - texture.type = texData.type; + fog: !! fog, + useFog: material.fog === true, + fogExp2: ( !! fog && fog.isFogExp2 ), - } + flatShading: material.flatShading === true, - if ( undefined !== texData.mipmaps ) { + sizeAttenuation: material.sizeAttenuation === true, + logarithmicDepthBuffer: logarithmicDepthBuffer, - texture.mipmaps = texData.mipmaps; + skinning: object.isSkinnedMesh === true, - } + morphTargets: geometry.morphAttributes.position !== undefined, + morphNormals: geometry.morphAttributes.normal !== undefined, + morphColors: geometry.morphAttributes.color !== undefined, + morphTargetsCount: morphTargetsCount, + morphTextureStride: morphTextureStride, - if ( 1 === texData.mipmapCount ) { + numDirLights: lights.directional.length, + numPointLights: lights.point.length, + numSpotLights: lights.spot.length, + numSpotLightMaps: lights.spotLightMap.length, + numRectAreaLights: lights.rectArea.length, + numHemiLights: lights.hemi.length, - texture.minFilter = LinearFilter; + numDirLightShadows: lights.directionalShadowMap.length, + numPointLightShadows: lights.pointShadowMap.length, + numSpotLightShadows: lights.spotShadowMap.length, + numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, - } + numLightProbes: lights.numLightProbes, - texture.needsUpdate = true; + numClippingPlanes: clipping.numPlanes, + numClipIntersection: clipping.numIntersection, - if ( onLoad ) { onLoad( texture, texData ); } + dithering: material.dithering, - }, onProgress, onError ); + shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, + shadowMapType: renderer.shadowMap.type, + toneMapping: toneMapping, - return texture; + decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ), - } + premultipliedAlpha: material.premultipliedAlpha, -} ); + doubleSided: material.side === DoubleSide, + flipSided: material.side === BackSide, -/** - * @author mrdoob / http://mrdoob.com/ - */ + useDepthPacking: material.depthPacking >= 0, + depthPacking: material.depthPacking || 0, -function ImageLoader( manager ) { + index0AttributeName: material.index0AttributeName, - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ), + extensionMultiDraw: ( HAS_EXTENSIONS && material.extensions.multiDraw === true || IS_BATCHEDMESH ) && extensions.has( 'WEBGL_multi_draw' ), -} + rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ), -Object.assign( ImageLoader.prototype, { + customProgramCacheKey: material.customProgramCacheKey() - crossOrigin: 'Anonymous', + }; - load: function ( url, onLoad, onProgress, onError ) { + // the usage of getChannel() determines the active texture channels for this shader - if ( url === undefined ) { url = ''; } + parameters.vertexUv1s = _activeChannels.has( 1 ); + parameters.vertexUv2s = _activeChannels.has( 2 ); + parameters.vertexUv3s = _activeChannels.has( 3 ); - if ( this.path !== undefined ) { url = this.path + url; } + _activeChannels.clear(); - url = this.manager.resolveURL( url ); + return parameters; - var scope = this; + } - var cached = Cache.get( url ); + function getProgramCacheKey( parameters ) { - if ( cached !== undefined ) { + const array = []; - scope.manager.itemStart( url ); + if ( parameters.shaderID ) { - setTimeout( function () { + array.push( parameters.shaderID ); - if ( onLoad ) { onLoad( cached ); } + } else { - scope.manager.itemEnd( url ); + array.push( parameters.customVertexShaderID ); + array.push( parameters.customFragmentShaderID ); - }, 0 ); + } - return cached; + if ( parameters.defines !== undefined ) { - } + for ( const name in parameters.defines ) { - var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' ); + array.push( name ); + array.push( parameters.defines[ name ] ); - image.addEventListener( 'load', function () { + } - Cache.add( url, this ); + } - if ( onLoad ) { onLoad( this ); } + if ( parameters.isRawShaderMaterial === false ) { - scope.manager.itemEnd( url ); + getProgramCacheKeyParameters( array, parameters ); + getProgramCacheKeyBooleans( array, parameters ); + array.push( renderer.outputColorSpace ); - }, false ); + } - /* - image.addEventListener( 'progress', function ( event ) { + array.push( parameters.customProgramCacheKey ); - if ( onProgress ) onProgress( event ); + return array.join(); - }, false ); - */ + } - image.addEventListener( 'error', function ( event ) { + function getProgramCacheKeyParameters( array, parameters ) { + + array.push( parameters.precision ); + array.push( parameters.outputColorSpace ); + array.push( parameters.envMapMode ); + array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); + array.push( parameters.combine ); + array.push( parameters.fogExp2 ); + array.push( parameters.sizeAttenuation ); + array.push( parameters.morphTargetsCount ); + array.push( parameters.morphAttributeCount ); + array.push( parameters.numDirLights ); + array.push( parameters.numPointLights ); + array.push( parameters.numSpotLights ); + array.push( parameters.numSpotLightMaps ); + array.push( parameters.numHemiLights ); + array.push( parameters.numRectAreaLights ); + array.push( parameters.numDirLightShadows ); + array.push( parameters.numPointLightShadows ); + array.push( parameters.numSpotLightShadows ); + array.push( parameters.numSpotLightShadowsWithMaps ); + array.push( parameters.numLightProbes ); + array.push( parameters.shadowMapType ); + array.push( parameters.toneMapping ); + array.push( parameters.numClippingPlanes ); + array.push( parameters.numClipIntersection ); + array.push( parameters.depthPacking ); + + } + + function getProgramCacheKeyBooleans( array, parameters ) { + + _programLayers.disableAll(); + + if ( parameters.supportsVertexTextures ) + _programLayers.enable( 0 ); + if ( parameters.instancing ) + _programLayers.enable( 1 ); + if ( parameters.instancingColor ) + _programLayers.enable( 2 ); + if ( parameters.instancingMorph ) + _programLayers.enable( 3 ); + if ( parameters.matcap ) + _programLayers.enable( 4 ); + if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) + _programLayers.enable( 6 ); + if ( parameters.normalMapTangentSpace ) + _programLayers.enable( 7 ); + if ( parameters.clearcoat ) + _programLayers.enable( 8 ); + if ( parameters.iridescence ) + _programLayers.enable( 9 ); + if ( parameters.alphaTest ) + _programLayers.enable( 10 ); + if ( parameters.vertexColors ) + _programLayers.enable( 11 ); + if ( parameters.vertexAlphas ) + _programLayers.enable( 12 ); + if ( parameters.vertexUv1s ) + _programLayers.enable( 13 ); + if ( parameters.vertexUv2s ) + _programLayers.enable( 14 ); + if ( parameters.vertexUv3s ) + _programLayers.enable( 15 ); + if ( parameters.vertexTangents ) + _programLayers.enable( 16 ); + if ( parameters.anisotropy ) + _programLayers.enable( 17 ); + if ( parameters.alphaHash ) + _programLayers.enable( 18 ); + if ( parameters.batching ) + _programLayers.enable( 19 ); + if ( parameters.dispersion ) + _programLayers.enable( 20 ); + if ( parameters.batchingColor ) + _programLayers.enable( 21 ); + + array.push( _programLayers.mask ); + _programLayers.disableAll(); + + if ( parameters.fog ) + _programLayers.enable( 0 ); + if ( parameters.useFog ) + _programLayers.enable( 1 ); + if ( parameters.flatShading ) + _programLayers.enable( 2 ); + if ( parameters.logarithmicDepthBuffer ) + _programLayers.enable( 3 ); + if ( parameters.skinning ) + _programLayers.enable( 4 ); + if ( parameters.morphTargets ) + _programLayers.enable( 5 ); + if ( parameters.morphNormals ) + _programLayers.enable( 6 ); + if ( parameters.morphColors ) + _programLayers.enable( 7 ); + if ( parameters.premultipliedAlpha ) + _programLayers.enable( 8 ); + if ( parameters.shadowMapEnabled ) + _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.transmission ) + _programLayers.enable( 14 ); + if ( parameters.sheen ) + _programLayers.enable( 15 ); + if ( parameters.opaque ) + _programLayers.enable( 16 ); + if ( parameters.pointsUvs ) + _programLayers.enable( 17 ); + if ( parameters.decodeVideoTexture ) + _programLayers.enable( 18 ); + if ( parameters.alphaToCoverage ) + _programLayers.enable( 19 ); + + array.push( _programLayers.mask ); + + } + + function getUniforms( material ) { + + const shaderID = shaderIDs[ material.type ]; + let uniforms; + + if ( shaderID ) { + + const shader = ShaderLib[ shaderID ]; + uniforms = UniformsUtils.clone( shader.uniforms ); - if ( onError ) { onError( event ); } + } else { - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + uniforms = material.uniforms; - }, false ); + } - if ( url.substr( 0, 5 ) !== 'data:' ) { + return uniforms; - if ( this.crossOrigin !== undefined ) { image.crossOrigin = this.crossOrigin; } + } - } + function acquireProgram( parameters, cacheKey ) { - scope.manager.itemStart( url ); + let program; - image.src = url; + // Check if code has been already compiled + for ( let p = 0, pl = programs.length; p < pl; p ++ ) { - return image; + const preexistingProgram = programs[ p ]; - }, + if ( preexistingProgram.cacheKey === cacheKey ) { - setCrossOrigin: function ( value ) { + program = preexistingProgram; + ++ program.usedTimes; - this.crossOrigin = value; - return this; + break; - }, + } - setPath: function ( value ) { + } - this.path = value; - return this; + if ( program === undefined ) { - } + program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); + programs.push( program ); -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + return program; -function CubeTextureLoader( manager ) { + } - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + function releaseProgram( program ) { -} + if ( -- program.usedTimes === 0 ) { -Object.assign( CubeTextureLoader.prototype, { + // Remove from unordered set + const i = programs.indexOf( program ); + programs[ i ] = programs[ programs.length - 1 ]; + programs.pop(); - crossOrigin: 'Anonymous', + // Free WebGL resources + program.destroy(); - load: function ( urls, onLoad, onProgress, onError ) { + } - var texture = new CubeTexture(); + } - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); + function releaseShaderCache( material ) { - var loaded = 0; + _customShaders.remove( material ); - function loadTexture( i ) { + } - loader.load( urls[ i ], function ( image ) { + function dispose() { - texture.images[ i ] = image; + _customShaders.dispose(); - loaded ++; + } - if ( loaded === 6 ) { + return { + getParameters: getParameters, + getProgramCacheKey: getProgramCacheKey, + getUniforms: getUniforms, + acquireProgram: acquireProgram, + releaseProgram: releaseProgram, + releaseShaderCache: releaseShaderCache, + // Exposed for resource monitoring & error feedback via renderer.info: + programs: programs, + dispose: dispose + }; - texture.needsUpdate = true; +} - if ( onLoad ) { onLoad( texture ); } +function WebGLProperties() { - } + let properties = new WeakMap(); - }, undefined, onError ); + function get( object ) { - } + let map = properties.get( object ); - for ( var i = 0; i < urls.length; ++ i ) { + if ( map === undefined ) { - loadTexture( i ); + map = {}; + properties.set( object, map ); } - return texture; + return map; - }, + } - setCrossOrigin: function ( value ) { + function remove( object ) { - this.crossOrigin = value; - return this; + properties.delete( object ); - }, + } - setPath: function ( value ) { + function update( object, key, value ) { - this.path = value; - return this; + properties.get( object )[ key ] = value; } -} ); + function dispose() { -/** - * @author mrdoob / http://mrdoob.com/ - */ + properties = new WeakMap(); -function TextureLoader( manager ) { + } - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + return { + get: get, + remove: remove, + update: update, + dispose: dispose + }; } -Object.assign( TextureLoader.prototype, { - - crossOrigin: 'Anonymous', - - load: function ( url, onLoad, onProgress, onError ) { - - var texture = new Texture(); - - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); +function painterSortStable( a, b ) { - loader.load( url, function ( image ) { + if ( a.groupOrder !== b.groupOrder ) { - texture.image = image; + return a.groupOrder - b.groupOrder; - // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB. - var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0; + } else if ( a.renderOrder !== b.renderOrder ) { - texture.format = isJPEG ? RGBFormat : RGBAFormat; - texture.needsUpdate = true; + return a.renderOrder - b.renderOrder; - if ( onLoad !== undefined ) { + } else if ( a.material.id !== b.material.id ) { - onLoad( texture ); + return a.material.id - b.material.id; - } + } else if ( a.z !== b.z ) { - }, onProgress, onError ); + return a.z - b.z; - return texture; + } else { - }, + return a.id - b.id; - setCrossOrigin: function ( value ) { + } - this.crossOrigin = value; - return this; +} - }, +function reversePainterSortStable( a, b ) { - setPath: function ( value ) { + if ( a.groupOrder !== b.groupOrder ) { - this.path = value; - return this; + return a.groupOrder - b.groupOrder; - } + } else if ( a.renderOrder !== b.renderOrder ) { -} ); + return a.renderOrder - b.renderOrder; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Extensible curve object - * - * Some common of curve methods: - * .getPoint( t, optionalTarget ), .getTangent( t ) - * .getPointAt( u, optionalTarget ), .getTangentAt( u ) - * .getPoints(), .getSpacedPoints() - * .getLength() - * .updateArcLengths() - * - * This following curves inherit from THREE.Curve: - * - * -- 2D curves -- - * THREE.ArcCurve - * THREE.CubicBezierCurve - * THREE.EllipseCurve - * THREE.LineCurve - * THREE.QuadraticBezierCurve - * THREE.SplineCurve - * - * -- 3D curves -- - * THREE.CatmullRomCurve3 - * THREE.CubicBezierCurve3 - * THREE.LineCurve3 - * THREE.QuadraticBezierCurve3 - * - * A series of curves can be represented as a THREE.CurvePath. - * - **/ + } else if ( a.z !== b.z ) { -/************************************************************** - * Abstract Curve base class - **************************************************************/ + return b.z - a.z; -function Curve() { + } else { - this.type = 'Curve'; + return a.id - b.id; - this.arcLengthDivisions = 200; + } } -Object.assign( Curve.prototype, { - // Virtual base class method to overwrite and implement in subclasses - // - t [0 .. 1] +function WebGLRenderList() { - getPoint: function ( /* t, optionalTarget */ ) { + const renderItems = []; + let renderItemsIndex = 0; - console.warn( 'THREE.Curve: .getPoint() not implemented.' ); - return null; + const opaque = []; + const transmissive = []; + const transparent = []; - }, + function init() { - // Get point at relative position in curve according to arc length - // - u [0 .. 1] + renderItemsIndex = 0; - getPointAt: function ( u, optionalTarget ) { + opaque.length = 0; + transmissive.length = 0; + transparent.length = 0; - var t = this.getUtoTmapping( u ); - return this.getPoint( t, optionalTarget ); + } - }, + function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { - // Get sequence of points using getPoint( t ) + let renderItem = renderItems[ renderItemsIndex ]; - getPoints: function ( divisions ) { + if ( renderItem === undefined ) { - if ( divisions === undefined ) { divisions = 5; } + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + groupOrder: groupOrder, + renderOrder: object.renderOrder, + z: z, + group: group + }; - var points = []; + renderItems[ renderItemsIndex ] = renderItem; - for ( var d = 0; d <= divisions; d ++ ) { + } else { - points.push( this.getPoint( d / divisions ) ); + 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; } - return points; + renderItemsIndex ++; - }, + return renderItem; - // Get sequence of points using getPointAt( u ) + } - getSpacedPoints: function ( divisions ) { + function push( object, geometry, material, groupOrder, z, group ) { - if ( divisions === undefined ) { divisions = 5; } + const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); - var points = []; + if ( material.transmission > 0.0 ) { - for ( var d = 0; d <= divisions; d ++ ) { + transmissive.push( renderItem ); - points.push( this.getPointAt( d / divisions ) ); + } else if ( material.transparent === true ) { - } + transparent.push( renderItem ); - return points; + } else { - }, + opaque.push( renderItem ); + + } - // Get total curve arc length + } - getLength: function () { + function unshift( object, geometry, material, groupOrder, z, group ) { - var lengths = this.getLengths(); - return lengths[ lengths.length - 1 ]; + const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); - }, + if ( material.transmission > 0.0 ) { - // Get list of cumulative segment lengths + transmissive.unshift( renderItem ); - getLengths: function ( divisions ) { + } else if ( material.transparent === true ) { - if ( divisions === undefined ) { divisions = this.arcLengthDivisions; } + transparent.unshift( renderItem ); - if ( this.cacheArcLengths && - ( this.cacheArcLengths.length === divisions + 1 ) && - ! this.needsUpdate ) { + } else { - return this.cacheArcLengths; + opaque.unshift( renderItem ); } - this.needsUpdate = false; + } - var cache = []; - var current, last = this.getPoint( 0 ); - var p, sum = 0; + function sort( customOpaqueSort, customTransparentSort ) { - cache.push( 0 ); + if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable ); + if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable ); + if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable ); - for ( p = 1; p <= divisions; p ++ ) { + } - current = this.getPoint( p / divisions ); - sum += current.distanceTo( last ); - cache.push( sum ); - last = current; + function finish() { - } + // Clear references from inactive renderItems in the list - this.cacheArcLengths = cache; + for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { - return cache; // { sums: cache, sum: sum }; Sum is in the last element. + const renderItem = renderItems[ i ]; - }, + if ( renderItem.id === null ) break; - updateArcLengths: function () { + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.group = null; - this.needsUpdate = true; - this.getLengths(); + } - }, + } - // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant + return { - getUtoTmapping: function ( u, distance ) { + opaque: opaque, + transmissive: transmissive, + transparent: transparent, - var arcLengths = this.getLengths(); + init: init, + push: push, + unshift: unshift, + finish: finish, - var i = 0, il = arcLengths.length; + sort: sort + }; - var targetArcLength; // The targeted u distance value to get +} - if ( distance ) { +function WebGLRenderLists() { - targetArcLength = distance; + let lists = new WeakMap(); - } else { + function get( scene, renderCallDepth ) { - targetArcLength = u * arcLengths[ il - 1 ]; + const listArray = lists.get( scene ); + let list; - } + if ( listArray === undefined ) { - // binary search for the index with largest value smaller than target u distance + list = new WebGLRenderList(); + lists.set( scene, [ list ] ); - var low = 0, high = il - 1, comparison; + } else { - while ( low <= high ) { + if ( renderCallDepth >= listArray.length ) { - i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats + list = new WebGLRenderList(); + listArray.push( list ); - comparison = arcLengths[ i ] - targetArcLength; + } else { - if ( comparison < 0 ) { + list = listArray[ renderCallDepth ]; - low = i + 1; + } - } else if ( comparison > 0 ) { + } - high = i - 1; + return list; - } else { + } - high = i; - break; + function dispose() { - // DONE + lists = new WeakMap(); - } + } - } + return { + get: get, + dispose: dispose + }; - i = high; +} - if ( arcLengths[ i ] === targetArcLength ) { +function UniformsCache() { - return i / ( il - 1 ); + const lights = {}; - } + return { - // we could get finer grain at lengths, or use simple interpolation between two points + get: function ( light ) { - var lengthBefore = arcLengths[ i ]; - var lengthAfter = arcLengths[ i + 1 ]; + if ( lights[ light.id ] !== undefined ) { - var segmentLength = lengthAfter - lengthBefore; + return lights[ light.id ]; - // determine where we are between the 'before' and 'after' points + } - var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; + let uniforms; - // add that fractional amount to t + switch ( light.type ) { - var t = ( i + segmentFraction ) / ( il - 1 ); + case 'DirectionalLight': + uniforms = { + direction: new Vector3(), + color: new Color() + }; + break; - return t; + case 'SpotLight': + uniforms = { + position: new Vector3(), + direction: new Vector3(), + color: new Color(), + distance: 0, + coneCos: 0, + penumbraCos: 0, + decay: 0 + }; + break; - }, + case 'PointLight': + uniforms = { + position: new Vector3(), + color: new Color(), + distance: 0, + decay: 0 + }; + break; - // Returns a unit vector tangent at t - // In case any sub curve does not implement its tangent derivation, - // 2 points a small delta apart will be used to find its gradient - // which seems to give a reasonable approximation + case 'HemisphereLight': + uniforms = { + direction: new Vector3(), + skyColor: new Color(), + groundColor: new Color() + }; + break; - getTangent: function ( t ) { + case 'RectAreaLight': + uniforms = { + color: new Color(), + position: new Vector3(), + halfWidth: new Vector3(), + halfHeight: new Vector3() + }; + break; - var delta = 0.0001; - var t1 = t - delta; - var t2 = t + delta; + } - // Capping in case of danger + lights[ light.id ] = uniforms; - if ( t1 < 0 ) { t1 = 0; } - if ( t2 > 1 ) { t2 = 1; } + return uniforms; - var pt1 = this.getPoint( t1 ); - var pt2 = this.getPoint( t2 ); + } - var vec = pt2.clone().sub( pt1 ); - return vec.normalize(); + }; - }, +} - getTangentAt: function ( u ) { +function ShadowUniformsCache() { - var t = this.getUtoTmapping( u ); - return this.getTangent( t ); + const lights = {}; - }, + return { - computeFrenetFrames: function ( segments, closed ) { + get: function ( light ) { - // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf + if ( lights[ light.id ] !== undefined ) { - var normal = new Vector3(); + return lights[ light.id ]; - var tangents = []; - var normals = []; - var binormals = []; + } - var vec = new Vector3(); - var mat = new Matrix4(); + let uniforms; - var i, u, theta; + switch ( light.type ) { - // compute the tangent vectors for each segment on the curve + case 'DirectionalLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; - for ( i = 0; i <= segments; i ++ ) { + case 'SpotLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; - u = i / segments; + case 'PointLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2(), + shadowCameraNear: 1, + shadowCameraFar: 1000 + }; + break; - tangents[ i ] = this.getTangentAt( u ); - tangents[ i ].normalize(); + // TODO (abelnation): set RectAreaLight shadow uniforms - } + } - // select an initial normal vector perpendicular to the first tangent vector, - // and in the direction of the minimum tangent xyz component + lights[ light.id ] = uniforms; - normals[ 0 ] = new Vector3(); - binormals[ 0 ] = new Vector3(); - var min = Number.MAX_VALUE; - var tx = Math.abs( tangents[ 0 ].x ); - var ty = Math.abs( tangents[ 0 ].y ); - var tz = Math.abs( tangents[ 0 ].z ); + return uniforms; - if ( tx <= min ) { + } - min = tx; - normal.set( 1, 0, 0 ); + }; - } +} - if ( ty <= min ) { - min = ty; - normal.set( 0, 1, 0 ); - } +let nextVersion = 0; - if ( tz <= min ) { +function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { - normal.set( 0, 0, 1 ); + return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); - } +} - vec.crossVectors( tangents[ 0 ], normal ).normalize(); +function WebGLLights( extensions ) { - normals[ 0 ].crossVectors( tangents[ 0 ], vec ); - binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); + const cache = new UniformsCache(); + const shadowCache = ShadowUniformsCache(); - // compute the slowly-varying normal and binormal vectors for each segment on the curve + const state = { - for ( i = 1; i <= segments; i ++ ) { + version: 0, - normals[ i ] = normals[ i - 1 ].clone(); + hash: { + directionalLength: - 1, + pointLength: - 1, + spotLength: - 1, + rectAreaLength: - 1, + hemiLength: - 1, - binormals[ i ] = binormals[ i - 1 ].clone(); + numDirectionalShadows: - 1, + numPointShadows: - 1, + numSpotShadows: - 1, + numSpotMaps: - 1, - vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); + numLightProbes: - 1 + }, - if ( vec.length() > Number.EPSILON ) { + ambient: [ 0, 0, 0 ], + probe: [], + directional: [], + directionalShadow: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotLightMap: [], + spotShadow: [], + spotShadowMap: [], + spotLightMatrix: [], + rectArea: [], + rectAreaLTC1: null, + rectAreaLTC2: null, + point: [], + pointShadow: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [], + numSpotLightShadowsWithMaps: 0, + numLightProbes: 0 - vec.normalize(); + }; - theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors + for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); - normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); + const vector3 = new Vector3(); + const matrix4 = new Matrix4(); + const matrix42 = new Matrix4(); - } + function setup( lights ) { - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + let r = 0, g = 0, b = 0; - } + for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 ); - // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; - if ( closed === true ) { + let numDirectionalShadows = 0; + let numPointShadows = 0; + let numSpotShadows = 0; + let numSpotMaps = 0; + let numSpotShadowsWithMaps = 0; - theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); - theta /= segments; + let numLightProbes = 0; - if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { + // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] + lights.sort( shadowCastingAndTexturingLightsFirst ); - theta = - theta; + for ( let i = 0, l = lights.length; i < l; i ++ ) { - } + const light = lights[ i ]; - for ( i = 1; i <= segments; i ++ ) { + const color = light.color; + const intensity = light.intensity; + const distance = light.distance; - // twist a little... - normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; - } + if ( light.isAmbientLight ) { - } + r += color.r * intensity; + g += color.g * intensity; + b += color.b * intensity; - return { - tangents: tangents, - normals: normals, - binormals: binormals - }; + } else if ( light.isLightProbe ) { - }, + for ( let j = 0; j < 9; j ++ ) { - clone: function () { + state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); - return new this.constructor().copy( this ); + } - }, + numLightProbes ++; - copy: function ( source ) { + } else if ( light.isDirectionalLight ) { - this.arcLengthDivisions = source.arcLengthDivisions; + const uniforms = cache.get( light ); - return this; + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - }, + if ( light.castShadow ) { - toJSON: function () { + const shadow = light.shadow; - var data = { - metadata: { - version: 4.5, - type: 'Curve', - generator: 'Curve.toJSON' - } - }; + const shadowUniforms = shadowCache.get( light ); - data.arcLengthDivisions = this.arcLengthDivisions; - data.type = this.type; + shadowUniforms.shadowIntensity = shadow.intensity; + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; - return data; + state.directionalShadow[ directionalLength ] = shadowUniforms; + state.directionalShadowMap[ directionalLength ] = shadowMap; + state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - }, + numDirectionalShadows ++; - fromJSON: function ( json ) { + } - this.arcLengthDivisions = json.arcLengthDivisions; + state.directional[ directionalLength ] = uniforms; - return this; + directionalLength ++; - } + } else if ( light.isSpotLight ) { -} ); + const uniforms = cache.get( light ); -function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + uniforms.position.setFromMatrixPosition( light.matrixWorld ); - Curve.call( this ); + uniforms.color.copy( color ).multiplyScalar( intensity ); + uniforms.distance = distance; - this.type = 'EllipseCurve'; + uniforms.coneCos = Math.cos( light.angle ); + uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); + uniforms.decay = light.decay; - this.aX = aX || 0; - this.aY = aY || 0; + state.spot[ spotLength ] = uniforms; - this.xRadius = xRadius || 1; - this.yRadius = yRadius || 1; + const shadow = light.shadow; - this.aStartAngle = aStartAngle || 0; - this.aEndAngle = aEndAngle || 2 * Math.PI; + if ( light.map ) { - this.aClockwise = aClockwise || false; + state.spotLightMap[ numSpotMaps ] = light.map; + numSpotMaps ++; - this.aRotation = aRotation || 0; + // make sure the lightMatrix is up to date + // TODO : do it if required only + shadow.updateMatrices( light ); -} + if ( light.castShadow ) numSpotShadowsWithMaps ++; -EllipseCurve.prototype = Object.create( Curve.prototype ); -EllipseCurve.prototype.constructor = EllipseCurve; + } -EllipseCurve.prototype.isEllipseCurve = true; + state.spotLightMatrix[ spotLength ] = shadow.matrix; -EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) { + if ( light.castShadow ) { - var point = optionalTarget || new Vector2(); + const shadowUniforms = shadowCache.get( light ); - var twoPi = Math.PI * 2; - var deltaAngle = this.aEndAngle - this.aStartAngle; - var samePoints = Math.abs( deltaAngle ) < Number.EPSILON; + shadowUniforms.shadowIntensity = shadow.intensity; + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; - // ensures that deltaAngle is 0 .. 2 PI - while ( deltaAngle < 0 ) { deltaAngle += twoPi; } - while ( deltaAngle > twoPi ) { deltaAngle -= twoPi; } + state.spotShadow[ spotLength ] = shadowUniforms; + state.spotShadowMap[ spotLength ] = shadowMap; - if ( deltaAngle < Number.EPSILON ) { + numSpotShadows ++; - if ( samePoints ) { + } - deltaAngle = 0; + spotLength ++; - } else { + } else if ( light.isRectAreaLight ) { - deltaAngle = twoPi; + const uniforms = cache.get( light ); - } + uniforms.color.copy( color ).multiplyScalar( intensity ); - } + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - if ( this.aClockwise === true && ! samePoints ) { + state.rectArea[ rectAreaLength ] = uniforms; - if ( deltaAngle === twoPi ) { + rectAreaLength ++; - deltaAngle = - twoPi; + } else if ( light.isPointLight ) { - } else { + const uniforms = cache.get( light ); - deltaAngle = deltaAngle - twoPi; + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.distance = light.distance; + uniforms.decay = light.decay; - } + if ( light.castShadow ) { - } + const shadow = light.shadow; - var angle = this.aStartAngle + t * deltaAngle; - var x = this.aX + this.xRadius * Math.cos( angle ); - var y = this.aY + this.yRadius * Math.sin( angle ); + const shadowUniforms = shadowCache.get( light ); - if ( this.aRotation !== 0 ) { + shadowUniforms.shadowIntensity = shadow.intensity; + 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; - var cos = Math.cos( this.aRotation ); - var sin = Math.sin( this.aRotation ); + state.pointShadow[ pointLength ] = shadowUniforms; + state.pointShadowMap[ pointLength ] = shadowMap; + state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - var tx = x - this.aX; - var ty = y - this.aY; + numPointShadows ++; - // Rotate the point about the center of the ellipse. - x = tx * cos - ty * sin + this.aX; - y = tx * sin + ty * cos + this.aY; + } - } + state.point[ pointLength ] = uniforms; - return point.set( x, y ); + pointLength ++; -}; + } else if ( light.isHemisphereLight ) { -EllipseCurve.prototype.copy = function ( source ) { + const uniforms = cache.get( light ); - Curve.prototype.copy.call( this, source ); + uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); + uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); - this.aX = source.aX; - this.aY = source.aY; + state.hemi[ hemiLength ] = uniforms; - this.xRadius = source.xRadius; - this.yRadius = source.yRadius; + hemiLength ++; - this.aStartAngle = source.aStartAngle; - this.aEndAngle = source.aEndAngle; + } - this.aClockwise = source.aClockwise; + } - this.aRotation = source.aRotation; + if ( rectAreaLength > 0 ) { - return this; + if ( extensions.has( 'OES_texture_float_linear' ) === true ) { -}; + state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; + } else { -EllipseCurve.prototype.toJSON = function () { + state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; + state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; - var data = Curve.prototype.toJSON.call( this ); + } - data.aX = this.aX; - data.aY = this.aY; + } - data.xRadius = this.xRadius; - data.yRadius = this.yRadius; + state.ambient[ 0 ] = r; + state.ambient[ 1 ] = g; + state.ambient[ 2 ] = b; - data.aStartAngle = this.aStartAngle; - data.aEndAngle = this.aEndAngle; + const hash = state.hash; - data.aClockwise = this.aClockwise; + 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 || + hash.numSpotMaps !== numSpotMaps || + hash.numLightProbes !== numLightProbes ) { - data.aRotation = this.aRotation; + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; - return data; + 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.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; + state.spotLightMap.length = numSpotMaps; + state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; + state.numLightProbes = numLightProbes; -}; + hash.directionalLength = directionalLength; + hash.pointLength = pointLength; + hash.spotLength = spotLength; + hash.rectAreaLength = rectAreaLength; + hash.hemiLength = hemiLength; -EllipseCurve.prototype.fromJSON = function ( json ) { + hash.numDirectionalShadows = numDirectionalShadows; + hash.numPointShadows = numPointShadows; + hash.numSpotShadows = numSpotShadows; + hash.numSpotMaps = numSpotMaps; - Curve.prototype.fromJSON.call( this, json ); + hash.numLightProbes = numLightProbes; - this.aX = json.aX; - this.aY = json.aY; + state.version = nextVersion ++; - this.xRadius = json.xRadius; - this.yRadius = json.yRadius; + } - this.aStartAngle = json.aStartAngle; - this.aEndAngle = json.aEndAngle; + } - this.aClockwise = json.aClockwise; + function setupView( lights, camera ) { - this.aRotation = json.aRotation; + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; - return this; + const viewMatrix = camera.matrixWorldInverse; -}; + for ( let i = 0, l = lights.length; i < l; i ++ ) { -function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + const light = lights[ i ]; - EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + if ( light.isDirectionalLight ) { - this.type = 'ArcCurve'; + const uniforms = state.directional[ directionalLength ]; -} + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); -ArcCurve.prototype = Object.create( EllipseCurve.prototype ); -ArcCurve.prototype.constructor = ArcCurve; + directionalLength ++; -ArcCurve.prototype.isArcCurve = true; + } else if ( light.isSpotLight ) { -/** - * @author zz85 https://github.com/zz85 - * - * Centripetal CatmullRom Curve - which is useful for avoiding - * cusps and self-intersections in non-uniform catmull rom curves. - * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf - * - * curve.type accepts centripetal(default), chordal and catmullrom - * curve.tension is used for catmullrom which defaults to 0.5 - */ + const uniforms = state.spot[ spotLength ]; + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); -/* -Based on an optimized c++ solution in - - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ - - http://ideone.com/NoEbVM + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); -This CubicPoly class could be used for reusing some variables and calculations, -but for three.js curve use, it could be possible inlined and flatten into a single function call -which can be placed in CurveUtils. -*/ + spotLength ++; -function CubicPoly() { + } else if ( light.isRectAreaLight ) { - var c0 = 0, c1 = 0, c2 = 0, c3 = 0; + const uniforms = state.rectArea[ rectAreaLength ]; - /* - * Compute coefficients for a cubic polynomial - * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 - * such that - * p(0) = x0, p(1) = x1 - * and - * p'(0) = t0, p'(1) = t1. - */ - function init( x0, x1, t0, t1 ) { + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - c0 = x0; - c1 = t0; - c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; - c3 = 2 * x0 - 2 * x1 + t0 + t1; + // extract local rotation of light to derive width/height half vectors + matrix42.identity(); + matrix4.copy( light.matrixWorld ); + matrix4.premultiply( viewMatrix ); + matrix42.extractRotation( matrix4 ); - } + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - return { + uniforms.halfWidth.applyMatrix4( matrix42 ); + uniforms.halfHeight.applyMatrix4( matrix42 ); - initCatmullRom: function ( x0, x1, x2, x3, tension ) { + rectAreaLength ++; - init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); + } else if ( light.isPointLight ) { - }, + const uniforms = state.point[ pointLength ]; - initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - // compute tangents when parameterized in [t1,t2] - var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; - var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; + pointLength ++; - // rescale tangents for parametrization in [0,1] - t1 *= dt1; - t2 *= dt1; + } else if ( light.isHemisphereLight ) { - init( x1, x2, t1, t2 ); + const uniforms = state.hemi[ hemiLength ]; - }, + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + uniforms.direction.transformDirection( viewMatrix ); - calc: function ( t ) { + hemiLength ++; - var t2 = t * t; - var t3 = t2 * t; - return c0 + c1 * t + c2 * t2 + c3 * t3; + } } + } + + return { + setup: setup, + setupView: setupView, + state: state }; } -// - -var tmp = new Vector3(); -var px = new CubicPoly(); -var py = new CubicPoly(); -var pz = new CubicPoly(); - -function CatmullRomCurve3( points, closed, curveType, tension ) { - - Curve.call( this ); - - this.type = 'CatmullRomCurve3'; +function WebGLRenderState( extensions ) { - this.points = points || []; - this.closed = closed || false; - this.curveType = curveType || 'centripetal'; - this.tension = tension || 0.5; + const lights = new WebGLLights( extensions ); -} - -CatmullRomCurve3.prototype = Object.create( Curve.prototype ); -CatmullRomCurve3.prototype.constructor = CatmullRomCurve3; + const lightsArray = []; + const shadowsArray = []; -CatmullRomCurve3.prototype.isCatmullRomCurve3 = true; + function init( camera ) { -CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) { + state.camera = camera; - var point = optionalTarget || new Vector3(); + lightsArray.length = 0; + shadowsArray.length = 0; - var points = this.points; - var l = points.length; + } - var p = ( l - ( this.closed ? 0 : 1 ) ) * t; - var intPoint = Math.floor( p ); - var weight = p - intPoint; + function pushLight( light ) { - if ( this.closed ) { + lightsArray.push( light ); - intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length; + } - } else if ( weight === 0 && intPoint === l - 1 ) { + function pushShadow( shadowLight ) { - intPoint = l - 2; - weight = 1; + shadowsArray.push( shadowLight ); } - var p0, p1, p2, p3; // 4 points + function setupLights() { - if ( this.closed || intPoint > 0 ) { + lights.setup( lightsArray ); - p0 = points[ ( intPoint - 1 ) % l ]; + } - } else { + function setupLightsView( camera ) { - // extrapolate first point - tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); - p0 = tmp; + lights.setupView( lightsArray, camera ); } - p1 = points[ intPoint % l ]; - p2 = points[ ( intPoint + 1 ) % l ]; + const state = { + lightsArray: lightsArray, + shadowsArray: shadowsArray, - if ( this.closed || intPoint + 2 < l ) { + camera: null, - p3 = points[ ( intPoint + 2 ) % l ]; + lights: lights, - } else { - - // extrapolate last point - tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); - p3 = tmp; + transmissionRenderTarget: {} + }; - } + return { + init: init, + state: state, + setupLights: setupLights, + setupLightsView: setupLightsView, - if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { + pushLight: pushLight, + pushShadow: pushShadow + }; - // init Centripetal / Chordal Catmull-Rom - var pow = this.curveType === 'chordal' ? 0.5 : 0.25; - var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); - var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); - var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); +} - // safety check for repeated points - if ( dt1 < 1e-4 ) { dt1 = 1.0; } - if ( dt0 < 1e-4 ) { dt0 = dt1; } - if ( dt2 < 1e-4 ) { dt2 = dt1; } +function WebGLRenderStates( extensions ) { - 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 ); + let renderStates = new WeakMap(); - } else if ( this.curveType === 'catmullrom' ) { + function get( scene, renderCallDepth = 0 ) { - 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 ); + const renderStateArray = renderStates.get( scene ); + let renderState; - } + if ( renderStateArray === undefined ) { - point.set( - px.calc( weight ), - py.calc( weight ), - pz.calc( weight ) - ); + renderState = new WebGLRenderState( extensions ); + renderStates.set( scene, [ renderState ] ); - return point; + } else { -}; + if ( renderCallDepth >= renderStateArray.length ) { -CatmullRomCurve3.prototype.copy = function ( source ) { + renderState = new WebGLRenderState( extensions ); + renderStateArray.push( renderState ); - Curve.prototype.copy.call( this, source ); + } else { - this.points = []; + renderState = renderStateArray[ renderCallDepth ]; - for ( var i = 0, l = source.points.length; i < l; i ++ ) { + } - var point = source.points[ i ]; + } - this.points.push( point.clone() ); + return renderState; } - this.closed = source.closed; - this.curveType = source.curveType; - this.tension = source.tension; - - return this; + function dispose() { -}; + renderStates = new WeakMap(); -CatmullRomCurve3.prototype.toJSON = function () { + } - var data = Curve.prototype.toJSON.call( this ); + return { + get: get, + dispose: dispose + }; - data.points = []; +} - for ( var i = 0, l = this.points.length; i < l; i ++ ) { +class MeshDepthMaterial extends Material { - var point = this.points[ i ]; - data.points.push( point.toArray() ); + constructor( parameters ) { - } + super(); - data.closed = this.closed; - data.curveType = this.curveType; - data.tension = this.tension; + this.isMeshDepthMaterial = true; - return data; + this.type = 'MeshDepthMaterial'; -}; + this.depthPacking = BasicDepthPacking; -CatmullRomCurve3.prototype.fromJSON = function ( json ) { + this.map = null; - Curve.prototype.fromJSON.call( this, json ); + this.alphaMap = null; - this.points = []; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - for ( var i = 0, l = json.points.length; i < l; i ++ ) { + this.wireframe = false; + this.wireframeLinewidth = 1; - var point = json.points[ i ]; - this.points.push( new Vector3().fromArray( point ) ); + this.setValues( parameters ); } - this.closed = json.closed; - this.curveType = json.curveType; - this.tension = json.tension; + copy( source ) { - return this; - -}; + super.copy( source ); -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve - */ + this.depthPacking = source.depthPacking; -function CatmullRom( t, p0, p1, p2, p3 ) { + this.map = source.map; - var v0 = ( p2 - p0 ) * 0.5; - var v1 = ( p3 - p1 ) * 0.5; - var t2 = t * t; - var t3 = t * t2; - return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; + this.alphaMap = source.alphaMap; -} + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; -// + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; -function QuadraticBezierP0( t, p ) { + return this; - var k = 1 - t; - return k * k * p; + } } -function QuadraticBezierP1( t, p ) { +class MeshDistanceMaterial extends Material { - return 2 * ( 1 - t ) * t * p; - -} + constructor( parameters ) { -function QuadraticBezierP2( t, p ) { + super(); - return t * t * p; + this.isMeshDistanceMaterial = true; -} + this.type = 'MeshDistanceMaterial'; -function QuadraticBezier( t, p0, p1, p2 ) { + this.map = null; - return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + - QuadraticBezierP2( t, p2 ); + this.alphaMap = null; -} + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; -// + this.setValues( parameters ); -function CubicBezierP0( t, p ) { + } - var k = 1 - t; - return k * k * k * p; + copy( source ) { -} + super.copy( source ); -function CubicBezierP1( t, p ) { + this.map = source.map; - var k = 1 - t; - return 3 * k * k * t * p; + this.alphaMap = source.alphaMap; -} + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; -function CubicBezierP2( t, p ) { + return this; - return 3 * ( 1 - t ) * t * t * p; + } } -function CubicBezierP3( t, p ) { - - return t * t * t * p; - -} +const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; -function CubicBezier( t, p0, p1, p2, p3 ) { +const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; - return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + - CubicBezierP3( t, p3 ); +function WebGLShadowMap( renderer, objects, capabilities ) { -} + let _frustum = new Frustum(); -function CubicBezierCurve( v0, v1, v2, v3 ) { + const _shadowMapSize = new Vector2(), + _viewportSize = new Vector2(), - Curve.call( this ); + _viewport = new Vector4(), - this.type = 'CubicBezierCurve'; + _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), + _distanceMaterial = new MeshDistanceMaterial(), - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); - this.v3 = v3 || new Vector2(); + _materialCache = {}, -} + _maxTextureSize = capabilities.maxTextureSize; -CubicBezierCurve.prototype = Object.create( Curve.prototype ); -CubicBezierCurve.prototype.constructor = CubicBezierCurve; + const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; -CubicBezierCurve.prototype.isCubicBezierCurve = true; + const shadowMaterialVertical = new ShaderMaterial( { + defines: { + VSM_SAMPLES: 8 + }, + uniforms: { + shadow_pass: { value: null }, + resolution: { value: new Vector2() }, + radius: { value: 4.0 } + }, -CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { + vertexShader: vertex, + fragmentShader: fragment - var point = optionalTarget || new Vector2(); + } ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + const shadowMaterialHorizontal = shadowMaterialVertical.clone(); + shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; - point.set( - CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), - CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) + const fullScreenTri = new BufferGeometry(); + fullScreenTri.setAttribute( + 'position', + new BufferAttribute( + new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ), + 3 + ) ); - return point; - -}; - -CubicBezierCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); - - return this; - -}; - -CubicBezierCurve.prototype.toJSON = function () { + const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); - var data = Curve.prototype.toJSON.call( this ); + const scope = this; - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); - data.v3 = this.v3.toArray(); - - return data; - -}; - -CubicBezierCurve.prototype.fromJSON = function ( json ) { - - Curve.prototype.fromJSON.call( this, json ); - - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); - this.v3.fromArray( json.v3 ); + this.enabled = false; - return this; + this.autoUpdate = true; + this.needsUpdate = false; -}; + this.type = PCFShadowMap; + let _previousType = this.type; -function CubicBezierCurve3( v0, v1, v2, v3 ) { + this.render = function ( lights, scene, camera ) { - Curve.call( this ); + if ( scope.enabled === false ) return; + if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; - this.type = 'CubicBezierCurve3'; + if ( lights.length === 0 ) return; - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); - this.v3 = v3 || new Vector3(); + const currentRenderTarget = renderer.getRenderTarget(); + const activeCubeFace = renderer.getActiveCubeFace(); + const activeMipmapLevel = renderer.getActiveMipmapLevel(); -} + const _state = renderer.state; -CubicBezierCurve3.prototype = Object.create( Curve.prototype ); -CubicBezierCurve3.prototype.constructor = CubicBezierCurve3; + // Set GL state for depth map. + _state.setBlending( NoBlending ); + _state.buffers.color.setClear( 1, 1, 1, 1 ); + _state.buffers.depth.setTest( true ); + _state.setScissorTest( false ); -CubicBezierCurve3.prototype.isCubicBezierCurve3 = true; + // check for shadow map type changes -CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); - var point = optionalTarget || new Vector3(); + // render depth map - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + for ( let i = 0, il = lights.length; i < il; i ++ ) { - 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 ) - ); + const light = lights[ i ]; + const shadow = light.shadow; - return point; + if ( shadow === undefined ) { -}; + console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); + continue; -CubicBezierCurve3.prototype.copy = function ( source ) { + } - Curve.prototype.copy.call( this, source ); + if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); + _shadowMapSize.copy( shadow.mapSize ); - return this; + const shadowFrameExtents = shadow.getFrameExtents(); -}; + _shadowMapSize.multiply( shadowFrameExtents ); -CubicBezierCurve3.prototype.toJSON = function () { + _viewportSize.copy( shadow.mapSize ); - var data = Curve.prototype.toJSON.call( this ); + if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); - data.v3 = this.v3.toArray(); + if ( _shadowMapSize.x > _maxTextureSize ) { - return data; + _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); + _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; + shadow.mapSize.x = _viewportSize.x; -}; + } -CubicBezierCurve3.prototype.fromJSON = function ( json ) { + if ( _shadowMapSize.y > _maxTextureSize ) { - Curve.prototype.fromJSON.call( this, json ); + _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); + _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; + shadow.mapSize.y = _viewportSize.y; - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); - this.v3.fromArray( json.v3 ); + } - return this; + } -}; + if ( shadow.map === null || toVSM === true || fromVSM === true ) { -function LineCurve( v1, v2 ) { + const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; - Curve.call( this ); + if ( shadow.map !== null ) { - this.type = 'LineCurve'; + shadow.map.dispose(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); + } -} + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); + shadow.map.texture.name = light.name + '.shadowMap'; -LineCurve.prototype = Object.create( Curve.prototype ); -LineCurve.prototype.constructor = LineCurve; + shadow.camera.updateProjectionMatrix(); -LineCurve.prototype.isLineCurve = true; + } -LineCurve.prototype.getPoint = function ( t, optionalTarget ) { + renderer.setRenderTarget( shadow.map ); + renderer.clear(); - var point = optionalTarget || new Vector2(); + const viewportCount = shadow.getViewportCount(); - if ( t === 1 ) { + for ( let vp = 0; vp < viewportCount; vp ++ ) { - point.copy( this.v2 ); + const viewport = shadow.getViewport( vp ); - } else { + _viewport.set( + _viewportSize.x * viewport.x, + _viewportSize.y * viewport.y, + _viewportSize.x * viewport.z, + _viewportSize.y * viewport.w + ); - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); + _state.viewport( _viewport ); - } + shadow.updateMatrices( light, vp ); - return point; + _frustum = shadow.getFrustum(); -}; + renderObject( scene, camera, shadow.camera, light, this.type ); -// Line curve is linear, so we can overwrite default getPointAt + } -LineCurve.prototype.getPointAt = function ( u, optionalTarget ) { + // do blur pass for VSM - return this.getPoint( u, optionalTarget ); + if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { -}; + VSMPass( shadow, camera ); -LineCurve.prototype.getTangent = function ( /* t */ ) { + } - var tangent = this.v2.clone().sub( this.v1 ); + shadow.needsUpdate = false; - return tangent.normalize(); + } -}; + _previousType = this.type; -LineCurve.prototype.copy = function ( source ) { + scope.needsUpdate = false; - Curve.prototype.copy.call( this, source ); + renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + }; - return this; + function VSMPass( shadow, camera ) { -}; + const geometry = objects.update( fullScreenMesh ); -LineCurve.prototype.toJSON = function () { + if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { - var data = Curve.prototype.toJSON.call( this ); + shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + shadowMaterialVertical.needsUpdate = true; + shadowMaterialHorizontal.needsUpdate = true; - return data; + } -}; + if ( shadow.mapPass === null ) { -LineCurve.prototype.fromJSON = function ( json ) { + shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); - Curve.prototype.fromJSON.call( this, json ); + } - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + // vertical pass - return this; + 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 ); -}; + // horizontal pass -function LineCurve3( v1, v2 ) { + 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 ); - Curve.call( this ); + } - this.type = 'LineCurve3'; + function getDepthMaterial( object, material, light, type ) { - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); + let result = null; -} + const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; -LineCurve3.prototype = Object.create( Curve.prototype ); -LineCurve3.prototype.constructor = LineCurve3; + if ( customMaterial !== undefined ) { -LineCurve3.prototype.isLineCurve3 = true; + result = customMaterial; -LineCurve3.prototype.getPoint = function ( t, optionalTarget ) { + } else { - var point = optionalTarget || new Vector3(); + result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial; - if ( t === 1 ) { + if ( ( renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || + ( material.displacementMap && material.displacementScale !== 0 ) || + ( material.alphaMap && material.alphaTest > 0 ) || + ( material.map && material.alphaTest > 0 ) ) { - point.copy( this.v2 ); + // in this case we need a unique material instance reflecting the + // appropriate state - } else { + const keyA = result.uuid, keyB = material.uuid; - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); + let materialsForVariant = _materialCache[ keyA ]; - } + if ( materialsForVariant === undefined ) { - return point; + materialsForVariant = {}; + _materialCache[ keyA ] = materialsForVariant; -}; + } -// Line curve is linear, so we can overwrite default getPointAt + let cachedMaterial = materialsForVariant[ keyB ]; -LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) { + if ( cachedMaterial === undefined ) { - return this.getPoint( u, optionalTarget ); + cachedMaterial = result.clone(); + materialsForVariant[ keyB ] = cachedMaterial; + material.addEventListener( 'dispose', onMaterialDispose ); -}; + } -LineCurve3.prototype.copy = function ( source ) { + result = cachedMaterial; - Curve.prototype.copy.call( this, source ); + } - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + } - return this; + result.visible = material.visible; + result.wireframe = material.wireframe; -}; + if ( type === VSMShadowMap ) { -LineCurve3.prototype.toJSON = function () { + result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; - var data = Curve.prototype.toJSON.call( this ); + } else { - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; - return data; + } -}; + result.alphaMap = material.alphaMap; + result.alphaTest = material.alphaTest; + result.map = material.map; -LineCurve3.prototype.fromJSON = function ( json ) { + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; - Curve.prototype.fromJSON.call( this, json ); + result.displacementMap = material.displacementMap; + result.displacementScale = material.displacementScale; + result.displacementBias = material.displacementBias; - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; - return this; + if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { -}; + const materialProperties = renderer.properties.get( result ); + materialProperties.light = light; -function QuadraticBezierCurve( v0, v1, v2 ) { + } - Curve.call( this ); + return result; - this.type = 'QuadraticBezierCurve'; + } - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); + function renderObject( object, camera, shadowCamera, light, type ) { -} + if ( object.visible === false ) return; -QuadraticBezierCurve.prototype = Object.create( Curve.prototype ); -QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve; + const visible = object.layers.test( camera.layers ); -QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true; + if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { -QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { + if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - var point = optionalTarget || new Vector2(); + object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2; + const geometry = objects.update( object ); + const material = object.material; - point.set( - QuadraticBezier( t, v0.x, v1.x, v2.x ), - QuadraticBezier( t, v0.y, v1.y, v2.y ) - ); + if ( Array.isArray( material ) ) { - return point; + const groups = geometry.groups; -}; + for ( let k = 0, kl = groups.length; k < kl; k ++ ) { -QuadraticBezierCurve.prototype.copy = function ( source ) { + const group = groups[ k ]; + const groupMaterial = material[ group.materialIndex ]; - Curve.prototype.copy.call( this, source ); + if ( groupMaterial && groupMaterial.visible ) { - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); - return this; + object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); -}; + renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); -QuadraticBezierCurve.prototype.toJSON = function () { + object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); - var data = Curve.prototype.toJSON.call( this ); + } - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + } - return data; + } else if ( material.visible ) { -}; + const depthMaterial = getDepthMaterial( object, material, light, type ); -QuadraticBezierCurve.prototype.fromJSON = function ( json ) { + object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); - Curve.prototype.fromJSON.call( this, json ); + renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); - return this; + } -}; + } -function QuadraticBezierCurve3( v0, v1, v2 ) { + } - Curve.call( this ); + const children = object.children; - this.type = 'QuadraticBezierCurve3'; + for ( let i = 0, l = children.length; i < l; i ++ ) { - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); + renderObject( children[ i ], camera, shadowCamera, light, type ); -} + } -QuadraticBezierCurve3.prototype = Object.create( Curve.prototype ); -QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3; + } -QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true; + function onMaterialDispose( event ) { -QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { + const material = event.target; - var point = optionalTarget || new Vector3(); + material.removeEventListener( 'dispose', onMaterialDispose ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2; + // make sure to remove the unique distance/depth materials used for shadow map rendering - 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 ) - ); + for ( const id in _materialCache ) { - return point; + const cache = _materialCache[ id ]; -}; + const uuid = event.target.uuid; -QuadraticBezierCurve3.prototype.copy = function ( source ) { + if ( uuid in cache ) { - Curve.prototype.copy.call( this, source ); + const shadowMaterial = cache[ uuid ]; + shadowMaterial.dispose(); + delete cache[ uuid ]; - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + } - return this; + } -}; + } -QuadraticBezierCurve3.prototype.toJSON = function () { +} - var data = Curve.prototype.toJSON.call( this ); +function WebGLState( gl ) { - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + function ColorBuffer() { - return data; + let locked = false; -}; + const color = new Vector4(); + let currentColorMask = null; + const currentColorClear = new Vector4( 0, 0, 0, 0 ); -QuadraticBezierCurve3.prototype.fromJSON = function ( json ) { + return { - Curve.prototype.fromJSON.call( this, json ); + setMask: function ( colorMask ) { - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + if ( currentColorMask !== colorMask && ! locked ) { - return this; + gl.colorMask( colorMask, colorMask, colorMask, colorMask ); + currentColorMask = colorMask; -}; + } -function SplineCurve( points /* array of Vector2 */ ) { + }, - Curve.call( this ); + setLocked: function ( lock ) { - this.type = 'SplineCurve'; + locked = lock; - this.points = points || []; + }, -} + setClear: function ( r, g, b, a, premultipliedAlpha ) { -SplineCurve.prototype = Object.create( Curve.prototype ); -SplineCurve.prototype.constructor = SplineCurve; + if ( premultipliedAlpha === true ) { -SplineCurve.prototype.isSplineCurve = true; + r *= a; g *= a; b *= a; -SplineCurve.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new Vector2(); + color.set( r, g, b, a ); - var points = this.points; - var p = ( points.length - 1 ) * t; + if ( currentColorClear.equals( color ) === false ) { - var intPoint = Math.floor( p ); - var weight = p - intPoint; + gl.clearColor( r, g, b, a ); + currentColorClear.copy( color ); - var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; - var p1 = points[ intPoint ]; - var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; - var 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; + reset: function () { -}; + locked = false; -SplineCurve.prototype.copy = function ( source ) { + currentColorMask = null; + currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state - Curve.prototype.copy.call( this, source ); + } - this.points = []; + }; - for ( var i = 0, l = source.points.length; i < l; i ++ ) { + } - var point = source.points[ i ]; + function DepthBuffer() { - this.points.push( point.clone() ); + let locked = false; - } + let currentDepthMask = null; + let currentDepthFunc = null; + let currentDepthClear = null; - return this; + return { -}; + setTest: function ( depthTest ) { -SplineCurve.prototype.toJSON = function () { + if ( depthTest ) { - var data = Curve.prototype.toJSON.call( this ); + enable( gl.DEPTH_TEST ); - data.points = []; + } else { - for ( var i = 0, l = this.points.length; i < l; i ++ ) { + disable( gl.DEPTH_TEST ); - var point = this.points[ i ]; - data.points.push( point.toArray() ); + } - } + }, - return data; + setMask: function ( depthMask ) { -}; + if ( currentDepthMask !== depthMask && ! locked ) { -SplineCurve.prototype.fromJSON = function ( json ) { + gl.depthMask( depthMask ); + currentDepthMask = depthMask; - Curve.prototype.fromJSON.call( this, json ); + } - this.points = []; + }, - for ( var i = 0, l = json.points.length; i < l; i ++ ) { + setFunc: function ( depthFunc ) { - var point = json.points[ i ]; - this.points.push( new Vector2().fromArray( point ) ); + if ( currentDepthFunc !== depthFunc ) { - } + switch ( depthFunc ) { - return this; + case NeverDepth: -}; + gl.depthFunc( gl.NEVER ); + break; + case AlwaysDepth: + gl.depthFunc( gl.ALWAYS ); + break; -var Curves = Object.freeze({ - ArcCurve: ArcCurve, - CatmullRomCurve3: CatmullRomCurve3, - CubicBezierCurve: CubicBezierCurve, - CubicBezierCurve3: CubicBezierCurve3, - EllipseCurve: EllipseCurve, - LineCurve: LineCurve, - LineCurve3: LineCurve3, - QuadraticBezierCurve: QuadraticBezierCurve, - QuadraticBezierCurve3: QuadraticBezierCurve3, - SplineCurve: SplineCurve -}); + case LessDepth: -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - **/ + gl.depthFunc( gl.LESS ); + break; -/************************************************************** - * Curved Path - a curve path is simply a array of connected - * curves, but retains the api of a curve - **************************************************************/ + case LessEqualDepth: -function CurvePath() { + gl.depthFunc( gl.LEQUAL ); + break; - Curve.call( this ); + case EqualDepth: - this.type = 'CurvePath'; + gl.depthFunc( gl.EQUAL ); + break; - this.curves = []; - this.autoClose = false; // Automatically closes the path + case GreaterEqualDepth: -} + gl.depthFunc( gl.GEQUAL ); + break; -CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), { + case GreaterDepth: - constructor: CurvePath, + gl.depthFunc( gl.GREATER ); + break; - add: function ( curve ) { + case NotEqualDepth: - this.curves.push( curve ); + gl.depthFunc( gl.NOTEQUAL ); + break; - }, + default: - closePath: function () { + gl.depthFunc( gl.LEQUAL ); - // Add a line curve if start and end of lines are not connected - var startPoint = this.curves[ 0 ].getPoint( 0 ); - var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); + } - if ( ! startPoint.equals( endPoint ) ) { + currentDepthFunc = depthFunc; - this.curves.push( new LineCurve( endPoint, startPoint ) ); + } - } + }, - }, + setLocked: function ( lock ) { - // To get accurate point with reference to - // entire path distance at time t, - // following has to be done: + locked = lock; - // 1. Length of each sub path have to be known - // 2. Locate and identify type of curve - // 3. Get t for the curve - // 4. Return curve.getPointAt(t') + }, - getPoint: function ( t ) { + setClear: function ( depth ) { - var d = t * this.getLength(); - var curveLengths = this.getCurveLengths(); - var i = 0; + if ( currentDepthClear !== depth ) { - // To think about boundaries points. + gl.clearDepth( depth ); + currentDepthClear = depth; - while ( i < curveLengths.length ) { + } - if ( curveLengths[ i ] >= d ) { + }, - var diff = curveLengths[ i ] - d; - var curve = this.curves[ i ]; + reset: function () { - var segmentLength = curve.getLength(); - var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; + locked = false; - return curve.getPointAt( u ); + currentDepthMask = null; + currentDepthFunc = null; + currentDepthClear = null; } - i ++; - - } - - return null; + }; - // loop where sum != 0, sum > d , sum+1 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { + const colorBuffer = new ColorBuffer(); + const depthBuffer = new DepthBuffer(); + const stencilBuffer = new StencilBuffer(); - points.push( points[ 0 ] ); + const uboBindings = new WeakMap(); + const uboProgramMap = new WeakMap(); - } + let enabledCapabilities = {}; - return points; + let currentBoundFramebuffers = {}; + let currentDrawbuffers = new WeakMap(); + let defaultDrawbuffers = []; - }, + let currentProgram = null; - copy: function ( source ) { + 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 currentBlendColor = new Color( 0, 0, 0 ); + let currentBlendAlpha = 0; + let currentPremultipledAlpha = false; - Curve.prototype.copy.call( this, source ); + let currentFlipSided = null; + let currentCullFace = null; - this.curves = []; + let currentLineWidth = null; - for ( var i = 0, l = source.curves.length; i < l; i ++ ) { + let currentPolygonOffsetFactor = null; + let currentPolygonOffsetUnits = null; - var curve = source.curves[ i ]; + const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); - this.curves.push( curve.clone() ); + let lineWidthAvailable = false; + let version = 0; + const glVersion = gl.getParameter( gl.VERSION ); - } + if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { - this.autoClose = source.autoClose; + version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); + lineWidthAvailable = ( version >= 1.0 ); - return this; + } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { - }, + version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); + lineWidthAvailable = ( version >= 2.0 ); - toJSON: function () { + } - var data = Curve.prototype.toJSON.call( this ); + let currentTextureSlot = null; + let currentBoundTextures = {}; - data.autoClose = this.autoClose; - data.curves = []; + const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); + const viewportParam = gl.getParameter( gl.VIEWPORT ); - for ( var i = 0, l = this.curves.length; i < l; i ++ ) { + const currentScissor = new Vector4().fromArray( scissorParam ); + const currentViewport = new Vector4().fromArray( viewportParam ); - var curve = this.curves[ i ]; - data.curves.push( curve.toJSON() ); + function createTexture( type, target, count, dimensions ) { - } + const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. + const texture = gl.createTexture(); - return data; + gl.bindTexture( type, texture ); + gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - }, + for ( let i = 0; i < count; i ++ ) { - fromJSON: function ( json ) { + if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) { - Curve.prototype.fromJSON.call( this, json ); + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); - this.autoClose = json.autoClose; - this.curves = []; + } else { - for ( var i = 0, l = json.curves.length; i < l; i ++ ) { + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); - var curve = json.curves[ i ]; - this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); + } } - return this; + return texture; } -} ); - -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Creates free form 2d path using series of points, lines or curves. - **/ + 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 ); + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); -function Path$1( points ) { + // init - CurvePath.call( this ); + colorBuffer.setClear( 0, 0, 0, 1 ); + depthBuffer.setClear( 1 ); + stencilBuffer.setClear( 0 ); - this.type = 'Path'; + enable( gl.DEPTH_TEST ); + depthBuffer.setFunc( LessEqualDepth ); - this.currentPoint = new Vector2(); + setFlipSided( false ); + setCullFace( CullFaceBack ); + enable( gl.CULL_FACE ); - if ( points ) { + setBlending( NoBlending ); - this.setFromPoints( points ); + // - } + function enable( id ) { -} + if ( enabledCapabilities[ id ] !== true ) { -Path$1.prototype = Object.assign( Object.create( CurvePath.prototype ), { + gl.enable( id ); + enabledCapabilities[ id ] = true; - constructor: Path$1, + } - setFromPoints: function ( points ) { + } - this.moveTo( points[ 0 ].x, points[ 0 ].y ); + function disable( id ) { - for ( var i = 1, l = points.length; i < l; i ++ ) { + if ( enabledCapabilities[ id ] !== false ) { - this.lineTo( points[ i ].x, points[ i ].y ); + gl.disable( id ); + enabledCapabilities[ id ] = false; } - }, - - moveTo: function ( x, y ) { + } - this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? + function bindFramebuffer( target, framebuffer ) { - }, + if ( currentBoundFramebuffers[ target ] !== framebuffer ) { - lineTo: function ( x, y ) { + gl.bindFramebuffer( target, framebuffer ); - var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); - this.curves.push( curve ); + currentBoundFramebuffers[ target ] = framebuffer; - this.currentPoint.set( x, y ); + // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER - }, + if ( target === gl.DRAW_FRAMEBUFFER ) { - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { + currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; - var curve = new QuadraticBezierCurve( - this.currentPoint.clone(), - new Vector2( aCPx, aCPy ), - new Vector2( aX, aY ) - ); + } - this.curves.push( curve ); + if ( target === gl.FRAMEBUFFER ) { - this.currentPoint.set( aX, aY ); + currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; - }, + } - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + return true; - var curve = new CubicBezierCurve( - this.currentPoint.clone(), - new Vector2( aCP1x, aCP1y ), - new Vector2( aCP2x, aCP2y ), - new Vector2( aX, aY ) - ); + } - this.curves.push( curve ); + return false; - this.currentPoint.set( aX, aY ); + } - }, + function drawBuffers( renderTarget, framebuffer ) { - splineThru: function ( pts /*Array of Vector*/ ) { + let drawBuffers = defaultDrawbuffers; - var npts = [ this.currentPoint.clone() ].concat( pts ); + let needsUpdate = false; - var curve = new SplineCurve( npts ); - this.curves.push( curve ); + if ( renderTarget ) { - this.currentPoint.copy( pts[ pts.length - 1 ] ); + drawBuffers = currentDrawbuffers.get( framebuffer ); - }, + if ( drawBuffers === undefined ) { - arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + drawBuffers = []; + currentDrawbuffers.set( framebuffer, drawBuffers ); - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; + } - this.absarc( aX + x0, aY + y0, aRadius, - aStartAngle, aEndAngle, aClockwise ); + const textures = renderTarget.textures; - }, + if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { - absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; - }, + } - ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + drawBuffers.length = textures.length; - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; + needsUpdate = true; - this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + } - }, + } else { - absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + if ( drawBuffers[ 0 ] !== gl.BACK ) { - var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + drawBuffers[ 0 ] = gl.BACK; - if ( this.curves.length > 0 ) { + needsUpdate = true; - // if a previous curve is present, attempt to join - var firstPoint = curve.getPoint( 0 ); + } - if ( ! firstPoint.equals( this.currentPoint ) ) { + } - this.lineTo( firstPoint.x, firstPoint.y ); + if ( needsUpdate ) { - } + gl.drawBuffers( drawBuffers ); } - this.curves.push( curve ); + } - var lastPoint = curve.getPoint( 1 ); - this.currentPoint.copy( lastPoint ); + function useProgram( program ) { - }, + if ( currentProgram !== program ) { - copy: function ( source ) { + gl.useProgram( program ); - CurvePath.prototype.copy.call( this, source ); + currentProgram = program; - this.currentPoint.copy( source.currentPoint ); + return true; - return this; + } - }, + return false; - toJSON: function () { + } - var data = CurvePath.prototype.toJSON.call( this ); + const equationToGL = { + [ AddEquation ]: gl.FUNC_ADD, + [ SubtractEquation ]: gl.FUNC_SUBTRACT, + [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT + }; - data.currentPoint = this.currentPoint.toArray(); + equationToGL[ MinEquation ] = gl.MIN; + equationToGL[ MaxEquation ] = gl.MAX; + + const factorToGL = { + [ ZeroFactor ]: gl.ZERO, + [ OneFactor ]: gl.ONE, + [ SrcColorFactor ]: gl.SRC_COLOR, + [ SrcAlphaFactor ]: gl.SRC_ALPHA, + [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, + [ DstColorFactor ]: gl.DST_COLOR, + [ DstAlphaFactor ]: gl.DST_ALPHA, + [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, + [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, + [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, + [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, + [ ConstantColorFactor ]: gl.CONSTANT_COLOR, + [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, + [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, + [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA + }; - return data; + function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { - }, + if ( blending === NoBlending ) { - fromJSON: function ( json ) { + if ( currentBlendingEnabled === true ) { - CurvePath.prototype.fromJSON.call( this, json ); + disable( gl.BLEND ); + currentBlendingEnabled = false; - this.currentPoint.fromArray( json.currentPoint ); + } - return this; + return; - } + } -} ); + if ( currentBlendingEnabled === false ) { -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Defines a 2d shape plane using paths. - **/ + enable( gl.BLEND ); + currentBlendingEnabled = true; -// STEP 1 Create a path. -// STEP 2 Turn path into shape. -// STEP 3 ExtrudeGeometry takes in Shape/Shapes -// STEP 3a - Extract points from each shape, turn to vertices -// STEP 3b - Triangulate each shape, add faces. + } -function Shape( points ) { + if ( blending !== CustomBlending ) { - Path$1.call( this, points ); + if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { - this.uuid = _Math.generateUUID(); + if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { - this.type = 'Shape'; + gl.blendEquation( gl.FUNC_ADD ); - this.holes = []; + currentBlendEquation = AddEquation; + currentBlendEquationAlpha = AddEquation; -} + } -Shape.prototype = Object.assign( Object.create( Path$1.prototype ), { + if ( premultipliedAlpha ) { - constructor: Shape, + switch ( blending ) { - getPointsHoles: function ( divisions ) { + case NormalBlending: + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; - var holesPts = []; + case AdditiveBlending: + gl.blendFunc( gl.ONE, gl.ONE ); + break; - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; - holesPts[ i ] = this.holes[ i ].getPoints( divisions ); + case MultiplyBlending: + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + break; - } + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; - return holesPts; + } - }, + } else { - // get points of shape and holes (keypoints based on segments parameter) + switch ( blending ) { - extractPoints: function ( divisions ) { + case NormalBlending: + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; - return { + case AdditiveBlending: + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + break; - shape: this.getPoints( divisions ), - holes: this.getPointsHoles( divisions ) + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; - }; + case MultiplyBlending: + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + break; - }, + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; - copy: function ( source ) { + } - Path$1.prototype.copy.call( this, source ); + } - this.holes = []; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlendColor.set( 0, 0, 0 ); + currentBlendAlpha = 0; - for ( var i = 0, l = source.holes.length; i < l; i ++ ) { + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; - var hole = source.holes[ i ]; + } - this.holes.push( hole.clone() ); + return; } - return this; - - }, - - toJSON: function () { + // custom blending - var data = Path$1.prototype.toJSON.call( this ); + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; - data.uuid = this.uuid; - data.holes = []; + if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { + gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); - var hole = this.holes[ i ]; - data.holes.push( hole.toJSON() ); + currentBlendEquation = blendEquation; + currentBlendEquationAlpha = blendEquationAlpha; } - return data; + if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { - }, + gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); - fromJSON: function ( json ) { + currentBlendSrc = blendSrc; + currentBlendDst = blendDst; + currentBlendSrcAlpha = blendSrcAlpha; + currentBlendDstAlpha = blendDstAlpha; - Path$1.prototype.fromJSON.call( this, json ); + } - this.uuid = json.uuid; - this.holes = []; + if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) { - for ( var i = 0, l = json.holes.length; i < l; i ++ ) { + gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); - var hole = json.holes[ i ]; - this.holes.push( new Path$1().fromJSON( hole ) ); + currentBlendColor.copy( blendColor ); + currentBlendAlpha = blendAlpha; } - return this; + currentBlending = blending; + currentPremultipledAlpha = false; } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + function setMaterial( material, frontFaceCW ) { -function Light( color, intensity ) { + material.side === DoubleSide + ? disable( gl.CULL_FACE ) + : enable( gl.CULL_FACE ); - Object3D.call( this ); + let flipSided = ( material.side === BackSide ); + if ( frontFaceCW ) flipSided = ! flipSided; - this.type = 'Light'; + setFlipSided( flipSided ); - this.color = new Color( color ); - this.intensity = intensity !== undefined ? intensity : 1; + ( material.blending === NormalBlending && material.transparent === false ) + ? setBlending( NoBlending ) + : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); - this.receiveShadow = undefined; + 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 ) { -Light.prototype = Object.assign( Object.create( Object3D.prototype ), { + stencilBuffer.setMask( material.stencilWriteMask ); + stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); + stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); - constructor: Light, + } - isLight: true, + setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - copy: function ( source ) { + material.alphaToCoverage === true + ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) + : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); - Object3D.prototype.copy.call( this, source ); + } - this.color.copy( source.color ); - this.intensity = source.intensity; + // - return this; + function setFlipSided( flipSided ) { - }, + if ( currentFlipSided !== flipSided ) { - toJSON: function ( meta ) { + if ( flipSided ) { - var data = Object3D.prototype.toJSON.call( this, meta ); + gl.frontFace( gl.CW ); - data.object.color = this.color.getHex(); - data.object.intensity = this.intensity; + } else { - if ( this.groundColor !== undefined ) { data.object.groundColor = this.groundColor.getHex(); } + gl.frontFace( gl.CCW ); - if ( this.distance !== undefined ) { data.object.distance = this.distance; } - if ( this.angle !== undefined ) { data.object.angle = this.angle; } - if ( this.decay !== undefined ) { data.object.decay = this.decay; } - if ( this.penumbra !== undefined ) { data.object.penumbra = this.penumbra; } + } - if ( this.shadow !== undefined ) { data.object.shadow = this.shadow.toJSON(); } + currentFlipSided = flipSided; - return data; + } } -} ); + function setCullFace( cullFace ) { -/** - * @author alteredq / http://alteredqualia.com/ - */ + if ( cullFace !== CullFaceNone ) { -function HemisphereLight( skyColor, groundColor, intensity ) { + enable( gl.CULL_FACE ); - Light.call( this, skyColor, intensity ); + if ( cullFace !== currentCullFace ) { - this.type = 'HemisphereLight'; + if ( cullFace === CullFaceBack ) { - this.castShadow = undefined; + gl.cullFace( gl.BACK ); - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + } else if ( cullFace === CullFaceFront ) { - this.groundColor = new Color( groundColor ); + gl.cullFace( gl.FRONT ); -} + } else { -HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), { + gl.cullFace( gl.FRONT_AND_BACK ); - constructor: HemisphereLight, + } - isHemisphereLight: true, + } - copy: function ( source ) { + } else { - Light.prototype.copy.call( this, source ); + disable( gl.CULL_FACE ); - this.groundColor.copy( source.groundColor ); + } - return this; + currentCullFace = cullFace; } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function LightShadow( camera ) { - - this.camera = camera; - - this.bias = 0; - this.radius = 1; - - this.mapSize = new Vector2( 512, 512 ); - - this.map = null; - this.matrix = new Matrix4(); - -} + function setLineWidth( width ) { -Object.assign( LightShadow.prototype, { + if ( width !== currentLineWidth ) { - copy: function ( source ) { + if ( lineWidthAvailable ) gl.lineWidth( width ); - this.camera = source.camera.clone(); + currentLineWidth = width; - this.bias = source.bias; - this.radius = source.radius; + } - this.mapSize.copy( source.mapSize ); + } - return this; + function setPolygonOffset( polygonOffset, factor, units ) { - }, + if ( polygonOffset ) { - clone: function () { + enable( gl.POLYGON_OFFSET_FILL ); - return new this.constructor().copy( this ); + if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { - }, + gl.polygonOffset( factor, units ); - toJSON: function () { + currentPolygonOffsetFactor = factor; + currentPolygonOffsetUnits = units; - var object = {}; + } - if ( this.bias !== 0 ) { object.bias = this.bias; } - if ( this.radius !== 1 ) { object.radius = this.radius; } - if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) { object.mapSize = this.mapSize.toArray(); } + } else { - object.camera = this.camera.toJSON( false ).object; - delete object.camera.matrix; + disable( gl.POLYGON_OFFSET_FILL ); - return object; + } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ + function setScissorTest( scissorTest ) { -function SpotLightShadow() { + if ( scissorTest ) { - LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) ); + enable( gl.SCISSOR_TEST ); -} + } else { -SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { + disable( gl.SCISSOR_TEST ); - constructor: SpotLightShadow, + } - isSpotLightShadow: true, + } - update: function ( light ) { + // texture - var camera = this.camera; + function activeTexture( webglSlot ) { - var fov = _Math.RAD2DEG * 2 * light.angle; - var aspect = this.mapSize.width / this.mapSize.height; - var far = light.distance || camera.far; + if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; - if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { + if ( currentTextureSlot !== webglSlot ) { - camera.fov = fov; - camera.aspect = aspect; - camera.far = far; - camera.updateProjectionMatrix(); + gl.activeTexture( webglSlot ); + currentTextureSlot = webglSlot; } } -} ); + function bindTexture( webglType, webglTexture, webglSlot ) { -/** - * @author alteredq / http://alteredqualia.com/ - */ + if ( webglSlot === undefined ) { -function SpotLight( color, intensity, distance, angle, penumbra, decay ) { + if ( currentTextureSlot === null ) { - Light.call( this, color, intensity ); + webglSlot = gl.TEXTURE0 + maxTextures - 1; - this.type = 'SpotLight'; + } else { - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + webglSlot = currentTextureSlot; - this.target = new Object3D(); + } - Object.defineProperty( this, 'power', { - get: function () { + } - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * Math.PI; + let boundTexture = currentBoundTextures[ webglSlot ]; - }, - set: function ( power ) { + if ( boundTexture === undefined ) { - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / Math.PI; + boundTexture = { type: undefined, texture: undefined }; + currentBoundTextures[ webglSlot ] = boundTexture; } - } ); - this.distance = ( distance !== undefined ) ? distance : 0; - this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; - this.penumbra = ( penumbra !== undefined ) ? penumbra : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. + if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { - this.shadow = new SpotLightShadow(); + if ( currentTextureSlot !== webglSlot ) { -} + gl.activeTexture( webglSlot ); + currentTextureSlot = webglSlot; -SpotLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: SpotLight, + gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); - isSpotLight: true, + boundTexture.type = webglType; + boundTexture.texture = webglTexture; - copy: function ( source ) { + } - Light.prototype.copy.call( this, source ); + } - this.distance = source.distance; - this.angle = source.angle; - this.penumbra = source.penumbra; - this.decay = source.decay; + function unbindTexture() { - this.target = source.target.clone(); + const boundTexture = currentBoundTextures[ currentTextureSlot ]; - this.shadow = source.shadow.clone(); + if ( boundTexture !== undefined && boundTexture.type !== undefined ) { - return this; + gl.bindTexture( boundTexture.type, null ); - } + boundTexture.type = undefined; + boundTexture.texture = undefined; -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + } + function compressedTexImage2D() { -function PointLight( color, intensity, distance, decay ) { + try { - Light.call( this, color, intensity ); + gl.compressedTexImage2D.apply( gl, arguments ); - this.type = 'PointLight'; + } catch ( error ) { - Object.defineProperty( this, 'power', { - get: function () { + console.error( 'THREE.WebGLState:', error ); - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * 4 * Math.PI; + } - }, - set: function ( power ) { + } - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / ( 4 * Math.PI ); + function compressedTexImage3D() { - } - } ); + try { - this.distance = ( distance !== undefined ) ? distance : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. + gl.compressedTexImage3D.apply( gl, arguments ); - this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -PointLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: PointLight, + } - isPointLight: true, + function texSubImage2D() { - copy: function ( source ) { + try { - Light.prototype.copy.call( this, source ); + gl.texSubImage2D.apply( gl, arguments ); - this.distance = source.distance; - this.decay = source.decay; + } catch ( error ) { - this.shadow = source.shadow.clone(); + console.error( 'THREE.WebGLState:', error ); - return this; + } } -} ); + function texSubImage3D() { -/** - * @author mrdoob / http://mrdoob.com/ - */ + try { -function DirectionalLightShadow( ) { + gl.texSubImage3D.apply( gl, arguments ); - LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { + } - constructor: DirectionalLightShadow + } -} ); + function compressedTexSubImage2D() { -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + try { + + gl.compressedTexSubImage2D.apply( gl, arguments ); -function DirectionalLight( color, intensity ) { + } catch ( error ) { - Light.call( this, color, intensity ); + console.error( 'THREE.WebGLState:', error ); - this.type = 'DirectionalLight'; + } - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + } - this.target = new Object3D(); + function compressedTexSubImage3D() { - this.shadow = new DirectionalLightShadow(); + try { -} + gl.compressedTexSubImage3D.apply( gl, arguments ); -DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), { + } catch ( error ) { - constructor: DirectionalLight, + console.error( 'THREE.WebGLState:', error ); - isDirectionalLight: true, + } - copy: function ( source ) { + } - Light.prototype.copy.call( this, source ); + function texStorage2D() { - this.target = source.target.clone(); + try { - this.shadow = source.shadow.clone(); + gl.texStorage2D.apply( gl, arguments ); - return this; + } catch ( error ) { - } + console.error( 'THREE.WebGLState:', error ); -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function AmbientLight( color, intensity ) { + function texStorage3D() { - Light.call( this, color, intensity ); + try { - this.type = 'AmbientLight'; + gl.texStorage3D.apply( gl, arguments ); - this.castShadow = undefined; + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: AmbientLight, + } - isAmbientLight: true + function texImage2D() { -} ); + try { -/** - * @author abelnation / http://github.com/abelnation - */ + gl.texImage2D.apply( gl, arguments ); -function RectAreaLight( color, intensity, width, height ) { + } catch ( error ) { - Light.call( this, color, intensity ); + console.error( 'THREE.WebGLState:', error ); - this.type = 'RectAreaLight'; + } - this.position.set( 0, 1, 0 ); - this.updateMatrix(); + } - this.width = ( width !== undefined ) ? width : 10; - this.height = ( height !== undefined ) ? height : 10; + function texImage3D() { - // TODO (abelnation): distance/decay + try { - // TODO (abelnation): update method for RectAreaLight to update transform to lookat target + gl.texImage3D.apply( gl, arguments ); - // TODO (abelnation): shadows + } catch ( error ) { -} + console.error( 'THREE.WebGLState:', error ); -// TODO (abelnation): RectAreaLight update when light shape is changed -RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), { + } - constructor: RectAreaLight, + } - isRectAreaLight: true, + // - copy: function ( source ) { + function scissor( scissor ) { - Light.prototype.copy.call( this, source ); + if ( currentScissor.equals( scissor ) === false ) { - this.width = source.width; - this.height = source.height; + gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); + currentScissor.copy( scissor ); - return this; + } - }, + } - toJSON: function ( meta ) { + function viewport( viewport ) { - var data = Light.prototype.toJSON.call( this, meta ); + if ( currentViewport.equals( viewport ) === false ) { - data.object.width = this.width; - data.object.height = this.height; + gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); + currentViewport.copy( viewport ); - return data; + } } -} ); + function updateUBOMapping( uniformsGroup, program ) { -/** - * - * A Track that interpolates Strings - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + let mapping = uboProgramMap.get( program ); -function StringKeyframeTrack( name, times, values, interpolation ) { + if ( mapping === undefined ) { - KeyframeTrack.call( this, name, times, values, interpolation ); + mapping = new WeakMap(); -} + uboProgramMap.set( program, mapping ); -StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + } - constructor: StringKeyframeTrack, + let blockIndex = mapping.get( uniformsGroup ); - ValueTypeName: 'string', - ValueBufferType: Array, + if ( blockIndex === undefined ) { - DefaultInterpolation: InterpolateDiscrete, + blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); - InterpolantFactoryMethodLinear: undefined, + mapping.set( uniformsGroup, blockIndex ); - InterpolantFactoryMethodSmooth: undefined + } -} ); + } -/** - * - * A Track of Boolean keyframe values. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + function uniformBlockBinding( uniformsGroup, program ) { -function BooleanKeyframeTrack( name, times, values ) { + const mapping = uboProgramMap.get( program ); + const blockIndex = mapping.get( uniformsGroup ); - KeyframeTrack.call( this, name, times, values ); + if ( uboBindings.get( program ) !== blockIndex ) { -} + // bind shader specific block index to global block point + gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); -BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + uboBindings.set( program, blockIndex ); - constructor: BooleanKeyframeTrack, + } - ValueTypeName: 'bool', - ValueBufferType: Array, + } - DefaultInterpolation: InterpolateDiscrete, + // - InterpolantFactoryMethodLinear: undefined, - InterpolantFactoryMethodSmooth: undefined + function reset() { - // Note: Actually this track could have a optimized / compressed - // representation of a single value and a custom interpolant that - // computes "firstValue ^ isOdd( index )". + // reset state -} ); + 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 ); -/** - * Abstract base class of interpolants over parametric samples. - * - * The parameter domain is one dimensional, typically the time or a path - * along a curve defined by the data. - * - * The sample values can have any dimensionality and derived classes may - * apply special interpretations to the data. - * - * This class provides the interval seek in a Template Method, deferring - * the actual interpolation to derived classes. - * - * Time complexity is O(1) for linear access crossing at most two points - * and O(log N) for random access, where N is the number of positions. - * - * References: - * - * http://www.oodesign.com/template-method-pattern.html - * - * @author tschw - */ + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ONE, gl.ZERO ); + gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); + gl.blendColor( 0, 0, 0, 0 ); -function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + gl.colorMask( true, true, true, true ); + gl.clearColor( 0, 0, 0, 0 ); - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; + gl.depthMask( true ); + gl.depthFunc( gl.LESS ); + gl.clearDepth( 1 ); - this.resultBuffer = resultBuffer !== undefined ? - resultBuffer : new sampleValues.constructor( sampleSize ); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; + gl.stencilMask( 0xffffffff ); + gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); + gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); + gl.clearStencil( 0 ); -} + gl.cullFace( gl.BACK ); + gl.frontFace( gl.CCW ); -Object.assign( Interpolant.prototype, { + gl.polygonOffset( 0, 0 ); - evaluate: function ( t ) { + gl.activeTexture( gl.TEXTURE0 ); - var pp = this.parameterPositions, - i1 = this._cachedIndex, + gl.bindFramebuffer( gl.FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); - t1 = pp[ i1 ], - t0 = pp[ i1 - 1 ]; + gl.useProgram( null ); - validate_interval: { + gl.lineWidth( 1 ); - seek: { + gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); + gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); - var right; + // reset internals - linear_scan: { + enabledCapabilities = {}; - //- See http://jsperf.com/comparison-to-undefined/3 - //- slower code: - //- - //- if ( t >= t1 || t1 === undefined ) { - forward_scan: if ( ! ( t < t1 ) ) { + currentTextureSlot = null; + currentBoundTextures = {}; - for ( var giveUpAt = i1 + 2; ; ) { + currentBoundFramebuffers = {}; + currentDrawbuffers = new WeakMap(); + defaultDrawbuffers = []; - if ( t1 === undefined ) { + currentProgram = null; - if ( t < t0 ) { break forward_scan; } + currentBlendingEnabled = false; + currentBlending = null; + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlendColor = new Color( 0, 0, 0 ); + currentBlendAlpha = 0; + currentPremultipledAlpha = false; - // after end + currentFlipSided = null; + currentCullFace = null; - i1 = pp.length; - this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t, t0 ); + currentLineWidth = null; - } + currentPolygonOffsetFactor = null; + currentPolygonOffsetUnits = null; - if ( i1 === giveUpAt ) { break; } // this loop + currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); + currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); - t0 = t1; - t1 = pp[ ++ i1 ]; + colorBuffer.reset(); + depthBuffer.reset(); + stencilBuffer.reset(); - if ( t < t1 ) { + } - // we have arrived at the sought interval - break seek; + return { - } + buffers: { + color: colorBuffer, + depth: depthBuffer, + stencil: stencilBuffer + }, - } + enable: enable, + disable: disable, - // prepare binary search on the right side of the index - right = pp.length; - break linear_scan; + bindFramebuffer: bindFramebuffer, + drawBuffers: drawBuffers, - } + useProgram: useProgram, - //- slower code: - //- if ( t < t0 || t0 === undefined ) { - if ( ! ( t >= t0 ) ) { + setBlending: setBlending, + setMaterial: setMaterial, - // looping? + setFlipSided: setFlipSided, + setCullFace: setCullFace, - var t1global = pp[ 1 ]; + setLineWidth: setLineWidth, + setPolygonOffset: setPolygonOffset, - if ( t < t1global ) { + setScissorTest: setScissorTest, - i1 = 2; // + 1, using the scan for the details - t0 = t1global; + activeTexture: activeTexture, + bindTexture: bindTexture, + unbindTexture: unbindTexture, + compressedTexImage2D: compressedTexImage2D, + compressedTexImage3D: compressedTexImage3D, + texImage2D: texImage2D, + texImage3D: texImage3D, - } + updateUBOMapping: updateUBOMapping, + uniformBlockBinding: uniformBlockBinding, - // linear reverse scan + texStorage2D: texStorage2D, + texStorage3D: texStorage3D, + texSubImage2D: texSubImage2D, + texSubImage3D: texSubImage3D, + compressedTexSubImage2D: compressedTexSubImage2D, + compressedTexSubImage3D: compressedTexSubImage3D, - for ( var giveUpAt = i1 - 2; ; ) { + scissor: scissor, + viewport: viewport, - if ( t0 === undefined ) { + reset: reset - // before start + }; - this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); +} - } - if ( i1 === giveUpAt ) { break; } // this loop - t1 = t0; - t0 = pp[ -- i1 - 1 ]; +/** + * Given the width, height, format, and type of a texture. Determines how many + * bytes must be used to represent the texture. + */ +function getByteLength( width, height, format, type ) { + + const typeByteLength = getTextureTypeByteLength( type ); + + switch ( format ) { + + // https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml + case AlphaFormat: + return width * height; + case LuminanceFormat: + return width * height; + case LuminanceAlphaFormat: + return width * height * 2; + case RedFormat: + return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength; + case RedIntegerFormat: + return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGFormat: + return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGIntegerFormat: + return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBFormat: + return ( ( width * height * 3 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBAFormat: + return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBAIntegerFormat: + return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_s3tc_srgb/ + case RGB_S3TC_DXT1_Format: + case RGBA_S3TC_DXT1_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; + case RGBA_S3TC_DXT3_Format: + case RGBA_S3TC_DXT5_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_pvrtc/ + case RGB_PVRTC_2BPPV1_Format: + case RGBA_PVRTC_2BPPV1_Format: + return ( Math.max( width, 16 ) * Math.max( height, 8 ) ) / 4; + case RGB_PVRTC_4BPPV1_Format: + case RGBA_PVRTC_4BPPV1_Format: + return ( Math.max( width, 8 ) * Math.max( height, 8 ) ) / 2; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_etc/ + case RGB_ETC1_Format: + case RGB_ETC2_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; + case RGBA_ETC2_EAC_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/ + case RGBA_ASTC_4x4_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + case RGBA_ASTC_5x4_Format: + return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + case RGBA_ASTC_5x5_Format: + return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_6x5_Format: + return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_6x6_Format: + return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_8x5_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_8x6_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_8x8_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 7 ) / 8 ) * 16; + case RGBA_ASTC_10x5_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_10x6_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_10x8_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 7 ) / 8 ) * 16; + case RGBA_ASTC_10x10_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 9 ) / 10 ) * 16; + case RGBA_ASTC_12x10_Format: + return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 9 ) / 10 ) * 16; + case RGBA_ASTC_12x12_Format: + return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 11 ) / 12 ) * 16; + + // https://registry.khronos.org/webgl/extensions/EXT_texture_compression_bptc/ + case RGBA_BPTC_Format: + case RGB_BPTC_SIGNED_Format: + case RGB_BPTC_UNSIGNED_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/EXT_texture_compression_rgtc/ + case RED_RGTC1_Format: + case SIGNED_RED_RGTC1_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 8; + case RED_GREEN_RGTC2_Format: + case SIGNED_RED_GREEN_RGTC2_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16; + + } + + throw new Error( + `Unable to determine texture byte length for ${format} format.`, + ); - if ( t >= t0 ) { +} - // we have arrived at the sought interval - break seek; +function getTextureTypeByteLength( type ) { - } + switch ( type ) { - } + case UnsignedByteType: + case ByteType: + return { byteLength: 1, components: 1 }; + case UnsignedShortType: + case ShortType: + case HalfFloatType: + return { byteLength: 2, components: 1 }; + case UnsignedShort4444Type: + case UnsignedShort5551Type: + return { byteLength: 2, components: 4 }; + case UnsignedIntType: + case IntType: + case FloatType: + return { byteLength: 4, components: 1 }; + case UnsignedInt5999Type: + return { byteLength: 4, components: 3 }; - // prepare binary search on the left side of the index - right = i1; - i1 = 0; - break linear_scan; + } - } + throw new Error( `Unknown texture type ${type}.` ); - // the interval is valid +} - break validate_interval; +function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { - } // linear scan + const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; + const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); - // binary search + const _imageDimensions = new Vector2(); + const _videoTextures = new WeakMap(); + let _canvas; - while ( i1 < right ) { + const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source - var mid = ( i1 + right ) >>> 1; + // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, + // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! + // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). - if ( t < pp[ mid ] ) { + let useOffscreenCanvas = false; - right = mid; + try { - } else { + useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' + // eslint-disable-next-line compat/compat + && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; - i1 = mid + 1; + } catch ( err ) { - } + // Ignore any errors - } + } - t1 = pp[ i1 ]; - t0 = pp[ i1 - 1 ]; + function createCanvas( width, height ) { - // check boundary cases, again + // Use OffscreenCanvas when available. Specially needed in web workers - if ( t0 === undefined ) { + return useOffscreenCanvas ? + // eslint-disable-next-line compat/compat + new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); - this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); + } - } + function resizeImage( image, needsNewCanvas, maxSize ) { - if ( t1 === undefined ) { + let scale = 1; - i1 = pp.length; - this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t0, t ); + const dimensions = getDimensions( image ); - } + // handle case if texture exceeds max size - } // seek + if ( dimensions.width > maxSize || dimensions.height > maxSize ) { - this._cachedIndex = i1; + scale = maxSize / Math.max( dimensions.width, dimensions.height ); - this.intervalChanged_( i1, t0, t1 ); + } - } // validate_interval + // only perform resize if necessary - return this.interpolate_( i1, t0, t, t1 ); + if ( scale < 1 ) { - }, + // only perform resize for certain image types - settings: null, // optional, subclass-specific settings structure - // Note: The indirection allows central control of many interpolants. + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) || + ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) { - // --- Protected interface + const width = Math.floor( scale * dimensions.width ); + const height = Math.floor( scale * dimensions.height ); - DefaultSettings_: {}, + if ( _canvas === undefined ) _canvas = createCanvas( width, height ); - getSettings_: function () { + // cube textures can't reuse the same canvas - return this.settings || this.DefaultSettings_; + const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; - }, + canvas.width = width; + canvas.height = height; - copySampleValue_: function ( index ) { + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, width, height ); - // copies a sample value to the result buffer + console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - offset = index * stride; + return canvas; - for ( var i = 0; i !== stride; ++ i ) { + } else { - result[ i ] = values[ offset + i ]; + if ( 'data' in image ) { - } + console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); - return result; + } - }, + return image; - // Template methods for derived classes: + } - interpolate_: function ( /* i1, t0, t, t1 */ ) { + } - throw new Error( 'call to abstract method' ); - // implementations shall return this.resultBuffer + return image; - }, + } - intervalChanged_: function ( /* i1, t0, t1 */ ) { + function textureNeedsGenerateMipmaps( texture ) { - // empty + return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; } -} ); + function generateMipmap( target ) { -//!\ DECLARE ALIAS AFTER assign prototype ! -Object.assign( Interpolant.prototype, { + _gl.generateMipmap( target ); - //( 0, t, t0 ), returns this.resultBuffer - beforeStart_: Interpolant.prototype.copySampleValue_, + } - //( N-1, tN-1, t ), returns this.resultBuffer - afterEnd_: Interpolant.prototype.copySampleValue_, + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { -} ); + if ( internalFormatName !== null ) { -/** - * Spherical linear unit quaternion interpolant. - * - * @author tschw - */ + if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; -function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + } -} + let internalFormat = glFormat; -QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + if ( glFormat === _gl.RED ) { - constructor: QuaternionLinearInterpolant, + if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; - interpolate_: function ( i1, t0, t, t1 ) { + } - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + if ( glFormat === _gl.RED_INTEGER ) { - offset = i1 * stride, + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.R8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.R16I; + if ( glType === _gl.INT ) internalFormat = _gl.R32I; - alpha = ( t - t0 ) / ( t1 - t0 ); + } - for ( var end = offset + stride; offset !== end; offset += 4 ) { + if ( glFormat === _gl.RG ) { - Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); + if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; } - return result; + if ( glFormat === _gl.RG_INTEGER ) { - } + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I; + if ( glType === _gl.INT ) internalFormat = _gl.RG32I; -} ); + } -/** - * - * A Track of quaternion keyframe values. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + if ( glFormat === _gl.RGB ) { -function QuaternionKeyframeTrack( name, times, values, interpolation ) { + if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; - KeyframeTrack.call( this, name, times, values, interpolation ); + } -} + if ( glFormat === _gl.RGBA ) { -QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace ); - constructor: QuaternionKeyframeTrack, + if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _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; - ValueTypeName: 'quaternion', + } - // ValueBufferType is inherited + if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || + internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || + internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { - DefaultInterpolation: InterpolateLinear, + extensions.get( 'EXT_color_buffer_float' ); - InterpolantFactoryMethodLinear: function ( result ) { + } - return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); + return internalFormat; - }, + } - InterpolantFactoryMethodSmooth: undefined // not yet implemented + function getInternalDepthFormat( useStencil, depthType ) { -} ); + let glInternalFormat; + if ( useStencil ) { -/** - * - * A Track of keyframe values that represent color. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { -function ColorKeyframeTrack( name, times, values, interpolation ) { + glInternalFormat = _gl.DEPTH24_STENCIL8; - KeyframeTrack.call( this, name, times, values, interpolation ); + } else if ( depthType === FloatType ) { -} + glInternalFormat = _gl.DEPTH32F_STENCIL8; -ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + } else if ( depthType === UnsignedShortType ) { - constructor: ColorKeyframeTrack, + glInternalFormat = _gl.DEPTH24_STENCIL8; + console.warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' ); - ValueTypeName: 'color' + } - // ValueBufferType is inherited + } else { - // DefaultInterpolation is inherited + if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { - // Note: Very basic implementation and nothing special yet. - // However, this is the place for color space parameterization. + glInternalFormat = _gl.DEPTH_COMPONENT24; -} ); + } else if ( depthType === FloatType ) { -/** - * - * A Track of numeric keyframe values. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + glInternalFormat = _gl.DEPTH_COMPONENT32F; -function NumberKeyframeTrack( name, times, values, interpolation ) { + } else if ( depthType === UnsignedShortType ) { - KeyframeTrack.call( this, name, times, values, interpolation ); + glInternalFormat = _gl.DEPTH_COMPONENT16; -} + } -NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + } - constructor: NumberKeyframeTrack, + return glInternalFormat; - ValueTypeName: 'number' + } - // ValueBufferType is inherited + function getMipLevels( texture, image ) { - // DefaultInterpolation is inherited + if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { -} ); + return Math.log2( Math.max( image.width, image.height ) ) + 1; -/** - * Fast and simple cubic spline interpolant. - * - * It was derived from a Hermitian construction setting the first derivative - * at each sample position to the linear slope between neighboring positions - * over their parameter interval. - * - * @author tschw - */ + } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { -function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + // user-defined mipmaps - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + return texture.mipmaps.length; - this._weightPrev = - 0; - this._offsetPrev = - 0; - this._weightNext = - 0; - this._offsetNext = - 0; + } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { -} + return image.mipmaps.length; -CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + } else { - constructor: CubicInterpolant, + // texture without mipmaps (only base level) - DefaultSettings_: { + return 1; - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding + } - }, + } - intervalChanged_: function ( i1, t0, t1 ) { + // - var pp = this.parameterPositions, - iPrev = i1 - 2, - iNext = i1 + 1, + function onTextureDispose( event ) { - tPrev = pp[ iPrev ], - tNext = pp[ iNext ]; + const texture = event.target; - if ( tPrev === undefined ) { + texture.removeEventListener( 'dispose', onTextureDispose ); - switch ( this.getSettings_().endingStart ) { + deallocateTexture( texture ); - case ZeroSlopeEnding: + if ( texture.isVideoTexture ) { - // f'(t0) = 0 - iPrev = i1; - tPrev = 2 * t0 - t1; + _videoTextures.delete( texture ); - break; + } - case WrapAroundEnding: + } - // use the other end of the curve - iPrev = pp.length - 2; - tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; + function onRenderTargetDispose( event ) { - break; + const renderTarget = event.target; - default: // ZeroCurvatureEnding + renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); - // f''(t0) = 0 a.k.a. Natural Spline - iPrev = i1; - tPrev = t1; + deallocateRenderTarget( renderTarget ); - } + } - } + // - if ( tNext === undefined ) { + function deallocateTexture( texture ) { - switch ( this.getSettings_().endingEnd ) { + const textureProperties = properties.get( texture ); - case ZeroSlopeEnding: + if ( textureProperties.__webglInit === undefined ) return; - // f'(tN) = 0 - iNext = i1; - tNext = 2 * t1 - t0; + // check if it's necessary to remove the WebGLTexture object - break; + const source = texture.source; + const webglTextures = _sources.get( source ); - case WrapAroundEnding: + if ( webglTextures ) { - // use the other end of the curve - iNext = 1; - tNext = t1 + pp[ 1 ] - pp[ 0 ]; + const webglTexture = webglTextures[ textureProperties.__cacheKey ]; + webglTexture.usedTimes --; - break; + // the WebGLTexture object is not used anymore, remove it - default: // ZeroCurvatureEnding + if ( webglTexture.usedTimes === 0 ) { - // f''(tN) = 0, a.k.a. Natural Spline - iNext = i1 - 1; - tNext = t0; + deleteTexture( texture ); } - } + // remove the weak map entry if no WebGLTexture uses the source anymore - var halfDt = ( t1 - t0 ) * 0.5, - stride = this.valueSize; + if ( Object.keys( webglTextures ).length === 0 ) { - this._weightPrev = halfDt / ( t0 - tPrev ); - this._weightNext = halfDt / ( tNext - t1 ); - this._offsetPrev = iPrev * stride; - this._offsetNext = iNext * stride; + _sources.delete( source ); - }, + } - interpolate_: function ( i1, t0, t, t1 ) { + } - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + properties.remove( texture ); - 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; + function deleteTexture( texture ) { - // evaluate polynomials + const textureProperties = properties.get( texture ); + _gl.deleteTexture( textureProperties.__webglTexture ); - var sP = - wP * ppp + 2 * wP * pp - wP * p; - var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; - var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; - var sN = wN * ppp - wN * pp; + const source = texture.source; + const webglTextures = _sources.get( source ); + delete webglTextures[ textureProperties.__cacheKey ]; - // combine data linearly + info.memory.textures --; - for ( var i = 0; i !== stride; ++ i ) { + } - result[ i ] = - sP * values[ oP + i ] + - s0 * values[ o0 + i ] + - s1 * values[ o1 + i ] + - sN * values[ oN + i ]; + function deallocateRenderTarget( renderTarget ) { - } + const renderTargetProperties = properties.get( renderTarget ); - return result; + if ( renderTarget.depthTexture ) { - } + renderTarget.depthTexture.dispose(); -} ); + } -/** - * @author tschw - */ + if ( renderTarget.isWebGLCubeRenderTarget ) { -function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + for ( let i = 0; i < 6; i ++ ) { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) { -} + for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] ); -LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + } else { - constructor: LinearInterpolant, + _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - interpolate_: function ( i1, t0, t, t1 ) { + } - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); - offset1 = i1 * stride, - offset0 = offset1 - stride, + } - weight1 = ( t - t0 ) / ( t1 - t0 ), - weight0 = 1 - weight1; + } else { - for ( var i = 0; i !== stride; ++ i ) { + if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) { - result[ i ] = - values[ offset0 + i ] * weight0 + - values[ offset1 + i ] * weight1; + for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] ); - } + } else { - return result; + _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - } + } -} ); + if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); + if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); -/** - * - * Interpolant that evaluates to the sample value at the position preceeding - * the parameter. - * - * @author tschw - */ + if ( renderTargetProperties.__webglColorRenderbuffer ) { -function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); -} + } -DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + } - constructor: DiscreteInterpolant, + if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); - interpolate_: function ( i1 /*, t0, t, t1 */ ) { + } - return this.copySampleValue_( i1 - 1 ); + const textures = renderTarget.textures; - } + for ( let i = 0, il = textures.length; i < il; i ++ ) { -} ); + const attachmentProperties = properties.get( textures[ i ] ); -/** - * @author tschw - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ + if ( attachmentProperties.__webglTexture ) { -var AnimationUtils = { + _gl.deleteTexture( attachmentProperties.__webglTexture ); - // same as Array.prototype.slice, but also works on typed arrays - arraySlice: function ( array, from, to ) { + info.memory.textures --; - if ( AnimationUtils.isTypedArray( array ) ) { + } - // in ios9 array.subarray(from, undefined) will return empty array - // but array.subarray(from) or array.subarray(from, len) is correct - return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) ); + properties.remove( textures[ i ] ); } - return array.slice( from, to ); - - }, + properties.remove( renderTarget ); - // converts an array to a specific type - convertArray: function ( array, type, forceClone ) { + } - if ( ! array || // let 'undefined' and 'null' pass - ! forceClone && array.constructor === type ) { return array; } + // - if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { + let textureUnits = 0; - return new type( array ); // create typed array + function resetTextureUnits() { - } + textureUnits = 0; - return Array.prototype.slice.call( array ); // create Array + } - }, + function allocateTextureUnit() { - isTypedArray: function ( object ) { + const textureUnit = textureUnits; - return ArrayBuffer.isView( object ) && - ! ( object instanceof DataView ); + if ( textureUnit >= capabilities.maxTextures ) { - }, + console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); - // returns an array by which times and values can be sorted - getKeyframeOrder: function ( times ) { + } - function compareTime( i, j ) { + textureUnits += 1; - return times[ i ] - times[ j ]; + return textureUnit; - } + } - var n = times.length; - var result = new Array( n ); - for ( var i = 0; i !== n; ++ i ) { result[ i ] = i; } + function getTextureCacheKey( texture ) { - result.sort( compareTime ); + const array = []; - return result; + array.push( texture.wrapS ); + array.push( texture.wrapT ); + array.push( texture.wrapR || 0 ); + array.push( texture.magFilter ); + array.push( texture.minFilter ); + array.push( texture.anisotropy ); + array.push( texture.internalFormat ); + array.push( texture.format ); + array.push( texture.type ); + array.push( texture.generateMipmaps ); + array.push( texture.premultiplyAlpha ); + array.push( texture.flipY ); + array.push( texture.unpackAlignment ); + array.push( texture.colorSpace ); - }, + return array.join(); - // uses the array previously returned by 'getKeyframeOrder' to sort data - sortedArray: function ( values, stride, order ) { + } - var nValues = values.length; - var result = new values.constructor( nValues ); + // - for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { + function setTexture2D( texture, slot ) { - var srcOffset = order[ i ] * stride; + const textureProperties = properties.get( texture ); - for ( var j = 0; j !== stride; ++ j ) { + if ( texture.isVideoTexture ) updateVideoTexture( texture ); - result[ dstOffset ++ ] = values[ srcOffset + j ]; + if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { - } + const image = texture.image; - } + if ( image === null ) { - return result; + console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); - }, + } else if ( image.complete === false ) { - // function for parsing AOS keyframe formats - flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) { + console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); - var i = 1, key = jsonKeys[ 0 ]; + } else { - while ( key !== undefined && key[ valuePropertyName ] === undefined ) { + uploadTexture( textureProperties, texture, slot ); + return; - key = jsonKeys[ i ++ ]; + } } - if ( key === undefined ) { return; } // no data - - var value = key[ valuePropertyName ]; - if ( value === undefined ) { return; } // no data + state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - if ( Array.isArray( value ) ) { + } - do { + function setTexture2DArray( texture, slot ) { - value = key[ valuePropertyName ]; + const textureProperties = properties.get( texture ); - if ( value !== undefined ) { + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - times.push( key.time ); - values.push.apply( values, value ); // push all elements + uploadTexture( textureProperties, texture, slot ); + return; - } + } - key = jsonKeys[ i ++ ]; + state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } while ( key !== undefined ); + } - } else if ( value.toArray !== undefined ) { + function setTexture3D( texture, slot ) { - // ...assume THREE.Math-ish + const textureProperties = properties.get( texture ); - do { + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - value = key[ valuePropertyName ]; + uploadTexture( textureProperties, texture, slot ); + return; - if ( value !== undefined ) { + } - times.push( key.time ); - value.toArray( values, values.length ); + state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } + } - key = jsonKeys[ i ++ ]; + function setTextureCube( texture, slot ) { - } while ( key !== undefined ); + const textureProperties = properties.get( texture ); - } else { + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - // otherwise push as-is + uploadCubeTexture( textureProperties, texture, slot ); + return; - do { + } - value = key[ valuePropertyName ]; + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - if ( value !== undefined ) { + } - times.push( key.time ); - values.push( value ); + const wrappingToGL = { + [ RepeatWrapping ]: _gl.REPEAT, + [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, + [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT + }; - } + const filterToGL = { + [ NearestFilter ]: _gl.NEAREST, + [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, + [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, - key = jsonKeys[ i ++ ]; + [ LinearFilter ]: _gl.LINEAR, + [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, + [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR + }; - } while ( key !== undefined ); + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL + }; - } + function setTextureParameters( textureType, texture ) { - } + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false && + ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || + texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) { -}; + console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); -/** - * - * A timed sequence of keyframes for a specific property. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + } -function KeyframeTrack( name, times, values, interpolation ) { + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); - if ( name === undefined ) { throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); } - if ( times === undefined || times.length === 0 ) { throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); } + if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { - this.name = name; + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); - this.times = AnimationUtils.convertArray( times, this.TimeBufferType ); - this.values = AnimationUtils.convertArray( values, this.ValueBufferType ); + } - this.setInterpolation( interpolation || this.DefaultInterpolation ); + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] ); - this.validate(); - this.optimize(); + if ( texture.compareFunction ) { -} + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); -// Static methods: + } -Object.assign( KeyframeTrack, { + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { - // Serialization (in static context, because of constructor invocation - // and automatic invocation of .toJSON): + if ( texture.magFilter === NearestFilter ) return; + if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension - parse: function ( json ) { + if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { - if ( json.type === undefined ) { + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); + properties.get( texture ).__currentAnisotropy = texture.anisotropy; - throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); + } } - var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type ); + } + + function initTexture( textureProperties, texture ) { - if ( json.times === undefined ) { + let forceUpload = false; - var times = [], values = []; + if ( textureProperties.__webglInit === undefined ) { - AnimationUtils.flattenJSON( json.keys, times, values, 'value' ); + textureProperties.__webglInit = true; - json.times = times; - json.values = values; + texture.addEventListener( 'dispose', onTextureDispose ); } - // derived classes can define a static parse method - if ( trackType.parse !== undefined ) { + // create Source <-> WebGLTextures mapping if necessary - return trackType.parse( json ); + const source = texture.source; + let webglTextures = _sources.get( source ); - } else { + if ( webglTextures === undefined ) { - // by default, we assume a constructor compatible with the base - return new trackType( json.name, json.times, json.values, json.interpolation ); + webglTextures = {}; + _sources.set( source, webglTextures ); } - }, + // check if there is already a WebGLTexture object for the given texture parameters - toJSON: function ( track ) { + const textureCacheKey = getTextureCacheKey( texture ); - var trackType = track.constructor; + if ( textureCacheKey !== textureProperties.__cacheKey ) { - var json; + // if not, create a new instance of WebGLTexture - // derived classes can define a static toJSON method - if ( trackType.toJSON !== undefined ) { + if ( webglTextures[ textureCacheKey ] === undefined ) { - json = trackType.toJSON( track ); + // create new entry - } else { + webglTextures[ textureCacheKey ] = { + texture: _gl.createTexture(), + usedTimes: 0 + }; - // by default, we assume the data can be serialized as-is - json = { + info.memory.textures ++; - 'name': track.name, - 'times': AnimationUtils.convertArray( track.times, Array ), - 'values': AnimationUtils.convertArray( track.values, Array ) + // when a new instance of WebGLTexture was created, a texture upload is required + // even if the image contents are identical - }; + forceUpload = true; - var interpolation = track.getInterpolation(); + } - if ( interpolation !== track.DefaultInterpolation ) { + webglTextures[ textureCacheKey ].usedTimes ++; - json.interpolation = interpolation; + // every time the texture cache key changes, it's necessary to check if an instance of + // WebGLTexture can be deleted in order to avoid a memory leak. - } + const webglTexture = webglTextures[ textureProperties.__cacheKey ]; - } + if ( webglTexture !== undefined ) { - json.type = track.ValueTypeName; // mandatory + webglTextures[ textureProperties.__cacheKey ].usedTimes --; - return json; + if ( webglTexture.usedTimes === 0 ) { - }, + deleteTexture( texture ); - _getTrackTypeForValueTypeName: function ( typeName ) { + } - switch ( typeName.toLowerCase() ) { + } - case 'scalar': - case 'double': - case 'float': - case 'number': - case 'integer': + // store references to cache key and WebGLTexture object - return NumberKeyframeTrack; + textureProperties.__cacheKey = textureCacheKey; + textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; - case 'vector': - case 'vector2': - case 'vector3': - case 'vector4': + } - return VectorKeyframeTrack; + return forceUpload; - case 'color': + } - return ColorKeyframeTrack; + function uploadTexture( textureProperties, texture, slot ) { - case 'quaternion': + let textureType = _gl.TEXTURE_2D; - return QuaternionKeyframeTrack; + if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; + if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; - case 'bool': - case 'boolean': + const forceUpload = initTexture( textureProperties, texture ); + const source = texture.source; - return BooleanKeyframeTrack; + state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - case 'string': + const sourceProperties = properties.get( source ); - return StringKeyframeTrack; + if ( source.version !== sourceProperties.__version || forceUpload === true ) { - } + state.activeTexture( _gl.TEXTURE0 + slot ); - throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); + const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - } + _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, unpackConversion ); -} ); + let image = resizeImage( texture.image, false, capabilities.maxTextureSize ); + image = verifyColorSpace( texture, image ); -Object.assign( KeyframeTrack.prototype, { + const glFormat = utils.convert( texture.format, texture.colorSpace ); - constructor: KeyframeTrack, + const glType = utils.convert( texture.type ); + let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); - TimeBufferType: Float32Array, + setTextureParameters( textureType, texture ); - ValueBufferType: Float32Array, + let mipmap; + const mipmaps = texture.mipmaps; - DefaultInterpolation: InterpolateLinear, + const useTexStorage = ( texture.isVideoTexture !== true ); + const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); + const dataReady = source.dataReady; + const levels = getMipLevels( texture, image ); - InterpolantFactoryMethodDiscrete: function ( result ) { + if ( texture.isDepthTexture ) { - return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); + glInternalFormat = getInternalDepthFormat( texture.format === DepthStencilFormat, texture.type ); - }, + // - InterpolantFactoryMethodLinear: function ( result ) { + if ( allocateMemory ) { - return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); + if ( useTexStorage ) { - }, + state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); - InterpolantFactoryMethodSmooth: function ( result ) { + } else { - return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); - }, + } - setInterpolation: function ( interpolation ) { + } - var factoryMethod; + } else if ( texture.isDataTexture ) { - switch ( interpolation ) { + // use manually created mipmaps if available + // if there are no manual mipmaps + // set 0 level mipmap and then use GL to generate other mipmap levels - case InterpolateDiscrete: + if ( mipmaps.length > 0 ) { - factoryMethod = this.InterpolantFactoryMethodDiscrete; + if ( useTexStorage && allocateMemory ) { - break; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); - case InterpolateLinear: + } - factoryMethod = this.InterpolantFactoryMethodLinear; + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - break; + mipmap = mipmaps[ i ]; - case InterpolateSmooth: + if ( useTexStorage ) { - factoryMethod = this.InterpolantFactoryMethodSmooth; + if ( dataReady ) { - break; + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - } + } - if ( factoryMethod === undefined ) { + } else { - var message = "unsupported interpolation for " + - this.ValueTypeName + " keyframe track named " + this.name; + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - if ( this.createInterpolant === undefined ) { + } - // fall back to default, unless the default itself is messed up - if ( interpolation !== this.DefaultInterpolation ) { + } - this.setInterpolation( this.DefaultInterpolation ); + texture.generateMipmaps = false; } else { - throw new Error( message ); // fatal, in this case + if ( useTexStorage ) { - } + if ( allocateMemory ) { - } + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); - console.warn( 'THREE.KeyframeTrack:', message ); - return; + } - } + if ( dataReady ) { - this.createInterpolant = factoryMethod; + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); - }, + } - getInterpolation: function () { + } else { - switch ( this.createInterpolant ) { + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); - case this.InterpolantFactoryMethodDiscrete: + } - return InterpolateDiscrete; + } - case this.InterpolantFactoryMethodLinear: + } else if ( texture.isCompressedTexture ) { - return InterpolateLinear; + if ( texture.isCompressedArrayTexture ) { - case this.InterpolantFactoryMethodSmooth: + if ( useTexStorage && allocateMemory ) { - return InterpolateSmooth; + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); - } + } - }, + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - getValueSize: function () { + mipmap = mipmaps[ i ]; - return this.values.length / this.times.length; + if ( texture.format !== RGBAFormat ) { - }, + if ( glFormat !== null ) { - // move all keyframes either forwards or backwards in time - shift: function ( timeOffset ) { + if ( useTexStorage ) { - if ( timeOffset !== 0.0 ) { + if ( dataReady ) { - var times = this.times; + if ( texture.layerUpdates.size > 0 ) { - for ( var i = 0, n = times.length; i !== n; ++ i ) { + const layerByteLength = getByteLength( mipmap.width, mipmap.height, texture.format, texture.type ); - times[ i ] += timeOffset; + for ( const layerIndex of texture.layerUpdates ) { - } + const layerData = mipmap.data.subarray( + layerIndex * layerByteLength / mipmap.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / mipmap.data.BYTES_PER_ELEMENT + ); + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, layerData, 0, 0 ); - } + } - return this; + texture.clearLayerUpdates(); - }, + } else { - // scale all keyframe times by a factor (useful for frame <-> seconds conversions) - scale: function ( timeScale ) { + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); - if ( timeScale !== 1.0 ) { + } - var times = this.times; + } - for ( var i = 0, n = times.length; i !== n; ++ i ) { + } else { - times[ i ] *= timeScale; + state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); - } + } - } + } else { - return this; + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - }, + } - // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. - // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values - trim: function ( startTime, endTime ) { + } else { - var times = this.times, - nKeys = times.length, - from = 0, - to = nKeys - 1; + if ( useTexStorage ) { - while ( from !== nKeys && times[ from ] < startTime ) { + if ( dataReady ) { - ++ from; + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); - } + } - while ( to !== - 1 && times[ to ] > endTime ) { + } else { - -- to; + state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); - } + } - ++ to; // inclusive -> exclusive bound + } - if ( from !== 0 || to !== nKeys ) { + } - // empty tracks are forbidden, so keep at least one keyframe - if ( from >= to ) { to = Math.max( to, 1 ), from = to - 1; } + } else { - var stride = this.getValueSize(); - this.times = AnimationUtils.arraySlice( times, from, to ); - this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride ); + if ( useTexStorage && allocateMemory ) { - } + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); - return this; + } - }, + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable - validate: function () { + mipmap = mipmaps[ i ]; - var valid = true; + if ( texture.format !== RGBAFormat ) { - var valueSize = this.getValueSize(); - if ( valueSize - Math.floor( valueSize ) !== 0 ) { + if ( glFormat !== null ) { - console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); - valid = false; + if ( useTexStorage ) { - } + if ( dataReady ) { - var times = this.times, - values = this.values, + state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); - nKeys = times.length; + } - if ( nKeys === 0 ) { + } else { - console.error( 'THREE.KeyframeTrack: Track is empty.', this ); - valid = false; + state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - } + } - var prevTime = null; + } else { - for ( var i = 0; i !== nKeys; i ++ ) { + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - var currTime = times[ i ]; + } - if ( typeof currTime === 'number' && isNaN( currTime ) ) { + } else { - console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); - valid = false; - break; + if ( useTexStorage ) { - } + if ( dataReady ) { - if ( prevTime !== null && prevTime > currTime ) { + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); - valid = false; - break; + } - } + } else { - prevTime = currTime; + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - } + } - if ( values !== undefined ) { + } + + } - if ( AnimationUtils.isTypedArray( values ) ) { + } - for ( var i = 0, n = values.length; i !== n; ++ i ) { + } else if ( texture.isDataArrayTexture ) { - var value = values[ i ]; + if ( useTexStorage ) { - if ( isNaN( value ) ) { + if ( allocateMemory ) { - console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); - valid = false; - break; + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); } - } - - } + if ( dataReady ) { - } + if ( texture.layerUpdates.size > 0 ) { - return valid; + const layerByteLength = getByteLength( image.width, image.height, texture.format, texture.type ); - }, + for ( const layerIndex of texture.layerUpdates ) { - // removes equivalent sequential keys as common in morph target sequences - // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) - optimize: function () { + const layerData = image.data.subarray( + layerIndex * layerByteLength / image.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / image.data.BYTES_PER_ELEMENT + ); + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, layerData ); - var times = this.times, - values = this.values, - stride = this.getValueSize(), + } - smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + texture.clearLayerUpdates(); - writeIndex = 1, - lastIndex = times.length - 1; + } else { - for ( var i = 1; i < lastIndex; ++ i ) { + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); - var keep = false; + } - var time = times[ i ]; - var timeNext = times[ i + 1 ]; + } - // remove adjacent keyframes scheduled at the same time + } else { - if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) { + state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); - if ( ! smoothInterpolation ) { + } - // remove unnecessary keyframes same as their neighbors + } else if ( texture.isData3DTexture ) { - var offset = i * stride, - offsetP = offset - stride, - offsetN = offset + stride; + if ( useTexStorage ) { - for ( var j = 0; j !== stride; ++ j ) { + if ( allocateMemory ) { - var value = values[ offset + j ]; + state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); - if ( value !== values[ offsetP + j ] || - value !== values[ offsetN + j ] ) { + } - keep = true; - break; + if ( dataReady ) { - } + state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); } } else { - keep = true; + state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); } - } - - // in-place compaction + } else if ( texture.isFramebufferTexture ) { - if ( keep ) { + if ( allocateMemory ) { - if ( i !== writeIndex ) { + if ( useTexStorage ) { - times[ writeIndex ] = times[ i ]; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); - var readOffset = i * stride, - writeOffset = writeIndex * stride; + } else { - for ( var j = 0; j !== stride; ++ j ) { + let width = image.width, height = image.height; - values[ writeOffset + j ] = values[ readOffset + j ]; + for ( let i = 0; i < levels; i ++ ) { - } + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); - } + width >>= 1; + height >>= 1; - ++ writeIndex; + } - } + } - } + } - // flush last keyframe (compaction looks ahead) + } else { - if ( lastIndex > 0 ) { + // regular Texture (image, video, canvas) - times[ writeIndex ] = times[ lastIndex ]; + // use manually created mipmaps if available + // if there are no manual mipmaps + // set 0 level mipmap and then use GL to generate other mipmap levels - for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { + if ( mipmaps.length > 0 ) { - values[ writeOffset + j ] = values[ readOffset + j ]; + if ( useTexStorage && allocateMemory ) { - } + const dimensions = getDimensions( mipmaps[ 0 ] ); - ++ writeIndex; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); - } + } - if ( writeIndex !== times.length ) { + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - this.times = AnimationUtils.arraySlice( times, 0, writeIndex ); - this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride ); + mipmap = mipmaps[ i ]; - } + if ( useTexStorage ) { - return this; + if ( dataReady ) { - } + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); -} ); + } -/** - * - * A Track of vectored keyframe values. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + } else { -function VectorKeyframeTrack( name, times, values, interpolation ) { + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); - KeyframeTrack.call( this, name, times, values, interpolation ); + } -} + } -VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + texture.generateMipmaps = false; - constructor: VectorKeyframeTrack, + } else { - ValueTypeName: 'vector' + if ( useTexStorage ) { - // ValueBufferType is inherited + if ( allocateMemory ) { - // DefaultInterpolation is inherited + const dimensions = getDimensions( image ); -} ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); -/** - * - * Reusable set of Tracks that represent an animation. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ + } -function AnimationClip( name, duration, tracks ) { + if ( dataReady ) { - this.name = name; - this.tracks = tracks; - this.duration = ( duration !== undefined ) ? duration : - 1; + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); - this.uuid = _Math.generateUUID(); + } - // this means it should figure out its duration by scanning the tracks - if ( this.duration < 0 ) { + } else { - this.resetDuration(); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); - } + } - this.optimize(); + } -} + } -Object.assign( AnimationClip, { + if ( textureNeedsGenerateMipmaps( texture ) ) { - parse: function ( json ) { + generateMipmap( textureType ); - var tracks = [], - jsonTracks = json.tracks, - frameTime = 1.0 / ( json.fps || 1.0 ); + } - for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) { + sourceProperties.__version = source.version; - tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) ); + if ( texture.onUpdate ) texture.onUpdate( texture ); } - return new AnimationClip( json.name, json.duration, tracks ); - - }, + textureProperties.__version = texture.version; - toJSON: function ( clip ) { + } - var tracks = [], - clipTracks = clip.tracks; + function uploadCubeTexture( textureProperties, texture, slot ) { - var json = { + if ( texture.image.length !== 6 ) return; - 'name': clip.name, - 'duration': clip.duration, - 'tracks': tracks + const forceUpload = initTexture( textureProperties, texture ); + const source = texture.source; - }; + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) { + const sourceProperties = properties.get( source ); - tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); + if ( source.version !== sourceProperties.__version || forceUpload === true ) { - } + state.activeTexture( _gl.TEXTURE0 + slot ); - return json; + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); + const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - }, + _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, unpackConversion ); - CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) { + const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); + const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); - var numMorphTargets = morphTargetSequence.length; - var tracks = []; + const cubeImage = []; - for ( var i = 0; i < numMorphTargets; i ++ ) { + for ( let i = 0; i < 6; i ++ ) { - var times = []; - var values = []; + if ( ! isCompressed && ! isDataTexture ) { - times.push( - ( i + numMorphTargets - 1 ) % numMorphTargets, - i, - ( i + 1 ) % numMorphTargets ); + cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize ); - values.push( 0, 1, 0 ); + } else { - var order = AnimationUtils.getKeyframeOrder( times ); - times = AnimationUtils.sortedArray( times, 1, order ); - values = AnimationUtils.sortedArray( values, 1, order ); + cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; - // if there is a key at the first frame, duplicate it as the - // last frame as well for perfect loop. - if ( ! noLoop && times[ 0 ] === 0 ) { + } - times.push( numMorphTargets ); - values.push( values[ 0 ] ); + cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); } - tracks.push( - new NumberKeyframeTrack( - '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', - times, values - ).scale( 1.0 / fps ) ); + const image = cubeImage[ 0 ], + glFormat = utils.convert( texture.format, texture.colorSpace ), + glType = utils.convert( texture.type ), + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); - } + const useTexStorage = ( texture.isVideoTexture !== true ); + const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); + const dataReady = source.dataReady; + let levels = getMipLevels( texture, image ); - return new AnimationClip( name, - 1, tracks ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); - }, + let mipmaps; - findByName: function ( objectOrClipArray, name ) { + if ( isCompressed ) { - var clipArray = objectOrClipArray; + if ( useTexStorage && allocateMemory ) { - if ( ! Array.isArray( objectOrClipArray ) ) { + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); - var o = objectOrClipArray; - clipArray = o.geometry && o.geometry.animations || o.animations; + } - } + for ( let i = 0; i < 6; i ++ ) { - for ( var i = 0; i < clipArray.length; i ++ ) { + mipmaps = cubeImage[ i ].mipmaps; - if ( clipArray[ i ].name === name ) { + for ( let j = 0; j < mipmaps.length; j ++ ) { - return clipArray[ i ]; + const mipmap = mipmaps[ j ]; - } + if ( texture.format !== RGBAFormat ) { - } + if ( glFormat !== null ) { - return null; + if ( useTexStorage ) { - }, + if ( dataReady ) { - CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) { + state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); - var animationToMorphTargets = {}; + } - // tested with https://regex101.com/ on trick sequences - // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 - var pattern = /^([\w-]*?)([\d]+)$/; + } else { - // sort morph target names into animation groups based - // patterns like Walk_001, Walk_002, Run_001, Run_002 - for ( var i = 0, il = morphTargets.length; i < il; i ++ ) { + state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - var morphTarget = morphTargets[ i ]; - var parts = morphTarget.name.match( pattern ); + } - if ( parts && parts.length > 1 ) { + } else { - var name = parts[ 1 ]; + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); - var animationMorphTargets = animationToMorphTargets[ name ]; - if ( ! animationMorphTargets ) { + } - animationToMorphTargets[ name ] = animationMorphTargets = []; + } else { - } + if ( useTexStorage ) { - animationMorphTargets.push( morphTarget ); + if ( dataReady ) { - } + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - } + } - var clips = []; + } else { - for ( var name in animationToMorphTargets ) { + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); + } - } + } - return clips; + } - }, + } - // parse the animation.hierarchy format - parseAnimation: function ( animation, bones ) { + } else { - if ( ! animation ) { + mipmaps = texture.mipmaps; - console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); - return null; + if ( useTexStorage && allocateMemory ) { - } + // TODO: Uniformly handle mipmap definitions + // Normal textures and compressed cube textures define base level + mips with their mipmap array + // Uncompressed cube textures use their mipmap array only for mips (no base level) - var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { + if ( mipmaps.length > 0 ) levels ++; - // only return track if there are actually keys. - if ( animationKeys.length !== 0 ) { + const dimensions = getDimensions( cubeImage[ 0 ] ); - var times = []; - var values = []; + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height ); - AnimationUtils.flattenJSON( animationKeys, times, values, propertyName ); + } - // empty keys are filtered out, so check again - if ( times.length !== 0 ) { + for ( let i = 0; i < 6; i ++ ) { - destTracks.push( new trackType( trackName, times, values ) ); + if ( isDataTexture ) { - } + if ( useTexStorage ) { - } + if ( dataReady ) { - }; + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); - var tracks = []; + } - var clipName = animation.name || 'default'; - // automatic length determination in AnimationClip. - var duration = animation.length || - 1; - var fps = animation.fps || 30; + } else { - var hierarchyTracks = animation.hierarchy || []; + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); - for ( var h = 0; h < hierarchyTracks.length; h ++ ) { + } - var animationKeys = hierarchyTracks[ h ].keys; + for ( let j = 0; j < mipmaps.length; j ++ ) { - // skip empty tracks - if ( ! animationKeys || animationKeys.length === 0 ) { continue; } + const mipmap = mipmaps[ j ]; + const mipmapImage = mipmap.image[ i ].image; - // process morph targets - if ( animationKeys[ 0 ].morphTargets ) { + if ( useTexStorage ) { - // figure out all morph targets used in this track - var morphTargetNames = {}; + if ( dataReady ) { - for ( var k = 0; k < animationKeys.length; k ++ ) { + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); - if ( animationKeys[ k ].morphTargets ) { + } - for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { + } else { - morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); + + } } - } + } else { - } + if ( useTexStorage ) { - // create a track for each morph target with all zero - // morphTargetInfluences except for the keys in which - // the morphTarget is named. - for ( var morphTargetName in morphTargetNames ) { + if ( dataReady ) { - var times = []; - var values = []; + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); - for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { + } - var animationKey = animationKeys[ k ]; + } else { - times.push( animationKey.time ); - values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); - } + } - tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); + for ( let j = 0; j < mipmaps.length; j ++ ) { - } + const mipmap = mipmaps[ j ]; - duration = morphTargetNames.length * ( fps || 1.0 ); + if ( useTexStorage ) { - } else { + if ( dataReady ) { - // ...assume skeletal animation + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); - var boneName = '.bones[' + bones[ h ].name + ']'; + } - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.position', - animationKeys, 'pos', tracks ); + } else { - addNonemptyTrack( - QuaternionKeyframeTrack, boneName + '.quaternion', - animationKeys, 'rot', tracks ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.scale', - animationKeys, 'scl', tracks ); + } - } + } - } + } - if ( tracks.length === 0 ) { + } - return null; + } - } + if ( textureNeedsGenerateMipmaps( texture ) ) { - var clip = new AnimationClip( clipName, duration, tracks ); + // We assume images for cube map have the same size. + generateMipmap( _gl.TEXTURE_CUBE_MAP ); - return clip; + } - } + sourceProperties.__version = source.version; -} ); + if ( texture.onUpdate ) texture.onUpdate( texture ); -Object.assign( AnimationClip.prototype, { + } + + textureProperties.__version = texture.version; - resetDuration: function () { + } - var tracks = this.tracks, duration = 0; + // Render targets - for ( var i = 0, n = tracks.length; i !== n; ++ i ) { + // Setup storage for target texture and bind it to correct framebuffer + function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) { - var track = this.tracks[ i ]; + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const renderTargetProperties = properties.get( renderTarget ); - duration = Math.max( duration, track.times[ track.times.length - 1 ] ); + if ( ! renderTargetProperties.__hasExternalTextures ) { - } + const width = Math.max( 1, renderTarget.width >> level ); + const height = Math.max( 1, renderTarget.height >> level ); - this.duration = duration; + if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { - }, + state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null ); - trim: function () { + } else { - for ( var i = 0; i < this.tracks.length; i ++ ) { + state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null ); - this.tracks[ i ].trim( 0, this.duration ); + } } - return this; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - }, + if ( useMultisampledRTT( renderTarget ) ) { - optimize: function () { + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); - for ( var i = 0; i < this.tracks.length; i ++ ) { + } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 - this.tracks[ i ].optimize(); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); } - return this; + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ + // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { -function MaterialLoader( manager ) { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.textures = {}; + if ( renderTarget.depthBuffer ) { -} + // retrieve the depth attachment types + const depthTexture = renderTarget.depthTexture; + const depthType = depthTexture && depthTexture.isDepthTexture ? depthTexture.type : null; + const glInternalFormat = getInternalDepthFormat( renderTarget.stencilBuffer, depthType ); + const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; -Object.assign( MaterialLoader.prototype, { + // set up the attachment + const samples = getRenderTargetSamples( renderTarget ); + const isUseMultisampledRTT = useMultisampledRTT( renderTarget ); + if ( isUseMultisampledRTT ) { - load: function ( url, onLoad, onProgress, onError ) { + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - var scope = this; + } else if ( isMultisample ) { - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - onLoad( scope.parse( JSON.parse( text ) ) ); + } else { - }, onProgress, onError ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); - }, + } - setTextures: function ( value ) { + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer ); - this.textures = value; + } else { - }, + const textures = renderTarget.textures; - parse: function ( json ) { + for ( let i = 0; i < textures.length; i ++ ) { - var textures = this.textures; + const texture = textures[ i ]; - function getTexture( name ) { + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const samples = getRenderTargetSamples( renderTarget ); - if ( textures[ name ] === undefined ) { + if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { - console.warn( 'THREE.MaterialLoader: Undefined texture', name ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - } + } else if ( useMultisampledRTT( renderTarget ) ) { - return textures[ name ]; + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - } + } else { - var material = new Materials[ json.type ](); + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); - if ( json.uuid !== undefined ) { material.uuid = json.uuid; } - if ( json.name !== undefined ) { material.name = json.name; } - if ( json.color !== undefined ) { material.color.setHex( json.color ); } - if ( json.roughness !== undefined ) { material.roughness = json.roughness; } - if ( json.metalness !== undefined ) { material.metalness = json.metalness; } - if ( json.emissive !== undefined ) { material.emissive.setHex( json.emissive ); } - if ( json.specular !== undefined ) { material.specular.setHex( json.specular ); } - if ( json.shininess !== undefined ) { material.shininess = json.shininess; } - if ( json.clearCoat !== undefined ) { material.clearCoat = json.clearCoat; } - if ( json.clearCoatRoughness !== undefined ) { material.clearCoatRoughness = json.clearCoatRoughness; } - if ( json.uniforms !== undefined ) { material.uniforms = json.uniforms; } - if ( json.vertexShader !== undefined ) { material.vertexShader = json.vertexShader; } - if ( json.fragmentShader !== undefined ) { material.fragmentShader = json.fragmentShader; } - if ( json.vertexColors !== undefined ) { material.vertexColors = json.vertexColors; } - if ( json.fog !== undefined ) { material.fog = json.fog; } - if ( json.flatShading !== undefined ) { material.flatShading = json.flatShading; } - if ( json.blending !== undefined ) { material.blending = json.blending; } - if ( json.side !== undefined ) { material.side = json.side; } - if ( json.opacity !== undefined ) { material.opacity = json.opacity; } - if ( json.transparent !== undefined ) { material.transparent = json.transparent; } - if ( json.alphaTest !== undefined ) { material.alphaTest = json.alphaTest; } - if ( json.depthTest !== undefined ) { material.depthTest = json.depthTest; } - if ( json.depthWrite !== undefined ) { material.depthWrite = json.depthWrite; } - if ( json.colorWrite !== undefined ) { material.colorWrite = json.colorWrite; } - if ( json.wireframe !== undefined ) { material.wireframe = json.wireframe; } - if ( json.wireframeLinewidth !== undefined ) { material.wireframeLinewidth = json.wireframeLinewidth; } - if ( json.wireframeLinecap !== undefined ) { material.wireframeLinecap = json.wireframeLinecap; } - if ( json.wireframeLinejoin !== undefined ) { material.wireframeLinejoin = json.wireframeLinejoin; } + } - if ( json.rotation !== undefined ) { material.rotation = json.rotation; } + } - if ( json.linewidth !== 1 ) { material.linewidth = json.linewidth; } - if ( json.dashSize !== undefined ) { material.dashSize = json.dashSize; } - if ( json.gapSize !== undefined ) { material.gapSize = json.gapSize; } - if ( json.scale !== undefined ) { material.scale = json.scale; } + } - if ( json.skinning !== undefined ) { material.skinning = json.skinning; } - if ( json.morphTargets !== undefined ) { material.morphTargets = json.morphTargets; } - if ( json.dithering !== undefined ) { material.dithering = json.dithering; } + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - if ( json.visible !== undefined ) { material.visible = json.visible; } - if ( json.userData !== undefined ) { material.userData = json.userData; } + } - // Deprecated + // Setup resources for a Depth Texture for a FBO (needs an extension) + function setupDepthTexture( framebuffer, renderTarget ) { - if ( json.shading !== undefined ) { material.flatShading = json.shading === 1; } // THREE.FlatShading + const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); + if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); - // for PointsMaterial + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( json.size !== undefined ) { material.size = json.size; } - if ( json.sizeAttenuation !== undefined ) { material.sizeAttenuation = json.sizeAttenuation; } + if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { - // maps + throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); - if ( json.map !== undefined ) { material.map = getTexture( json.map ); } + } - if ( json.alphaMap !== undefined ) { + // upload an empty depth texture with framebuffer size + if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || + renderTarget.depthTexture.image.width !== renderTarget.width || + renderTarget.depthTexture.image.height !== renderTarget.height ) { - material.alphaMap = getTexture( json.alphaMap ); - material.transparent = true; + renderTarget.depthTexture.image.width = renderTarget.width; + renderTarget.depthTexture.image.height = renderTarget.height; + renderTarget.depthTexture.needsUpdate = true; } - if ( json.bumpMap !== undefined ) { material.bumpMap = getTexture( json.bumpMap ); } - if ( json.bumpScale !== undefined ) { material.bumpScale = json.bumpScale; } - - if ( json.normalMap !== undefined ) { material.normalMap = getTexture( json.normalMap ); } - if ( json.normalScale !== undefined ) { - - var normalScale = json.normalScale; + setTexture2D( renderTarget.depthTexture, 0 ); - if ( Array.isArray( normalScale ) === false ) { + const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + const samples = getRenderTargetSamples( renderTarget ); - // Blender exporter used to export a scalar. See #7459 + if ( renderTarget.depthTexture.format === DepthFormat ) { - normalScale = [ normalScale, normalScale ]; + if ( useMultisampledRTT( renderTarget ) ) { - } + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); - material.normalScale = new Vector2().fromArray( normalScale ); + } else { - } + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - if ( json.displacementMap !== undefined ) { material.displacementMap = getTexture( json.displacementMap ); } - if ( json.displacementScale !== undefined ) { material.displacementScale = json.displacementScale; } - if ( json.displacementBias !== undefined ) { material.displacementBias = json.displacementBias; } + } - if ( json.roughnessMap !== undefined ) { material.roughnessMap = getTexture( json.roughnessMap ); } - if ( json.metalnessMap !== undefined ) { material.metalnessMap = getTexture( json.metalnessMap ); } + } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { - if ( json.emissiveMap !== undefined ) { material.emissiveMap = getTexture( json.emissiveMap ); } - if ( json.emissiveIntensity !== undefined ) { material.emissiveIntensity = json.emissiveIntensity; } + if ( useMultisampledRTT( renderTarget ) ) { - if ( json.specularMap !== undefined ) { material.specularMap = getTexture( json.specularMap ); } + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); - if ( json.envMap !== undefined ) { material.envMap = getTexture( json.envMap ); } + } else { - if ( json.reflectivity !== undefined ) { material.reflectivity = json.reflectivity; } + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - if ( json.lightMap !== undefined ) { material.lightMap = getTexture( json.lightMap ); } - if ( json.lightMapIntensity !== undefined ) { material.lightMapIntensity = json.lightMapIntensity; } + } - if ( json.aoMap !== undefined ) { material.aoMap = getTexture( json.aoMap ); } - if ( json.aoMapIntensity !== undefined ) { material.aoMapIntensity = json.aoMapIntensity; } + } else { - if ( json.gradientMap !== undefined ) { material.gradientMap = getTexture( json.gradientMap ); } + throw new Error( 'Unknown depthTexture format' ); - return material; + } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ + // Setup GL resources for a non-texture depth buffer + function setupDepthRenderbuffer( renderTarget ) { -function BufferGeometryLoader( manager ) { + const renderTargetProperties = properties.get( renderTarget ); + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { -} + if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); -Object.assign( BufferGeometryLoader.prototype, { + setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); - load: function ( url, onLoad, onProgress, onError ) { + } else { - var scope = this; + if ( isCube ) { - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + renderTargetProperties.__webglDepthbuffer = []; - onLoad( scope.parse( JSON.parse( text ) ) ); + for ( let i = 0; i < 6; i ++ ) { - }, onProgress, onError ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); + renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); - }, + } - parse: function ( json ) { + } else { - var geometry = new BufferGeometry(); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); - var index = json.data.index; + } - if ( index !== undefined ) { + } - var typedArray = new TYPED_ARRAYS[ index.type ]( index.array ); - geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - } + } - var attributes = json.data.attributes; + // rebind framebuffer with external textures + function rebindTextures( renderTarget, colorTexture, depthTexture ) { - for ( var key in attributes ) { + const renderTargetProperties = properties.get( renderTarget ); - var attribute = attributes[ key ]; - var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); + if ( colorTexture !== undefined ) { - geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 ); } - var groups = json.data.groups || json.data.drawcalls || json.data.offsets; + if ( depthTexture !== undefined ) { - if ( groups !== undefined ) { + setupDepthRenderbuffer( renderTarget ); - for ( var i = 0, n = groups.length; i !== n; ++ i ) { + } - var group = groups[ i ]; + } - geometry.addGroup( group.start, group.count, group.materialIndex ); + // Set up GL resources for the render target + function setupRenderTarget( renderTarget ) { - } + const texture = renderTarget.texture; - } + const renderTargetProperties = properties.get( renderTarget ); + const textureProperties = properties.get( texture ); + + renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); - var boundingSphere = json.data.boundingSphere; + const textures = renderTarget.textures; - if ( boundingSphere !== undefined ) { + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); + const isMultipleRenderTargets = ( textures.length > 1 ); - var center = new Vector3(); + if ( ! isMultipleRenderTargets ) { - if ( boundingSphere.center !== undefined ) { + if ( textureProperties.__webglTexture === undefined ) { - center.fromArray( boundingSphere.center ); + textureProperties.__webglTexture = _gl.createTexture(); } - geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); + textureProperties.__version = texture.version; + info.memory.textures ++; } - return geometry; - - } - -} ); - -var TYPED_ARRAYS = { - Int8Array: Int8Array, - Uint8Array: Uint8Array, - // Workaround for IE11 pre KB2929437. See #11440 - Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, - Int16Array: Int16Array, - Uint16Array: Uint16Array, - Int32Array: Int32Array, - Uint32Array: Uint32Array, - Float32Array: Float32Array, - Float64Array: Float64Array -}; + // Setup framebuffer -/** - * @author alteredq / http://alteredqualia.com/ - */ + if ( isCube ) { -function Loader() { + renderTargetProperties.__webglFramebuffer = []; - this.onLoadStart = function () {}; - this.onLoadProgress = function () {}; - this.onLoadComplete = function () {}; + for ( let i = 0; i < 6; i ++ ) { -} + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { -Loader.Handlers = { + renderTargetProperties.__webglFramebuffer[ i ] = []; - handlers: [], + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - add: function ( regex, loader ) { + renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer(); - this.handlers.push( regex, loader ); + } - }, + } else { - get: function ( file ) { + renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); - var handlers = this.handlers; + } - for ( var i = 0, l = handlers.length; i < l; i += 2 ) { + } - var regex = handlers[ i ]; - var loader = handlers[ i + 1 ]; + } else { - if ( regex.test( file ) ) { + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - return loader; + renderTargetProperties.__webglFramebuffer = []; - } + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - } + renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer(); - return null; + } - } + } else { -}; + renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); -Object.assign( Loader.prototype, { + } - crossOrigin: undefined, + if ( isMultipleRenderTargets ) { - initMaterials: function ( materials, texturePath, crossOrigin ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - var array = []; + const attachmentProperties = properties.get( textures[ i ] ); - for ( var i = 0; i < materials.length; ++ i ) { + if ( attachmentProperties.__webglTexture === undefined ) { - array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin ); + attachmentProperties.__webglTexture = _gl.createTexture(); - } + info.memory.textures ++; - return array; + } - }, + } - createMaterial: ( function () { + } - var BlendingMode = { - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending - }; + if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { - var color = new Color(); - var textureLoader = new TextureLoader(); - var materialLoader = new MaterialLoader(); + renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); + renderTargetProperties.__webglColorRenderbuffer = []; - return function createMaterial( m, texturePath, crossOrigin ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); - // convert from old material format + for ( let i = 0; i < textures.length; i ++ ) { - var textures = {}; + const texture = textures[ i ]; + renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); - function loadTexture( path, repeat, offset, wrap, anisotropy ) { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - var fullPath = texturePath + path; - var loader = Loader.Handlers.get( fullPath ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); + const samples = getRenderTargetSamples( renderTarget ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - var texture; + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - if ( loader !== null ) { + } - texture = loader.load( fullPath ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - } else { + if ( renderTarget.depthBuffer ) { - textureLoader.setCrossOrigin( crossOrigin ); - texture = textureLoader.load( fullPath ); + renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); } - if ( repeat !== undefined ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - texture.repeat.fromArray( repeat ); + } - if ( repeat[ 0 ] !== 1 ) { texture.wrapS = RepeatWrapping; } - if ( repeat[ 1 ] !== 1 ) { texture.wrapT = RepeatWrapping; } + } - } + // Setup color buffer - if ( offset !== undefined ) { + if ( isCube ) { - texture.offset.fromArray( offset ); + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); - } + for ( let i = 0; i < 6; i ++ ) { - if ( wrap !== undefined ) { + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - if ( wrap[ 0 ] === 'repeat' ) { texture.wrapS = RepeatWrapping; } - if ( wrap[ 0 ] === 'mirror' ) { texture.wrapS = MirroredRepeatWrapping; } + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - if ( wrap[ 1 ] === 'repeat' ) { texture.wrapT = RepeatWrapping; } - if ( wrap[ 1 ] === 'mirror' ) { texture.wrapT = MirroredRepeatWrapping; } + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level ); - } + } - if ( anisotropy !== undefined ) { + } else { - texture.anisotropy = anisotropy; + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 ); } - var uuid = _Math.generateUUID(); + } - textures[ uuid ] = texture; + if ( textureNeedsGenerateMipmaps( texture ) ) { - return uuid; + generateMipmap( _gl.TEXTURE_CUBE_MAP ); } - // + state.unbindTexture(); - var json = { - uuid: _Math.generateUUID(), - type: 'MeshLambertMaterial' - }; + } else if ( isMultipleRenderTargets ) { - for ( var name in m ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - var value = m[ name ]; + const attachment = textures[ i ]; + const attachmentProperties = properties.get( attachment ); - switch ( name ) { + state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_2D, attachment ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 ); - case 'DbgColor': - case 'DbgIndex': - case 'opticalDensity': - case 'illumination': - break; - case 'DbgName': - json.name = value; - break; - case 'blending': - json.blending = BlendingMode[ value ]; - break; - case 'colorAmbient': - case 'mapAmbient': - console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' ); - break; - case 'colorDiffuse': - json.color = color.fromArray( value ).getHex(); - break; - case 'colorSpecular': - json.specular = color.fromArray( value ).getHex(); - break; - case 'colorEmissive': - json.emissive = color.fromArray( value ).getHex(); - break; - case 'specularCoef': - json.shininess = value; - break; - case 'shading': - if ( value.toLowerCase() === 'basic' ) { json.type = 'MeshBasicMaterial'; } - if ( value.toLowerCase() === 'phong' ) { json.type = 'MeshPhongMaterial'; } - if ( value.toLowerCase() === 'standard' ) { json.type = 'MeshStandardMaterial'; } - break; - case 'mapDiffuse': - json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy ); - break; - case 'mapDiffuseRepeat': - case 'mapDiffuseOffset': - case 'mapDiffuseWrap': - case 'mapDiffuseAnisotropy': - break; - case 'mapEmissive': - json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy ); - break; - case 'mapEmissiveRepeat': - case 'mapEmissiveOffset': - case 'mapEmissiveWrap': - case 'mapEmissiveAnisotropy': - break; - case 'mapLight': - json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy ); - break; - case 'mapLightRepeat': - case 'mapLightOffset': - case 'mapLightWrap': - case 'mapLightAnisotropy': - break; - case 'mapAO': - json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy ); - break; - case 'mapAORepeat': - case 'mapAOOffset': - case 'mapAOWrap': - case 'mapAOAnisotropy': - break; - case 'mapBump': - json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy ); - break; - case 'mapBumpScale': - json.bumpScale = value; - break; - case 'mapBumpRepeat': - case 'mapBumpOffset': - case 'mapBumpWrap': - case 'mapBumpAnisotropy': - break; - case 'mapNormal': - json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy ); - break; - case 'mapNormalFactor': - json.normalScale = [ value, value ]; - break; - case 'mapNormalRepeat': - case 'mapNormalOffset': - case 'mapNormalWrap': - case 'mapNormalAnisotropy': - break; - case 'mapSpecular': - json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy ); - break; - case 'mapSpecularRepeat': - case 'mapSpecularOffset': - case 'mapSpecularWrap': - case 'mapSpecularAnisotropy': - break; - case 'mapMetalness': - json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy ); - break; - case 'mapMetalnessRepeat': - case 'mapMetalnessOffset': - case 'mapMetalnessWrap': - case 'mapMetalnessAnisotropy': - break; - case 'mapRoughness': - json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy ); - break; - case 'mapRoughnessRepeat': - case 'mapRoughnessOffset': - case 'mapRoughnessWrap': - case 'mapRoughnessAnisotropy': - break; - case 'mapAlpha': - json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy ); - break; - case 'mapAlphaRepeat': - case 'mapAlphaOffset': - case 'mapAlphaWrap': - case 'mapAlphaAnisotropy': - break; - case 'flipSided': - json.side = BackSide; - break; - case 'doubleSided': - json.side = DoubleSide; - break; - case 'transparency': - console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' ); - json.opacity = value; - break; - case 'depthTest': - case 'depthWrite': - case 'colorWrite': - case 'opacity': - case 'reflectivity': - case 'transparent': - case 'visible': - case 'wireframe': - json[ name ] = value; - break; - case 'vertexColors': - if ( value === true ) { json.vertexColors = VertexColors; } - if ( value === 'face' ) { json.vertexColors = FaceColors; } - break; - default: - console.error( 'THREE.Loader.createMaterial: Unsupported', name, value ); - break; + if ( textureNeedsGenerateMipmaps( attachment ) ) { + + generateMipmap( _gl.TEXTURE_2D ); } } - if ( json.type === 'MeshBasicMaterial' ) { delete json.emissive; } - if ( json.type !== 'MeshPhongMaterial' ) { delete json.specular; } + state.unbindTexture(); - if ( json.opacity < 1 ) { json.transparent = true; } + } else { - materialLoader.setTextures( textures ); + let glTextureType = _gl.TEXTURE_2D; - return materialLoader.parse( json ); + if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { - }; + glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; - } )() + } -} ); + state.bindTexture( glTextureType, textureProperties.__webglTexture ); + setTextureParameters( glTextureType, texture ); -/** - * @author Don McCurdy / https://www.donmccurdy.com - */ + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { -var LoaderUtils = { + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - decodeText: function ( array ) { + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level ); - if ( typeof TextDecoder !== 'undefined' ) { + } - return new TextDecoder().decode( array ); + } else { - } + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 ); - // Avoid the String.fromCharCode.apply(null, array) shortcut, which - // throws a "maximum call stack size exceeded" error for large arrays. + } - var s = ''; + if ( textureNeedsGenerateMipmaps( texture ) ) { - for ( var i = 0, il = array.length; i < il; i ++ ) { + generateMipmap( glTextureType ); - // Implicitly assumes little-endian. - s += String.fromCharCode( array[ i ] ); + } + + state.unbindTexture(); } - return s; + // Setup depth and stencil buffers + + if ( renderTarget.depthBuffer ) { - }, + setupDepthRenderbuffer( renderTarget ); - extractUrlBase: function ( url ) { + } - var parts = url.split( '/' ); + } - if ( parts.length === 1 ) { return './'; } + function updateRenderTargetMipmap( renderTarget ) { - parts.pop(); + const textures = renderTarget.textures; - return parts.join( '/' ) + '/'; + for ( let i = 0, il = textures.length; i < il; i ++ ) { - } + const texture = textures[ i ]; -}; + if ( textureNeedsGenerateMipmaps( texture ) ) { -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; + const webglTexture = properties.get( texture ).__webglTexture; -function JSONLoader( manager ) { + state.bindTexture( target, webglTexture ); + generateMipmap( target ); + state.unbindTexture(); - if ( typeof manager === 'boolean' ) { + } - console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' ); - manager = undefined; + } } - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + const invalidationArrayRead = []; + const invalidationArrayDraw = []; - this.withCredentials = false; + function updateMultisampleRenderTarget( renderTarget ) { -} + if ( renderTarget.samples > 0 ) { -Object.assign( JSONLoader.prototype, { + if ( useMultisampledRTT( renderTarget ) === false ) { - load: function ( url, onLoad, onProgress, onError ) { + const textures = renderTarget.textures; + const width = renderTarget.width; + const height = renderTarget.height; + let mask = _gl.COLOR_BUFFER_BIT; + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + const renderTargetProperties = properties.get( renderTarget ); + const isMultipleRenderTargets = ( textures.length > 1 ); - var scope = this; + // If MRT we need to remove FBO attachments + if ( isMultipleRenderTargets ) { - var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url ); + for ( let i = 0; i < textures.length; i ++ ) { - var loader = new FileLoader( this.manager ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); - var json = JSON.parse( text ); - var metadata = json.metadata; + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); - if ( metadata !== undefined ) { + } - var type = metadata.type; + } - if ( type !== undefined ) { + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - if ( type.toLowerCase() === 'object' ) { + for ( let i = 0; i < textures.length; i ++ ) { - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); - return; + if ( renderTarget.resolveDepthBuffer ) { - } + if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; - if ( type.toLowerCase() === 'scene' ) { + // resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' ); - return; + if ( renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; } - } - - } - - var object = scope.parse( json, texturePath ); - onLoad( object.geometry, object.materials ); + if ( isMultipleRenderTargets ) { - }, onProgress, onError ); + _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - }, + const webglTexture = properties.get( textures[ i ] ).__webglTexture; + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); - setTexturePath: function ( value ) { + } - this.texturePath = value; + _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); - }, + if ( supportsInvalidateFramebuffer === true ) { - parse: ( function () { + invalidationArrayRead.length = 0; + invalidationArrayDraw.length = 0; - function parseModel( json, geometry ) { + invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i ); - function isBitSet( value, position ) { + if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false ) { - return value & ( 1 << position ); + invalidationArrayRead.push( depthStyle ); + invalidationArrayDraw.push( depthStyle ); - } + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw ); - var i, j, fi, + } - offset, zLength, + _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArrayRead ); - colorIndex, normalIndex, uvIndex, materialIndex, + } - type, - isQuad, - hasMaterial, - hasFaceVertexUv, - hasFaceNormal, hasFaceVertexNormal, - hasFaceColor, hasFaceVertexColor, + } - vertex, face, faceA, faceB, hex, normal, + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); - uvLayer, uv, u, v, + // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments + if ( isMultipleRenderTargets ) { - faces = json.faces, - vertices = json.vertices, - normals = json.normals, - colors = json.colors, + for ( let i = 0; i < textures.length; i ++ ) { - scale = json.scale, + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - nUvLayers = 0; + 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 ); - if ( json.uvs !== undefined ) { + } - // disregard empty arrays + } - for ( i = 0; i < json.uvs.length; i ++ ) { + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); - if ( json.uvs[ i ].length ) { nUvLayers ++; } + } else { - } + if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false && supportsInvalidateFramebuffer ) { - for ( i = 0; i < nUvLayers; i ++ ) { + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; - geometry.faceVertexUvs[ i ] = []; + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); } } - offset = 0; - zLength = vertices.length; - - while ( offset < zLength ) { + } - vertex = new Vector3(); + } - vertex.x = vertices[ offset ++ ] * scale; - vertex.y = vertices[ offset ++ ] * scale; - vertex.z = vertices[ offset ++ ] * scale; + function getRenderTargetSamples( renderTarget ) { - geometry.vertices.push( vertex ); + return Math.min( capabilities.maxSamples, renderTarget.samples ); - } + } - offset = 0; - zLength = faces.length; + function useMultisampledRTT( renderTarget ) { - while ( offset < zLength ) { + const renderTargetProperties = properties.get( renderTarget ); - type = faces[ offset ++ ]; + return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; - isQuad = isBitSet( type, 0 ); - hasMaterial = isBitSet( type, 1 ); - hasFaceVertexUv = isBitSet( type, 3 ); - hasFaceNormal = isBitSet( type, 4 ); - hasFaceVertexNormal = isBitSet( type, 5 ); - hasFaceColor = isBitSet( type, 6 ); - hasFaceVertexColor = isBitSet( type, 7 ); + } - // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); + function updateVideoTexture( texture ) { - if ( isQuad ) { + const frame = info.render.frame; - faceA = new Face3(); - faceA.a = faces[ offset ]; - faceA.b = faces[ offset + 1 ]; - faceA.c = faces[ offset + 3 ]; + // Check the last frame we updated the VideoTexture - faceB = new Face3(); - faceB.a = faces[ offset + 1 ]; - faceB.b = faces[ offset + 2 ]; - faceB.c = faces[ offset + 3 ]; + if ( _videoTextures.get( texture ) !== frame ) { - offset += 4; + _videoTextures.set( texture, frame ); + texture.update(); - if ( hasMaterial ) { + } - materialIndex = faces[ offset ++ ]; - faceA.materialIndex = materialIndex; - faceB.materialIndex = materialIndex; + } - } + function verifyColorSpace( texture, image ) { - // to get face <=> uv index correspondence + const colorSpace = texture.colorSpace; + const format = texture.format; + const type = texture.type; - fi = geometry.faces.length; + if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image; - if ( hasFaceVertexUv ) { + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { - for ( i = 0; i < nUvLayers; i ++ ) { + // sRGB - uvLayer = json.uvs[ i ]; + if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) { - geometry.faceVertexUvs[ i ][ fi ] = []; - geometry.faceVertexUvs[ i ][ fi + 1 ] = []; + // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format - for ( j = 0; j < 4; j ++ ) { + if ( format !== RGBAFormat || type !== UnsignedByteType ) { - uvIndex = faces[ offset ++ ]; + console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; + } - uv = new Vector2( u, v ); + } else { - if ( j !== 2 ) { geometry.faceVertexUvs[ i ][ fi ].push( uv ); } - if ( j !== 0 ) { geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv ); } + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); - } + } - } + } - } + return image; - if ( hasFaceNormal ) { + } - normalIndex = faces[ offset ++ ] * 3; + function getDimensions( image ) { - faceA.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) { - faceB.normal.copy( faceA.normal ); + // if intrinsic data are not available, fallback to width/height - } + _imageDimensions.width = image.naturalWidth || image.width; + _imageDimensions.height = image.naturalHeight || image.height; - if ( hasFaceVertexNormal ) { + } else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) { - for ( i = 0; i < 4; i ++ ) { + _imageDimensions.width = image.displayWidth; + _imageDimensions.height = image.displayHeight; - normalIndex = faces[ offset ++ ] * 3; + } else { - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + _imageDimensions.width = image.width; + _imageDimensions.height = image.height; + } - if ( i !== 2 ) { faceA.vertexNormals.push( normal ); } - if ( i !== 0 ) { faceB.vertexNormals.push( normal ); } + return _imageDimensions; - } + } - } + // + this.allocateTextureUnit = allocateTextureUnit; + this.resetTextureUnits = resetTextureUnits; - if ( hasFaceColor ) { + 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; - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; +} - faceA.color.setHex( hex ); - faceB.color.setHex( hex ); +function WebGLUtils( gl, extensions ) { - } + function convert( p, colorSpace = NoColorSpace ) { + let extension; - if ( hasFaceVertexColor ) { + const transfer = ColorManagement.getTransfer( colorSpace ); - for ( i = 0; i < 4; i ++ ) { + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; + if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV; - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; + if ( p === HalfFloatType ) return gl.HALF_FLOAT; - if ( i !== 2 ) { faceA.vertexColors.push( new Color( hex ) ); } - if ( i !== 0 ) { faceB.vertexColors.push( new Color( hex ) ); } + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBFormat ) return gl.RGB; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; - } + // WebGL2 formats. - } + if ( p === RedFormat ) return gl.RED; + if ( p === RedIntegerFormat ) return gl.RED_INTEGER; + if ( p === RGFormat ) return gl.RG; + if ( p === RGIntegerFormat ) return gl.RG_INTEGER; + if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; - geometry.faces.push( faceA ); - geometry.faces.push( faceB ); + // S3TC - } else { + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - face = new Face3(); - face.a = faces[ offset ++ ]; - face.b = faces[ offset ++ ]; - face.c = faces[ offset ++ ]; + if ( transfer === SRGBTransfer ) { - if ( hasMaterial ) { + extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); - materialIndex = faces[ offset ++ ]; - face.materialIndex = materialIndex; + 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; - // to get face <=> uv index correspondence + } else { - fi = geometry.faces.length; + return null; - if ( hasFaceVertexUv ) { + } - for ( i = 0; i < nUvLayers; i ++ ) { + } else { - uvLayer = json.uvs[ i ]; + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); - geometry.faceVertexUvs[ i ][ fi ] = []; + if ( extension !== null ) { - for ( j = 0; j < 3; j ++ ) { + 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; - uvIndex = faces[ offset ++ ]; + } else { - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; + return null; - uv = new Vector2( u, v ); + } - geometry.faceVertexUvs[ i ][ fi ].push( uv ); + } - } + } - } + // PVRTC - } + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { - if ( hasFaceNormal ) { + extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - normalIndex = faces[ offset ++ ] * 3; + if ( extension !== null ) { - face.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + 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 { - if ( hasFaceVertexNormal ) { + return null; - for ( i = 0; i < 3; i ++ ) { + } - normalIndex = faces[ offset ++ ] * 3; + } - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + // ETC - face.vertexNormals.push( normal ); + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { - } + extension = extensions.get( 'WEBGL_compressed_texture_etc' ); - } + if ( extension !== null ) { + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; - if ( hasFaceColor ) { + } else { - colorIndex = faces[ offset ++ ]; - face.color.setHex( colors[ colorIndex ] ); + return null; - } + } + } - if ( hasFaceVertexColor ) { + // ASTC - for ( i = 0; i < 3; i ++ ) { + 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 ) { - colorIndex = faces[ offset ++ ]; - face.vertexColors.push( new Color( colors[ colorIndex ] ) ); + extension = extensions.get( 'WEBGL_compressed_texture_astc' ); - } + if ( extension !== null ) { - } + if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; - geometry.faces.push( face ); + } else { - } + return null; } } - function parseSkin( json, geometry ) { + // BPTC - var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2; + if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) { - if ( json.skinWeights ) { + extension = extensions.get( 'EXT_texture_compression_bptc' ); - for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) { + if ( extension !== null ) { - var x = json.skinWeights[ i ]; - var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0; - var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0; - var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0; + if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT; + if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT; - geometry.skinWeights.push( new Vector4( x, y, z, w ) ); + } else { - } + return null; } - if ( json.skinIndices ) { - - for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) { + } - var a = json.skinIndices[ i ]; - var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0; - var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0; - var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0; + // RGTC - geometry.skinIndices.push( new Vector4( a, b, c, d ) ); + if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { - } + extension = extensions.get( 'EXT_texture_compression_rgtc' ); - } + if ( extension !== null ) { - geometry.bones = json.bones; + if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; + if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; + if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; + if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; - if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { + } else { - console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + - geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); + return null; } } - function parseMorphing( json, geometry ) { + // - var scale = json.scale; + if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8; - if ( json.morphTargets !== undefined ) { + // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) - for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) { + return ( gl[ p ] !== undefined ) ? gl[ p ] : null; - geometry.morphTargets[ i ] = {}; - geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; - geometry.morphTargets[ i ].vertices = []; + } - var dstVertices = geometry.morphTargets[ i ].vertices; - var srcVertices = json.morphTargets[ i ].vertices; + return { convert: convert }; - for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) { +} - var vertex = new Vector3(); - vertex.x = srcVertices[ v ] * scale; - vertex.y = srcVertices[ v + 1 ] * scale; - vertex.z = srcVertices[ v + 2 ] * scale; +class ArrayCamera extends PerspectiveCamera { - dstVertices.push( vertex ); + constructor( array = [] ) { - } + super(); - } + this.isArrayCamera = true; - } + this.cameras = array; - if ( json.morphColors !== undefined && json.morphColors.length > 0 ) { + } - console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' ); +} - var faces = geometry.faces; - var morphColors = json.morphColors[ 0 ].colors; +class Group extends Object3D { - for ( var i = 0, l = faces.length; i < l; i ++ ) { + constructor() { - faces[ i ].color.fromArray( morphColors, i * 3 ); + super(); - } + this.isGroup = true; - } + this.type = 'Group'; - } + } + +} + +const _moveEvent = { type: 'move' }; + +class WebXRController { + + constructor() { + + this._targetRay = null; + this._grip = null; + this._hand = null; + + } - function parseAnimations( json, geometry ) { + getHandSpace() { - var outputAnimations = []; + if ( this._hand === null ) { - // parse old style Bone/Hierarchy animations - var animations = []; + this._hand = new Group(); + this._hand.matrixAutoUpdate = false; + this._hand.visible = false; - if ( json.animation !== undefined ) { + this._hand.joints = {}; + this._hand.inputState = { pinching: false }; - animations.push( json.animation ); + } - } + return this._hand; - if ( json.animations !== undefined ) { + } - if ( json.animations.length ) { + getTargetRaySpace() { - animations = animations.concat( json.animations ); + if ( this._targetRay === null ) { - } else { + 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(); - animations.push( json.animations ); + } - } + return this._targetRay; - } + } - for ( var i = 0; i < animations.length; i ++ ) { + getGripSpace() { - var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones ); - if ( clip ) { outputAnimations.push( clip ); } + 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(); - // parse implicit morph animations - if ( geometry.morphTargets ) { + } - // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary. - var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 ); - outputAnimations = outputAnimations.concat( morphAnimationClips ); + return this._grip; - } + } - if ( outputAnimations.length > 0 ) { geometry.animations = outputAnimations; } + dispatchEvent( event ) { - } + if ( this._targetRay !== null ) { - return function ( json, texturePath ) { + this._targetRay.dispatchEvent( event ); - if ( json.data !== undefined ) { + } - // Geometry 4.0 spec - json = json.data; + if ( this._grip !== null ) { - } + this._grip.dispatchEvent( event ); - if ( json.scale !== undefined ) { + } - json.scale = 1.0 / json.scale; + if ( this._hand !== null ) { - } else { + this._hand.dispatchEvent( event ); - json.scale = 1.0; + } - } + return this; - var geometry = new Geometry(); + } - parseModel( json, geometry ); - parseSkin( json, geometry ); - parseMorphing( json, geometry ); - parseAnimations( json, geometry ); + connect( inputSource ) { - geometry.computeFaceNormals(); - geometry.computeBoundingSphere(); + if ( inputSource && inputSource.hand ) { - if ( json.materials === undefined || json.materials.length === 0 ) { + const hand = this._hand; - return { geometry: geometry }; + if ( hand ) { - } else { + for ( const inputjoint of inputSource.hand.values() ) { - var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin ); + // Initialize hand with joints when connected + this._getHandJoint( hand, inputjoint ); - return { geometry: geometry, materials: materials }; + } } - }; + } - } )() + this.dispatchEvent( { type: 'connected', data: inputSource } ); -} ); + return this; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function ObjectLoader( manager ) { + disconnect( inputSource ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.texturePath = ''; + this.dispatchEvent( { type: 'disconnected', data: inputSource } ); -} + if ( this._targetRay !== null ) { -Object.assign( ObjectLoader.prototype, { + this._targetRay.visible = false; - load: function ( url, onLoad, onProgress, onError ) { + } - if ( this.texturePath === '' ) { + if ( this._grip !== null ) { - this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); + this._grip.visible = false; } - var scope = this; + if ( this._hand !== null ) { - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + this._hand.visible = false; - var json = null; + } - try { + return this; - json = JSON.parse( text ); + } - } catch ( error ) { + update( inputSource, frame, referenceSpace ) { - if ( onError !== undefined ) { onError( error ); } + let inputPose = null; + let gripPose = null; + let handPose = null; - console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); + const targetRay = this._targetRay; + const grip = this._grip; + const hand = this._hand; - return; + if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { - } + if ( hand && inputSource.hand ) { - var metadata = json.metadata; + handPose = true; - if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + for ( const inputjoint of inputSource.hand.values() ) { - console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' ); - return; + // Update the joints groups with the XRJoint poses + const jointPose = frame.getJointPose( inputjoint, referenceSpace ); - } + // The transform of this joint will be updated with the joint pose on each frame + const joint = this._getHandJoint( hand, inputjoint ); - scope.parse( json, onLoad ); + if ( jointPose !== null ) { - }, onProgress, onError ); + joint.matrix.fromArray( jointPose.transform.matrix ); + joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; + joint.jointRadius = jointPose.radius; - }, + } - setTexturePath: function ( value ) { + joint.visible = jointPose !== null; - this.texturePath = value; + } - }, + // Custom events - setCrossOrigin: function ( value ) { + // Check pinchz + const indexTip = hand.joints[ 'index-finger-tip' ]; + const thumbTip = hand.joints[ 'thumb-tip' ]; + const distance = indexTip.position.distanceTo( thumbTip.position ); - this.crossOrigin = value; + const distanceToPinch = 0.02; + const threshold = 0.005; - }, + if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { - parse: function ( json, onLoad ) { + hand.inputState.pinching = false; + this.dispatchEvent( { + type: 'pinchend', + handedness: inputSource.handedness, + target: this + } ); - var shapes = this.parseShape( json.shapes ); - var geometries = this.parseGeometries( json.geometries, shapes ); + } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { - var images = this.parseImages( json.images, function () { + hand.inputState.pinching = true; + this.dispatchEvent( { + type: 'pinchstart', + handedness: inputSource.handedness, + target: this + } ); - if ( onLoad !== undefined ) { onLoad( object ); } + } - } ); + } else { - var textures = this.parseTextures( json.textures, images ); - var materials = this.parseMaterials( json.materials, textures ); + if ( grip !== null && inputSource.gripSpace ) { - var object = this.parseObject( json.object, geometries, materials ); + gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); - if ( json.animations ) { + if ( gripPose !== null ) { - object.animations = this.parseAnimations( json.animations ); + grip.matrix.fromArray( gripPose.transform.matrix ); + grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; - } + if ( gripPose.linearVelocity ) { - if ( json.images === undefined || json.images.length === 0 ) { + grip.hasLinearVelocity = true; + grip.linearVelocity.copy( gripPose.linearVelocity ); - if ( onLoad !== undefined ) { onLoad( object ); } + } else { - } + grip.hasLinearVelocity = false; - return object; + } - }, + if ( gripPose.angularVelocity ) { - parseShape: function ( json ) { + grip.hasAngularVelocity = true; + grip.angularVelocity.copy( gripPose.angularVelocity ); - var shapes = {}; + } else { - if ( json !== undefined ) { + grip.hasAngularVelocity = false; - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var shape = new Shape().fromJSON( json[ i ] ); + } - shapes[ shape.uuid ] = shape; + } } - } - - return shapes; - - }, - - parseGeometries: function ( json, shapes ) { + if ( targetRay !== null ) { - var geometries = {}; + inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); - if ( json !== undefined ) { + // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it + if ( inputPose === null && gripPose !== null ) { - var geometryLoader = new JSONLoader(); - var bufferGeometryLoader = new BufferGeometryLoader(); + inputPose = gripPose; - for ( var i = 0, l = json.length; i < l; i ++ ) { - - var geometry; - var data = json[ i ]; - - switch ( data.type ) { + } - case 'PlaneGeometry': - case 'PlaneBufferGeometry': + if ( inputPose !== null ) { - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.widthSegments, - data.heightSegments - ); + targetRay.matrix.fromArray( inputPose.transform.matrix ); + targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; - break; + if ( inputPose.linearVelocity ) { - case 'BoxGeometry': - case 'BoxBufferGeometry': - case 'CubeGeometry': // backwards compatible - - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.depth, - data.widthSegments, - data.heightSegments, - data.depthSegments - ); + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy( inputPose.linearVelocity ); - break; + } else { - case 'CircleGeometry': - case 'CircleBufferGeometry': + targetRay.hasLinearVelocity = false; - geometry = new Geometries[ data.type ]( - data.radius, - data.segments, - data.thetaStart, - data.thetaLength - ); + } - break; + if ( inputPose.angularVelocity ) { - case 'CylinderGeometry': - case 'CylinderBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radiusTop, - data.radiusBottom, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy( inputPose.angularVelocity ); - break; + } else { - case 'ConeGeometry': - case 'ConeBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); + targetRay.hasAngularVelocity = false; - break; + } - case 'SphereGeometry': - case 'SphereBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.widthSegments, - data.heightSegments, - data.phiStart, - data.phiLength, - data.thetaStart, - data.thetaLength - ); + this.dispatchEvent( _moveEvent ); - break; + } - case 'DodecahedronGeometry': - case 'DodecahedronBufferGeometry': - case 'IcosahedronGeometry': - case 'IcosahedronBufferGeometry': - case 'OctahedronGeometry': - case 'OctahedronBufferGeometry': - case 'TetrahedronGeometry': - case 'TetrahedronBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.detail - ); + } - break; - case 'RingGeometry': - case 'RingBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.innerRadius, - data.outerRadius, - data.thetaSegments, - data.phiSegments, - data.thetaStart, - data.thetaLength - ); + if ( targetRay !== null ) { - break; + targetRay.visible = ( inputPose !== null ); - case 'TorusGeometry': - case 'TorusBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.radialSegments, - data.tubularSegments, - data.arc - ); + if ( grip !== null ) { - break; + grip.visible = ( gripPose !== null ); - case 'TorusKnotGeometry': - case 'TorusKnotBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.tubularSegments, - data.radialSegments, - data.p, - data.q - ); + if ( hand !== null ) { - break; + hand.visible = ( handPose !== null ); - case 'LatheGeometry': - case 'LatheBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.points, - data.segments, - data.phiStart, - data.phiLength - ); + return this; - break; + } - case 'PolyhedronGeometry': - case 'PolyhedronBufferGeometry': + // private method - geometry = new Geometries[ data.type ]( - data.vertices, - data.indices, - data.radius, - data.details - ); + _getHandJoint( hand, inputjoint ) { - break; + if ( hand.joints[ inputjoint.jointName ] === undefined ) { - case 'ShapeGeometry': - case 'ShapeBufferGeometry': + const joint = new Group(); + joint.matrixAutoUpdate = false; + joint.visible = false; + hand.joints[ inputjoint.jointName ] = joint; - var geometryShapes = []; + hand.add( joint ); - for ( var i = 0, l = data.shapes.length; i < l; i ++ ) { + } - var shape = shapes[ data.shapes[ i ] ]; + return hand.joints[ inputjoint.jointName ]; - geometryShapes.push( shape ); + } - } +} - geometry = new Geometries[ data.type ]( - geometryShapes, - data.curveSegments - ); +const _occlusion_vertex = ` +void main() { - break; + gl_Position = vec4( position, 1.0 ); - case 'BufferGeometry': +}`; - geometry = bufferGeometryLoader.parse( data ); +const _occlusion_fragment = ` +uniform sampler2DArray depthColor; +uniform float depthWidth; +uniform float depthHeight; - break; +void main() { - case 'Geometry': + vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); - geometry = geometryLoader.parse( data, this.texturePath ).geometry; + if ( coord.x >= 1.0 ) { - break; + gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; - default: + } else { - console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' ); + gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; - continue; + } - } +}`; - geometry.uuid = data.uuid; +class WebXRDepthSensing { - if ( data.name !== undefined ) { geometry.name = data.name; } + constructor() { - geometries[ data.uuid ] = geometry; + this.texture = null; + this.mesh = null; - } + this.depthNear = 0; + this.depthFar = 0; - } + } - return geometries; + init( renderer, depthData, renderState ) { - }, + if ( this.texture === null ) { - parseMaterials: function ( json, textures ) { + const texture = new Texture(); - var materials = {}; + const texProps = renderer.properties.get( texture ); + texProps.__webglTexture = depthData.texture; - if ( json !== undefined ) { + if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) { - var loader = new MaterialLoader(); - loader.setTextures( textures ); + this.depthNear = depthData.depthNear; + this.depthFar = depthData.depthFar; - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var data = json[ i ]; + this.texture = texture; - if ( data.type === 'MultiMaterial' ) { + } - // Deprecated + } - var array = []; + getMesh( cameraXR ) { - for ( var j = 0; j < data.materials.length; j ++ ) { + if ( this.texture !== null ) { - array.push( loader.parse( data.materials[ j ] ) ); + if ( this.mesh === null ) { + const viewport = cameraXR.cameras[ 0 ].viewport; + const material = new ShaderMaterial( { + vertexShader: _occlusion_vertex, + fragmentShader: _occlusion_fragment, + uniforms: { + depthColor: { value: this.texture }, + depthWidth: { value: viewport.z }, + depthHeight: { value: viewport.w } } + } ); - materials[ data.uuid ] = array; + this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material ); - } else { + } - materials[ data.uuid ] = loader.parse( data ); + } - } + return this.mesh; - } + } - } + reset() { - return materials; + this.texture = null; + this.mesh = null; - }, + } - parseAnimations: function ( json ) { + getDepthTexture() { - var animations = []; + return this.texture; - for ( var i = 0; i < json.length; i ++ ) { + } - var clip = AnimationClip.parse( json[ i ] ); +} - animations.push( clip ); +class WebXRManager extends EventDispatcher { - } + constructor( renderer, gl ) { - return animations; + super(); - }, + const scope = this; - parseImages: function ( json, onLoad ) { + let session = null; - var scope = this; - var images = {}; + let framebufferScaleFactor = 1.0; - function loadImage( url ) { + let referenceSpace = null; + let referenceSpaceType = 'local-floor'; + // Set default foveation to maximum. + let foveation = 1.0; + let customReferenceSpace = null; - scope.manager.itemStart( url ); + let pose = null; + let glBinding = null; + let glProjLayer = null; + let glBaseLayer = null; + let xrFrame = null; - return loader.load( url, function () { + const depthSensing = new WebXRDepthSensing(); + const attributes = gl.getContextAttributes(); - scope.manager.itemEnd( url ); + let initialRenderTarget = null; + let newRenderTarget = null; - }, undefined, function () { + const controllers = []; + const controllerInputSources = []; - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + const currentSize = new Vector2(); + let currentPixelRatio = null; - } ); + // - } + const cameraL = new PerspectiveCamera(); + cameraL.layers.enable( 1 ); + cameraL.viewport = new Vector4(); - if ( json !== undefined && json.length > 0 ) { + const cameraR = new PerspectiveCamera(); + cameraR.layers.enable( 2 ); + cameraR.viewport = new Vector4(); - var manager = new LoadingManager( onLoad ); + const cameras = [ cameraL, cameraR ]; - var loader = new ImageLoader( manager ); - loader.setCrossOrigin( this.crossOrigin ); + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); - for ( var i = 0, l = json.length; i < l; i ++ ) { + let _currentDepthNear = null; + let _currentDepthFar = null; - var image = json[ i ]; - var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; + // - images[ image.uuid ] = loadImage( path ); + this.cameraAutoUpdate = true; + this.enabled = false; - } + this.isPresenting = false; - } + this.getController = function ( index ) { - return images; + let controller = controllers[ index ]; - }, + if ( controller === undefined ) { - parseTextures: function ( json, images ) { + controller = new WebXRController(); + controllers[ index ] = controller; - function parseConstant( value, type ) { + } - if ( typeof value === 'number' ) { return value; } + return controller.getTargetRaySpace(); - console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); + }; - return type[ value ]; + this.getControllerGrip = function ( index ) { - } + let controller = controllers[ index ]; - var textures = {}; + if ( controller === undefined ) { - if ( json !== undefined ) { + controller = new WebXRController(); + controllers[ index ] = controller; - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var data = json[ i ]; + return controller.getGripSpace(); - if ( data.image === undefined ) { + }; - console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); + this.getHand = function ( index ) { - } + let controller = controllers[ index ]; - if ( images[ data.image ] === undefined ) { + if ( controller === undefined ) { - console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); + controller = new WebXRController(); + controllers[ index ] = controller; - } + } - var texture = new Texture( images[ data.image ] ); - texture.needsUpdate = true; + return controller.getHandSpace(); - texture.uuid = data.uuid; + }; - if ( data.name !== undefined ) { texture.name = data.name; } + // - if ( data.mapping !== undefined ) { texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); } + function onSessionEvent( event ) { - if ( data.offset !== undefined ) { texture.offset.fromArray( data.offset ); } - if ( data.repeat !== undefined ) { texture.repeat.fromArray( data.repeat ); } - if ( data.center !== undefined ) { texture.center.fromArray( data.center ); } - if ( data.rotation !== undefined ) { texture.rotation = data.rotation; } + const controllerIndex = controllerInputSources.indexOf( event.inputSource ); - if ( data.wrap !== undefined ) { + if ( controllerIndex === - 1 ) { - texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); - texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); + return; - } + } - if ( data.minFilter !== undefined ) { texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); } - if ( data.magFilter !== undefined ) { texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); } - if ( data.anisotropy !== undefined ) { texture.anisotropy = data.anisotropy; } + const controller = controllers[ controllerIndex ]; - if ( data.flipY !== undefined ) { texture.flipY = data.flipY; } + if ( controller !== undefined ) { - textures[ data.uuid ] = texture; + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); + controller.dispatchEvent( { type: event.type, data: event.inputSource } ); } } - return textures; + 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 ); - parseObject: function () { + for ( let i = 0; i < controllers.length; i ++ ) { - var matrix = new Matrix4(); + const inputSource = controllerInputSources[ i ]; - return function parseObject( data, geometries, materials ) { + if ( inputSource === null ) continue; - var object; + controllerInputSources[ i ] = null; - function getGeometry( name ) { + controllers[ i ].disconnect( inputSource ); - if ( geometries[ name ] === undefined ) { + } - console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); + _currentDepthNear = null; + _currentDepthFar = null; - } + depthSensing.reset(); - return geometries[ name ]; + // restore framebuffer/rendering state - } + renderer.setRenderTarget( initialRenderTarget ); - function getMaterial( name ) { + glBaseLayer = null; + glProjLayer = null; + glBinding = null; + session = null; + newRenderTarget = null; - if ( name === undefined ) { return undefined; } + // - if ( Array.isArray( name ) ) { + animation.stop(); - var array = []; + scope.isPresenting = false; - for ( var i = 0, l = name.length; i < l; i ++ ) { + renderer.setPixelRatio( currentPixelRatio ); + renderer.setSize( currentSize.width, currentSize.height, false ); - var uuid = name[ i ]; + scope.dispatchEvent( { type: 'sessionend' } ); - if ( materials[ uuid ] === undefined ) { + } - console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); + this.setFramebufferScaleFactor = function ( value ) { - } + framebufferScaleFactor = value; - array.push( materials[ uuid ] ); + if ( scope.isPresenting === true ) { - } + console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); - return array; + } - } + }; - if ( materials[ name ] === undefined ) { + this.setReferenceSpaceType = function ( value ) { - console.warn( 'THREE.ObjectLoader: Undefined material', name ); + referenceSpaceType = value; - } + if ( scope.isPresenting === true ) { - return materials[ name ]; + console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); } - switch ( data.type ) { - - case 'Scene': + }; - object = new Scene(); + this.getReferenceSpace = function () { - if ( data.background !== undefined ) { + return customReferenceSpace || referenceSpace; - if ( Number.isInteger( data.background ) ) { + }; - object.background = new Color( data.background ); + this.setReferenceSpace = function ( space ) { - } + customReferenceSpace = space; - } + }; - if ( data.fog !== undefined ) { + this.getBaseLayer = function () { - if ( data.fog.type === 'Fog' ) { + return glProjLayer !== null ? glProjLayer : glBaseLayer; - object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); + }; - } else if ( data.fog.type === 'FogExp2' ) { + this.getBinding = function () { - object.fog = new FogExp2( data.fog.color, data.fog.density ); + return glBinding; - } + }; - } + this.getFrame = function () { - break; + return xrFrame; - case 'PerspectiveCamera': + }; - object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); + this.getSession = function () { - if ( data.focus !== undefined ) { object.focus = data.focus; } - if ( data.zoom !== undefined ) { object.zoom = data.zoom; } - if ( data.filmGauge !== undefined ) { object.filmGauge = data.filmGauge; } - if ( data.filmOffset !== undefined ) { object.filmOffset = data.filmOffset; } - if ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); } + return session; - break; + }; - case 'OrthographicCamera': + this.setSession = async function ( value ) { - object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); + session = value; - break; + if ( session !== null ) { - case 'AmbientLight': + initialRenderTarget = renderer.getRenderTarget(); - object = new AmbientLight( data.color, data.intensity ); + 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 ); - break; + if ( attributes.xrCompatible !== true ) { - case 'DirectionalLight': + await gl.makeXRCompatible(); - object = new DirectionalLight( data.color, data.intensity ); + } - break; + currentPixelRatio = renderer.getPixelRatio(); + renderer.getSize( currentSize ); - case 'PointLight': + if ( session.renderState.layers === undefined ) { - object = new PointLight( data.color, data.intensity, data.distance, data.decay ); + const layerInit = { + antialias: attributes.antialias, + alpha: true, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor: framebufferScaleFactor + }; - break; + glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); - case 'RectAreaLight': + session.updateRenderState( { baseLayer: glBaseLayer } ); - object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); + renderer.setPixelRatio( 1 ); + renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); - break; + newRenderTarget = new WebGLRenderTarget( + glBaseLayer.framebufferWidth, + glBaseLayer.framebufferHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + colorSpace: renderer.outputColorSpace, + stencilBuffer: attributes.stencil + } + ); - case 'SpotLight': + } else { - object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); + let depthFormat = null; + let depthType = null; + let glDepthFormat = null; - break; + if ( attributes.depth ) { - case 'HemisphereLight': + glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; + depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; + depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; - object = new HemisphereLight( data.color, data.groundColor, data.intensity ); + } - break; + const projectionlayerInit = { + colorFormat: gl.RGBA8, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; - case 'SkinnedMesh': + glBinding = new XRWebGLBinding( session, gl ); - console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' ); + glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); - case 'Mesh': + session.updateRenderState( { layers: [ glProjLayer ] } ); - var geometry = getGeometry( data.geometry ); - var material = getMaterial( data.material ); + renderer.setPixelRatio( 1 ); + renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false ); - if ( geometry.bones && geometry.bones.length > 0 ) { + newRenderTarget = new WebGLRenderTarget( + glProjLayer.textureWidth, + glProjLayer.textureHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), + stencilBuffer: attributes.stencil, + colorSpace: renderer.outputColorSpace, + samples: attributes.antialias ? 4 : 0, + resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false ) + } ); - object = new SkinnedMesh( geometry, material ); + } - } else { + newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 - object = new Mesh( geometry, material ); + this.setFoveation( foveation ); - } + customReferenceSpace = null; + referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); - break; + animation.setContext( session ); + animation.start(); - case 'LOD': + scope.isPresenting = true; - object = new LOD(); + scope.dispatchEvent( { type: 'sessionstart' } ); - break; + } - case 'Line': + }; - object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); + this.getEnvironmentBlendMode = function () { - break; + if ( session !== null ) { - case 'LineLoop': + return session.environmentBlendMode; - object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); + } - break; + }; - case 'LineSegments': + this.getDepthTexture = function () { - object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); + return depthSensing.getDepthTexture(); - break; + }; - case 'PointCloud': - case 'Points': + function onInputSourcesChange( event ) { - object = new Points$1( getGeometry( data.geometry ), getMaterial( data.material ) ); + // Notify disconnected - break; + for ( let i = 0; i < event.removed.length; i ++ ) { - case 'Sprite': + const inputSource = event.removed[ i ]; + const index = controllerInputSources.indexOf( inputSource ); - object = new Sprite( getMaterial( data.material ) ); + if ( index >= 0 ) { - break; + controllerInputSources[ index ] = null; + controllers[ index ].disconnect( inputSource ); - case 'Group': + } - object = new Group(); + } - break; + // Notify connected - default: + for ( let i = 0; i < event.added.length; i ++ ) { - object = new Object3D(); + const inputSource = event.added[ i ]; - } + let controllerIndex = controllerInputSources.indexOf( inputSource ); - object.uuid = data.uuid; + if ( controllerIndex === - 1 ) { - if ( data.name !== undefined ) { object.name = data.name; } - if ( data.matrix !== undefined ) { + // Assign input source a controller that currently has no input source - matrix.fromArray( data.matrix ); - matrix.decompose( object.position, object.quaternion, object.scale ); + for ( let i = 0; i < controllers.length; i ++ ) { - } else { + if ( i >= controllerInputSources.length ) { - if ( data.position !== undefined ) { object.position.fromArray( data.position ); } - if ( data.rotation !== undefined ) { object.rotation.fromArray( data.rotation ); } - if ( data.quaternion !== undefined ) { object.quaternion.fromArray( data.quaternion ); } - if ( data.scale !== undefined ) { object.scale.fromArray( data.scale ); } + controllerInputSources.push( inputSource ); + controllerIndex = i; + break; - } + } else if ( controllerInputSources[ i ] === null ) { - if ( data.castShadow !== undefined ) { object.castShadow = data.castShadow; } - if ( data.receiveShadow !== undefined ) { object.receiveShadow = data.receiveShadow; } + controllerInputSources[ i ] = inputSource; + controllerIndex = i; + break; - if ( data.shadow ) { + } - if ( data.shadow.bias !== undefined ) { object.shadow.bias = data.shadow.bias; } - if ( data.shadow.radius !== undefined ) { object.shadow.radius = data.shadow.radius; } - if ( data.shadow.mapSize !== undefined ) { object.shadow.mapSize.fromArray( data.shadow.mapSize ); } - if ( data.shadow.camera !== undefined ) { object.shadow.camera = this.parseObject( data.shadow.camera ); } + } - } + // If all controllers do currently receive input we ignore new ones - if ( data.visible !== undefined ) { object.visible = data.visible; } - if ( data.userData !== undefined ) { object.userData = data.userData; } + if ( controllerIndex === - 1 ) break; - if ( data.children !== undefined ) { + } - var children = data.children; + const controller = controllers[ controllerIndex ]; - for ( var i = 0; i < children.length; i ++ ) { + if ( controller ) { - object.add( this.parseObject( children[ i ], geometries, materials ) ); + controller.connect( inputSource ); } } - if ( data.type === 'LOD' ) { + } + + // - var levels = data.levels; + const cameraLPos = new Vector3(); + const cameraRPos = new Vector3(); - for ( var l = 0; l < levels.length; l ++ ) { + /** + * Assumes 2 cameras that are parallel and share an X-axis, and that + * the cameras' projection and world matrices have already been set. + * And that near and far planes are identical for both cameras. + * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 + */ + function setProjectionFromUnion( camera, cameraL, cameraR ) { - var level = levels[ l ]; - var child = object.getObjectByProperty( 'uuid', level.object ); + cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); + cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); - if ( child !== undefined ) { + const ipd = cameraLPos.distanceTo( cameraRPos ); - object.addLevel( child, level.distance ); + const projL = cameraL.projectionMatrix.elements; + const projR = cameraR.projectionMatrix.elements; - } + // VR systems will have identical far and near planes, and + // most likely identical top and bottom frustum extents. + // Use the left camera for these values. + 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; - } + // Calculate the new camera's position offset from the + // left camera. xOffset should be roughly half `ipd`. + const zOffset = ipd / ( - leftFov + rightFov ); + const xOffset = zOffset * - leftFov; - return object; + // TODO: Better way to apply this offset? + cameraL.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(); - }; + // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // although must now be relative to the new union camera. + 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 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); -} ); + } -var TEXTURE_MAPPING = { - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping -}; + function updateCamera( camera, parent ) { -var TEXTURE_WRAPPING = { - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping -}; + if ( parent === null ) { -var TEXTURE_FILTER = { - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter -}; + camera.matrixWorld.copy( camera.matrix ); -/** - * @author thespite / http://clicktorelease.com/ - */ + } else { + + camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); + + } -function ImageBitmapLoader( manager ) { + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); - if ( typeof createImageBitmap === 'undefined' ) { + } - console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); + this.updateCamera = function ( camera ) { - } + if ( session === null ) return; - if ( typeof fetch === 'undefined' ) { + if ( depthSensing.texture !== null ) { - console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); + camera.near = depthSensing.depthNear; + camera.far = depthSensing.depthFar; - } + } - this.manager = manager !== undefined ? manager : DefaultLoadingManager; - this.options = undefined; + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; -} + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { -ImageBitmapLoader.prototype = { + // Note that the new renderState won't apply until the next frame. See #18320 - constructor: ImageBitmapLoader, + session.updateRenderState( { + depthNear: cameraXR.near, + depthFar: cameraXR.far + } ); - setOptions: function setOptions( options ) { + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; - this.options = options; + cameraL.near = _currentDepthNear; + cameraL.far = _currentDepthFar; + cameraR.near = _currentDepthNear; + cameraR.far = _currentDepthFar; - return this; + cameraL.updateProjectionMatrix(); + cameraR.updateProjectionMatrix(); + camera.updateProjectionMatrix(); - }, + } - load: function load( url, onLoad, onProgress, onError ) { + const parent = camera.parent; + const cameras = cameraXR.cameras; - if ( url === undefined ) { url = ''; } + updateCamera( cameraXR, parent ); - if ( this.path !== undefined ) { url = this.path + url; } + for ( let i = 0; i < cameras.length; i ++ ) { - var scope = this; + updateCamera( cameras[ i ], parent ); - var cached = Cache.get( url ); + } - if ( cached !== undefined ) { + // update projection matrix for proper view frustum culling - scope.manager.itemStart( url ); + if ( cameras.length === 2 ) { - setTimeout( function () { + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - if ( onLoad ) { onLoad( cached ); } + } else { - scope.manager.itemEnd( url ); + // assume single camera setup (AR) - }, 0 ); + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); - return cached; + } - } + // update user camera and its children - fetch( url ).then( function ( res ) { + updateUserCamera( camera, cameraXR, parent ); - return res.blob(); + }; - } ).then( function ( blob ) { + function updateUserCamera( camera, cameraXR, parent ) { - return createImageBitmap( blob, scope.options ); + if ( parent === null ) { - } ).then( function ( imageBitmap ) { + camera.matrix.copy( cameraXR.matrixWorld ); - Cache.add( url, imageBitmap ); + } else { - if ( onLoad ) { onLoad( imageBitmap ); } + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); - scope.manager.itemEnd( url ); + } - } ).catch( function ( e ) { + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); - if ( onError ) { onError( e ); } + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + if ( camera.isPerspectiveCamera ) { - } ); + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - }, + } - setCrossOrigin: function ( /* value */ ) { + } - return this; + this.getCamera = function () { - }, + return cameraXR; - setPath: function ( value ) { + }; - this.path = value; - return this; + this.getFoveation = function () { - } + if ( glProjLayer === null && glBaseLayer === null ) { -}; + return undefined; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * minimal class for proxing functions to Path. Replaces old "extractSubpaths()" - **/ + } -function ShapePath() { + return foveation; - this.type = 'ShapePath'; + }; - this.subPaths = []; - this.currentPath = null; + this.setFoveation = function ( value ) { -} + // 0 = no foveation = full resolution + // 1 = maximum foveation = the edges render at lower resolution -Object.assign( ShapePath.prototype, { + foveation = value; - moveTo: function ( x, y ) { + if ( glProjLayer !== null ) { - this.currentPath = new Path$1(); - this.subPaths.push( this.currentPath ); - this.currentPath.moveTo( x, y ); + glProjLayer.fixedFoveation = value; - }, + } - lineTo: function ( x, y ) { + if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { - this.currentPath.lineTo( x, y ); + glBaseLayer.fixedFoveation = value; - }, + } - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { + }; - this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); + this.hasDepthSensing = function () { - }, + return depthSensing.texture !== null; - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + }; - this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); + this.getDepthSensingMesh = function () { - }, + return depthSensing.getMesh( cameraXR ); - splineThru: function ( pts ) { + }; - this.currentPath.splineThru( pts ); + // Animation Loop - }, + let onAnimationFrameCallback = null; - toShapes: function ( isCCW, noHoles ) { + function onAnimationFrame( time, frame ) { - function toShapesNoHoles( inSubpaths ) { + pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); + xrFrame = frame; - var shapes = []; + if ( pose !== null ) { - for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) { + const views = pose.views; - var tmpPath = inSubpaths[ i ]; + if ( glBaseLayer !== null ) { - var tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; + renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); + renderer.setRenderTarget( newRenderTarget ); - shapes.push( tmpShape ); + } - } + let cameraXRNeedsUpdate = false; - return shapes; + // check if it's necessary to rebuild cameraXR's camera list - } + if ( views.length !== cameraXR.cameras.length ) { - function isPointInsidePolygon( inPt, inPolygon ) { + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; - var polyLen = inPolygon.length; + } - // inPt on polygon contour => immediate success or - // toggling of inside/outside at every single! intersection point of an edge - // with the horizontal line through inPt, left of inPt - // not counting lowerY endpoints of edges and whole edges on that line - var inside = false; - for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { + for ( let i = 0; i < views.length; i ++ ) { - var edgeLowPt = inPolygon[ p ]; - var edgeHighPt = inPolygon[ q ]; + const view = views[ i ]; - var edgeDx = edgeHighPt.x - edgeLowPt.x; - var edgeDy = edgeHighPt.y - edgeLowPt.y; + let viewport = null; - if ( Math.abs( edgeDy ) > Number.EPSILON ) { + if ( glBaseLayer !== null ) { - // not parallel - if ( edgeDy < 0 ) { + viewport = glBaseLayer.getViewport( view ); - edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; - edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; + } else { - } - if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) { continue; } + const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); + viewport = glSubImage.viewport; - if ( inPt.y === edgeLowPt.y ) { + // For side-by-side projection, we only produce a single texture for both eyes. + if ( i === 0 ) { - if ( inPt.x === edgeLowPt.x ) { return true; } // inPt is on contour ? - // continue; // no intersection or edgeLowPt => doesn't count !!! + renderer.setRenderTargetTextures( + newRenderTarget, + glSubImage.colorTexture, + glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); - } else { + renderer.setRenderTarget( newRenderTarget ); - var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); - if ( perpEdge === 0 ) { return true; } // inPt is on contour ? - if ( perpEdge < 0 ) { continue; } - inside = ! inside; // true intersection left of inPt + } } - } else { - - // parallel or collinear - if ( inPt.y !== edgeLowPt.y ) { continue; } // parallel - // edge lies on the same horizontal line as inPt - if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || - ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) { return true; } // inPt: Point on contour ! - // continue; + let camera = cameras[ i ]; - } + if ( camera === undefined ) { - } + camera = new PerspectiveCamera(); + camera.layers.enable( i ); + camera.viewport = new Vector4(); + cameras[ i ] = camera; - return inside; + } - } + camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); + camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); - var isClockWise = ShapeUtils.isClockWise; + if ( i === 0 ) { - var subPaths = this.subPaths; - if ( subPaths.length === 0 ) { return []; } + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); - if ( noHoles === true ) { return toShapesNoHoles( subPaths ); } + } + if ( cameraXRNeedsUpdate === true ) { - var solid, tmpPath, tmpShape, shapes = []; + cameraXR.cameras.push( camera ); - if ( subPaths.length === 1 ) { + } - tmpPath = subPaths[ 0 ]; - tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; - shapes.push( tmpShape ); - return shapes; + } - } + // - var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); - holesFirst = isCCW ? ! holesFirst : holesFirst; + const enabledFeatures = session.enabledFeatures; - // console.log("Holes first", holesFirst); + if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { - var betterShapeHoles = []; - var newShapes = []; - var newShapeHoles = []; - var mainIdx = 0; - var tmpPoints; + const depthData = glBinding.getDepthInformation( views[ 0 ] ); - newShapes[ mainIdx ] = undefined; - newShapeHoles[ mainIdx ] = []; + if ( depthData && depthData.isValid && depthData.texture ) { - for ( var i = 0, l = subPaths.length; i < l; i ++ ) { + depthSensing.init( renderer, depthData, session.renderState ); - 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 ] = []; + for ( let i = 0; i < controllers.length; i ++ ) { - //console.log('cw', i); + const inputSource = controllerInputSources[ i ]; + const controller = controllers[ i ]; - } else { + if ( inputSource !== null && controller !== undefined ) { - newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); + controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); - //console.log('ccw', i); + } } - } - - // only Holes? -> probably all Shapes with wrong orientation - if ( ! newShapes[ 0 ] ) { return toShapesNoHoles( subPaths ); } + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); + if ( frame.detectedPlanes ) { - if ( newShapes.length > 1 ) { + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); - var ambiguous = false; - var toChange = []; - - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + } - betterShapeHoles[ sIdx ] = []; + xrFrame = null; - } + } - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + const animation = new WebGLAnimation(); - var sho = newShapeHoles[ sIdx ]; + animation.setAnimationLoop( onAnimationFrame ); - for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) { + this.setAnimationLoop = function ( callback ) { - var ho = sho[ hIdx ]; - var hole_unassigned = true; + onAnimationFrameCallback = callback; - for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { + }; - if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { + this.dispose = function () {}; - if ( sIdx !== s2Idx ) { toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); } - if ( hole_unassigned ) { + } - hole_unassigned = false; - betterShapeHoles[ s2Idx ].push( ho ); +} - } else { +const _e1 = /*@__PURE__*/ new Euler(); +const _m1 = /*@__PURE__*/ new Matrix4(); - ambiguous = true; +function WebGLMaterials( renderer, properties ) { - } + function refreshTransformUniform( map, uniform ) { - } + if ( map.matrixAutoUpdate === true ) { - } - if ( hole_unassigned ) { + map.updateMatrix(); - betterShapeHoles[ sIdx ].push( ho ); + } - } + uniform.value.copy( map.matrix ); - } + } - } - // console.log("ambiguous: ", ambiguous); - if ( toChange.length > 0 ) { + function refreshFogUniforms( uniforms, fog ) { - // console.log("to change: ", toChange); - if ( ! ambiguous ) { newShapeHoles = betterShapeHoles; } + fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); - } + if ( fog.isFog ) { - } + uniforms.fogNear.value = fog.near; + uniforms.fogFar.value = fog.far; - var tmpHoles; + } else if ( fog.isFogExp2 ) { - for ( var i = 0, il = newShapes.length; i < il; i ++ ) { + uniforms.fogDensity.value = fog.density; - tmpShape = newShapes[ i ].s; - shapes.push( tmpShape ); - tmpHoles = newShapeHoles[ i ]; + } - for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) { + } - tmpShape.holes.push( tmpHoles[ j ].h ); + function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { - } + if ( material.isMeshBasicMaterial ) { - } + refreshUniformsCommon( uniforms, material ); - //console.log("shape", shapes); + } else if ( material.isMeshLambertMaterial ) { - return shapes; + refreshUniformsCommon( uniforms, material ); - } + } else if ( material.isMeshToonMaterial ) { -} ); + refreshUniformsCommon( uniforms, material ); + refreshUniformsToon( uniforms, material ); -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author mrdoob / http://mrdoob.com/ - */ + } else if ( material.isMeshPhongMaterial ) { -function Font( data ) { + refreshUniformsCommon( uniforms, material ); + refreshUniformsPhong( uniforms, material ); - this.type = 'Font'; + } else if ( material.isMeshStandardMaterial ) { - this.data = data; + refreshUniformsCommon( uniforms, material ); + refreshUniformsStandard( uniforms, material ); -} + if ( material.isMeshPhysicalMaterial ) { -Object.assign( Font.prototype, { + refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); - isFont: true, + } - generateShapes: function ( text, size, divisions ) { + } else if ( material.isMeshMatcapMaterial ) { - function createPaths( text ) { + refreshUniformsCommon( uniforms, material ); + refreshUniformsMatcap( uniforms, material ); - var chars = String( text ).split( '' ); - var scale = size / data.resolution; - var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale; + } else if ( material.isMeshDepthMaterial ) { - var offsetX = 0, offsetY = 0; + refreshUniformsCommon( uniforms, material ); - var paths = []; + } else if ( material.isMeshDistanceMaterial ) { - for ( var i = 0; i < chars.length; i ++ ) { + refreshUniformsCommon( uniforms, material ); + refreshUniformsDistance( uniforms, material ); - var char = chars[ i ]; + } else if ( material.isMeshNormalMaterial ) { - if ( char === '\n' ) { + refreshUniformsCommon( uniforms, material ); - offsetX = 0; - offsetY -= line_height; + } else if ( material.isLineBasicMaterial ) { - } else { + refreshUniformsLine( uniforms, material ); - var ret = createPath( char, scale, offsetX, offsetY ); - offsetX += ret.offsetX; - paths.push( ret.path ); + if ( material.isLineDashedMaterial ) { - } + refreshUniformsDash( uniforms, material ); } - return paths; + } else if ( material.isPointsMaterial ) { - } + refreshUniformsPoints( uniforms, material, pixelRatio, height ); - function createPath( c, scale, offsetX, offsetY ) { + } else if ( material.isSpriteMaterial ) { - var glyph = data.glyphs[ c ] || data.glyphs[ '?' ]; + refreshUniformsSprites( uniforms, material ); - if ( ! glyph ) { return; } + } else if ( material.isShadowMaterial ) { - var path = new ShapePath(); + uniforms.color.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - var pts = []; - var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2, laste; + } else if ( material.isShaderMaterial ) { - if ( glyph.o ) { + material.uniformsNeedUpdate = false; // #15581 - var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); + } - for ( var i = 0, l = outline.length; i < l; ) { + } - var action = outline[ i ++ ]; + function refreshUniformsCommon( uniforms, material ) { - switch ( action ) { + uniforms.opacity.value = material.opacity; - case 'm': // moveTo + if ( material.color ) { - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; + uniforms.diffuse.value.copy( material.color ); - path.moveTo( x, y ); + } - break; + if ( material.emissive ) { - case 'l': // lineTo + uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; + } - path.lineTo( x, y ); + if ( material.map ) { - break; + uniforms.map.value = material.map; - case 'q': // quadraticCurveTo + refreshTransformUniform( material.map, uniforms.mapTransform ); - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; + } - path.quadraticCurveTo( cpx1, cpy1, cpx, cpy ); + if ( material.alphaMap ) { - laste = pts[ pts.length - 1 ]; + uniforms.alphaMap.value = material.alphaMap; - if ( laste ) { + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - laste.x; - laste.y; + } - + if ( material.bumpMap ) { - } + uniforms.bumpMap.value = material.bumpMap; - break; + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); - case 'b': // bezierCurveTo + uniforms.bumpScale.value = material.bumpScale; - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; - cpx2 = outline[ i ++ ] * scale + offsetX; - cpy2 = outline[ i ++ ] * scale + offsetY; + if ( material.side === BackSide ) { - path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy ); + uniforms.bumpScale.value *= - 1; - laste = pts[ pts.length - 1 ]; + } - if ( laste ) { + } - laste.x; - laste.y; + if ( material.normalMap ) { - + uniforms.normalMap.value = material.normalMap; - } + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); - break; + uniforms.normalScale.value.copy( material.normalScale ); - } + if ( material.side === BackSide ) { - } + uniforms.normalScale.value.negate(); } - return { offsetX: glyph.ha * scale, path: path }; - } - // + if ( material.displacementMap ) { - if ( size === undefined ) { size = 100; } + uniforms.displacementMap.value = material.displacementMap; - var data = this.data; + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); - var paths = createPaths( text ); - var shapes = []; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; - for ( var p = 0, pl = paths.length; p < pl; p ++ ) { + } - Array.prototype.push.apply( shapes, paths[ p ].toShapes() ); + if ( material.emissiveMap ) { - } + uniforms.emissiveMap.value = material.emissiveMap; - return shapes; + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); - } + } -} ); + if ( material.specularMap ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + uniforms.specularMap.value = material.specularMap; -function FontLoader( manager ) { + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + } -} + if ( material.alphaTest > 0 ) { -Object.assign( FontLoader.prototype, { + uniforms.alphaTest.value = material.alphaTest; - load: function ( url, onLoad, onProgress, onError ) { + } - var scope = this; + const materialProperties = properties.get( material ); - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { + const envMap = materialProperties.envMap; + const envMapRotation = materialProperties.envMapRotation; - var json; + if ( envMap ) { - try { + uniforms.envMap.value = envMap; - json = JSON.parse( text ); + _e1.copy( envMapRotation ); - } catch ( e ) { + // accommodate left-handed frame + _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1; + + if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) { - console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' ); - json = JSON.parse( text.substring( 65, text.length - 2 ) ); + // environment maps which are not cube render targets or PMREMs follow a different convention + _e1.y *= - 1; + _e1.z *= - 1; } - var font = scope.parse( json ); + uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) ); - if ( onLoad ) { onLoad( font ); } + uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - }, onProgress, onError ); + uniforms.reflectivity.value = material.reflectivity; + uniforms.ior.value = material.ior; + uniforms.refractionRatio.value = material.refractionRatio; - }, + } + + if ( material.lightMap ) { - parse: function ( json ) { + uniforms.lightMap.value = material.lightMap; + uniforms.lightMapIntensity.value = material.lightMapIntensity; - return new Font( json ); + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); - }, + } - setPath: function ( value ) { + if ( material.aoMap ) { - this.path = value; - return this; + uniforms.aoMap.value = material.aoMap; + uniforms.aoMapIntensity.value = material.aoMapIntensity; - } + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -var context; + function refreshUniformsLine( uniforms, material ) { -var AudioContext = { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - getContext: function () { + if ( material.map ) { - if ( context === undefined ) { + uniforms.map.value = material.map; - context = new ( window.AudioContext || window.webkitAudioContext )(); + refreshTransformUniform( material.map, uniforms.mapTransform ); } - return context; - - }, + } - setContext: function ( value ) { + function refreshUniformsDash( uniforms, material ) { - context = value; + uniforms.dashSize.value = material.dashSize; + uniforms.totalSize.value = material.dashSize + material.gapSize; + uniforms.scale.value = material.scale; } -}; + function refreshUniformsPoints( uniforms, material, pixelRatio, height ) { -/** - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; + uniforms.size.value = material.size * pixelRatio; + uniforms.scale.value = height * 0.5; -function AudioLoader( manager ) { + if ( material.map ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + uniforms.map.value = material.map; -} + refreshTransformUniform( material.map, uniforms.uvTransform ); -Object.assign( AudioLoader.prototype, { + } - load: function ( url, onLoad, onProgress, onError ) { + if ( material.alphaMap ) { - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - loader.load( url, function ( buffer ) { + uniforms.alphaMap.value = material.alphaMap; - var context = AudioContext.getContext(); + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - context.decodeAudioData( buffer, function ( audioBuffer ) { + } - onLoad( audioBuffer ); + if ( material.alphaTest > 0 ) { - } ); + uniforms.alphaTest.value = material.alphaTest; - }, onProgress, onError ); + } } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function StereoCamera() { + function refreshUniformsSprites( uniforms, material ) { - this.type = 'StereoCamera'; + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; + uniforms.rotation.value = material.rotation; - this.aspect = 1; + if ( material.map ) { - this.eyeSep = 0.064; + uniforms.map.value = material.map; - this.cameraL = new PerspectiveCamera(); - this.cameraL.layers.enable( 1 ); - this.cameraL.matrixAutoUpdate = false; + refreshTransformUniform( material.map, uniforms.mapTransform ); - this.cameraR = new PerspectiveCamera(); - this.cameraR.layers.enable( 2 ); - this.cameraR.matrixAutoUpdate = false; + } -} + if ( material.alphaMap ) { -Object.assign( StereoCamera.prototype, { + uniforms.alphaMap.value = material.alphaMap; - update: ( function () { + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - var instance, focus, fov, aspect, near, far, zoom, eyeSep; + } - var eyeRight = new Matrix4(); - var eyeLeft = new Matrix4(); + if ( material.alphaTest > 0 ) { - return function update( camera ) { + uniforms.alphaTest.value = material.alphaTest; - var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov || - aspect !== camera.aspect * this.aspect || near !== camera.near || - far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep; + } - if ( needsUpdate ) { + } - instance = this; - focus = camera.focus; - fov = camera.fov; - aspect = camera.aspect * this.aspect; - near = camera.near; - far = camera.far; - zoom = camera.zoom; + function refreshUniformsPhong( uniforms, material ) { - // Off-axis stereoscopic effect based on - // http://paulbourke.net/stereographics/stereorender/ + uniforms.specular.value.copy( material.specular ); + uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) - var projectionMatrix = camera.projectionMatrix.clone(); - eyeSep = this.eyeSep / 2; - var eyeSepOnProjection = eyeSep * near / focus; - var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom; - var xmin, xmax; + } - // translate xOffset + function refreshUniformsToon( uniforms, material ) { - eyeLeft.elements[ 12 ] = - eyeSep; - eyeRight.elements[ 12 ] = eyeSep; + if ( material.gradientMap ) { - // for left eye + uniforms.gradientMap.value = material.gradientMap; - xmin = - ymax * aspect + eyeSepOnProjection; - xmax = ymax * aspect + eyeSepOnProjection; + } - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + } - this.cameraL.projectionMatrix.copy( projectionMatrix ); + function refreshUniformsStandard( uniforms, material ) { - // for right eye + uniforms.metalness.value = material.metalness; - xmin = - ymax * aspect - eyeSepOnProjection; - xmax = ymax * aspect - eyeSepOnProjection; + if ( material.metalnessMap ) { - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + uniforms.metalnessMap.value = material.metalnessMap; - this.cameraR.projectionMatrix.copy( projectionMatrix ); + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); - } + } - this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft ); - this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight ); + uniforms.roughness.value = material.roughness; - }; + if ( material.roughnessMap ) { - } )() + uniforms.roughnessMap.value = material.roughnessMap; -} ); + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); -/** - * Camera for rendering cube maps - * - renders scene into axis-aligned cube - * - * @author alteredq / http://alteredqualia.com/ - */ + } -function CubeCamera( near, far, cubeResolution ) { + if ( material.envMap ) { - Object3D.call( this ); + //uniforms.envMap.value = material.envMap; // part of uniforms common - this.type = 'CubeCamera'; + uniforms.envMapIntensity.value = material.envMapIntensity; - var fov = 90, aspect = 1; + } - var cameraPX = new PerspectiveCamera( fov, aspect, near, far ); - cameraPX.up.set( 0, - 1, 0 ); - cameraPX.lookAt( new Vector3( 1, 0, 0 ) ); - this.add( cameraPX ); + } - var cameraNX = new PerspectiveCamera( fov, aspect, near, far ); - cameraNX.up.set( 0, - 1, 0 ); - cameraNX.lookAt( new Vector3( - 1, 0, 0 ) ); - this.add( cameraNX ); + function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { - var cameraPY = new PerspectiveCamera( fov, aspect, near, far ); - cameraPY.up.set( 0, 0, 1 ); - cameraPY.lookAt( new Vector3( 0, 1, 0 ) ); - this.add( cameraPY ); + uniforms.ior.value = material.ior; // also part of uniforms common - var cameraNY = new PerspectiveCamera( fov, aspect, near, far ); - cameraNY.up.set( 0, 0, - 1 ); - cameraNY.lookAt( new Vector3( 0, - 1, 0 ) ); - this.add( cameraNY ); + if ( material.sheen > 0 ) { - var cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraPZ.up.set( 0, - 1, 0 ); - cameraPZ.lookAt( new Vector3( 0, 0, 1 ) ); - this.add( cameraPZ ); + uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); - var cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraNZ.up.set( 0, - 1, 0 ); - cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) ); - this.add( cameraNZ ); + uniforms.sheenRoughness.value = material.sheenRoughness; - var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter }; + if ( material.sheenColorMap ) { - this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options ); - this.renderTarget.texture.name = "CubeCamera"; + uniforms.sheenColorMap.value = material.sheenColorMap; - this.update = function ( renderer, scene ) { + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); - if ( this.parent === null ) { this.updateMatrixWorld(); } + } - var renderTarget = this.renderTarget; - var generateMipmaps = renderTarget.texture.generateMipmaps; + if ( material.sheenRoughnessMap ) { - renderTarget.texture.generateMipmaps = false; + uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; - renderTarget.activeCubeFace = 0; - renderer.render( scene, cameraPX, renderTarget ); + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); - renderTarget.activeCubeFace = 1; - renderer.render( scene, cameraNX, renderTarget ); + } - renderTarget.activeCubeFace = 2; - renderer.render( scene, cameraPY, renderTarget ); + } - renderTarget.activeCubeFace = 3; - renderer.render( scene, cameraNY, renderTarget ); + if ( material.clearcoat > 0 ) { - renderTarget.activeCubeFace = 4; - renderer.render( scene, cameraPZ, renderTarget ); + uniforms.clearcoat.value = material.clearcoat; + uniforms.clearcoatRoughness.value = material.clearcoatRoughness; - renderTarget.texture.generateMipmaps = generateMipmaps; + if ( material.clearcoatMap ) { - renderTarget.activeCubeFace = 5; - renderer.render( scene, cameraNZ, renderTarget ); + uniforms.clearcoatMap.value = material.clearcoatMap; - renderer.setRenderTarget( null ); + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); - }; + } - this.clear = function ( renderer, color, depth, stencil ) { + if ( material.clearcoatRoughnessMap ) { - var renderTarget = this.renderTarget; + uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; - for ( var i = 0; i < 6; i ++ ) { + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); - renderTarget.activeCubeFace = i; - renderer.setRenderTarget( renderTarget ); + } - renderer.clear( color, depth, stencil ); + if ( material.clearcoatNormalMap ) { - } + uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; - renderer.setRenderTarget( null ); + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); - }; + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); -} + if ( material.side === BackSide ) { -CubeCamera.prototype = Object.create( Object3D.prototype ); -CubeCamera.prototype.constructor = CubeCamera; + uniforms.clearcoatNormalScale.value.negate(); -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function AudioListener() { + } - Object3D.call( this ); + } - this.type = 'AudioListener'; + if ( material.dispersion > 0 ) { - this.context = AudioContext.getContext(); + uniforms.dispersion.value = material.dispersion; - this.gain = this.context.createGain(); - this.gain.connect( this.context.destination ); + } - this.filter = null; + 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 ]; -AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), { + if ( material.iridescenceMap ) { - constructor: AudioListener, + uniforms.iridescenceMap.value = material.iridescenceMap; - getInput: function () { + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); - return this.gain; + } - }, + if ( material.iridescenceThicknessMap ) { - removeFilter: function ( ) { + uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; - if ( this.filter !== null ) { + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); - this.gain.connect( this.context.destination ); - this.filter = null; + } } - }, + if ( material.transmission > 0 ) { - getFilter: function () { + uniforms.transmission.value = material.transmission; + uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; + uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); - return this.filter; + if ( material.transmissionMap ) { - }, + uniforms.transmissionMap.value = material.transmissionMap; - setFilter: function ( value ) { + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); - if ( this.filter !== null ) { + } - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); + uniforms.thickness.value = material.thickness; - } else { + if ( material.thicknessMap ) { - this.gain.disconnect( this.context.destination ); + uniforms.thicknessMap.value = material.thicknessMap; - } + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); - this.filter = value; - this.gain.connect( this.filter ); - this.filter.connect( this.context.destination ); + } - }, + uniforms.attenuationDistance.value = material.attenuationDistance; + uniforms.attenuationColor.value.copy( material.attenuationColor ); - getMasterVolume: function () { + } - return this.gain.gain.value; + if ( material.anisotropy > 0 ) { - }, + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - setMasterVolume: function ( value ) { + if ( material.anisotropyMap ) { - this.gain.gain.value = value; + uniforms.anisotropyMap.value = material.anisotropyMap; - }, + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); - updateMatrixWorld: ( function () { + } - var position = new Vector3(); - var quaternion = new Quaternion(); - var scale = new Vector3(); + } - var orientation = new Vector3(); + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); - return function updateMatrixWorld( force ) { + if ( material.specularColorMap ) { - Object3D.prototype.updateMatrixWorld.call( this, force ); + uniforms.specularColorMap.value = material.specularColorMap; - var listener = this.context.listener; - var up = this.up; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); - this.matrixWorld.decompose( position, quaternion, scale ); + } - orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion ); + if ( material.specularIntensityMap ) { - if ( listener.positionX ) { + uniforms.specularIntensityMap.value = material.specularIntensityMap; - listener.positionX.setValueAtTime( position.x, this.context.currentTime ); - listener.positionY.setValueAtTime( position.y, this.context.currentTime ); - listener.positionZ.setValueAtTime( position.z, this.context.currentTime ); - listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime ); - listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime ); - listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime ); - listener.upX.setValueAtTime( up.x, this.context.currentTime ); - listener.upY.setValueAtTime( up.y, this.context.currentTime ); - listener.upZ.setValueAtTime( up.z, this.context.currentTime ); + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); - } else { + } - listener.setPosition( position.x, position.y, position.z ); - listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z ); + } - } + function refreshUniformsMatcap( uniforms, material ) { - }; + if ( material.matcap ) { - } )() + uniforms.matcap.value = material.matcap; -} ); + } -/** - * @author mrdoob / http://mrdoob.com/ - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ + } -function Audio( listener ) { + function refreshUniformsDistance( uniforms, material ) { - Object3D.call( this ); + const light = properties.get( material ).light; - this.type = 'Audio'; + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; - this.context = listener.context; + } - this.gain = this.context.createGain(); - this.gain.connect( listener.getInput() ); + return { + refreshFogUniforms: refreshFogUniforms, + refreshMaterialUniforms: refreshMaterialUniforms + }; - this.autoplay = false; +} - this.buffer = null; - this.loop = false; - this.startTime = 0; - this.offset = 0; - this.playbackRate = 1; - this.isPlaying = false; - this.hasPlaybackControl = true; - this.sourceType = 'empty'; +function WebGLUniformsGroups( gl, info, capabilities, state ) { - this.filters = []; + let buffers = {}; + let updateList = {}; + let allocatedBindingPoints = []; -} + const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program -Audio.prototype = Object.assign( Object.create( Object3D.prototype ), { + function bind( uniformsGroup, program ) { - constructor: Audio, + const webglProgram = program.program; + state.uniformBlockBinding( uniformsGroup, webglProgram ); - getOutput: function () { + } - return this.gain; + function update( uniformsGroup, program ) { - }, + let buffer = buffers[ uniformsGroup.id ]; - setNodeSource: function ( audioNode ) { + if ( buffer === undefined ) { - this.hasPlaybackControl = false; - this.sourceType = 'audioNode'; - this.source = audioNode; - this.connect(); + prepareUniformsGroup( uniformsGroup ); - return this; + buffer = createBuffer( uniformsGroup ); + buffers[ uniformsGroup.id ] = buffer; - }, + uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); - setBuffer: function ( audioBuffer ) { + } - this.buffer = audioBuffer; - this.sourceType = 'buffer'; + // ensure to update the binding points/block indices mapping for this program - if ( this.autoplay ) { this.play(); } + const webglProgram = program.program; + state.updateUBOMapping( uniformsGroup, webglProgram ); - return this; + // update UBO once per frame - }, + const frame = info.render.frame; - play: function () { + if ( updateList[ uniformsGroup.id ] !== frame ) { - if ( this.isPlaying === true ) { + updateBufferData( uniformsGroup ); - console.warn( 'THREE.Audio: Audio is already playing.' ); - return; + updateList[ uniformsGroup.id ] = frame; } - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + function createBuffer( uniformsGroup ) { - } + // the setup of an UBO is independent of a particular shader program but global + + const bindingPointIndex = allocateBindingPointIndex(); + uniformsGroup.__bindingPointIndex = bindingPointIndex; - var source = this.context.createBufferSource(); + const buffer = gl.createBuffer(); + const size = uniformsGroup.__size; + const usage = uniformsGroup.usage; - source.buffer = this.buffer; - source.loop = this.loop; - source.onended = this.onEnded.bind( this ); - source.playbackRate.setValueAtTime( this.playbackRate, this.startTime ); - this.startTime = this.context.currentTime; - source.start( this.startTime, this.offset ); + 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 ); - this.isPlaying = true; + return buffer; - this.source = source; + } - return this.connect(); + function allocateBindingPointIndex() { - }, + for ( let i = 0; i < maxBindingPoints; i ++ ) { - pause: function () { + if ( allocatedBindingPoints.indexOf( i ) === - 1 ) { - if ( this.hasPlaybackControl === false ) { + allocatedBindingPoints.push( i ); + return i; - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + } } - if ( this.isPlaying === true ) { + console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); - this.source.stop(); - this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate; - this.isPlaying = false; + return 0; - } + } - return this; + function updateBufferData( uniformsGroup ) { - }, + const buffer = buffers[ uniformsGroup.id ]; + const uniforms = uniformsGroup.uniforms; + const cache = uniformsGroup.__cache; - stop: function () { + gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); - if ( this.hasPlaybackControl === false ) { + for ( let i = 0, il = uniforms.length; i < il; i ++ ) { - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; - } + for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { - this.source.stop(); - this.offset = 0; - this.isPlaying = false; + const uniform = uniformArray[ j ]; - return this; + if ( hasUniformChanged( uniform, i, j, cache ) === true ) { - }, + const offset = uniform.__offset; - connect: function () { + const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; - if ( this.filters.length > 0 ) { + let arrayOffset = 0; - this.source.connect( this.filters[ 0 ] ); + for ( let k = 0; k < values.length; k ++ ) { - for ( var i = 1, l = this.filters.length; i < l; i ++ ) { + const value = values[ k ]; - this.filters[ i - 1 ].connect( this.filters[ i ] ); + const info = getUniformSize( value ); - } + // TODO add integer and struct support + if ( typeof value === 'number' || typeof value === 'boolean' ) { - this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); + uniform.__data[ 0 ] = value; + gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); - } else { + } else if ( value.isMatrix3 ) { - this.source.connect( this.getOutput() ); + // manually converting 3x3 to 3x4 - } + uniform.__data[ 0 ] = value.elements[ 0 ]; + uniform.__data[ 1 ] = value.elements[ 1 ]; + uniform.__data[ 2 ] = value.elements[ 2 ]; + uniform.__data[ 3 ] = 0; + uniform.__data[ 4 ] = value.elements[ 3 ]; + uniform.__data[ 5 ] = value.elements[ 4 ]; + uniform.__data[ 6 ] = value.elements[ 5 ]; + uniform.__data[ 7 ] = 0; + uniform.__data[ 8 ] = value.elements[ 6 ]; + uniform.__data[ 9 ] = value.elements[ 7 ]; + uniform.__data[ 10 ] = value.elements[ 8 ]; + uniform.__data[ 11 ] = 0; - return this; + } else { - }, + value.toArray( uniform.__data, arrayOffset ); - disconnect: function () { + arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; - if ( this.filters.length > 0 ) { + } - this.source.disconnect( this.filters[ 0 ] ); + } - for ( var i = 1, l = this.filters.length; i < l; i ++ ) { + gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); - this.filters[ i - 1 ].disconnect( this.filters[ i ] ); + } } - this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); + } - } else { + gl.bindBuffer( gl.UNIFORM_BUFFER, null ); - this.source.disconnect( this.getOutput() ); + } - } + function hasUniformChanged( uniform, index, indexArray, cache ) { - return this; + const value = uniform.value; + const indexString = index + '_' + indexArray; - }, + if ( cache[ indexString ] === undefined ) { - getFilters: function () { + // cache entry does not exist so far - return this.filters; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - }, + cache[ indexString ] = value; - setFilters: function ( value ) { + } else { - if ( ! value ) { value = []; } + cache[ indexString ] = value.clone(); - if ( this.isPlaying === true ) { + } - this.disconnect(); - this.filters = value; - this.connect(); + return true; } else { - this.filters = value; + const cachedObject = cache[ indexString ]; - } + // compare current value with cached entry - return this; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - }, + if ( cachedObject !== value ) { - getFilter: function () { + cache[ indexString ] = value; + return true; - return this.getFilters()[ 0 ]; + } - }, + } else { - setFilter: function ( filter ) { + if ( cachedObject.equals( value ) === false ) { - return this.setFilters( filter ? [ filter ] : [] ); + cachedObject.copy( value ); + return true; - }, + } - setPlaybackRate: function ( value ) { + } - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + return false; - } + } - this.playbackRate = value; + function prepareUniformsGroup( uniformsGroup ) { - if ( this.isPlaying === true ) { + // determine total buffer size according to the STD140 layout + // Hint: STD140 is the only supported layout in WebGL 2 - this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime ); + const uniforms = uniformsGroup.uniforms; - } + let offset = 0; // global buffer offset in bytes + const chunkSize = 16; // size of a chunk in bytes - return this; + for ( let i = 0, l = uniforms.length; i < l; i ++ ) { - }, + const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; - getPlaybackRate: function () { + for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { - return this.playbackRate; + const uniform = uniformArray[ j ]; - }, + const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; - onEnded: function () { + for ( let k = 0, kl = values.length; k < kl; k ++ ) { - this.isPlaying = false; + const value = values[ k ]; - }, + const info = getUniformSize( value ); - getLoop: function () { + const chunkOffset = offset % chunkSize; // offset in the current chunk + const chunkPadding = chunkOffset % info.boundary; // required padding to match boundary + const chunkStart = chunkOffset + chunkPadding; // the start position in the current chunk for the data - if ( this.hasPlaybackControl === false ) { + offset += chunkPadding; - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return false; + // Check for chunk overflow + if ( chunkStart !== 0 && ( chunkSize - chunkStart ) < info.storage ) { - } + // Add padding and adjust offset + offset += ( chunkSize - chunkStart ); - return this.loop; + } - }, + // the following two properties will be used for partial buffer updates + uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT ); + uniform.__offset = offset; - setLoop: function ( value ) { + // Update the global offset + offset += info.storage; - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + } } - this.loop = value; + // ensure correct final padding - if ( this.isPlaying === true ) { + const chunkOffset = offset % chunkSize; - this.source.loop = this.loop; - - } + if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); - return this; + // - }, + uniformsGroup.__size = offset; + uniformsGroup.__cache = {}; - getVolume: function () { + return this; - return this.gain.gain.value; + } - }, + function getUniformSize( value ) { - setVolume: function ( value ) { + const info = { + boundary: 0, // bytes + storage: 0 // bytes + }; - this.gain.gain.value = value; + // determine sizes according to STD140 - return this; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - } + // float/int/bool -} ); + info.boundary = 4; + info.storage = 4; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } else if ( value.isVector2 ) { -function PositionalAudio( listener ) { + // vec2 - Audio.call( this, listener ); + info.boundary = 8; + info.storage = 8; - this.panner = this.context.createPanner(); - this.panner.connect( this.gain ); + } else if ( value.isVector3 || value.isColor ) { -} + // vec3 -PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), { + info.boundary = 16; + info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes - constructor: PositionalAudio, + } else if ( value.isVector4 ) { - getOutput: function () { + // vec4 - return this.panner; + info.boundary = 16; + info.storage = 16; - }, + } else if ( value.isMatrix3 ) { - getRefDistance: function () { + // mat3 (in STD140 a 3x3 matrix is represented as 3x4) - return this.panner.refDistance; + info.boundary = 48; + info.storage = 48; - }, + } else if ( value.isMatrix4 ) { - setRefDistance: function ( value ) { + // mat4 - this.panner.refDistance = value; + info.boundary = 64; + info.storage = 64; - }, + } else if ( value.isTexture ) { - getRolloffFactor: function () { + console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); - return this.panner.rolloffFactor; + } else { - }, + console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); - setRolloffFactor: function ( value ) { + } - this.panner.rolloffFactor = value; + return info; - }, + } - getDistanceModel: function () { + function onUniformsGroupsDispose( event ) { - return this.panner.distanceModel; + const uniformsGroup = event.target; - }, + uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); - setDistanceModel: function ( value ) { + const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); + allocatedBindingPoints.splice( index, 1 ); - this.panner.distanceModel = value; + gl.deleteBuffer( buffers[ uniformsGroup.id ] ); - }, + delete buffers[ uniformsGroup.id ]; + delete updateList[ uniformsGroup.id ]; - getMaxDistance: function () { + } - return this.panner.maxDistance; + function dispose() { - }, + for ( const id in buffers ) { - setMaxDistance: function ( value ) { + gl.deleteBuffer( buffers[ id ] ); - this.panner.maxDistance = value; + } - }, + allocatedBindingPoints = []; + buffers = {}; + updateList = {}; - updateMatrixWorld: ( function () { + } - var position = new Vector3(); + return { - return function updateMatrixWorld( force ) { + bind: bind, + update: update, - Object3D.prototype.updateMatrixWorld.call( this, force ); + dispose: dispose - position.setFromMatrixPosition( this.matrixWorld ); + }; - this.panner.setPosition( position.x, position.y, position.z ); +} - }; +class WebGLRenderer { - } )() + constructor( parameters = {} ) { + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = false, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; -} ); + this.isWebGLRenderer = true; -/** - * @author mrdoob / http://mrdoob.com/ - */ + let _alpha; -function AudioAnalyser( audio, fftSize ) { + if ( context !== null ) { - this.analyser = audio.context.createAnalyser(); - this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048; + if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) { - this.data = new Uint8Array( this.analyser.frequencyBinCount ); + throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' ); - audio.getOutput().connect( this.analyser ); + } -} + _alpha = context.getContextAttributes().alpha; -Object.assign( AudioAnalyser.prototype, { + } else { - getFrequencyData: function () { + _alpha = alpha; - this.analyser.getByteFrequencyData( this.data ); + } - return this.data; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - }, + let currentRenderList = null; + let currentRenderState = null; - getAverageFrequency: function () { + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - var value = 0, data = this.getFrequencyData(); + const renderListStack = []; + const renderStateStack = []; - for ( var i = 0; i < data.length; i ++ ) { + // public properties - value += data[ i ]; + this.domElement = canvas; - } + // Debug configuration container + this.debug = { - return value / data.length; + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - } + // clearing -} ); + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; -/** - * - * Buffered scene graph property that allows weighted accumulation. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + // scene graph -function PropertyMixer( binding, typeName, valueSize ) { + this.sortObjects = true; - this.binding = binding; - this.valueSize = valueSize; + // user-defined clipping - var bufferType = Float64Array, - mixFunction; + this.clippingPlanes = []; + this.localClippingEnabled = false; - switch ( typeName ) { + // physically based shading - case 'quaternion': - mixFunction = this._slerp; - break; + this._outputColorSpace = SRGBColorSpace; - case 'string': - case 'bool': - bufferType = Array; - mixFunction = this._select; - break; + // tone mapping - default: - mixFunction = this._lerp; + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - } + // internal properties - this.buffer = new bufferType( valueSize * 4 ); - // layout: [ incoming | accu0 | accu1 | orig ] - // - // interpolators can use .buffer as their .result - // the data then goes to 'incoming' - // - // 'accu0' and 'accu1' are used frame-interleaved for - // the cumulative result and are compared to detect - // changes - // - // 'orig' stores the original state of the property + const _this = this; - this._mixBufferRegion = mixFunction; + let _isContextLost = false; - this.cumulativeWeight = 0; + // internal state cache - this.useCount = 0; - this.referenceCount = 0; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; -} + let _currentCamera = null; -Object.assign( PropertyMixer.prototype, { + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - // accumulate data in the 'incoming' region into 'accu' - accumulate: function ( accuIndex, weight ) { + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - // note: happily accumulating nothing when weight = 0, the caller knows - // the weight and shouldn't have made the call in the first place + // - var buffer = this.buffer, - stride = this.valueSize, - offset = accuIndex * stride + stride, + let _width = canvas.width; + let _height = canvas.height; - currentWeight = this.cumulativeWeight; + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - if ( currentWeight === 0 ) { + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - // accuN := incoming * weight + // frustum - for ( var i = 0; i !== stride; ++ i ) { + const _frustum = new Frustum(); - buffer[ offset + i ] = buffer[ i ]; + // clipping - } + let _clippingEnabled = false; + let _localClippingEnabled = false; - currentWeight = weight; + // camera matrices cache - } else { + const _projScreenMatrix = new Matrix4(); - // accuN := accuN + incoming * weight + const _vector3 = new Vector3(); - currentWeight += weight; - var mix = weight / currentWeight; - this._mixBufferRegion( buffer, offset, 0, mix, stride ); + const _vector4 = new Vector4(); - } + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - this.cumulativeWeight = currentWeight; + let _renderBackground = false; - }, + function getTargetPixelRatio() { - // apply the state of 'accu' to the binding when accus differ - apply: function ( accuIndex ) { + return _currentRenderTarget === null ? _pixelRatio : 1; - var stride = this.valueSize, - buffer = this.buffer, - offset = accuIndex * stride + stride, + } - weight = this.cumulativeWeight, + // initialize - binding = this.binding; + let _gl = context; - this.cumulativeWeight = 0; + function getContext( contextName, contextAttributes ) { - if ( weight < 1 ) { + return canvas.getContext( contextName, contextAttributes ); - // accuN := accuN + original * ( 1 - cumulativeWeight ) + } - var originalValueOffset = stride * 3; + try { - this._mixBufferRegion( - buffer, offset, originalValueOffset, 1 - weight, stride ); + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - } + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - for ( var i = stride, e = stride + stride; i !== e; ++ i ) { + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - if ( buffer[ i ] !== buffer[ i + stride ] ) { + if ( _gl === null ) { - // value has changed -> update scene graph + const contextName = 'webgl2'; - binding.setValue( buffer, offset ); - break; + _gl = getContext( contextName, contextAttributes ); - } + if ( _gl === null ) { - } + if ( getContext( contextName ) ) { - }, + throw new Error( 'Error creating WebGL context with your selected attributes.' ); - // remember the state of the bound property and copy it to both accus - saveOriginalState: function () { + } else { - var binding = this.binding; + throw new Error( 'Error creating WebGL context.' ); - var buffer = this.buffer, - stride = this.valueSize, + } - originalValueOffset = stride * 3; + } - binding.getValue( buffer, originalValueOffset ); + } - // accu[0..1] := orig -- initially detect changes against the original - for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) { + } catch ( error ) { - buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; } - this.cumulativeWeight = 0; + 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; - // apply the state previously taken via 'saveOriginalState' to the binding - restoreOriginalState: function () { + let utils, bindingStates, uniformsGroups; - var originalValueOffset = this.valueSize * 3; - this.binding.setValue( this.buffer, originalValueOffset ); + function initGLContext() { - }, + extensions = new WebGLExtensions( _gl ); + extensions.init(); + utils = new WebGLUtils( _gl, extensions ); - // mix functions + capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils ); - _select: function ( buffer, dstOffset, srcOffset, t, stride ) { + state = new WebGLState( _gl ); - if ( t >= 0.5 ) { + info = new WebGLInfo( _gl ); + 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 ); + bindingStates = new WebGLBindingStates( _gl, attributes ); + 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 ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); - for ( var i = 0; i !== stride; ++ i ) { + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info ); - buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; + 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; } - }, - - _slerp: function ( buffer, dstOffset, srcOffset, t ) { + initGLContext(); - Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); + // xr - }, + const xr = new WebXRManager( _this, _gl ); - _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) { + this.xr = xr; - var s = 1 - t; + // API - for ( var i = 0; i !== stride; ++ i ) { + this.getContext = function () { - var j = dstOffset + i; + return _gl; - buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; + }; - } + this.getContextAttributes = function () { - } + return _gl.getContextAttributes(); -} ); + }; -/** - * - * A reference to a real property in the scene graph. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + this.forceContextLoss = function () { -function Composite( targetGroup, path, optionalParsedPath ) { + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); - var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); + }; - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_( path, parsedPath ); + this.forceContextRestore = function () { -} + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); -Object.assign( Composite.prototype, { + }; - getValue: function ( array, offset ) { + this.getPixelRatio = function () { - this.bind(); // bind all binding + return _pixelRatio; - var firstValidIndex = this._targetGroup.nCachedObjects_, - binding = this._bindings[ firstValidIndex ]; + }; - // and only call .getValue on the first - if ( binding !== undefined ) { binding.getValue( array, offset ); } + this.setPixelRatio = function ( value ) { - }, + if ( value === undefined ) return; - setValue: function ( array, offset ) { + _pixelRatio = value; - var bindings = this._bindings; + this.setSize( _width, _height, false ); - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { + }; - bindings[ i ].setValue( array, offset ); + this.getSize = function ( target ) { - } + return target.set( _width, _height ); - }, + }; - bind: function () { + this.setSize = function ( width, height, updateStyle = true ) { - var bindings = this._bindings; + if ( xr.isPresenting ) { - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; - bindings[ i ].bind(); + } - } + _width = width; + _height = height; - }, + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); - unbind: function () { + if ( updateStyle === true ) { - var bindings = this._bindings; + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { + } - bindings[ i ].unbind(); + this.setViewport( 0, 0, width, height ); - } + }; - } + this.getDrawingBufferSize = function ( target ) { -} ); + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + }; -function PropertyBinding( rootNode, path, parsedPath ) { + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); + _width = width; + _height = height; - this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; + _pixelRatio = pixelRatio; - this.rootNode = rootNode; + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); -} + this.setViewport( 0, 0, width, height ); -Object.assign( PropertyBinding, { + }; - Composite: Composite, + this.getCurrentViewport = function ( target ) { - create: function ( root, path, parsedPath ) { + return target.copy( _currentViewport ); - if ( ! ( root && root.isAnimationObjectGroup ) ) { + }; - return new PropertyBinding( root, path, parsedPath ); + this.getViewport = function ( target ) { - } else { + return target.copy( _viewport ); - return new PropertyBinding.Composite( root, path, parsedPath ); + }; - } + this.setViewport = function ( x, y, width, height ) { - }, + if ( x.isVector4 ) { - /** - * Replaces spaces with underscores and removes unsupported characters from - * node names, to ensure compatibility with parseTrackName(). - * - * @param {string} name Node name to be sanitized. - * @return {string} - */ - sanitizeNodeName: function ( name ) { + _viewport.set( x.x, x.y, x.z, x.w ); - return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' ); + } else { - }, + _viewport.set( x, y, width, height ); - parseTrackName: function () { + } - // Parent directories, delimited by '/' or ':'. Currently unused, but must - // be matched to parse the rest of the track name. - var directoryRe = /((?:[\w-]+[\/:])*)/; + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() ); - // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. - var nodeRe = /([\w-\.]+)?/; + }; - // Object on target node, and accessor. Name may contain only word - // characters. Accessor may contain any character except closing bracket. - var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/; + this.getScissor = function ( target ) { - // Property and accessor. May contain only word characters. Accessor may - // contain any non-bracket characters. - var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/; + return target.copy( _scissor ); - var trackRe = new RegExp( '' - + '^' - + directoryRe.source - + nodeRe.source - + objectRe.source - + propertyRe.source - + '$' - ); + }; - var supportedObjectNames = [ 'material', 'materials', 'bones' ]; + this.setScissor = function ( x, y, width, height ) { - return function ( trackName ) { + if ( x.isVector4 ) { - var matches = trackRe.exec( trackName ); + _scissor.set( x.x, x.y, x.z, x.w ); - if ( ! matches ) { + } else { - throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); + _scissor.set( x, y, width, height ); } - var results = { - // directoryName: matches[ 1 ], // (tschw) currently unused - nodeName: matches[ 2 ], - objectName: matches[ 3 ], - objectIndex: matches[ 4 ], - propertyName: matches[ 5 ], // required - propertyIndex: matches[ 6 ] - }; + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() ); + + }; - var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); + this.getScissorTest = function () { - if ( lastDot !== undefined && lastDot !== - 1 ) { + return _scissorTest; - var objectName = results.nodeName.substring( lastDot + 1 ); + }; - // Object names must be checked against a whitelist. Otherwise, there - // is no way to parse 'foo.bar.baz': 'baz' must be a property, but - // 'bar' could be the objectName, or part of a nodeName (which can - // include '.' characters). - if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) { + this.setScissorTest = function ( boolean ) { - results.nodeName = results.nodeName.substring( 0, lastDot ); - results.objectName = objectName; + state.setScissorTest( _scissorTest = boolean ); - } + }; - } + this.setOpaqueSort = function ( method ) { - if ( results.propertyName === null || results.propertyName.length === 0 ) { + _opaqueSort = method; - throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); + }; - } + this.setTransparentSort = function ( method ) { - return results; + _transparentSort = method; }; - }(), + // Clearing - findNode: function ( root, nodeName ) { + this.getClearColor = function ( target ) { - if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { + return target.copy( background.getClearColor() ); - return root; + }; - } + this.setClearColor = function () { - // search into skeleton bones. - if ( root.skeleton ) { + background.setClearColor.apply( background, arguments ); - var searchSkeleton = function ( skeleton ) { + }; - for ( var i = 0; i < skeleton.bones.length; i ++ ) { + this.getClearAlpha = function () { - var bone = skeleton.bones[ i ]; + return background.getClearAlpha(); - if ( bone.name === nodeName ) { + }; - return bone; + this.setClearAlpha = function () { - } + background.setClearAlpha.apply( background, arguments ); - } + }; - return null; + this.clear = function ( color = true, depth = true, stencil = true ) { - }; + let bits = 0; - var bone = searchSkeleton( root.skeleton ); + if ( color ) { - if ( bone ) { + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - return bone; + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - } + } - } + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - // search into node subtree. - if ( root.children ) { + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - var searchNodeSubtree = function ( children ) { + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - for ( var i = 0; i < children.length; i ++ ) { + if ( isUnsignedType ) { - var childNode = children[ i ]; + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor ); - if ( childNode.name === nodeName || childNode.uuid === nodeName ) { + } else { - return childNode; + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, 0, intClearColor ); } - var result = searchNodeSubtree( childNode.children ); + } else { - if ( result ) { return result; } + bits |= _gl.COLOR_BUFFER_BIT; } - return null; - - }; - - var subTreeNode = searchNodeSubtree( root.children ); + } - if ( subTreeNode ) { + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) { - return subTreeNode; + bits |= _gl.STENCIL_BUFFER_BIT; + this.state.buffers.stencil.setMask( 0xffffffff ); } - } + _gl.clear( bits ); - return null; + }; - } + this.clearColor = function () { -} ); + this.clear( true, false, false ); -Object.assign( PropertyBinding.prototype, { // prototype, continued + }; - // these are used to "bind" a nonexistent property - _getValue_unavailable: function () {}, - _setValue_unavailable: function () {}, + this.clearDepth = function () { - BindingType: { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 - }, + this.clear( false, true, false ); - Versioning: { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 - }, + }; - GetterByBindingType: [ + this.clearStencil = function () { - function getValue_direct( buffer, offset ) { + this.clear( false, false, true ); - buffer[ offset ] = this.node[ this.propertyName ]; + }; - }, + // - function getValue_array( buffer, offset ) { + this.dispose = function () { - var source = this.resolvedProperty; + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - for ( var i = 0, n = source.length; i !== n; ++ i ) { + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - buffer[ offset ++ ] = source[ i ]; + xr.dispose(); - } + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - }, + animation.stop(); - function getValue_arrayElement( buffer, offset ) { + }; - buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; + // Events - }, + function onContextLost( event ) { - function getValue_toArray( buffer, offset ) { + event.preventDefault(); - this.resolvedProperty.toArray( buffer, offset ); + console.log( 'THREE.WebGLRenderer: Context Lost.' ); + + _isContextLost = true; } - ], + function onContextRestore( /* event */ ) { - SetterByBindingTypeAndVersioning: [ + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - [ - // Direct + _isContextLost = false; - function setValue_direct( buffer, offset ) { + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - this.targetObject[ this.propertyName ] = buffer[ offset ]; + initGLContext(); - }, + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - function setValue_direct_setNeedsUpdate( buffer, offset ) { + } - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + function onContextCreationError( event ) { - }, + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); - function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { + } - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + function onMaterialDispose( event ) { - } + const material = event.target; - ], [ + material.removeEventListener( 'dispose', onMaterialDispose ); - // EntireArray + deallocateMaterial( material ); - function setValue_array( buffer, offset ) { + } - var dest = this.resolvedProperty; + // Buffer deallocation - for ( var i = 0, n = dest.length; i !== n; ++ i ) { + function deallocateMaterial( material ) { - dest[ i ] = buffer[ offset ++ ]; + releaseMaterialProgramReferences( material ); - } + properties.remove( material ); - }, + } - function setValue_array_setNeedsUpdate( buffer, offset ) { - var dest = this.resolvedProperty; + function releaseMaterialProgramReferences( material ) { - for ( var i = 0, n = dest.length; i !== n; ++ i ) { + const programs = properties.get( material ).programs; - dest[ i ] = buffer[ offset ++ ]; + if ( programs !== undefined ) { - } + programs.forEach( function ( program ) { - this.targetObject.needsUpdate = true; + programCache.releaseProgram( program ); - }, + } ); - function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { + if ( material.isShaderMaterial ) { - var dest = this.resolvedProperty; + programCache.releaseShaderCache( material ); - for ( var i = 0, n = dest.length; i !== n; ++ i ) { + } - dest[ i ] = buffer[ offset ++ ]; + } - } + } - this.targetObject.matrixWorldNeedsUpdate = true; + // Buffer rendering - } + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - ], [ + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - // ArrayElement + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - function setValue_arrayElement( buffer, offset ) { + const program = setProgram( camera, scene, geometry, material, object ); - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + state.setMaterial( material, frontFaceCW ); - }, + // - function setValue_arrayElement_setNeedsUpdate( buffer, offset ) { + let index = geometry.index; + let rangeFactor = 1; - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + if ( material.wireframe === true ) { - }, + index = geometries.getWireframeAttribute( geometry ); - function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { + if ( index === undefined ) return; - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + rangeFactor = 2; } - ], [ + // - // HasToFromArray + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - function setValue_fromArray( buffer, offset ) { + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - this.resolvedProperty.fromArray( buffer, offset ); + if ( group !== null ) { - }, + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - function setValue_fromArray_setNeedsUpdate( buffer, offset ) { + } - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.needsUpdate = true; + if ( index !== null ) { - }, + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { + } else if ( position !== undefined && position !== null ) { - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.matrixWorldNeedsUpdate = true; + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); } - ] + const drawCount = drawEnd - drawStart; - ], + if ( drawCount < 0 || drawCount === Infinity ) return; - getValue: function getValue_unbound( targetArray, offset ) { + // - this.bind(); - this.getValue( targetArray, offset ); + bindingStates.setup( object, material, program, geometry, index ); - // Note: This class uses a State pattern on a per-method basis: - // 'bind' sets 'this.getValue' / 'setValue' and shadows the - // prototype version of these methods with one that represents - // the bound state. When the property is not found, the methods - // become no-ops. + let attribute; + let renderer = bufferRenderer; - }, + if ( index !== null ) { - setValue: function getValue_unbound( sourceArray, offset ) { + attribute = attributes.get( index ); - this.bind(); - this.setValue( sourceArray, offset ); + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - }, + } - // create getter / setter pair for a property in the scene graph - bind: function () { + // - var targetObject = this.node, - parsedPath = this.parsedPath, + if ( object.isMesh ) { - objectName = parsedPath.objectName, - propertyName = parsedPath.propertyName, - propertyIndex = parsedPath.propertyIndex; + if ( material.wireframe === true ) { - if ( ! targetObject ) { + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode; + } else { - this.node = targetObject; + renderer.setMode( _gl.TRIANGLES ); - } + } - // set fail state so we can just 'return' on error - this.getValue = this._getValue_unavailable; - this.setValue = this._setValue_unavailable; + } else if ( object.isLine ) { - // ensure there is a value node - if ( ! targetObject ) { + let lineWidth = material.linewidth; - console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' ); - return; + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - } + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - if ( objectName ) { + if ( object.isLineSegments ) { - var objectIndex = parsedPath.objectIndex; + renderer.setMode( _gl.LINES ); - // special cases were we need to reach deeper into the hierarchy to get the face materials.... - switch ( objectName ) { + } else if ( object.isLineLoop ) { - case 'materials': + renderer.setMode( _gl.LINE_LOOP ); - if ( ! targetObject.material ) { + } else { - console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); - return; + renderer.setMode( _gl.LINE_STRIP ); - } + } - if ( ! targetObject.material.materials ) { + } else if ( object.isPoints ) { - console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); - return; + renderer.setMode( _gl.POINTS ); - } + } else if ( object.isSprite ) { - targetObject = targetObject.material.materials; + renderer.setMode( _gl.TRIANGLES ); - break; + } - case 'bones': + if ( object.isBatchedMesh ) { - if ( ! targetObject.skeleton ) { + if ( object._multiDrawInstances !== null ) { - console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); - return; + renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); - } + } else { - // potential future optimization: skip this if propertyIndex is already an integer - // and convert the integer string to a true integer. + if ( ! extensions.get( 'WEBGL_multi_draw' ) ) { - targetObject = targetObject.skeleton.bones; + const starts = object._multiDrawStarts; + const counts = object._multiDrawCounts; + const drawCount = object._multiDrawCount; + const bytesPerElement = index ? attributes.get( index ).bytesPerElement : 1; + const uniforms = properties.get( material ).currentProgram.getUniforms(); + for ( let i = 0; i < drawCount; i ++ ) { - // support resolving morphTarget names into indices. - for ( var i = 0; i < targetObject.length; i ++ ) { + uniforms.setValue( _gl, '_gl_DrawID', i ); + renderer.render( starts[ i ] / bytesPerElement, counts[ i ] ); - if ( targetObject[ i ].name === objectIndex ) { + } - objectIndex = i; - break; + } else { - } + renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); } - break; + } - default: + } else if ( object.isInstancedMesh ) { - if ( targetObject[ objectName ] === undefined ) { + renderer.renderInstances( drawStart, drawCount, object.count ); - console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); - return; + } else if ( geometry.isInstancedBufferGeometry ) { - } + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); - targetObject = targetObject[ objectName ]; + renderer.renderInstances( drawStart, drawCount, instanceCount ); - } + } else { + renderer.render( drawStart, drawCount ); - if ( objectIndex !== undefined ) { + } - if ( targetObject[ objectIndex ] === undefined ) { + }; - console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); - return; + // Compile - } + function prepareMaterial( material, scene, object ) { - targetObject = targetObject[ objectIndex ]; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - } + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - } + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - // resolve property - var nodeProperty = targetObject[ propertyName ]; + material.side = DoubleSide; - if ( nodeProperty === undefined ) { + } else { - var nodeName = parsedPath.nodeName; + getProgram( material, scene, object ); - console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + - '.' + propertyName + ' but it wasn\'t found.', targetObject ); - return; + } } - // determine versioning scheme - var versioning = this.Versioning.None; - - if ( targetObject.needsUpdate !== undefined ) { // material + this.compile = function ( scene, camera, targetScene = null ) { - versioning = this.Versioning.NeedsUpdate; - this.targetObject = targetObject; + if ( targetScene === null ) targetScene = scene; - } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform + currentRenderState = renderStates.get( targetScene ); + currentRenderState.init( camera ); - versioning = this.Versioning.MatrixWorldNeedsUpdate; - this.targetObject = targetObject; + renderStateStack.push( currentRenderState ); - } - - // determine how the property gets bound - var bindingType = this.BindingType.Direct; + // gather lights from both the target scene and the new object that will be added to the scene. - if ( propertyIndex !== undefined ) { + targetScene.traverseVisible( function ( object ) { - // access a sub element of the property array (only primitives are supported right now) + if ( object.isLight && object.layers.test( camera.layers ) ) { - if ( propertyName === "morphTargetInfluences" ) { + currentRenderState.pushLight( object ); - // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. + if ( object.castShadow ) { - // support resolving morphTarget names into indices. - if ( ! targetObject.geometry ) { + currentRenderState.pushShadow( object ); - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); - return; + } } - if ( targetObject.geometry.isBufferGeometry ) { + } ); - if ( ! targetObject.geometry.morphAttributes ) { + if ( scene !== targetScene ) { - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); - return; + scene.traverseVisible( function ( object ) { - } + if ( object.isLight && object.layers.test( camera.layers ) ) { - for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) { + currentRenderState.pushLight( object ); - if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) { + if ( object.castShadow ) { - propertyIndex = i; - break; + currentRenderState.pushShadow( object ); } } + } ); - } else { + } - if ( ! targetObject.geometry.morphTargets ) { + currentRenderState.setupLights(); - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this ); - return; + // Only initialize materials in the new scene, not the targetScene. - } + const materials = new Set(); - for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) { + scene.traverse( function ( object ) { - if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) { + const material = object.material; - propertyIndex = i; - break; + if ( material ) { + + if ( Array.isArray( material ) ) { + + for ( let i = 0; i < material.length; i ++ ) { + + const material2 = material[ i ]; + + prepareMaterial( material2, targetScene, object ); + materials.add( material2 ); } + } else { + + prepareMaterial( material, targetScene, object ); + materials.add( material ); + } } - } + } ); - bindingType = this.BindingType.ArrayElement; + renderStateStack.pop(); + currentRenderState = null; - this.resolvedProperty = nodeProperty; - this.propertyIndex = propertyIndex; + return materials; - } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { + }; - // must use copy for Object3D.Euler/Quaternion + // compileAsync - bindingType = this.BindingType.HasFromToArray; + this.compileAsync = function ( scene, camera, targetScene = null ) { - this.resolvedProperty = nodeProperty; + const materials = this.compile( scene, camera, targetScene ); - } else if ( Array.isArray( nodeProperty ) ) { + // Wait for all the materials in the new object to indicate that they're + // ready to be used before resolving the promise. - bindingType = this.BindingType.EntireArray; + return new Promise( ( resolve ) => { - this.resolvedProperty = nodeProperty; + function checkMaterialsReady() { - } else { + materials.forEach( function ( material ) { - this.propertyName = propertyName; + const materialProperties = properties.get( material ); + const program = materialProperties.currentProgram; - } + if ( program.isReady() ) { - // select getter / setter - this.getValue = this.GetterByBindingType[ bindingType ]; - this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; + // remove any programs that report they're ready to use from the list + materials.delete( material ); - }, + } - unbind: function () { + } ); - this.node = null; + // once the list of compiling materials is empty, call the callback - // back to the prototype version of getValue / setValue - // note: avoiding to mutate the shape of 'this' via 'delete' - this.getValue = this._getValue_unbound; - this.setValue = this._setValue_unbound; + if ( materials.size === 0 ) { - } + resolve( scene ); + return; -} ); + } -//!\ DECLARE ALIAS AFTER assign prototype ! -Object.assign( PropertyBinding.prototype, { + // if some materials are still not ready, wait a bit and check again - // initial state of these methods that calls 'bind' - _getValue_unbound: PropertyBinding.prototype.getValue, - _setValue_unbound: PropertyBinding.prototype.setValue, + setTimeout( checkMaterialsReady, 10 ); -} ); + } -/** - * - * A group of objects that receives a shared animation state. - * - * Usage: - * - * - Add objects you would otherwise pass as 'root' to the - * constructor or the .clipAction method of AnimationMixer. - * - * - Instead pass this object as 'root'. - * - * - You can also add and remove objects later when the mixer - * is running. - * - * Note: - * - * Objects of this class appear as one object to the mixer, - * so cache control of the individual objects must be done - * on the group. - * - * Limitation: - * - * - The animated properties must be compatible among the - * all objects in the group. - * - * - A single property can either be controlled through a - * target group or directly, but not both. - * - * @author tschw - */ + if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) { -function AnimationObjectGroup() { - var arguments$1 = arguments; + // If we can check the compilation status of the materials without + // blocking then do so right away. + checkMaterialsReady(); - this.uuid = _Math.generateUUID(); + } else { - // cached objects followed by the active ones - this._objects = Array.prototype.slice.call( arguments ); + // Otherwise start by waiting a bit to give the materials we just + // initialized a chance to finish. - this.nCachedObjects_ = 0; // threshold - // note: read by PropertyBinding.Composite + setTimeout( checkMaterialsReady, 10 ); - var indices = {}; - this._indicesByUUID = indices; // for bookkeeping + } - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + } ); - indices[ arguments$1[ i ].uuid ] = i; + }; - } + // Animation Loop - this._paths = []; // inside: string - this._parsedPaths = []; // inside: { we don't care, here } - this._bindings = []; // inside: Array< PropertyBinding > - this._bindingsIndicesByPath = {}; // inside: indices in these arrays + let onAnimationFrameCallback = null; - var scope = this; + function onAnimationFrame( time ) { - this.stats = { + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - objects: { - get total() { + } - return scope._objects.length; + function onXRSessionStart() { - }, - get inUse() { + animation.stop(); - return this.total - scope.nCachedObjects_; + } - } - }, - get bindingsPerObject() { + function onXRSessionEnd() { - return scope._bindings.length; + animation.start(); } - }; + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); -} + if ( typeof self !== 'undefined' ) animation.setContext( self ); -Object.assign( AnimationObjectGroup.prototype, { + this.setAnimationLoop = function ( callback ) { - isAnimationObjectGroup: true, + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - add: function () { - var arguments$1 = arguments; + ( callback === null ) ? animation.stop() : animation.start(); + }; - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - nBindings = bindings.length; + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + // Rendering - var object = arguments$1[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ], - knownObject = undefined; + this.render = function ( scene, camera ) { - if ( index === undefined ) { + if ( camera !== undefined && camera.isCamera !== true ) { - // unknown object -> add it to the ACTIVE region + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; - index = nObjects ++; - indicesByUUID[ uuid ] = index; - objects.push( object ); + } - // accounting is done, now do the same for all bindings + if ( _isContextLost === true ) return; - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // update scene graph - bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - } + // update camera matrices and frustum - } else if ( index < nCachedObjects ) { + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - knownObject = objects[ index ]; + if ( xr.enabled === true && xr.isPresenting === true ) { - // move existing object to the ACTIVE region + if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ]; + camera = xr.getCamera(); // use XR camera for rendering - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; + } + + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - indicesByUUID[ uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = object; + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init( camera ); - // accounting is done, now do the same for all bindings + renderStateStack.push( currentRenderState ); - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - binding = bindingsForPath[ index ]; + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - bindingsForPath[ index ] = lastCached; + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - if ( binding === undefined ) { + renderListStack.push( currentRenderList ); - // since we do not bother to create new bindings - // for objects that are cached, the binding may - // or may not exist + if ( xr.enabled === true && xr.isPresenting === true ) { - binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); + const depthSensingMesh = _this.xr.getDepthSensingMesh(); - } + if ( depthSensingMesh !== null ) { - bindingsForPath[ firstActiveIndex ] = binding; + projectObject( depthSensingMesh, camera, - Infinity, _this.sortObjects ); } - } else if ( objects[ index ] !== knownObject ) { + } - console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + - 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); + projectObject( scene, camera, 0, _this.sortObjects ); - } // else the object is already where we want it to be + currentRenderList.finish(); - } // for arguments + if ( _this.sortObjects === true ) { - this.nCachedObjects_ = nCachedObjects; + currentRenderList.sort( _opaqueSort, _transparentSort ); - }, + } - remove: function () { - var arguments$1 = arguments; + _renderBackground = xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false; + if ( _renderBackground ) { + background.addToRenderList( currentRenderList, scene ); - var objects = this._objects, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; + } - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + // - var object = arguments$1[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; + this.info.render.frame ++; - if ( index !== undefined && index >= nCachedObjects ) { + if ( _clippingEnabled === true ) clipping.beginShadows(); - // move existing object into the CACHED region + const shadowsArray = currentRenderState.state.shadowsArray; - var lastCachedIndex = nCachedObjects ++, - firstActiveObject = objects[ lastCachedIndex ]; + shadowMap.render( shadowsArray, scene, camera ); - indicesByUUID[ firstActiveObject.uuid ] = index; - objects[ index ] = firstActiveObject; + if ( _clippingEnabled === true ) clipping.endShadows(); - indicesByUUID[ uuid ] = lastCachedIndex; - objects[ lastCachedIndex ] = object; + // - // accounting is done, now do the same for all bindings + if ( this.info.autoReset === true ) this.info.reset(); - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // render scene - var bindingsForPath = bindings[ j ], - firstActive = bindingsForPath[ lastCachedIndex ], - binding = bindingsForPath[ index ]; + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; - bindingsForPath[ index ] = firstActive; - bindingsForPath[ lastCachedIndex ] = binding; + currentRenderState.setupLights(); - } + if ( camera.isArrayCamera ) { - } + const cameras = camera.cameras; - } // for arguments + if ( transmissiveObjects.length > 0 ) { - this.nCachedObjects_ = nCachedObjects; + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - }, + const camera2 = cameras[ i ]; - // remove & forget - uncache: function () { - var arguments$1 = arguments; + renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 ); + } - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; + } - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { + if ( _renderBackground ) background.render( scene ); - var object = arguments$1[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - if ( index !== undefined ) { + const camera2 = cameras[ i ]; - delete indicesByUUID[ uuid ]; + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - if ( index < nCachedObjects ) { + } - // object is cached, shrink the CACHED region + } else { - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ], - lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - // last cached object takes this object's place - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; + if ( _renderBackground ) background.render( scene ); - // last object goes to the activated slot and pop - indicesByUUID[ lastObject.uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = lastObject; - objects.pop(); + renderScene( currentRenderList, scene, camera ); - // accounting is done, now do the same for all bindings + } - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - last = bindingsForPath[ lastIndex ]; + if ( _currentRenderTarget !== null ) { - bindingsForPath[ index ] = lastCached; - bindingsForPath[ firstActiveIndex ] = last; - bindingsForPath.pop(); + // resolve multisample renderbuffers to a single-sample texture if necessary - } + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - } else { + // Generate mipmap if we're using any kind of mipmap filtering - // object is active, just swap with the last and pop + textures.updateRenderTargetMipmap( _currentRenderTarget ); - var lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; + } - indicesByUUID[ lastObject.uuid ] = index; - objects[ index ] = lastObject; - objects.pop(); + // - // accounting is done, now do the same for all bindings + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - for ( var j = 0, m = nBindings; j !== m; ++ j ) { + // _gl.finish(); - var bindingsForPath = bindings[ j ]; + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; - bindingsForPath.pop(); + renderStateStack.pop(); - } + if ( renderStateStack.length > 0 ) { - } // cached or active + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - } // if object is known + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, currentRenderState.state.camera ); - } // for arguments + } else { - this.nCachedObjects_ = nCachedObjects; + currentRenderState = null; - }, + } - // Internal interface used by befriended PropertyBinding.Composite: + renderListStack.pop(); - subscribe_: function ( path, parsedPath ) { + if ( renderListStack.length > 0 ) { - // returns an array of bindings for the given path that is changed - // according to the contained objects in the group + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ], - bindings = this._bindings; + } else { - if ( index !== undefined ) { return bindings[ index ]; } + currentRenderList = null; - var paths = this._paths, - parsedPaths = this._parsedPaths, - objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - bindingsForPath = new Array( nObjects ); + } - index = bindings.length; + }; - indicesByPath[ path ] = index; + function projectObject( object, camera, groupOrder, sortObjects ) { - paths.push( path ); - parsedPaths.push( parsedPath ); - bindings.push( bindingsForPath ); + if ( object.visible === false ) return; - for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) { + const visible = object.layers.test( camera.layers ); - var object = objects[ i ]; - bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); + if ( visible ) { - } + if ( object.isGroup ) { - return bindingsForPath; + groupOrder = object.renderOrder; - }, + } else if ( object.isLOD ) { - unsubscribe_: function ( path ) { + if ( object.autoUpdate === true ) object.update( camera ); - // tells the group to forget about a property path and no longer - // update the array previously obtained with 'subscribe_' + } else if ( object.isLight ) { - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ]; + currentRenderState.pushLight( object ); - if ( index !== undefined ) { + if ( object.castShadow ) { - var paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - lastBindingsIndex = bindings.length - 1, - lastBindings = bindings[ lastBindingsIndex ], - lastBindingsPath = path[ lastBindingsIndex ]; + currentRenderState.pushShadow( object ); - indicesByPath[ lastBindingsPath ] = index; + } - bindings[ index ] = lastBindings; - bindings.pop(); + } else if ( object.isSprite ) { - parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; - parsedPaths.pop(); + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - paths[ index ] = paths[ lastBindingsIndex ]; - paths.pop(); + if ( sortObjects ) { - } + _vector4.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - } + } -} ); + const geometry = objects.update( object ); + const material = object.material; -/** - * - * Action provided by AnimationMixer for scheduling clip playback on specific - * objects. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - * - */ + if ( material.visible ) { -function AnimationAction( mixer, clip, localRoot ) { + currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null ); - this._mixer = mixer; - this._clip = clip; - this._localRoot = localRoot || null; + } - var tracks = clip.tracks, - nTracks = tracks.length, - interpolants = new Array( nTracks ); + } - var interpolantSettings = { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - }; + } else if ( object.isMesh || object.isLine || object.isPoints ) { - for ( var i = 0; i !== nTracks; ++ i ) { + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - var interpolant = tracks[ i ].createInterpolant( null ); - interpolants[ i ] = interpolant; - interpolant.settings = interpolantSettings; + const geometry = objects.update( object ); + const material = object.material; - } + if ( sortObjects ) { - this._interpolantSettings = interpolantSettings; + if ( object.boundingSphere !== undefined ) { - this._interpolants = interpolants; // bound by the mixer + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector4.copy( object.boundingSphere.center ); - // inside: PropertyMixer (managed by the mixer) - this._propertyBindings = new Array( nTracks ); + } else { - this._cacheIndex = null; // for the memory manager - this._byClipCacheIndex = null; // for the memory manager + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector4.copy( geometry.boundingSphere.center ); - this._timeScaleInterpolant = null; - this._weightInterpolant = null; + } - this.loop = LoopRepeat; - this._loopCount = - 1; + _vector4 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - // global mixer time when the action is to be started - // it's set back to 'null' upon start of the action - this._startTime = null; + } - // scaled local time of the action - // gets clamped or wrapped to 0..clip.duration according to loop - this.time = 0; + if ( Array.isArray( material ) ) { - this.timeScale = 1; - this._effectiveTimeScale = 1; + const groups = geometry.groups; - this.weight = 1; - this._effectiveWeight = 1; + for ( let i = 0, l = groups.length; i < l; i ++ ) { - this.repetitions = Infinity; // no. of repetitions when looping + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - this.paused = false; // true -> zero effective time scale - this.enabled = true; // false -> zero effective weight + if ( groupMaterial && groupMaterial.visible ) { - this.clampWhenFinished = false; // keep feeding the last frame? + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group ); - this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate - this.zeroSlopeAtEnd = true; // clips for start, loop and end + } -} + } -Object.assign( AnimationAction.prototype, { + } else if ( material.visible ) { - // State & Scheduling + currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null ); - play: function () { + } - this._mixer._activateAction( this ); + } - return this; + } - }, + } - stop: function () { + const children = object.children; - this._mixer._deactivateAction( this ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - return this.reset(); + projectObject( children[ i ], camera, groupOrder, sortObjects ); - }, + } - reset: function () { + } - this.paused = false; - this.enabled = true; + function renderScene( currentRenderList, scene, camera, viewport ) { - this.time = 0; // restart clip - this._loopCount = - 1; // forget previous loops - this._startTime = null; // forget scheduling + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - return this.stopFading().stopWarping(); + currentRenderState.setupLightsView( camera ); - }, + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, 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 ); + + // Ensure depth buffer writing is enabled so it can be cleared on next render + + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); + + state.setPolygonOffset( false ); + + } - isRunning: function () { + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - return this.enabled && ! this.paused && this.timeScale !== 0 && - this._startTime === null && this._mixer._isActiveAction( this ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - }, + if ( overrideMaterial !== null ) { - // return true when play has been called - isScheduled: function () { + return; - return this._mixer._isActiveAction( this ); + } - }, + if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) { - startAt: function ( time ) { + currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: 4, + stencilBuffer: stencil, + resolveDepthBuffer: false, + resolveStencilBuffer: false, + colorSpace: ColorManagement.workingColorSpace, + } ); - this._startTime = time; + // debug - return this; + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - }, + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - setLoop: function ( mode, repetitions ) { + } - this.loop = mode; - this.repetitions = repetitions; + const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget[ camera.id ]; - return this; + const activeViewport = camera.viewport || _currentViewport; + transmissionRenderTarget.setSize( activeViewport.z, activeViewport.w ); - }, + // - // Weight + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( transmissionRenderTarget ); - // set the weight stopping any scheduled fading - // although .enabled = false yields an effective weight of zero, this - // method does *not* change .enabled, because it would be confusing - setEffectiveWeight: function ( weight ) { + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - this.weight = weight; + _this.clear(); - // note: same logic as when updated at runtime - this._effectiveWeight = this.enabled ? weight : 0; + if ( _renderBackground ) background.render( scene ); - return this.stopFading(); + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - }, + // Remove viewport from camera to avoid nested render calls resetting viewport to it (e.g Reflector). + // Transmission render pass requires viewport to match the transmissionRenderTarget. + const currentCameraViewport = camera.viewport; + if ( camera.viewport !== undefined ) camera.viewport = undefined; - // return the weight considering fading and .enabled - getEffectiveWeight: function () { + currentRenderState.setupLightsView( camera ); - return this._effectiveWeight; + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - }, + renderObjects( opaqueObjects, scene, camera ); - fadeIn: function ( duration ) { + textures.updateMultisampleRenderTarget( transmissionRenderTarget ); + textures.updateRenderTargetMipmap( transmissionRenderTarget ); - return this._scheduleFading( duration, 0, 1 ); + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === false ) { // see #28131 - }, + let renderTargetNeedsUpdate = false; - fadeOut: function ( duration ) { + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - return this._scheduleFading( duration, 1, 0 ); + const renderItem = transmissiveObjects[ i ]; - }, + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - crossFadeFrom: function ( fadeOutAction, duration, warp ) { + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - fadeOutAction.fadeOut( duration ); - this.fadeIn( duration ); + const currentSide = material.side; - if ( warp ) { + material.side = BackSide; + material.needsUpdate = true; - var fadeInDuration = this._clip.duration, - fadeOutDuration = fadeOutAction._clip.duration, + renderObject( object, scene, camera, geometry, material, group ); - startEndRatio = fadeOutDuration / fadeInDuration, - endStartRatio = fadeInDuration / fadeOutDuration; + material.side = currentSide; + material.needsUpdate = true; - fadeOutAction.warp( 1.0, startEndRatio, duration ); - this.warp( endStartRatio, 1.0, duration ); + renderTargetNeedsUpdate = true; - } + } - return this; + } - }, + if ( renderTargetNeedsUpdate === true ) { - crossFadeTo: function ( fadeInAction, duration, warp ) { + textures.updateMultisampleRenderTarget( transmissionRenderTarget ); + textures.updateRenderTargetMipmap( transmissionRenderTarget ); - return fadeInAction.crossFadeFrom( this, duration, warp ); + } - }, + } - stopFading: function () { + _this.setRenderTarget( currentRenderTarget ); - var weightInterpolant = this._weightInterpolant; + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - if ( weightInterpolant !== null ) { + if ( currentCameraViewport !== undefined ) camera.viewport = currentCameraViewport; - this._weightInterpolant = null; - this._mixer._takeBackControlInterpolant( weightInterpolant ); + _this.toneMapping = currentToneMapping; } - return this; - - }, + function renderObjects( renderList, scene, camera ) { - // Time Scale Control + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - // set the time scale stopping any scheduled warping - // although .paused = true yields an effective time scale of zero, this - // method does *not* change .paused, because it would be confusing - setEffectiveTimeScale: function ( timeScale ) { + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - this.timeScale = timeScale; - this._effectiveTimeScale = this.paused ? 0 : timeScale; + const renderItem = renderList[ i ]; - return this.stopWarping(); + 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 ) ) { - // return the time scale considering warping and .paused - getEffectiveTimeScale: function () { + renderObject( object, scene, camera, geometry, material, group ); - return this._effectiveTimeScale; + } - }, + } - setDuration: function ( duration ) { + } - this.timeScale = this._clip.duration / duration; + function renderObject( object, scene, camera, geometry, material, group ) { - return this.stopWarping(); + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - }, + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - syncWith: function ( action ) { + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - this.time = action.time; - this.timeScale = action.timeScale; + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - return this.stopWarping(); + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - }, + material.side = DoubleSide; - halt: function ( duration ) { + } else { - return this.warp( this._effectiveTimeScale, 0, duration ); + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - }, + } - warp: function ( startTimeScale, endTimeScale, duration ) { + object.onAfterRender( _this, scene, camera, geometry, material, group ); - var mixer = this._mixer, now = mixer.time, - interpolant = this._timeScaleInterpolant, + } - timeScale = this.timeScale; + function getProgram( material, scene, object ) { - if ( interpolant === null ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - interpolant = mixer._lendControlInterpolant(); - this._timeScaleInterpolant = interpolant; + const materialProperties = properties.get( material ); - } + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; + const lightsStateVersion = lights.state.version; - times[ 0 ] = now; - times[ 1 ] = now + duration; + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - values[ 0 ] = startTimeScale / timeScale; - values[ 1 ] = endTimeScale / timeScale; + let programs = materialProperties.programs; - return this; + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - }, + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; - stopWarping: function () { + if ( programs === undefined ) { - var timeScaleInterpolant = this._timeScaleInterpolant; + // new material - if ( timeScaleInterpolant !== null ) { + material.addEventListener( 'dispose', onMaterialDispose ); - this._timeScaleInterpolant = null; - this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); + programs = new Map(); + materialProperties.programs = programs; - } + } - return this; + let program = programs.get( programCacheKey ); - }, + if ( program !== undefined ) { - // Object Accessors + // early out if program and light state is identical - getMixer: function () { + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { - return this._mixer; + updateCommonMaterialProperties( material, parameters ); - }, + return program; - getClip: function () { + } - return this._clip; + } else { - }, + parameters.uniforms = programCache.getUniforms( material ); - getRoot: function () { + material.onBeforeCompile( parameters, _this ); - return this._localRoot || this._mixer._root; + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - }, + materialProperties.uniforms = parameters.uniforms; - // Interna + } - _update: function ( time, deltaTime, timeDirection, accuIndex ) { + const uniforms = materialProperties.uniforms; - // called by the mixer + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - if ( ! this.enabled ) { + uniforms.clippingPlanes = clipping.uniform; - // call ._updateWeight() to update ._effectiveWeight + } - this._updateWeight( time ); - return; + updateCommonMaterialProperties( material, parameters ); - } + // store the light setup it was created for - var startTime = this._startTime; + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - if ( startTime !== null ) { + if ( materialProperties.needsLights ) { - // check for scheduled start of action + // wire up the material to this renderer's lighting state - var timeRunning = ( time - startTime ) * timeDirection; - if ( timeRunning < 0 || timeDirection === 0 ) { + 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; - return; // yet to come / don't decide when delta = 0 + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms } - // start + materialProperties.currentProgram = program; + materialProperties.uniformsList = null; - this._startTime = null; // unschedule - deltaTime = timeDirection * timeRunning; + return program; } - // apply time scale and advance time + function getUniformList( materialProperties ) { - deltaTime *= this._updateTimeScale( time ); - var clipTime = this._updateTime( deltaTime ); + if ( materialProperties.uniformsList === null ) { - // note: _updateTime may disable the action resulting in - // an effective weight of 0 + const progUniforms = materialProperties.currentProgram.getUniforms(); + materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms ); - var weight = this._updateWeight( time ); + } - if ( weight > 0 ) { + return materialProperties.uniformsList; - var interpolants = this._interpolants; - var propertyMixers = this._propertyBindings; + } - for ( var j = 0, m = interpolants.length; j !== m; ++ j ) { + function updateCommonMaterialProperties( material, parameters ) { - interpolants[ j ].evaluate( clipTime ); - propertyMixers[ j ].accumulate( accuIndex, weight ); + const materialProperties = properties.get( material ); - } + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.batching = parameters.batching; + materialProperties.batchingColor = parameters.batchingColor; + materialProperties.instancing = parameters.instancing; + materialProperties.instancingColor = parameters.instancingColor; + materialProperties.instancingMorph = parameters.instancingMorph; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } - }, + function setProgram( camera, scene, geometry, material, object ) { - _updateWeight: function ( time ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - var weight = 0; + textures.resetTextureUnits(); - if ( this.enabled ) { + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + 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 = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; - weight = this.weight; - var interpolant = this._weightInterpolant; + let toneMapping = NoToneMapping; - if ( interpolant !== null ) { + if ( material.toneMapped ) { - var interpolantValue = interpolant.evaluate( time )[ 0 ]; + if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) { - weight *= interpolantValue; + toneMapping = _this.toneMapping; - if ( time > interpolant.parameterPositions[ 1 ] ) { + } - this.stopFading(); + } - if ( interpolantValue === 0 ) { + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - // faded out, disable - this.enabled = false; + 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; + + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); } } - } - - this._effectiveWeight = weight; - return weight; + // - }, + let needsProgramChange = false; - _updateTimeScale: function ( time ) { + if ( material.version === materialProperties.__version ) { - var timeScale = 0; + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - if ( ! this.paused ) { + needsProgramChange = true; - timeScale = this.timeScale; + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - var interpolant = this._timeScaleInterpolant; + needsProgramChange = true; - if ( interpolant !== null ) { + } else if ( object.isBatchedMesh && materialProperties.batching === false ) { - var interpolantValue = interpolant.evaluate( time )[ 0 ]; + needsProgramChange = true; - timeScale *= interpolantValue; + } else if ( ! object.isBatchedMesh && materialProperties.batching === true ) { - if ( time > interpolant.parameterPositions[ 1 ] ) { + needsProgramChange = true; - this.stopWarping(); + } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { - if ( timeScale === 0 ) { + needsProgramChange = true; - // motion has halted, pause - this.paused = true; + } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { - } else { + needsProgramChange = true; - // warp done - apply final time scale - this.timeScale = timeScale; + } 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 ) { - this._effectiveTimeScale = timeScale; - return timeScale; + needsProgramChange = true; - }, + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - _updateTime: function ( deltaTime ) { + needsProgramChange = true; - var time = this.time + deltaTime; + } else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) { - if ( deltaTime === 0 ) { return time; } + needsProgramChange = true; - var duration = this._clip.duration, + } else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) { - loop = this.loop, - loopCount = this._loopCount; + needsProgramChange = true; - if ( loop === LoopOnce ) { + } else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) { - if ( loopCount === - 1 ) { + needsProgramChange = true; - // just started + } else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) { - this._loopCount = 0; - this._setEndings( true, true, false ); + needsProgramChange = true; - } + } else if ( materialProperties.envMap !== envMap ) { - handle_stop: { + needsProgramChange = true; - if ( time >= duration ) { + } else if ( material.fog === true && materialProperties.fog !== fog ) { - time = duration; + needsProgramChange = true; - } else if ( time < 0 ) { + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - time = 0; + needsProgramChange = true; - } else { break handle_stop; } + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - if ( this.clampWhenFinished ) { this.paused = true; } - else { this.enabled = false; } + needsProgramChange = true; - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime < 0 ? - 1 : 1 - } ); + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - } + needsProgramChange = true; - } else { // repetitive Repeat or PingPong + } else if ( materialProperties.morphTargets !== morphTargets ) { - var pingPong = ( loop === LoopPingPong ); + needsProgramChange = true; - if ( loopCount === - 1 ) { + } else if ( materialProperties.morphNormals !== morphNormals ) { - // just started + needsProgramChange = true; - if ( deltaTime >= 0 ) { + } else if ( materialProperties.morphColors !== morphColors ) { - loopCount = 0; + needsProgramChange = true; - this._setEndings( true, this.repetitions === 0, pingPong ); + } else if ( materialProperties.toneMapping !== toneMapping ) { - } else { + needsProgramChange = true; - // when looping in reverse direction, the initial - // transition through zero counts as a repetition, - // so leave loopCount at -1 + } else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) { - this._setEndings( this.repetitions === 0, true, pingPong ); + needsProgramChange = true; } - } + } else { - if ( time >= duration || time < 0 ) { + needsProgramChange = true; + materialProperties.__version = material.version; - // wrap around + } - var loopDelta = Math.floor( time / duration ); // signed - time -= duration * loopDelta; + // - loopCount += Math.abs( loopDelta ); + let program = materialProperties.currentProgram; - var pending = this.repetitions - loopCount; + if ( needsProgramChange === true ) { - if ( pending < 0 ) { + program = getProgram( material, scene, object ); - // have to stop (switch state, clamp time, fire event) + } - if ( this.clampWhenFinished ) { this.paused = true; } - else { this.enabled = false; } + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - time = deltaTime > 0 ? duration : 0; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime > 0 ? 1 : - 1 - } ); + if ( state.useProgram( program.program ) ) { - } else { + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - // keep running + } - if ( pending === 0 ) { + if ( material.id !== _currentMaterialId ) { - // entering the last round + _currentMaterialId = material.id; - var atStart = deltaTime < 0; - this._setEndings( atStart, ! atStart, pingPong ); + refreshMaterial = true; - } else { + } - this._setEndings( false, false, pingPong ); + if ( refreshProgram || _currentCamera !== camera ) { - } + // common camera uniforms - this._loopCount = loopCount; + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - this._mixer.dispatchEvent( { - type: 'loop', action: this, loopDelta: loopDelta - } ); + const uCamPos = p_uniforms.map.cameraPosition; - } + if ( uCamPos !== undefined ) { - } + uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) ); - if ( pingPong && ( loopCount & 1 ) === 1 ) { + } - // invert time for the "pong round" + if ( capabilities.logarithmicDepthBuffer ) { - this.time = time; - return duration - time; + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); - } + } - } + // consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067 - this.time = time; - return time; + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - }, + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - _setEndings: function ( atStart, atEnd, pingPong ) { + } - var settings = this._interpolantSettings; + if ( _currentCamera !== camera ) { - if ( pingPong ) { + _currentCamera = camera; - settings.endingStart = ZeroSlopeEnding; - settings.endingEnd = ZeroSlopeEnding; + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - } else { + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - // assuming for LoopOnce atStart == atEnd == true + } - if ( atStart ) { + } - settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - } else { + if ( object.isSkinnedMesh ) { - settings.endingStart = WrapAroundEnding; + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - } + const skeleton = object.skeleton; - if ( atEnd ) { + if ( skeleton ) { - settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - } else { + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - settings.endingEnd = WrapAroundEnding; + } } - } - - }, + if ( object.isBatchedMesh ) { - _scheduleFading: function ( duration, weightNow, weightThen ) { + p_uniforms.setOptional( _gl, object, 'batchingTexture' ); + p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); - var mixer = this._mixer, now = mixer.time, - interpolant = this._weightInterpolant; + p_uniforms.setOptional( _gl, object, 'batchingIdTexture' ); + p_uniforms.setValue( _gl, 'batchingIdTexture', object._indirectTexture, textures ); - if ( interpolant === null ) { + p_uniforms.setOptional( _gl, object, 'batchingColorTexture' ); + if ( object._colorsTexture !== null ) { - interpolant = mixer._lendControlInterpolant(); - this._weightInterpolant = interpolant; + p_uniforms.setValue( _gl, 'batchingColorTexture', object._colorsTexture, textures ); - } + } - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; + } - times[ 0 ] = now; values[ 0 ] = weightNow; - times[ 1 ] = now + duration; values[ 1 ] = weightThen; + const morphAttributes = geometry.morphAttributes; - return this; + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) { - } + morphtargets.update( object, geometry, program ); -} ); + } -/** - * - * Player for AnimationClips. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { -function AnimationMixer( root ) { + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); - this._root = root; - this._initMemoryManager(); - this._accuIndex = 0; + } - this.time = 0; + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - this.timeScale = 1.0; + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { -} + m_uniforms.envMap.value = envMap; -AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - constructor: AnimationMixer, + } - _bindAction: function ( action, prototypeAction ) { + if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) { - var root = action._localRoot || this._root, - tracks = action._clip.tracks, - nTracks = tracks.length, - bindings = action._propertyBindings, - interpolants = action._interpolants, - rootUuid = root.uuid, - bindingsByRoot = this._bindingsByRootAndName, - bindingsByName = bindingsByRoot[ rootUuid ]; + m_uniforms.envMapIntensity.value = scene.environmentIntensity; - if ( bindingsByName === undefined ) { + } - bindingsByName = {}; - bindingsByRoot[ rootUuid ] = bindingsByName; + if ( refreshMaterial ) { - } + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - for ( var i = 0; i !== nTracks; ++ i ) { + if ( materialProperties.needsLights ) { - var track = tracks[ i ], - trackName = track.name, - binding = bindingsByName[ trackName ]; + // the current material requires lighting info - if ( binding !== undefined ) { + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - bindings[ i ] = binding; + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); - } else { + } - binding = bindings[ i ]; + // refresh uniforms common to several materials - if ( binding !== undefined ) { + if ( fog && material.fog === true ) { - // existing binding, make sure the cache knows + materials.refreshFogUniforms( m_uniforms, fog ); - if ( binding._cacheIndex === null ) { + } - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget[ camera.id ] ); - } + WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); - continue; + } - } + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - var path = prototypeAction && prototypeAction. - _propertyBindings[ i ].binding.parsedPath; + WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); + material.uniformsNeedUpdate = false; - binding = new PropertyMixer( - PropertyBinding.create( root, trackName, path ), - track.ValueTypeName, track.getValueSize() ); + } - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); + if ( material.isSpriteMaterial ) { - bindings[ i ] = binding; + p_uniforms.setValue( _gl, 'center', object.center ); } - interpolants[ i ].resultBuffer = binding.buffer; + // common matrices - } - - }, + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - _activateAction: function ( action ) { + // UBOs - if ( ! this._isActiveAction( action ) ) { + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - if ( action._cacheIndex === null ) { + const groups = material.uniformsGroups; - // this action has been forgotten by the cache, but the user - // appears to be still using it -> rebind + for ( let i = 0, l = groups.length; i < l; i ++ ) { - var rootUuid = ( action._localRoot || this._root ).uuid, - clipUuid = action._clip.uuid, - actionsForClip = this._actionsByClip[ clipUuid ]; + const group = groups[ i ]; - this._bindAction( action, - actionsForClip && actionsForClip.knownActions[ 0 ] ); + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - this._addInactiveAction( action, clipUuid, rootUuid ); + } } - var bindings = action._propertyBindings; + return program; - // increment reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( binding.useCount ++ === 0 ) { + } - this._lendBinding( binding ); - binding.saveOriginalState(); + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - } + function markUniformsLightsNeedsUpdate( uniforms, value ) { - } + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - this._lendAction( action ); + 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 ) { - _deactivateAction: function ( action ) { + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - if ( this._isActiveAction( action ) ) { + } - var bindings = action._propertyBindings; + this.getActiveCubeFace = function () { - // decrement reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { + return _currentActiveCubeFace; - var binding = bindings[ i ]; + }; - if ( -- binding.useCount === 0 ) { + this.getActiveMipmapLevel = function () { - binding.restoreOriginalState(); - this._takeBackBinding( binding ); + return _currentActiveMipmapLevel; - } + }; - } + this.getRenderTarget = function () { - this._takeBackAction( action ); + return _currentRenderTarget; - } + }; - }, + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - // Memory manager + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - _initMemoryManager: function () { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - this._actions = []; // 'nActiveActions' followed by inactive ones - this._nActiveActions = 0; + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - this._actionsByClip = {}; - // inside: - // { - // knownActions: Array< AnimationAction > - used as prototypes - // actionByRoot: AnimationAction - lookup - // } + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - this._bindings = []; // 'nActiveBindings' followed by inactive ones - this._nActiveBindings = 0; + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > + } + } - this._controlInterpolants = []; // same game as above - this._nActiveControlInterpolants = 0; + }; - var scope = this; + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - this.stats = { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - actions: { - get total() { + }; - return scope._actions.length; + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - }, - get inUse() { + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - return scope._nActiveActions; + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - } - }, - bindings: { - get total() { + if ( renderTarget ) { - return scope._bindings.length; + const renderTargetProperties = properties.get( renderTarget ); - }, - get inUse() { + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - return scope._nActiveBindings; + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - } - }, - controlInterpolants: { - get total() { + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - return scope._controlInterpolants.length; + textures.setupRenderTarget( renderTarget ); - }, - get inUse() { + } else if ( renderTargetProperties.__hasExternalTextures ) { - return scope._nActiveControlInterpolants; + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); } - } - }; + const texture = renderTarget.texture; - }, + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - // Memory management for AnimationAction objects + isRenderTarget3D = true; - _isActiveAction: function ( action ) { + } - var index = action._cacheIndex; - return index !== null && index < this._nActiveActions; + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - }, + if ( renderTarget.isWebGLCubeRenderTarget ) { - _addInactiveAction: function ( action, clipUuid, rootUuid ) { + if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) { - var actions = this._actions, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; + framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ]; - if ( actionsForClip === undefined ) { + } else { - actionsForClip = { + framebuffer = __webglFramebuffer[ activeCubeFace ]; - knownActions: [ action ], - actionByRoot: {} + } - }; + isCube = true; - action._byClipCacheIndex = 0; + } else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - actionsByClip[ clipUuid ] = actionsForClip; + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - } else { + } else { - var knownActions = actionsForClip.knownActions; + if ( Array.isArray( __webglFramebuffer ) ) { - action._byClipCacheIndex = knownActions.length; - knownActions.push( action ); + framebuffer = __webglFramebuffer[ activeMipmapLevel ]; - } + } else { - action._cacheIndex = actions.length; - actions.push( action ); + framebuffer = __webglFramebuffer; - actionsForClip.actionByRoot[ rootUuid ] = action; + } - }, + } - _removeInactiveAction: function ( action ) { + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; - var actions = this._actions, - lastInactiveAction = actions[ actions.length - 1 ], - cacheIndex = action._cacheIndex; + } else { - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; - action._cacheIndex = null; + } + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - var clipUuid = action._clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ], - knownActionsForClip = actionsForClip.knownActions, + if ( framebufferBound && useDefaultFramebuffer ) { - lastKnownAction = - knownActionsForClip[ knownActionsForClip.length - 1 ], + state.drawBuffers( renderTarget, framebuffer ); - byClipCacheIndex = action._byClipCacheIndex; + } - lastKnownAction._byClipCacheIndex = byClipCacheIndex; - knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; - knownActionsForClip.pop(); + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - action._byClipCacheIndex = null; + 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 ); - var actionByRoot = actionsForClip.actionByRoot, - rootUuid = ( action._localRoot || this._root ).uuid; + } else if ( isRenderTarget3D ) { - delete actionByRoot[ rootUuid ]; + const textureProperties = properties.get( renderTarget.texture ); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); - if ( knownActionsForClip.length === 0 ) { + } - delete actionsByClip[ clipUuid ]; + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - } + }; - this._removeInactiveBindingsForAction( action ); + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - }, + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - _removeInactiveBindingsForAction: function ( action ) { + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - var bindings = action._propertyBindings; - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { + } - var binding = bindings[ i ]; + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( -- binding.referenceCount === 0 ) { + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - this._removeInactiveBinding( binding ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; } - } - - }, + if ( framebuffer ) { - _lendAction: function ( action ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - // [ active actions | inactive actions ] - // [ active actions >| inactive actions ] - // s a - // <-swap-> - // a s + try { - var actions = this._actions, - prevIndex = action._cacheIndex, + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - lastActiveIndex = this._nActiveActions ++, + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - firstInactiveAction = actions[ lastActiveIndex ]; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - action._cacheIndex = lastActiveIndex; - actions[ lastActiveIndex ] = action; + } - firstInactiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = firstInactiveAction; + if ( ! capabilities.textureTypeReadable( textureType ) ) { - }, + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - _takeBackAction: function ( action ) { + } - // [ active actions | inactive actions ] - // [ active actions |< inactive actions ] - // a s - // <-swap-> - // s a + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - var actions = this._actions, - prevIndex = action._cacheIndex, + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - firstInactiveIndex = -- this._nActiveActions, + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - lastActiveAction = actions[ firstInactiveIndex ]; + } - action._cacheIndex = firstInactiveIndex; - actions[ firstInactiveIndex ] = action; + } finally { - lastActiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = lastActiveAction; + // restore framebuffer of current render target if necessary - }, + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - // Memory management for PropertyMixer objects + } - _addInactiveBinding: function ( binding, rootUuid, trackName ) { + } - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], + }; - bindings = this._bindings; + this.readRenderTargetPixelsAsync = async function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - if ( bindingByName === undefined ) { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - bindingByName = {}; - bindingsByRoot[ rootUuid ] = bindingByName; + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - } + } - bindingByName[ trackName ] = binding; + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - binding._cacheIndex = bindings.length; - bindings.push( binding ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; - }, + } - _removeInactiveBinding: function ( binding ) { + if ( framebuffer ) { - var bindings = this._bindings, - propBinding = binding.binding, - rootUuid = propBinding.rootNode.uuid, - trackName = propBinding.path, - bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - lastInactiveBinding = bindings[ bindings.length - 1 ], - cacheIndex = binding._cacheIndex; + try { - lastInactiveBinding._cacheIndex = cacheIndex; - bindings[ cacheIndex ] = lastInactiveBinding; - bindings.pop(); + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - delete bindingByName[ trackName ]; + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - remove_empty_map: { + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); - for ( var _ in bindingByName ) { break remove_empty_map; } // eslint-disable-line no-unused-vars + } - delete bindingsByRoot[ rootUuid ]; + if ( ! capabilities.textureTypeReadable( textureType ) ) { - } + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); - }, + } - _lendBinding: function ( binding ) { + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - var bindings = this._bindings, - prevIndex = binding._cacheIndex, + const glBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); + _gl.flush(); - lastActiveIndex = this._nActiveBindings ++, + // check if the commands have finished every 8 ms + const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); + await probeAsync( _gl, sync, 4 ); - firstInactiveBinding = bindings[ lastActiveIndex ]; + try { - binding._cacheIndex = lastActiveIndex; - bindings[ lastActiveIndex ] = binding; + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); - firstInactiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = firstInactiveBinding; + } finally { - }, + _gl.deleteBuffer( glBuffer ); + _gl.deleteSync( sync ); - _takeBackBinding: function ( binding ) { + } - var bindings = this._bindings, - prevIndex = binding._cacheIndex, + return buffer; - firstInactiveIndex = -- this._nActiveBindings, + } - lastActiveBinding = bindings[ firstInactiveIndex ]; + } finally { - binding._cacheIndex = firstInactiveIndex; - bindings[ firstInactiveIndex ] = binding; + // restore framebuffer of current render target if necessary - lastActiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = lastActiveBinding; + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - }, + } + } - // Memory management of Interpolants for weight and time scale + }; - _lendControlInterpolant: function () { + this.copyFramebufferToTexture = function ( texture, position = null, level = 0 ) { - var interpolants = this._controlInterpolants, - lastActiveIndex = this._nActiveControlInterpolants ++, - interpolant = interpolants[ lastActiveIndex ]; + // support previous signature with position first + if ( texture.isTexture !== true ) { - if ( interpolant === undefined ) { + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyFramebufferToTexture function signature has changed.' ); - interpolant = new LinearInterpolant( - new Float32Array( 2 ), new Float32Array( 2 ), - 1, this._controlInterpolantsResultBuffer ); + position = arguments[ 0 ] || null; + texture = arguments[ 1 ]; - interpolant.__cacheIndex = lastActiveIndex; - interpolants[ lastActiveIndex ] = interpolant; + } - } + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - return interpolant; + const x = position !== null ? position.x : 0; + const y = position !== null ? position.y : 0; - }, + textures.setTexture2D( texture, 0 ); - _takeBackControlInterpolant: function ( interpolant ) { + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, x, y, width, height ); - var interpolants = this._controlInterpolants, - prevIndex = interpolant.__cacheIndex, + state.unbindTexture(); - firstInactiveIndex = -- this._nActiveControlInterpolants, + }; - lastActiveInterpolant = interpolants[ firstInactiveIndex ]; + this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { - interpolant.__cacheIndex = firstInactiveIndex; - interpolants[ firstInactiveIndex ] = interpolant; + // support previous signature with dstPosition first + if ( srcTexture.isTexture !== true ) { - lastActiveInterpolant.__cacheIndex = prevIndex; - interpolants[ prevIndex ] = lastActiveInterpolant; + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyTextureToTexture function signature has changed.' ); - }, + dstPosition = arguments[ 0 ] || null; + srcTexture = arguments[ 1 ]; + dstTexture = arguments[ 2 ]; + level = arguments[ 3 ] || 0; + srcRegion = null; - _controlInterpolantsResultBuffer: new Float32Array( 1 ), + } - // return an action for a clip optionally using a custom root target - // object (this method allocates a lot of dynamic memory in case a - // previously unknown clip/root combination is specified) - clipAction: function ( clip, optionalRoot ) { + let width, height, minX, minY; + let dstX, dstY; + if ( srcRegion !== null ) { - var root = optionalRoot || this._root, - rootUuid = root.uuid, + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + minX = srcRegion.min.x; + minY = srcRegion.min.y; - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, + } else { - clipUuid = clipObject !== null ? clipObject.uuid : clip, + width = srcTexture.image.width; + height = srcTexture.image.height; + minX = 0; + minY = 0; - actionsForClip = this._actionsByClip[ clipUuid ], - prototypeAction = null; + } - if ( actionsForClip !== undefined ) { + if ( dstPosition !== null ) { - var existingAction = - actionsForClip.actionByRoot[ rootUuid ]; + dstX = dstPosition.x; + dstY = dstPosition.y; - if ( existingAction !== undefined ) { + } else { - return existingAction; + dstX = 0; + dstY = 0; } - // we know the clip, so we don't have to parse all - // the bindings again but can just copy - prototypeAction = actionsForClip.knownActions[ 0 ]; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - // also, take the clip from the prototype action - if ( clipObject === null ) - { clipObject = prototypeAction._clip; } + textures.setTexture2D( dstTexture, 0 ); - } - - // clip must be known when specified via string - if ( clipObject === null ) { return null; } + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _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 ); - // allocate all resources required to run it - var newAction = new AnimationAction( this, clipObject, optionalRoot ); + const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - this._bindAction( newAction, prototypeAction ); + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; - // and make the action known to the memory manager - this._addInactiveAction( newAction, clipUuid, rootUuid ); + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); - return newAction; + if ( srcTexture.isDataTexture ) { - }, + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); - // get an existing action - existingAction: function ( clip, optionalRoot ) { + } else { - var root = optionalRoot || this._root, - rootUuid = root.uuid, + if ( srcTexture.isCompressedTexture ) { - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); - clipUuid = clipObject ? clipObject.uuid : clip, + } else { - actionsForClip = this._actionsByClip[ clipUuid ]; + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image ); - if ( actionsForClip !== undefined ) { + } - return actionsForClip.actionByRoot[ rootUuid ] || null; + } - } + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); - return null; + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - }, + state.unbindTexture(); - // deactivates all previously scheduled actions - stopAllAction: function () { + }; - var actions = this._actions, - nActions = this._nActiveActions, - bindings = this._bindings, - nBindings = this._nActiveBindings; + this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { - this._nActiveActions = 0; - this._nActiveBindings = 0; + // support previous signature with source box first + if ( srcTexture.isTexture !== true ) { - for ( var i = 0; i !== nActions; ++ i ) { + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' ); - actions[ i ].reset(); + srcRegion = arguments[ 0 ] || null; + dstPosition = arguments[ 1 ] || null; + srcTexture = arguments[ 2 ]; + dstTexture = arguments[ 3 ]; + level = arguments[ 4 ] || 0; - } + } - for ( var i = 0; i !== nBindings; ++ i ) { + let width, height, depth, minX, minY, minZ; + let dstX, dstY, dstZ; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; + if ( srcRegion !== null ) { - bindings[ i ].useCount = 0; + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + depth = srcRegion.max.z - srcRegion.min.z; + minX = srcRegion.min.x; + minY = srcRegion.min.y; + minZ = srcRegion.min.z; - } + } else { - return this; + width = image.width; + height = image.height; + depth = image.depth; + minX = 0; + minY = 0; + minZ = 0; - }, + } - // advance the time and update apply the animation - update: function ( deltaTime ) { + if ( dstPosition !== null ) { - deltaTime *= this.timeScale; + dstX = dstPosition.x; + dstY = dstPosition.y; + dstZ = dstPosition.z; - var actions = this._actions, - nActions = this._nActiveActions, + } else { - time = this.time += deltaTime, - timeDirection = Math.sign( deltaTime ), + dstX = 0; + dstY = 0; + dstZ = 0; - accuIndex = this._accuIndex ^= 1; + } - // run active actions + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - for ( var i = 0; i !== nActions; ++ i ) { + if ( dstTexture.isData3DTexture ) { - var action = actions[ i ]; + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - action._update( time, deltaTime, timeDirection, accuIndex ); + } else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) { - } + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; - // update scene graph + } else { - var bindings = this._bindings, - nBindings = this._nActiveBindings; + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; - for ( var i = 0; i !== nBindings; ++ i ) { + } - bindings[ i ].apply( accuIndex ); + _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 currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - return this; + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ ); - }, + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - // return this mixer's root target object - getRoot: function () { + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data ); - return this._root; + } else { - }, + if ( dstTexture.isCompressedArrayTexture ) { - // free all resources specific to a particular clip - uncacheClip: function ( clip ) { + _gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data ); - var actions = this._actions, - clipUuid = clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; + } else { - if ( actionsForClip !== undefined ) { + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image ); - // note: just calling _removeInactiveAction would mess up the - // iteration state and also require updating the state we can - // just throw away + } - var actionsToRemove = actionsForClip.knownActions; + } - for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); - var action = actionsToRemove[ i ]; + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - this._deactivateAction( action ); + state.unbindTexture(); - var cacheIndex = action._cacheIndex, - lastInactiveAction = actions[ actions.length - 1 ]; + }; - action._cacheIndex = null; - action._byClipCacheIndex = null; + this.initRenderTarget = function ( target ) { - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); + if ( properties.get( target ).__webglFramebuffer === undefined ) { - this._removeInactiveBindingsForAction( action ); + textures.setupRenderTarget( target ); } - delete actionsByClip[ clipUuid ]; + }; - } + this.initTexture = function ( texture ) { - }, + if ( texture.isCubeTexture ) { - // free all resources specific to a particular root target object - uncacheRoot: function ( root ) { + textures.setTextureCube( texture, 0 ); - var rootUuid = root.uuid, - actionsByClip = this._actionsByClip; + } else if ( texture.isData3DTexture ) { - for ( var clipUuid in actionsByClip ) { + textures.setTexture3D( texture, 0 ); - var actionByRoot = actionsByClip[ clipUuid ].actionByRoot, - action = actionByRoot[ rootUuid ]; + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - if ( action !== undefined ) { + textures.setTexture2DArray( texture, 0 ); - this._deactivateAction( action ); - this._removeInactiveAction( action ); + } else { + + textures.setTexture2D( texture, 0 ); } - } + state.unbindTexture(); + + }; + + this.resetState = function () { - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ]; + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - if ( bindingByName !== undefined ) { + state.reset(); + bindingStates.reset(); - for ( var trackName in bindingByName ) { + }; - var binding = bindingByName[ trackName ]; - binding.restoreOriginalState(); - this._removeInactiveBinding( binding ); + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - } + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); } - }, + } - // remove a targeted clip from the cache - uncacheAction: function ( clip, optionalRoot ) { + get coordinateSystem() { - var action = this.existingAction( clip, optionalRoot ); + return WebGLCoordinateSystem; - if ( action !== null ) { + } - this._deactivateAction( action ); - this._removeInactiveAction( action ); + get outputColorSpace() { - } + return this._outputColorSpace; } -} ); + set outputColorSpace( colorSpace ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + this._outputColorSpace = colorSpace; -function Uniform( value ) { + const gl = this.getContext(); + gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb'; + gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb'; - if ( typeof value === 'string' ) { + } - console.warn( 'THREE.Uniform: Type parameter is no longer needed.' ); - value = arguments[ 1 ]; +} - } +class Scene extends Object3D { - this.value = value; + constructor() { -} + super(); -Uniform.prototype.clone = function () { + this.isScene = true; - return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); + this.type = 'Scene'; -}; + this.background = null; + this.environment = null; + this.fog = null; -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + this.backgroundBlurriness = 0; + this.backgroundIntensity = 1; + this.backgroundRotation = new Euler(); -function InstancedBufferGeometry() { + this.environmentIntensity = 1; + this.environmentRotation = new Euler(); - BufferGeometry.call( this ); + this.overrideMaterial = null; - this.type = 'InstancedBufferGeometry'; - this.maxInstancedCount = undefined; + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { -} + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); -InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), { + } - constructor: InstancedBufferGeometry, + } - isInstancedBufferGeometry: true, + copy( source, recursive ) { - copy: function ( source ) { + super.copy( source, recursive ); - BufferGeometry.prototype.copy.call( this, source ); + 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(); - this.maxInstancedCount = source.maxInstancedCount; + this.backgroundBlurriness = source.backgroundBlurriness; + this.backgroundIntensity = source.backgroundIntensity; + this.backgroundRotation.copy( source.backgroundRotation ); - return this; + this.environmentIntensity = source.environmentIntensity; + this.environmentRotation.copy( source.environmentRotation ); - }, + if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); - clone: function () { + this.matrixAutoUpdate = source.matrixAutoUpdate; - return new this.constructor().copy( this ); + return this; } -} ); + toJSON( meta ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + const data = super.toJSON( meta ); + + if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); -function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) { + if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; + if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; + data.object.backgroundRotation = this.backgroundRotation.toArray(); - this.uuid = _Math.generateUUID(); + if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity; + data.object.environmentRotation = this.environmentRotation.toArray(); - this.data = interleavedBuffer; - this.itemSize = itemSize; - this.offset = offset; + return data; - this.normalized = normalized === true; + } } -Object.defineProperties( InterleavedBufferAttribute.prototype, { +class InterleavedBuffer { - count: { + constructor( array, stride ) { - get: function () { + this.isInterleavedBuffer = true; - return this.data.count; + this.array = array; + this.stride = stride; + this.count = array !== undefined ? array.length / stride : 0; - } + this.usage = StaticDrawUsage; + this._updateRange = { offset: 0, count: - 1 }; + this.updateRanges = []; - }, + this.version = 0; + + this.uuid = generateUUID(); - array: { + } - get: function () { + onUploadCallback() {} - return this.data.array; + set needsUpdate( value ) { - } + if ( value === true ) this.version ++; } -} ); + get updateRange() { -Object.assign( InterleavedBufferAttribute.prototype, { + warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 + return this._updateRange; - isInterleavedBufferAttribute: true, + } - setX: function ( index, x ) { + setUsage( value ) { - this.data.array[ index * this.data.stride + this.offset ] = x; + this.usage = value; return this; - }, + } - setY: function ( index, y ) { + addUpdateRange( start, count ) { - this.data.array[ index * this.data.stride + this.offset + 1 ] = y; + this.updateRanges.push( { start, count } ); - return this; + } - }, + clearUpdateRanges() { - setZ: function ( index, z ) { + this.updateRanges.length = 0; - this.data.array[ index * this.data.stride + this.offset + 2 ] = z; + } - return this; + copy( source ) { - }, + this.array = new source.array.constructor( source.array ); + this.count = source.count; + this.stride = source.stride; + this.usage = source.usage; - setW: function ( index, w ) { + return this; - this.data.array[ index * this.data.stride + this.offset + 3 ] = w; + } - return this; + copyAt( index1, attribute, index2 ) { - }, + index1 *= this.stride; + index2 *= attribute.stride; - getX: function ( index ) { + for ( let i = 0, l = this.stride; i < l; i ++ ) { - return this.data.array[ index * this.data.stride + this.offset ]; + this.array[ index1 + i ] = attribute.array[ index2 + i ]; - }, + } - getY: function ( index ) { + return this; - return this.data.array[ index * this.data.stride + this.offset + 1 ]; + } - }, + set( value, offset = 0 ) { - getZ: function ( index ) { + this.array.set( value, offset ); - return this.data.array[ index * this.data.stride + this.offset + 2 ]; + return this; - }, + } - getW: function ( index ) { + clone( data ) { - return this.data.array[ index * this.data.stride + this.offset + 3 ]; + if ( data.arrayBuffers === undefined ) { - }, + data.arrayBuffers = {}; - setXY: function ( index, x, y ) { + } - index = index * this.data.stride + this.offset; + if ( this.array.buffer._uuid === undefined ) { - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; + this.array.buffer._uuid = generateUUID(); - return this; + } - }, + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { - setXYZ: function ( index, x, y, z ) { + data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; - index = index * this.data.stride + this.offset; + } - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; + const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); - return this; + const ib = new this.constructor( array, this.stride ); + ib.setUsage( this.usage ); - }, + return ib; - setXYZW: function ( index, x, y, z, w ) { + } - index = index * this.data.stride + this.offset; + onUpload( callback ) { - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; - this.data.array[ index + 3 ] = w; + this.onUploadCallback = callback; return this; } -} ); - -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ - -function InterleavedBuffer( array, stride ) { + toJSON( data ) { - this.uuid = _Math.generateUUID(); + if ( data.arrayBuffers === undefined ) { - this.array = array; - this.stride = stride; - this.count = array !== undefined ? array.length / stride : 0; + data.arrayBuffers = {}; - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; + } - this.onUploadCallback = function () {}; + // generate UUID for array buffer if necessary - this.version = 0; + if ( this.array.buffer._uuid === undefined ) { -} + this.array.buffer._uuid = generateUUID(); -Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', { + } - set: function ( value ) { + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { - if ( value === true ) { this.version ++; } + data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); - } + } -} ); + // -Object.assign( InterleavedBuffer.prototype, { + return { + uuid: this.uuid, + buffer: this.array.buffer._uuid, + type: this.array.constructor.name, + stride: this.stride + }; - isInterleavedBuffer: true, + } - setArray: function ( array ) { +} - if ( Array.isArray( array ) ) { +const _vector$6 = /*@__PURE__*/ new Vector3(); - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); +class InterleavedBufferAttribute { - } + constructor( interleavedBuffer, itemSize, offset, normalized = false ) { - this.count = array !== undefined ? array.length / this.stride : 0; - this.array = array; + this.isInterleavedBufferAttribute = true; - }, + this.name = ''; - setDynamic: function ( value ) { + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; - this.dynamic = value; + this.normalized = normalized; - return this; + } - }, + get count() { - copy: function ( source ) { + return this.data.count; - this.array = new source.array.constructor( source.array ); - this.count = source.count; - this.stride = source.stride; - this.dynamic = source.dynamic; + } - return this; + get array() { - }, + return this.data.array; - copyAt: function ( index1, attribute, index2 ) { + } - index1 *= this.stride; - index2 *= attribute.stride; + set needsUpdate( value ) { - for ( var i = 0, l = this.stride; i < l; i ++ ) { + this.data.needsUpdate = value; - this.array[ index1 + i ] = attribute.array[ index2 + i ]; + } - } + applyMatrix4( m ) { - return this; + for ( let i = 0, l = this.data.count; i < l; i ++ ) { - }, + _vector$6.fromBufferAttribute( this, i ); - set: function ( value, offset ) { + _vector$6.applyMatrix4( m ); - if ( offset === undefined ) { offset = 0; } + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); - this.array.set( value, offset ); + } return this; - }, + } - clone: function () { + applyNormalMatrix( m ) { - return new this.constructor().copy( this ); + for ( let i = 0, l = this.count; i < l; i ++ ) { - }, + _vector$6.fromBufferAttribute( this, i ); - onUpload: function ( callback ) { + _vector$6.applyNormalMatrix( m ); - this.onUploadCallback = callback; + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + + } return this; } -} ); + transformDirection( m ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + for ( let i = 0, l = this.count; i < l; i ++ ) { -function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) { + _vector$6.fromBufferAttribute( this, i ); - InterleavedBuffer.call( this, array, stride ); + _vector$6.transformDirection( m ); - this.meshPerAttribute = meshPerAttribute || 1; - -} + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); -InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), { + } - constructor: InstancedInterleavedBuffer, + return this; - isInstancedInterleavedBuffer: true, + } - copy: function ( source ) { + getComponent( index, component ) { - InterleavedBuffer.prototype.copy.call( this, source ); + let value = this.array[ index * this.data.stride + this.offset + component ]; - this.meshPerAttribute = source.meshPerAttribute; + if ( this.normalized ) value = denormalize( value, this.array ); - return this; + return value; } -} ); + setComponent( index, component, value ) { -/** - * @author benaadams / https://twitter.com/ben_a_adams - */ + if ( this.normalized ) value = normalize( value, this.array ); -function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) { + this.data.array[ index * this.data.stride + this.offset + component ] = value; + + return this; - BufferAttribute.call( this, array, itemSize ); + } - this.meshPerAttribute = meshPerAttribute || 1; + setX( index, x ) { -} + if ( this.normalized ) x = normalize( x, this.array ); -InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), { + this.data.array[ index * this.data.stride + this.offset ] = x; - constructor: InstancedBufferAttribute, + return this; - isInstancedBufferAttribute: true, + } - copy: function ( source ) { + setY( index, y ) { - BufferAttribute.prototype.copy.call( this, source ); + if ( this.normalized ) y = normalize( y, this.array ); - this.meshPerAttribute = source.meshPerAttribute; + this.data.array[ index * this.data.stride + this.offset + 1 ] = y; return this; } -} ); - -/** - * @author mrdoob / http://mrdoob.com/ - * @author bhouston / http://clara.io/ - * @author stephomi / http://stephaneginier.com/ - */ - -function Raycaster( origin, direction, near, far ) { + setZ( index, z ) { - this.ray = new Ray( origin, direction ); - // direction is assumed to be normalized (for accurate distance calculations) + if ( this.normalized ) z = normalize( z, this.array ); - this.near = near || 0; - this.far = far || Infinity; + this.data.array[ index * this.data.stride + this.offset + 2 ] = z; - this.params = { - Mesh: {}, - Line: {}, - LOD: {}, - Points: { threshold: 1 }, - Sprite: {} - }; + return this; - Object.defineProperties( this.params, { - PointCloud: { - get: function () { + } - console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); - return this.Points; + setW( index, w ) { - } - } - } ); + if ( this.normalized ) w = normalize( w, this.array ); -} + this.data.array[ index * this.data.stride + this.offset + 3 ] = w; -function ascSort( a, b ) { + return this; - return a.distance - b.distance; + } -} + getX( index ) { -function intersectObject( object, raycaster, intersects, recursive ) { + let x = this.data.array[ index * this.data.stride + this.offset ]; - if ( object.visible === false ) { return; } + if ( this.normalized ) x = denormalize( x, this.array ); - object.raycast( raycaster, intersects ); + return x; - if ( recursive === true ) { + } - var children = object.children; + getY( index ) { - for ( var i = 0, l = children.length; i < l; i ++ ) { + let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; - intersectObject( children[ i ], raycaster, intersects, true ); + if ( this.normalized ) y = denormalize( y, this.array ); - } + return y; } -} + getZ( index ) { -Object.assign( Raycaster.prototype, { + let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; - linePrecision: 1, + if ( this.normalized ) z = denormalize( z, this.array ); - set: function ( origin, direction ) { + return z; - // direction is assumed to be normalized (for accurate distance calculations) + } - this.ray.set( origin, direction ); + getW( index ) { - }, + let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; - setFromCamera: function ( coords, camera ) { + if ( this.normalized ) w = denormalize( w, this.array ); - if ( ( camera && camera.isPerspectiveCamera ) ) { + return w; - this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); - this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); + } - } else if ( ( camera && camera.isOrthographicCamera ) ) { + setXY( index, x, y ) { - this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera - this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + index = index * this.data.stride + this.offset; - } else { + if ( this.normalized ) { - console.error( 'THREE.Raycaster: Unsupported camera type.' ); + x = normalize( x, this.array ); + y = normalize( y, this.array ); } - }, + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; - intersectObject: function ( object, recursive ) { + return this; - var intersects = []; + } - intersectObject( object, this, intersects, recursive ); + setXYZ( index, x, y, z ) { - intersects.sort( ascSort ); + index = index * this.data.stride + this.offset; - return intersects; + if ( this.normalized ) { - }, + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } - intersectObjects: function ( objects, recursive ) { + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; - var intersects = []; + return this; - if ( Array.isArray( objects ) === false ) { + } - console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); - return intersects; + setXYZW( index, x, y, z, w ) { - } + index = index * this.data.stride + this.offset; - for ( var i = 0, l = objects.length; i < l; i ++ ) { + if ( this.normalized ) { - intersectObject( objects[ i ], this, intersects, recursive ); + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); } - intersects.sort( ascSort ); + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; + this.data.array[ index + 3 ] = w; - return intersects; + return this; } -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - */ - -function Clock( autoStart ) { - - this.autoStart = ( autoStart !== undefined ) ? autoStart : true; + clone( data ) { - this.startTime = 0; - this.oldTime = 0; - this.elapsedTime = 0; + if ( data === undefined ) { - this.running = false; + console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); -} + const array = []; -Object.assign( Clock.prototype, { + for ( let i = 0; i < this.count; i ++ ) { - start: function () { + const index = i * this.data.stride + this.offset; - this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 + for ( let j = 0; j < this.itemSize; j ++ ) { - this.oldTime = this.startTime; - this.elapsedTime = 0; - this.running = true; + array.push( this.data.array[ index + j ] ); - }, + } - stop: function () { + } - this.getElapsedTime(); - this.running = false; - this.autoStart = false; + return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); - }, + } else { - getElapsedTime: function () { + if ( data.interleavedBuffers === undefined ) { - this.getDelta(); - return this.elapsedTime; + data.interleavedBuffers = {}; - }, + } - getDelta: function () { + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { - var diff = 0; + data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); - if ( this.autoStart && ! this.running ) { + } - this.start(); - return 0; + return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); } - if ( this.running ) { + } - var newTime = ( typeof performance === 'undefined' ? Date : performance ).now(); + toJSON( data ) { - diff = ( newTime - this.oldTime ) / 1000; - this.oldTime = newTime; + if ( data === undefined ) { - this.elapsedTime += diff; + console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); - } + const array = []; - return diff; + for ( let i = 0; i < this.count; i ++ ) { - } + const index = i * this.data.stride + this.offset; -} ); + for ( let j = 0; j < this.itemSize; j ++ ) { -/** - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - * - * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system - * - * The poles (phi) are at the positive and negative y axis. - * The equator starts at positive z. - */ + array.push( this.data.array[ index + j ] ); + + } -function Spherical( radius, phi, theta ) { + } - this.radius = ( radius !== undefined ) ? radius : 1.0; - this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole - this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere + // de-interleave data and save it as an ordinary buffer attribute for now - return this; + return { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: array, + normalized: this.normalized + }; -} + } else { -Object.assign( Spherical.prototype, { + // save as true interleaved attribute - set: function ( radius, phi, theta ) { + if ( data.interleavedBuffers === undefined ) { - this.radius = radius; - this.phi = phi; - this.theta = theta; + data.interleavedBuffers = {}; - return this; + } - }, + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { - clone: function () { + data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); - return new this.constructor().copy( this ); + } - }, + return { + isInterleavedBufferAttribute: true, + itemSize: this.itemSize, + data: this.data.uuid, + offset: this.offset, + normalized: this.normalized + }; - copy: function ( other ) { + } - this.radius = other.radius; - this.phi = other.phi; - this.theta = other.theta; + } - return this; +} - }, +class SpriteMaterial extends Material { - // restrict phi to be betwee EPS and PI-EPS - makeSafe: function () { + constructor( parameters ) { - var EPS = 0.000001; - this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); + super(); - return this; + this.isSpriteMaterial = true; - }, + this.type = 'SpriteMaterial'; - setFromVector3: function ( vec3 ) { + this.color = new Color( 0xffffff ); - this.radius = vec3.length(); + this.map = null; - if ( this.radius === 0 ) { + this.alphaMap = null; - this.theta = 0; - this.phi = 0; + this.rotation = 0; - } else { + this.sizeAttenuation = true; - this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis - this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle + this.transparent = true; - } + this.fog = true; - return this; + this.setValues( parameters ); } -} ); - -/** - * @author Mugen87 / https://github.com/Mugen87 - * - * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system - * - */ + copy( source ) { -function Cylindrical( radius, theta, y ) { + super.copy( source ); - this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane - this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis - this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane + this.color.copy( source.color ); - return this; + this.map = source.map; -} + this.alphaMap = source.alphaMap; -Object.assign( Cylindrical.prototype, { + this.rotation = source.rotation; - set: function ( radius, theta, y ) { + this.sizeAttenuation = source.sizeAttenuation; - this.radius = radius; - this.theta = theta; - this.y = y; + this.fog = source.fog; return this; - }, + } - clone: function () { +} - return new this.constructor().copy( this ); +let _geometry; - }, +const _intersectPoint = /*@__PURE__*/ new Vector3(); +const _worldScale = /*@__PURE__*/ new Vector3(); +const _mvPosition = /*@__PURE__*/ new Vector3(); - copy: function ( other ) { +const _alignedPosition = /*@__PURE__*/ new Vector2(); +const _rotatedPosition = /*@__PURE__*/ new Vector2(); +const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); - this.radius = other.radius; - this.theta = other.theta; - this.y = other.y; +const _vA$2 = /*@__PURE__*/ new Vector3(); +const _vB$2 = /*@__PURE__*/ new Vector3(); +const _vC$2 = /*@__PURE__*/ new Vector3(); - return this; +const _uvA = /*@__PURE__*/ new Vector2(); +const _uvB = /*@__PURE__*/ new Vector2(); +const _uvC = /*@__PURE__*/ new Vector2(); - }, +class Sprite extends Object3D { - setFromVector3: function ( vec3 ) { + constructor( material = new SpriteMaterial() ) { - this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z ); - this.theta = Math.atan2( vec3.x, vec3.z ); - this.y = vec3.y; + super(); - return this; + this.isSprite = true; - } + this.type = 'Sprite'; -} ); + if ( _geometry === undefined ) { -/** - * @author alteredq / http://alteredqualia.com/ - */ + _geometry = new BufferGeometry(); -function ImmediateRenderObject( material ) { + 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 + ] ); - Object3D.call( this ); + const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); - this.material = material; - this.render = function ( /* renderCallback */ ) {}; + _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 ) ); -} + } -ImmediateRenderObject.prototype = Object.create( Object3D.prototype ); -ImmediateRenderObject.prototype.constructor = ImmediateRenderObject; + this.geometry = _geometry; + this.material = material; -ImmediateRenderObject.prototype.isImmediateRenderObject = true; + this.center = new Vector2( 0.5, 0.5 ); -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + } -function VertexNormalsHelper( object, size, hex, linewidth ) { + raycast( raycaster, intersects ) { - this.object = object; + if ( raycaster.camera === null ) { - this.size = ( size !== undefined ) ? size : 1; + console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); - var color = ( hex !== undefined ) ? hex : 0xff0000; + } - var width = ( linewidth !== undefined ) ? linewidth : 1; + _worldScale.setFromMatrixScale( this.matrixWorld ); - // + _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); + this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); - var nNormals = 0; + _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); - var objGeometry = this.object.geometry; + if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { - if ( objGeometry && objGeometry.isGeometry ) { + _worldScale.multiplyScalar( - _mvPosition.z ); - nNormals = objGeometry.faces.length * 3; + } - } else if ( objGeometry && objGeometry.isBufferGeometry ) { + const rotation = this.material.rotation; + let sin, cos; - nNormals = objGeometry.attributes.normal.count; + if ( rotation !== 0 ) { - } + cos = Math.cos( rotation ); + sin = Math.sin( rotation ); - // + } - var geometry = new BufferGeometry(); + const center = this.center; - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); + transformVertex( _vA$2.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vB$2.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vC$2.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); - geometry.addAttribute( 'position', positions ); + _uvA.set( 0, 0 ); + _uvB.set( 1, 0 ); + _uvC.set( 1, 1 ); - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); + // check first triangle + let intersect = raycaster.ray.intersectTriangle( _vA$2, _vB$2, _vC$2, false, _intersectPoint ); - // + if ( intersect === null ) { - this.matrixAutoUpdate = false; + // check second triangle + transformVertex( _vB$2.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + _uvB.set( 0, 1 ); - this.update(); + intersect = raycaster.ray.intersectTriangle( _vA$2, _vC$2, _vB$2, false, _intersectPoint ); + if ( intersect === null ) { -} + return; -VertexNormalsHelper.prototype = Object.create( LineSegments.prototype ); -VertexNormalsHelper.prototype.constructor = VertexNormalsHelper; + } -VertexNormalsHelper.prototype.update = ( function () { + } - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); + const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); - return function update() { + if ( distance < raycaster.near || distance > raycaster.far ) return; - var keys = [ 'a', 'b', 'c' ]; + intersects.push( { - this.object.updateMatrixWorld( true ); + distance: distance, + point: _intersectPoint.clone(), + uv: Triangle.getInterpolation( _intersectPoint, _vA$2, _vB$2, _vC$2, _uvA, _uvB, _uvC, new Vector2() ), + face: null, + object: this - normalMatrix.getNormalMatrix( this.object.matrixWorld ); + } ); - var matrixWorld = this.object.matrixWorld; + } - var position = this.geometry.attributes.position; + copy( source, recursive ) { - // + super.copy( source, recursive ); - var objGeometry = this.object.geometry; + if ( source.center !== undefined ) this.center.copy( source.center ); - if ( objGeometry && objGeometry.isGeometry ) { + this.material = source.material; - var vertices = objGeometry.vertices; + return this; - var faces = objGeometry.faces; + } - var idx = 0; +} - for ( var i = 0, l = faces.length; i < l; i ++ ) { +function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { - var face = faces[ i ]; + // compute position in camera space + _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { + // to check if rotation is not zero + if ( sin !== undefined ) { - var vertex = vertices[ face[ keys[ j ] ] ]; + _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); + _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); - var normal = face.vertexNormals[ j ]; + } else { - v1.copy( vertex ).applyMatrix4( matrixWorld ); + _rotatedPosition.copy( _alignedPosition ); - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); + } - position.setXYZ( idx, v1.x, v1.y, v1.z ); - idx = idx + 1; + vertexPosition.copy( mvPosition ); + vertexPosition.x += _rotatedPosition.x; + vertexPosition.y += _rotatedPosition.y; - position.setXYZ( idx, v2.x, v2.y, v2.z ); + // transform to world space + vertexPosition.applyMatrix4( _viewWorldMatrix ); - idx = idx + 1; +} - } +const _basePosition = /*@__PURE__*/ new Vector3(); - } +const _skinIndex = /*@__PURE__*/ new Vector4(); +const _skinWeight = /*@__PURE__*/ new Vector4(); - } else if ( objGeometry && objGeometry.isBufferGeometry ) { +const _vector3 = /*@__PURE__*/ new Vector3(); +const _matrix4 = /*@__PURE__*/ new Matrix4(); +const _vertex = /*@__PURE__*/ new Vector3(); - var objPos = objGeometry.attributes.position; +const _sphere$4 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _ray$2 = /*@__PURE__*/ new Ray(); - var objNorm = objGeometry.attributes.normal; +class SkinnedMesh extends Mesh { - var idx = 0; + constructor( geometry, material ) { - // for simplicity, ignore index and drawcalls, and render every normal + super( geometry, material ); - for ( var j = 0, jl = objPos.count; j < jl; j ++ ) { + this.isSkinnedMesh = true; - v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); + this.type = 'SkinnedMesh'; - v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) ); + this.bindMode = AttachedBindMode; + this.bindMatrix = new Matrix4(); + this.bindMatrixInverse = new Matrix4(); - v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); + this.boundingBox = null; + this.boundingSphere = null; - position.setXYZ( idx, v1.x, v1.y, v1.z ); + } - idx = idx + 1; + computeBoundingBox() { - position.setXYZ( idx, v2.x, v2.y, v2.z ); + const geometry = this.geometry; - idx = idx + 1; + if ( this.boundingBox === null ) { - } + this.boundingBox = new Box3(); } - position.needsUpdate = true; + this.boundingBox.makeEmpty(); - }; + const positionAttribute = geometry.getAttribute( 'position' ); -}() ); + for ( let i = 0; i < positionAttribute.count; i ++ ) { -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + this.getVertexPosition( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); -function SpotLightHelper( light, color ) { + } - Object3D.call( this ); + } - this.light = light; - this.light.updateMatrixWorld(); + computeBoundingSphere() { - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + const geometry = this.geometry; - this.color = color; + if ( this.boundingSphere === null ) { - var geometry = new BufferGeometry(); + this.boundingSphere = new Sphere(); - var 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 ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { + this.boundingSphere.makeEmpty(); - var p1 = ( i / l ) * Math.PI * 2; - var p2 = ( j / l ) * Math.PI * 2; + const positionAttribute = geometry.getAttribute( 'position' ); - positions.push( - Math.cos( p1 ), Math.sin( p1 ), 1, - Math.cos( p2 ), Math.sin( p2 ), 1 - ); + for ( let i = 0; i < positionAttribute.count; i ++ ) { - } + this.getVertexPosition( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + } - var material = new LineBasicMaterial( { fog: false } ); + } - this.cone = new LineSegments( geometry, material ); - this.add( this.cone ); + copy( source, recursive ) { - this.update(); + super.copy( source, recursive ); -} + this.bindMode = source.bindMode; + this.bindMatrix.copy( source.bindMatrix ); + this.bindMatrixInverse.copy( source.bindMatrixInverse ); -SpotLightHelper.prototype = Object.create( Object3D.prototype ); -SpotLightHelper.prototype.constructor = SpotLightHelper; + this.skeleton = source.skeleton; -SpotLightHelper.prototype.dispose = function () { + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); - this.cone.geometry.dispose(); - this.cone.material.dispose(); + return this; -}; + } -SpotLightHelper.prototype.update = function () { + raycast( raycaster, intersects ) { - var vector = new Vector3(); - var vector2 = new Vector3(); + const material = this.material; + const matrixWorld = this.matrixWorld; - return function update() { + if ( material === undefined ) return; - this.light.updateMatrixWorld(); + // test with bounding sphere in world space - var coneLength = this.light.distance ? this.light.distance : 1000; - var coneWidth = coneLength * Math.tan( this.light.angle ); + if ( this.boundingSphere === null ) this.computeBoundingSphere(); - this.cone.scale.set( coneWidth, coneWidth, coneLength ); + _sphere$4.copy( this.boundingSphere ); + _sphere$4.applyMatrix4( matrixWorld ); - vector.setFromMatrixPosition( this.light.matrixWorld ); - vector2.setFromMatrixPosition( this.light.target.matrixWorld ); + if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; - this.cone.lookAt( vector2.sub( vector ) ); + // convert ray to local space of skinned mesh - if ( this.color !== undefined ) { + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); - this.cone.material.color.set( this.color ); + // test with bounding box in local space - } else { + if ( this.boundingBox !== null ) { - this.cone.material.color.copy( this.light.color ); + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; } - }; + // test for intersections with geometry -}(); + this._computeIntersections( raycaster, intersects, _ray$2 ); -/** - * @author Sean Griffin / http://twitter.com/sgrif - * @author Michael Guerrero / http://realitymeltdown.com - * @author mrdoob / http://mrdoob.com/ - * @author ikerr / http://verold.com - * @author Mugen87 / https://github.com/Mugen87 - */ + } -function getBoneList( object ) { + getVertexPosition( index, target ) { - var boneList = []; + super.getVertexPosition( index, target ); - if ( object && object.isBone ) { + this.applyBoneTransform( index, target ); - boneList.push( object ); + return target; } - for ( var i = 0; i < object.children.length; i ++ ) { - - boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); + bind( skeleton, bindMatrix ) { - } + this.skeleton = skeleton; - return boneList; + if ( bindMatrix === undefined ) { -} + this.updateMatrixWorld( true ); -function SkeletonHelper( object ) { + this.skeleton.calculateInverses(); - var bones = getBoneList( object ); + bindMatrix = this.matrixWorld; - var geometry = new BufferGeometry(); + } - var vertices = []; - var colors = []; + this.bindMatrix.copy( bindMatrix ); + this.bindMatrixInverse.copy( bindMatrix ).invert(); - var color1 = new Color( 0, 0, 1 ); - var color2 = new Color( 0, 1, 0 ); + } - for ( var i = 0; i < bones.length; i ++ ) { + pose() { - var bone = bones[ i ]; + this.skeleton.pose(); - 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 ); + normalizeSkinWeights() { - } + const vector = new Vector4(); - } + const skinWeight = this.geometry.attributes.skinWeight; - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { - var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } ); + vector.fromBufferAttribute( skinWeight, i ); - LineSegments.call( this, geometry, material ); + const scale = 1.0 / vector.manhattanLength(); - this.root = object; - this.bones = bones; + if ( scale !== Infinity ) { - this.matrix = object.matrixWorld; - this.matrixAutoUpdate = false; + vector.multiplyScalar( scale ); -} + } else { -SkeletonHelper.prototype = Object.create( LineSegments.prototype ); -SkeletonHelper.prototype.constructor = SkeletonHelper; + vector.set( 1, 0, 0, 0 ); // do something reasonable -SkeletonHelper.prototype.updateMatrixWorld = function () { + } - var vector = new Vector3(); + skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); - var boneMatrix = new Matrix4(); - var matrixWorldInv = new Matrix4(); + } - return function updateMatrixWorld( force ) { + } - var bones = this.bones; + updateMatrixWorld( force ) { - var geometry = this.geometry; - var position = geometry.getAttribute( 'position' ); + super.updateMatrixWorld( force ); - matrixWorldInv.getInverse( this.root.matrixWorld ); + if ( this.bindMode === AttachedBindMode ) { - for ( var i = 0, j = 0; i < bones.length; i ++ ) { + this.bindMatrixInverse.copy( this.matrixWorld ).invert(); - var bone = bones[ i ]; + } else if ( this.bindMode === DetachedBindMode ) { - if ( bone.parent && bone.parent.isBone ) { + this.bindMatrixInverse.copy( this.bindMatrix ).invert(); - boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j, vector.x, vector.y, vector.z ); + } else { - boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j + 1, vector.x, vector.y, vector.z ); + console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); - j += 2; + } - } + } - } + applyBoneTransform( index, vector ) { - geometry.getAttribute( 'position' ).needsUpdate = true; + const skeleton = this.skeleton; + const geometry = this.geometry; - Object3D.prototype.updateMatrixWorld.call( this, force ); + _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); + _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - }; + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); -}(); + vector.set( 0, 0, 0 ); -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + for ( let i = 0; i < 4; i ++ ) { -function PointLightHelper( light, sphereSize, color ) { + const weight = _skinWeight.getComponent( i ); - this.light = light; - this.light.updateMatrixWorld(); + if ( weight !== 0 ) { - this.color = color; + const boneIndex = _skinIndex.getComponent( i ); - var geometry = new SphereBufferGeometry( sphereSize, 4, 2 ); - var material = new MeshBasicMaterial( { wireframe: true, fog: false } ); + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - Mesh.call( this, geometry, material ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); - this.matrix = this.light.matrixWorld; - this.matrixAutoUpdate = false; + } - this.update(); + } + return vector.applyMatrix4( this.bindMatrixInverse ); - /* - var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); - var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); + } - this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); - this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); +} - var d = light.distance; +class Bone extends Object3D { - if ( d === 0.0 ) { + constructor() { - this.lightDistance.visible = false; + super(); - } else { + this.isBone = true; - this.lightDistance.scale.set( d, d, d ); + this.type = 'Bone'; } - this.add( this.lightDistance ); - */ - } -PointLightHelper.prototype = Object.create( Mesh.prototype ); -PointLightHelper.prototype.constructor = PointLightHelper; - -PointLightHelper.prototype.dispose = function () { +class DataTexture extends Texture { - this.geometry.dispose(); - this.material.dispose(); + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { -}; - -PointLightHelper.prototype.update = function () { + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); - if ( this.color !== undefined ) { + this.isDataTexture = true; - this.material.color.set( this.color ); - - } else { + this.image = { data: data, width: width, height: height }; - this.material.color.copy( this.light.color ); + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; } - /* - var d = this.light.distance; +} - if ( d === 0.0 ) { +const _offsetMatrix = /*@__PURE__*/ new Matrix4(); +const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); - this.lightDistance.visible = false; +class Skeleton { - } else { + constructor( bones = [], boneInverses = [] ) { - this.lightDistance.visible = true; - this.lightDistance.scale.set( d, d, d ); + this.uuid = generateUUID(); - } - */ + this.bones = bones.slice( 0 ); + this.boneInverses = boneInverses; + this.boneMatrices = null; -}; + this.boneTexture = null; -/** - * @author abelnation / http://github.com/abelnation - * @author Mugen87 / http://github.com/Mugen87 - * @author WestLangley / http://github.com/WestLangley - */ + this.init(); -function RectAreaLightHelper( light, color ) { + } - Object3D.call( this ); + init() { - this.light = light; - this.light.updateMatrixWorld(); + const bones = this.bones; + const boneInverses = this.boneInverses; - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + this.boneMatrices = new Float32Array( bones.length * 16 ); - this.color = color; + // calculate inverse bone matrices if necessary - var material = new LineBasicMaterial( { fog: false } ); + if ( boneInverses.length === 0 ) { - var geometry = new BufferGeometry(); + this.calculateInverses(); - geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) ); + } else { - this.line = new Line( geometry, material ); - this.add( this.line ); + // handle special case + if ( bones.length !== boneInverses.length ) { - this.update(); + console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); -} + this.boneInverses = []; -RectAreaLightHelper.prototype = Object.create( Object3D.prototype ); -RectAreaLightHelper.prototype.constructor = RectAreaLightHelper; + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { -RectAreaLightHelper.prototype.dispose = function () { + this.boneInverses.push( new Matrix4() ); - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); + } -}; + } -RectAreaLightHelper.prototype.update = function () { + } - // calculate new dimensions of the helper + } - var hx = this.light.width * 0.5; - var hy = this.light.height * 0.5; + calculateInverses() { - var position = this.line.geometry.attributes.position; - var array = position.array; + this.boneInverses.length = 0; - // update vertices + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0; - array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0; - array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0; - array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0; - array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0; + const inverse = new Matrix4(); - position.needsUpdate = true; + if ( this.bones[ i ] ) { - if ( this.color !== undefined ) { + inverse.copy( this.bones[ i ].matrixWorld ).invert(); - this.line.material.color.set( this.color ); + } - } else { + this.boneInverses.push( inverse ); - this.line.material.color.copy( this.light.color ); + } } -}; + pose() { -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + // recover the bind-time world matrices -function HemisphereLightHelper( light, size, color ) { + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - Object3D.call( this ); + const bone = this.bones[ i ]; - this.light = light; - this.light.updateMatrixWorld(); + if ( bone ) { - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); - this.color = color; + } - var geometry = new OctahedronBufferGeometry( size ); - geometry.rotateY( Math.PI * 0.5 ); + } - this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - if ( this.color === undefined ) { this.material.vertexColors = VertexColors; } + // compute the local matrices, positions, rotations and scales - var position = geometry.getAttribute( 'position' ); - var colors = new Float32Array( position.count * 3 ); + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); + const bone = this.bones[ i ]; - this.add( new Mesh( geometry, this.material ) ); + if ( bone ) { - this.update(); + if ( bone.parent && bone.parent.isBone ) { -} + bone.matrix.copy( bone.parent.matrixWorld ).invert(); + bone.matrix.multiply( bone.matrixWorld ); -HemisphereLightHelper.prototype = Object.create( Object3D.prototype ); -HemisphereLightHelper.prototype.constructor = HemisphereLightHelper; + } else { -HemisphereLightHelper.prototype.dispose = function () { + bone.matrix.copy( bone.matrixWorld ); - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); + } -}; + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); -HemisphereLightHelper.prototype.update = function () { + } - var vector = new Vector3(); + } - var color1 = new Color(); - var color2 = new Color(); + } - return function update() { + update() { - var mesh = this.children[ 0 ]; + const bones = this.bones; + const boneInverses = this.boneInverses; + const boneMatrices = this.boneMatrices; + const boneTexture = this.boneTexture; - if ( this.color !== undefined ) { + // flatten bone matrices to array - this.material.color.set( this.color ); + for ( let i = 0, il = bones.length; i < il; i ++ ) { - } else { + // compute the offset between the current and the original transform - var colors = mesh.geometry.getAttribute( 'color' ); + const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; - color1.copy( this.light.color ); - color2.copy( this.light.groundColor ); + _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); + _offsetMatrix.toArray( boneMatrices, i * 16 ); - for ( var i = 0, l = colors.count; i < l; i ++ ) { + } - var color = ( i < ( l / 2 ) ) ? color1 : color2; + if ( boneTexture !== null ) { - colors.setXYZ( i, color.r, color.g, color.b ); + boneTexture.needsUpdate = true; - } + } - colors.needsUpdate = true; + } - } + clone() { - mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); + return new Skeleton( this.bones, this.boneInverses ); - }; + } -}(); + computeBoneTexture() { -/** - * @author mrdoob / http://mrdoob.com/ - */ + // layout (1 matrix = 4 pixels) + // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) + // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) + // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) + // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) + // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) -function GridHelper( size, divisions, color1, color2 ) { + let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix + size = Math.ceil( size / 4 ) * 4; + size = Math.max( size, 4 ); - size = size || 10; - divisions = divisions || 10; - color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); - color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); + const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel + boneMatrices.set( this.boneMatrices ); // copy current values - var center = divisions / 2; - var step = size / divisions; - var halfSize = size / 2; + const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + boneTexture.needsUpdate = true; - var vertices = [], colors = []; + this.boneMatrices = boneMatrices; + this.boneTexture = boneTexture; - for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { + return this; - vertices.push( - halfSize, 0, k, halfSize, 0, k ); - vertices.push( k, 0, - halfSize, k, 0, halfSize ); + } - var color = i === center ? color1 : color2; + getBoneByName( name ) { - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - } + const bone = this.bones[ i ]; - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + if ( bone.name === name ) { - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); + return bone; - LineSegments.call( this, geometry, material ); + } -} + } -GridHelper.prototype = Object.create( LineSegments.prototype ); -GridHelper.prototype.constructor = GridHelper; + return undefined; -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - * @author Hectate / http://www.github.com/Hectate - */ + } -function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) { + dispose( ) { - radius = radius || 10; - radials = radials || 16; - circles = circles || 8; - divisions = divisions || 64; - color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); - color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); + if ( this.boneTexture !== null ) { - var vertices = []; - var colors = []; + this.boneTexture.dispose(); - var x, z; - var v, i, j, r, color; + this.boneTexture = null; - // create the radials + } - for ( i = 0; i <= radials; i ++ ) { + } - v = ( i / radials ) * ( Math.PI * 2 ); + fromJSON( json, bones ) { - x = Math.sin( v ) * radius; - z = Math.cos( v ) * radius; + this.uuid = json.uuid; - vertices.push( 0, 0, 0 ); - vertices.push( x, 0, z ); + for ( let i = 0, l = json.bones.length; i < l; i ++ ) { - color = ( i & 1 ) ? color1 : color2; + const uuid = json.bones[ i ]; + let bone = bones[ uuid ]; - colors.push( color.r, color.g, color.b ); - colors.push( color.r, color.g, color.b ); + if ( bone === undefined ) { - } + console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); + bone = new Bone(); - // create the circles + } - for ( i = 0; i <= circles; i ++ ) { + this.bones.push( bone ); + this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); - color = ( i & 1 ) ? color1 : color2; + } - r = radius - ( radius / circles * i ); + this.init(); - for ( j = 0; j < divisions; j ++ ) { + return this; - // first vertex + } - v = ( j / divisions ) * ( Math.PI * 2 ); + toJSON() { - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; + const data = { + metadata: { + version: 4.6, + type: 'Skeleton', + generator: 'Skeleton.toJSON' + }, + bones: [], + boneInverses: [] + }; - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); + data.uuid = this.uuid; - // second vertex + const bones = this.bones; + const boneInverses = this.boneInverses; - v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); + for ( let i = 0, l = bones.length; i < l; i ++ ) { - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; + const bone = bones[ i ]; + data.bones.push( bone.uuid ); - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); + const boneInverse = boneInverses[ i ]; + data.boneInverses.push( boneInverse.toArray() ); } + return data; + } - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); +} - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); +class LineBasicMaterial extends Material { - LineSegments.call( this, geometry, material ); + constructor( parameters ) { -} + super(); -PolarGridHelper.prototype = Object.create( LineSegments.prototype ); -PolarGridHelper.prototype.constructor = PolarGridHelper; + this.isLineBasicMaterial = true; -/** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + this.type = 'LineBasicMaterial'; -function FaceNormalsHelper( object, size, hex, linewidth ) { + this.color = new Color( 0xffffff ); - // FaceNormalsHelper only supports THREE.Geometry + this.map = null; - this.object = object; + this.linewidth = 1; + this.linecap = 'round'; + this.linejoin = 'round'; - this.size = ( size !== undefined ) ? size : 1; + this.fog = true; - var color = ( hex !== undefined ) ? hex : 0xffff00; + this.setValues( parameters ); - var width = ( linewidth !== undefined ) ? linewidth : 1; + } - // - var nNormals = 0; + copy( source ) { - var objGeometry = this.object.geometry; + super.copy( source ); - if ( objGeometry && objGeometry.isGeometry ) { + this.color.copy( source.color ); - nNormals = objGeometry.faces.length; + this.map = source.map; - } else { + this.linewidth = source.linewidth; + this.linecap = source.linecap; + this.linejoin = source.linejoin; - console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' ); + this.fog = source.fog; - } + return this; - // + } - var geometry = new BufferGeometry(); +} - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); +const _vStart = /*@__PURE__*/ new Vector3(); +const _vEnd = /*@__PURE__*/ new Vector3(); - geometry.addAttribute( 'position', positions ); +const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _ray$1 = /*@__PURE__*/ new Ray(); +const _sphere$1 = /*@__PURE__*/ new Sphere(); - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); +const _intersectPointOnRay = /*@__PURE__*/ new Vector3(); +const _intersectPointOnSegment = /*@__PURE__*/ new Vector3(); - // +class Line extends Object3D { - this.matrixAutoUpdate = false; - this.update(); + constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { -} + super(); -FaceNormalsHelper.prototype = Object.create( LineSegments.prototype ); -FaceNormalsHelper.prototype.constructor = FaceNormalsHelper; + this.isLine = true; -FaceNormalsHelper.prototype.update = ( function () { + this.type = 'Line'; - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); + this.geometry = geometry; + this.material = material; - return function update() { + this.updateMorphTargets(); - this.object.updateMatrixWorld( true ); + } - normalMatrix.getNormalMatrix( this.object.matrixWorld ); + copy( source, recursive ) { - var matrixWorld = this.object.matrixWorld; + super.copy( source, recursive ); - var position = this.geometry.attributes.position; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - // + return this; - var objGeometry = this.object.geometry; + } - var vertices = objGeometry.vertices; + computeLineDistances() { - var faces = objGeometry.faces; + const geometry = this.geometry; - var idx = 0; + // we assume non-indexed geometry - for ( var i = 0, l = faces.length; i < l; i ++ ) { + if ( geometry.index === null ) { - var face = faces[ i ]; + const positionAttribute = geometry.attributes.position; + const lineDistances = [ 0 ]; - var normal = face.normal; + for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { - v1.copy( vertices[ face.a ] ) - .add( vertices[ face.b ] ) - .add( vertices[ face.c ] ) - .divideScalar( 3 ) - .applyMatrix4( matrixWorld ); + _vStart.fromBufferAttribute( positionAttribute, i - 1 ); + _vEnd.fromBufferAttribute( positionAttribute, i ); - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); + lineDistances[ i ] = lineDistances[ i - 1 ]; + lineDistances[ i ] += _vStart.distanceTo( _vEnd ); - position.setXYZ( idx, v1.x, v1.y, v1.z ); + } - idx = idx + 1; + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); - position.setXYZ( idx, v2.x, v2.y, v2.z ); + } else { - idx = idx + 1; + console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); } - position.needsUpdate = true; + return this; - }; + } -}() ); + raycast( raycaster, intersects ) { -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Line.threshold; + const drawRange = geometry.drawRange; -function DirectionalLightHelper( light, size, color ) { + // Checking boundingSphere distance to ray - Object3D.call( this ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - this.light = light; - this.light.updateMatrixWorld(); + _sphere$1.copy( geometry.boundingSphere ); + _sphere$1.applyMatrix4( matrixWorld ); + _sphere$1.radius += threshold; - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; - this.color = color; + // - if ( size === undefined ) { size = 1; } + _inverseMatrix$1.copy( matrixWorld ).invert(); + _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( [ - - size, size, 0, - size, size, 0, - size, - size, 0, - - size, - size, 0, - - size, size, 0 - ], 3 ) ); + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; - var material = new LineBasicMaterial( { fog: false } ); + const step = this.isLineSegments ? 2 : 1; - this.lightPlane = new Line( geometry, material ); - this.add( this.lightPlane ); + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; - geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); + if ( index !== null ) { - this.targetLine = new Line( geometry, material ); - this.add( this.targetLine ); + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - this.update(); + for ( let i = start, l = end - 1; i < l; i += step ) { -} + const a = index.getX( i ); + const b = index.getX( i + 1 ); -DirectionalLightHelper.prototype = Object.create( Object3D.prototype ); -DirectionalLightHelper.prototype.constructor = DirectionalLightHelper; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); -DirectionalLightHelper.prototype.dispose = function () { + if ( intersect ) { - this.lightPlane.geometry.dispose(); - this.lightPlane.material.dispose(); - this.targetLine.geometry.dispose(); - this.targetLine.material.dispose(); + intersects.push( intersect ); -}; + } + + } -DirectionalLightHelper.prototype.update = function () { + if ( this.isLineLoop ) { - var v1 = new Vector3(); - var v2 = new Vector3(); - var v3 = new Vector3(); + const a = index.getX( end - 1 ); + const b = index.getX( start ); - return function update() { + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); - v1.setFromMatrixPosition( this.light.matrixWorld ); - v2.setFromMatrixPosition( this.light.target.matrixWorld ); - v3.subVectors( v2, v1 ); + if ( intersect ) { - this.lightPlane.lookAt( v3 ); + intersects.push( intersect ); - if ( this.color !== undefined ) { + } - 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 ); - - } + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); - this.targetLine.lookAt( v3 ); - this.targetLine.scale.z = v3.length(); + for ( let i = start, l = end - 1; i < l; i += step ) { - }; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1 ); -}(); + if ( intersect ) { -/** - * @author alteredq / http://alteredqualia.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - shows frustum, line of sight and up of the camera - * - suitable for fast updates - * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html - */ + intersects.push( intersect ); -function CameraHelper( camera ) { + } - var geometry = new BufferGeometry(); - var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } ); + } - var vertices = []; - var colors = []; + if ( this.isLineLoop ) { - var pointMap = {}; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start ); - // colors + if ( intersect ) { - var colorFrustum = new Color( 0xffaa00 ); - var colorCone = new Color( 0xff0000 ); - var colorUp = new Color( 0x00aaff ); - var colorTarget = new Color( 0xffffff ); - var colorCross = new Color( 0x333333 ); + intersects.push( intersect ); - // near + } - addLine( 'n1', 'n2', colorFrustum ); - addLine( 'n2', 'n4', colorFrustum ); - addLine( 'n4', 'n3', colorFrustum ); - addLine( 'n3', 'n1', colorFrustum ); + } - // far + } - addLine( 'f1', 'f2', colorFrustum ); - addLine( 'f2', 'f4', colorFrustum ); - addLine( 'f4', 'f3', colorFrustum ); - addLine( 'f3', 'f1', colorFrustum ); + } - // sides + updateMorphTargets() { - addLine( 'n1', 'f1', colorFrustum ); - addLine( 'n2', 'f2', colorFrustum ); - addLine( 'n3', 'f3', colorFrustum ); - addLine( 'n4', 'f4', colorFrustum ); + const geometry = this.geometry; - // cone + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - addLine( 'p', 'n1', colorCone ); - addLine( 'p', 'n2', colorCone ); - addLine( 'p', 'n3', colorCone ); - addLine( 'p', 'n4', colorCone ); + if ( keys.length > 0 ) { - // up + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - addLine( 'u1', 'u2', colorUp ); - addLine( 'u2', 'u3', colorUp ); - addLine( 'u3', 'u1', colorUp ); + if ( morphAttribute !== undefined ) { - // target + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - addLine( 'c', 't', colorTarget ); - addLine( 'p', 'c', colorCross ); + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - // cross + const name = morphAttribute[ m ].name || String( m ); - addLine( 'cn1', 'cn2', colorCross ); - addLine( 'cn3', 'cn4', colorCross ); + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - addLine( 'cf1', 'cf2', colorCross ); - addLine( 'cf3', 'cf4', colorCross ); + } - function addLine( a, b, color ) { + } - addPoint( a, color ); - addPoint( b, color ); + } } - function addPoint( id, color ) { - - vertices.push( 0, 0, 0 ); - colors.push( color.r, color.g, color.b ); +} - if ( pointMap[ id ] === undefined ) { +function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { - pointMap[ id ] = []; + const positionAttribute = object.geometry.attributes.position; - } + _vStart.fromBufferAttribute( positionAttribute, a ); + _vEnd.fromBufferAttribute( positionAttribute, b ); - pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); + const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment ); - } + if ( distSq > thresholdSq ) return; - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + _intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation - LineSegments.call( this, geometry, material ); + const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay ); - this.camera = camera; - if ( this.camera.updateProjectionMatrix ) { this.camera.updateProjectionMatrix(); } + if ( distance < raycaster.near || distance > raycaster.far ) return; - this.matrix = camera.matrixWorld; - this.matrixAutoUpdate = false; + return { - this.pointMap = pointMap; + distance: distance, + // What do we want? intersection point on the ray or on the segment?? + // point: raycaster.ray.at( distance ), + point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ), + index: a, + face: null, + faceIndex: null, + object: object - this.update(); + }; } -CameraHelper.prototype = Object.create( LineSegments.prototype ); -CameraHelper.prototype.constructor = CameraHelper; +const _start = /*@__PURE__*/ new Vector3(); +const _end = /*@__PURE__*/ new Vector3(); -CameraHelper.prototype.update = function () { +class LineSegments extends Line { - var geometry, pointMap; + constructor( geometry, material ) { - var vector = new Vector3(); - var camera = new Camera(); + super( geometry, material ); - function setPoint( point, x, y, z ) { + this.isLineSegments = true; - vector.set( x, y, z ).unproject( camera ); + this.type = 'LineSegments'; - var points = pointMap[ point ]; + } - if ( points !== undefined ) { + computeLineDistances() { - var position = geometry.getAttribute( 'position' ); + const geometry = this.geometry; - for ( var i = 0, l = points.length; i < l; i ++ ) { + // we assume non-indexed geometry - position.setXYZ( points[ i ], vector.x, vector.y, vector.z ); + 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 ); - return function update() { + lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; + lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); - geometry = this.geometry; - pointMap = this.pointMap; + } - var w = 1, h = 1; + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); - // we need just camera projection matrix - // world matrix must be identity + } else { - camera.projectionMatrix.copy( this.camera.projectionMatrix ); + console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); - // center / target + } - setPoint( 'c', 0, 0, - 1 ); - setPoint( 't', 0, 0, 1 ); + return this; - // near + } - setPoint( 'n1', - w, - h, - 1 ); - setPoint( 'n2', w, - h, - 1 ); - setPoint( 'n3', - w, h, - 1 ); - setPoint( 'n4', w, h, - 1 ); +} - // far +class PointsMaterial extends Material { - setPoint( 'f1', - w, - h, 1 ); - setPoint( 'f2', w, - h, 1 ); - setPoint( 'f3', - w, h, 1 ); - setPoint( 'f4', w, h, 1 ); + constructor( parameters ) { - // up + super(); - setPoint( 'u1', w * 0.7, h * 1.1, - 1 ); - setPoint( 'u2', - w * 0.7, h * 1.1, - 1 ); - setPoint( 'u3', 0, h * 2, - 1 ); + this.isPointsMaterial = true; - // cross + this.type = 'PointsMaterial'; - setPoint( 'cf1', - w, 0, 1 ); - setPoint( 'cf2', w, 0, 1 ); - setPoint( 'cf3', 0, - h, 1 ); - setPoint( 'cf4', 0, h, 1 ); + this.color = new Color( 0xffffff ); - setPoint( 'cn1', - w, 0, - 1 ); - setPoint( 'cn2', w, 0, - 1 ); - setPoint( 'cn3', 0, - h, - 1 ); - setPoint( 'cn4', 0, h, - 1 ); + this.map = null; - geometry.getAttribute( 'position' ).needsUpdate = true; + this.alphaMap = null; - }; + this.size = 1; + this.sizeAttenuation = true; -}(); + this.fog = true; -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - */ + this.setValues( parameters ); + + } + + copy( source ) { -function BoxHelper( object, color ) { + super.copy( source ); - this.object = object; + this.color.copy( source.color ); - if ( color === undefined ) { color = 0xffff00; } + this.map = source.map; - var 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 ] ); - var positions = new Float32Array( 8 * 3 ); + this.alphaMap = source.alphaMap; - var geometry = new BufferGeometry(); - geometry.setIndex( new BufferAttribute( indices, 1 ) ); - geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) ); + this.size = source.size; + this.sizeAttenuation = source.sizeAttenuation; - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + this.fog = source.fog; - this.matrixAutoUpdate = false; + return this; - this.update(); + } } -BoxHelper.prototype = Object.create( LineSegments.prototype ); -BoxHelper.prototype.constructor = BoxHelper; +const _inverseMatrix = /*@__PURE__*/ new Matrix4(); +const _ray = /*@__PURE__*/ new Ray(); +const _sphere = /*@__PURE__*/ new Sphere(); +const _position$2 = /*@__PURE__*/ new Vector3(); -BoxHelper.prototype.update = ( function () { +class Points$1 extends Object3D { - var box = new Box3(); + constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { - return function update( object ) { + super(); - if ( object !== undefined ) { + this.isPoints = true; - console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); + this.type = 'Points'; - } + this.geometry = geometry; + this.material = material; - if ( this.object !== undefined ) { + this.updateMorphTargets(); - box.setFromObject( this.object ); + } - } + copy( source, recursive ) { - if ( box.isEmpty() ) { return; } + super.copy( source, recursive ); - var min = box.min; - var max = box.max; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - /* - 5____4 - 1/___0/| - | 6__|_7 - 2/___3/ + return this; - 0: max.x, max.y, max.z - 1: min.x, max.y, max.z - 2: min.x, min.y, max.z - 3: max.x, min.y, max.z - 4: max.x, max.y, min.z - 5: min.x, max.y, min.z - 6: min.x, min.y, min.z - 7: max.x, min.y, min.z - */ + } - var position = this.geometry.attributes.position; - var array = position.array; + raycast( raycaster, intersects ) { - array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; - array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; - array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; - array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; - array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; - array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; - array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; - array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Points.threshold; + const drawRange = geometry.drawRange; - position.needsUpdate = true; + // Checking boundingSphere distance to ray - this.geometry.computeBoundingSphere(); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - }; + _sphere.copy( geometry.boundingSphere ); + _sphere.applyMatrix4( matrixWorld ); + _sphere.radius += threshold; -} )(); + if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; -BoxHelper.prototype.setFromObject = function ( object ) { + // - this.object = object; - this.update(); + _inverseMatrix.copy( matrixWorld ).invert(); + _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); - return this; + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; -}; + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; -/** - * @author WestLangley / http://github.com/WestLangley - */ + if ( index !== null ) { -function Box3Helper( box, hex ) { + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - this.type = 'Box3Helper'; + for ( let i = start, il = end; i < il; i ++ ) { - this.box = box; + const a = index.getX( i ); - var color = ( hex !== undefined ) ? hex : 0xffff00; + _position$2.fromBufferAttribute( positionAttribute, a ); - var 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 ] ); + testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); - var 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 ]; + } - var geometry = new BufferGeometry(); + } else { - geometry.setIndex( new BufferAttribute( indices, 1 ) ); + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + for ( let i = start, l = end; i < l; i ++ ) { - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + _position$2.fromBufferAttribute( positionAttribute, i ); - this.geometry.computeBoundingSphere(); + testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); -} + } -Box3Helper.prototype = Object.create( LineSegments.prototype ); -Box3Helper.prototype.constructor = Box3Helper; + } -Box3Helper.prototype.updateMatrixWorld = function ( force ) { + } - var box = this.box; + updateMorphTargets() { - if ( box.isEmpty() ) { return; } + const geometry = this.geometry; - box.getCenter( this.position ); + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - box.getSize( this.scale ); + if ( keys.length > 0 ) { - this.scale.multiplyScalar( 0.5 ); + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - Object3D.prototype.updateMatrixWorld.call( this, force ); + if ( morphAttribute !== undefined ) { -}; + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; -/** - * @author WestLangley / http://github.com/WestLangley - */ + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { -function PlaneHelper( plane, size, hex ) { + const name = morphAttribute[ m ].name || String( m ); - this.type = 'PlaneHelper'; + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - this.plane = plane; + } - this.size = ( size === undefined ) ? 1 : size; + } - var color = ( hex !== undefined ) ? hex : 0xffff00; + } - var 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, 0, 0, 1, 0, 0, 0 ]; + } - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - geometry.computeBoundingSphere(); +} - Line.call( this, geometry, new LineBasicMaterial( { color: color } ) ); +function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { - // + const rayPointDistanceSq = _ray.distanceSqToPoint( point ); - var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ]; + if ( rayPointDistanceSq < localThresholdSq ) { - var geometry2 = new BufferGeometry(); - geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); - geometry2.computeBoundingSphere(); + const intersectPoint = new Vector3(); - this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) ); + _ray.closestPointToPoint( point, intersectPoint ); + intersectPoint.applyMatrix4( matrixWorld ); -} + const distance = raycaster.ray.origin.distanceTo( intersectPoint ); -PlaneHelper.prototype = Object.create( Line.prototype ); -PlaneHelper.prototype.constructor = PlaneHelper; + if ( distance < raycaster.near || distance > raycaster.far ) return; -PlaneHelper.prototype.updateMatrixWorld = function ( force ) { + intersects.push( { - var scale = - this.plane.constant; + distance: distance, + distanceToRay: Math.sqrt( rayPointDistanceSq ), + point: intersectPoint, + index: index, + face: null, + object: object - if ( Math.abs( scale ) < 1e-8 ) { scale = 1e-8; } // sign does not matter + } ); - this.scale.set( 0.5 * this.size, 0.5 * this.size, scale ); + } - this.lookAt( this.plane.normal ); +} - Object3D.prototype.updateMatrixWorld.call( this, force ); +class CylinderGeometry extends BufferGeometry { -}; + constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { -/** - * @author WestLangley / http://github.com/WestLangley - * @author zz85 / http://github.com/zz85 - * @author bhouston / http://clara.io - * - * Creates an arrow for visualizing directions - * - * Parameters: - * dir - Vector3 - * origin - Vector3 - * length - Number - * color - color in hex value - * headLength - Number - * headWidth - Number - */ + super(); -var lineGeometry; -var coneGeometry; + this.type = 'CylinderGeometry'; -function ArrowHelper( dir, origin, length, color, headLength, headWidth ) { + this.parameters = { + radiusTop: radiusTop, + radiusBottom: radiusBottom, + height: height, + radialSegments: radialSegments, + heightSegments: heightSegments, + openEnded: openEnded, + thetaStart: thetaStart, + thetaLength: thetaLength + }; - // dir is assumed to be normalized + const scope = this; - Object3D.call( this ); + radialSegments = Math.floor( radialSegments ); + heightSegments = Math.floor( heightSegments ); - if ( color === undefined ) { color = 0xffff00; } - if ( length === undefined ) { length = 1; } - if ( headLength === undefined ) { headLength = 0.2 * length; } - if ( headWidth === undefined ) { headWidth = 0.2 * headLength; } + // buffers - if ( lineGeometry === undefined ) { + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - lineGeometry = new BufferGeometry(); - lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); + // helper variables - coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 ); - coneGeometry.translate( 0, - 0.5, 0 ); + let index = 0; + const indexArray = []; + const halfHeight = height / 2; + let groupStart = 0; - } + // generate geometry - this.position.copy( origin ); + generateTorso(); - this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) ); - this.line.matrixAutoUpdate = false; - this.add( this.line ); + if ( openEnded === false ) { - this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) ); - this.cone.matrixAutoUpdate = false; - this.add( this.cone ); + if ( radiusTop > 0 ) generateCap( true ); + if ( radiusBottom > 0 ) generateCap( false ); - this.setDirection( dir ); - this.setLength( length, headLength, headWidth ); + } -} + // build geometry -ArrowHelper.prototype = Object.create( Object3D.prototype ); -ArrowHelper.prototype.constructor = ArrowHelper; + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); -ArrowHelper.prototype.setDirection = ( function () { + function generateTorso() { - var axis = new Vector3(); - var radians; + const normal = new Vector3(); + const vertex = new Vector3(); - return function setDirection( dir ) { + let groupCount = 0; - // dir is assumed to be normalized + // this will be used to calculate the normal + const slope = ( radiusBottom - radiusTop ) / height; - if ( dir.y > 0.99999 ) { + // generate vertices, normals and uvs - this.quaternion.set( 0, 0, 0, 1 ); + for ( let y = 0; y <= heightSegments; y ++ ) { - } else if ( dir.y < - 0.99999 ) { + const indexRow = []; - this.quaternion.set( 1, 0, 0, 0 ); + const v = y / heightSegments; - } else { + // calculate the radius of the current row - axis.set( dir.z, 0, - dir.x ).normalize(); + const radius = v * ( radiusBottom - radiusTop ) + radiusTop; - radians = Math.acos( dir.y ); + for ( let x = 0; x <= radialSegments; x ++ ) { - this.quaternion.setFromAxisAngle( axis, radians ); + const u = x / radialSegments; - } + const theta = u * thetaLength + thetaStart; - }; + const sinTheta = Math.sin( theta ); + const cosTheta = Math.cos( theta ); -}() ); + // vertex -ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) { + vertex.x = radius * sinTheta; + vertex.y = - v * height + halfHeight; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); - if ( headLength === undefined ) { headLength = 0.2 * length; } - if ( headWidth === undefined ) { headWidth = 0.2 * headLength; } + // normal - this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 ); - this.line.updateMatrix(); + normal.set( sinTheta, slope, cosTheta ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - this.cone.scale.set( headWidth, headLength, headWidth ); - this.cone.position.y = length; - this.cone.updateMatrix(); + // uv -}; + uvs.push( u, 1 - v ); -ArrowHelper.prototype.setColor = function ( color ) { + // save index of vertex in respective row - this.line.material.color.copy( color ); - this.cone.material.color.copy( color ); + indexRow.push( index ++ ); -}; + } -/** - * @author sroucheray / http://sroucheray.org/ - * @author mrdoob / http://mrdoob.com/ - */ + // now save vertices of the row in our index array -function AxesHelper( size ) { + indexArray.push( indexRow ); - size = size || 1; + } - var vertices = [ - 0, 0, 0, size, 0, 0, - 0, 0, 0, 0, size, 0, - 0, 0, 0, 0, 0, size - ]; + // generate indices - var colors = [ - 1, 0, 0, 1, 0.6, 0, - 0, 1, 0, 0.6, 1, 0, - 0, 0, 1, 0, 0.6, 1 - ]; + for ( let x = 0; x < radialSegments; x ++ ) { - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + for ( let y = 0; y < heightSegments; y ++ ) { - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); + // we use the index array to access the correct indices - LineSegments.call( this, geometry, material ); + const a = indexArray[ y ][ x ]; + const b = indexArray[ y + 1 ][ x ]; + const c = indexArray[ y + 1 ][ x + 1 ]; + const d = indexArray[ y ][ x + 1 ]; -} + // faces -AxesHelper.prototype = Object.create( LineSegments.prototype ); -AxesHelper.prototype.constructor = AxesHelper; + indices.push( a, b, d ); + indices.push( b, c, d ); -/** - * @author alteredq / http://alteredqualia.com/ - */ + // update group counter -var SceneUtils = { + groupCount += 6; - createMultiMaterialObject: function ( geometry, materials ) { + } - var group = new Group(); + } - for ( var i = 0, l = materials.length; i < l; i ++ ) { + // add a group to the geometry. this will ensure multi material support - group.add( new Mesh( geometry, materials[ i ] ) ); + scope.addGroup( groupStart, groupCount, 0 ); - } + // calculate new start value for groups - return group; + groupStart += groupCount; - }, + } - detach: function ( child, parent, scene ) { + function generateCap( top ) { - child.applyMatrix( parent.matrixWorld ); - parent.remove( child ); - scene.add( child ); + // save the index of the first center vertex + const centerIndexStart = index; - }, + const uv = new Vector2(); + const vertex = new Vector3(); - attach: function ( child, scene, parent ) { + let groupCount = 0; - child.applyMatrix( new Matrix4().getInverse( parent.matrixWorld ) ); + const radius = ( top === true ) ? radiusTop : radiusBottom; + const sign = ( top === true ) ? 1 : - 1; - scene.remove( child ); - parent.add( child ); + // first we generate the center vertex data of the cap. + // because the geometry needs one set of uvs per face, + // we must generate a center vertex per face/segment - } + for ( let x = 1; x <= radialSegments; x ++ ) { -}; + // vertex -/** - * @author mrdoob / http://mrdoob.com/ - */ + vertices.push( 0, halfHeight * sign, 0 ); -function Face4( a, b, c, d, normal, color, materialIndex ) { + // normal - console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' ); - return new Face3( a, b, c, normal, color, materialIndex ); + normals.push( 0, sign, 0 ); -} + // uv -var LineStrip = 0; + uvs.push( 0.5, 0.5 ); -var LinePieces = 1; + // increase index -function MeshFaceMaterial( materials ) { + index ++; - console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' ); - return materials; + } -} + // save the index of the last center vertex + const centerIndexEnd = index; -function MultiMaterial( materials ) { + // now we generate the surrounding vertices, normals and uvs - if ( materials === undefined ) { materials = []; } + for ( let x = 0; x <= radialSegments; x ++ ) { - console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' ); - materials.isMultiMaterial = true; - materials.materials = materials; - materials.clone = function () { + const u = x / radialSegments; + const theta = u * thetaLength + thetaStart; - return materials.slice(); + const cosTheta = Math.cos( theta ); + const sinTheta = Math.sin( theta ); - }; - return materials; + // vertex -} + vertex.x = radius * sinTheta; + vertex.y = halfHeight * sign; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); -function PointCloud( geometry, material ) { + // normal - console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' ); - return new Points$1( geometry, material ); + normals.push( 0, sign, 0 ); -} + // uv -function Particle( material ) { + uv.x = ( cosTheta * 0.5 ) + 0.5; + uv.y = ( sinTheta * 0.5 * sign ) + 0.5; + uvs.push( uv.x, uv.y ); - console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' ); - return new Sprite( material ); + // increase index -} + index ++; -function ParticleSystem( geometry, material ) { + } - console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' ); - return new Points$1( geometry, material ); + // generate indices -} + for ( let x = 0; x < radialSegments; x ++ ) { -function PointCloudMaterial( parameters ) { + const c = centerIndexStart + x; + const i = centerIndexEnd + x; - console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); + if ( top === true ) { -} + // face top -function ParticleBasicMaterial( parameters ) { + indices.push( i, i + 1, c ); - console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); + } else { -} + // face bottom -function ParticleSystemMaterial( parameters ) { + indices.push( i + 1, i, c ); - console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); + } -} + groupCount += 3; -function Vertex( x, y, z ) { + } - console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' ); - return new Vector3( x, y, z ); + // add a group to the geometry. this will ensure multi material support -} + scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); -// + // calculate new start value for groups -function DynamicBufferAttribute( array, itemSize ) { + groupStart += groupCount; - console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' ); - return new BufferAttribute( array, itemSize ).setDynamic( true ); + } -} + } -function Int8Attribute( array, itemSize ) { + copy( source ) { - console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' ); - return new Int8BufferAttribute( array, itemSize ); + super.copy( source ); -} + this.parameters = Object.assign( {}, source.parameters ); -function Uint8Attribute( array, itemSize ) { + return this; - console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' ); - return new Uint8BufferAttribute( array, itemSize ); + } -} + static fromJSON( data ) { -function Uint8ClampedAttribute( array, itemSize ) { + return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); - console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' ); - return new Uint8ClampedBufferAttribute( array, itemSize ); + } } -function Int16Attribute( array, itemSize ) { +class SphereGeometry extends BufferGeometry { - console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' ); - return new Int16BufferAttribute( array, itemSize ); + constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { -} + super(); -function Uint16Attribute( array, itemSize ) { + this.type = 'SphereGeometry'; - console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' ); - return new Uint16BufferAttribute( array, itemSize ); + this.parameters = { + radius: radius, + widthSegments: widthSegments, + heightSegments: heightSegments, + phiStart: phiStart, + phiLength: phiLength, + thetaStart: thetaStart, + thetaLength: thetaLength + }; -} + widthSegments = Math.max( 3, Math.floor( widthSegments ) ); + heightSegments = Math.max( 2, Math.floor( heightSegments ) ); -function Int32Attribute( array, itemSize ) { + const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); - console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' ); - return new Int32BufferAttribute( array, itemSize ); + let index = 0; + const grid = []; -} + const vertex = new Vector3(); + const normal = new Vector3(); -function Uint32Attribute( array, itemSize ) { + // buffers - console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' ); - return new Uint32BufferAttribute( array, itemSize ); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; -} + // generate vertices, normals and uvs -function Float32Attribute( array, itemSize ) { + for ( let iy = 0; iy <= heightSegments; iy ++ ) { - console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' ); - return new Float32BufferAttribute( array, itemSize ); + const verticesRow = []; -} + const v = iy / heightSegments; -function Float64Attribute( array, itemSize ) { + // special case for the poles - console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' ); - return new Float64BufferAttribute( array, itemSize ); + let uOffset = 0; -} + if ( iy === 0 && thetaStart === 0 ) { -// + uOffset = 0.5 / widthSegments; -Curve.create = function ( construct, getPoint ) { + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { - console.log( 'THREE.Curve.create() has been deprecated' ); + uOffset = - 0.5 / widthSegments; - construct.prototype = Object.create( Curve.prototype ); - construct.prototype.constructor = construct; - construct.prototype.getPoint = getPoint; + } - return construct; + for ( let ix = 0; ix <= widthSegments; ix ++ ) { -}; + const u = ix / widthSegments; -// + // vertex -Object.assign( CurvePath.prototype, { + vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); + vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); + vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - createPointsGeometry: function ( divisions ) { + vertices.push( vertex.x, vertex.y, vertex.z ); - console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); + // normal - // generate geometry from path points (for Line or Points objects) + normal.copy( vertex ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - var pts = this.getPoints( divisions ); - return this.createGeometry( pts ); + // uv - }, + uvs.push( u + uOffset, 1 - v ); - createSpacedPointsGeometry: function ( divisions ) { + verticesRow.push( index ++ ); - console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); + } - // generate geometry from equidistant sampling along the path + grid.push( verticesRow ); - var pts = this.getSpacedPoints( divisions ); - return this.createGeometry( pts ); + } - }, + // indices - createGeometry: function ( points ) { + for ( let iy = 0; iy < heightSegments; iy ++ ) { - console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); + for ( let ix = 0; ix < widthSegments; ix ++ ) { - var geometry = new Geometry(); + const a = grid[ iy ][ ix + 1 ]; + const b = grid[ iy ][ ix ]; + const c = grid[ iy + 1 ][ ix ]; + const d = grid[ iy + 1 ][ ix + 1 ]; - for ( var i = 0, l = points.length; i < l; i ++ ) { + if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); + if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); - var point = points[ i ]; - geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); + } } - return geometry; + // build geometry - } + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); -} ); + } -// + copy( source ) { -Object.assign( Path$1.prototype, { + super.copy( source ); - fromPoints: function ( points ) { + this.parameters = Object.assign( {}, source.parameters ); - console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' ); - this.setFromPoints( points ); + return this; } -} ); + static fromJSON( data ) { -// - -function ClosedSplineCurve3( points ) { + return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); - console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' ); - - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; - this.closed = true; + } } -ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype ); +class MeshPhongMaterial extends Material { -// + constructor( parameters ) { -function SplineCurve3( points ) { + super(); - console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' ); + this.isMeshPhongMaterial = true; - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; + this.type = 'MeshPhongMaterial'; -} + this.color = new Color( 0xffffff ); // diffuse + this.specular = new Color( 0x111111 ); + this.shininess = 30; -SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype ); + this.map = null; -// + this.lightMap = null; + this.lightMapIntensity = 1.0; -function Spline( points ) { + this.aoMap = null; + this.aoMapIntensity = 1.0; - console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' ); + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; + this.bumpMap = null; + this.bumpScale = 1; -} + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); -Spline.prototype = Object.create( CatmullRomCurve3.prototype ); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; -Object.assign( Spline.prototype, { + this.specularMap = null; - initFromArray: function ( /* a */ ) { + this.alphaMap = null; - console.error( 'THREE.Spline: .initFromArray() has been removed.' ); + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - }, - getControlPointsArray: function ( /* optionalTarget */ ) { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' ); + this.flatShading = false; - }, - reparametrizeByArcLength: function ( /* samplingCoef */ ) { + this.fog = true; - console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' ); + this.setValues( parameters ); } -} ); - -// + copy( source ) { -function AxisHelper( size ) { + super.copy( source ); - console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' ); - return new AxesHelper( size ); + this.color.copy( source.color ); + this.specular.copy( source.specular ); + this.shininess = source.shininess; -} + this.map = source.map; -function BoundingBoxHelper( object, color ) { + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' ); - return new BoxHelper( object, color ); + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; -} + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; -function EdgesHelper( object, hex ) { + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' ); - return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) ); + 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; -GridHelper.prototype.setColors = function () { + this.specularMap = source.specularMap; - console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' ); + this.alphaMap = source.alphaMap; -}; + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; -SkeletonHelper.prototype.update = function () { + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' ); + this.flatShading = source.flatShading; -}; + this.fog = source.fog; -function WireframeHelper( object, hex ) { + return this; - console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' ); - return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) ); + } } -// +class MeshLambertMaterial extends Material { -Object.assign( Loader.prototype, { + constructor( parameters ) { - extractUrlBase: function ( url ) { + super(); - console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' ); - return LoaderUtils.extractUrlBase( url ); + this.isMeshLambertMaterial = true; - } + this.type = 'MeshLambertMaterial'; -} ); + this.color = new Color( 0xffffff ); // diffuse -function XHRLoader( manager ) { + this.map = null; - console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' ); - return new FileLoader( manager ); + this.lightMap = null; + this.lightMapIntensity = 1.0; -} + this.aoMap = null; + this.aoMapIntensity = 1.0; -function BinaryTextureLoader( manager ) { + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' ); - return new DataTextureLoader( manager ); + this.bumpMap = null; + this.bumpScale = 1; -} + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); -// + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; -Object.assign( Box2.prototype, { + this.specularMap = null; - center: function ( optionalTarget ) { + this.alphaMap = null; - console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - }, - empty: function () { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' ); - return this.isEmpty(); + this.flatShading = false; - }, - isIntersectionBox: function ( box ) { + this.fog = true; - console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); + this.setValues( parameters ); - }, - size: function ( optionalTarget ) { + } - console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' ); - return this.getSize( optionalTarget ); + copy( source ) { - } -} ); + super.copy( source ); -Object.assign( Box3.prototype, { + this.color.copy( source.color ); - center: function ( optionalTarget ) { + this.map = source.map; - console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - }, - empty: function () { + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' ); - return this.isEmpty(); + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; - }, - isIntersectionBox: function ( box ) { + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); - }, - isIntersectionSphere: function ( sphere ) { + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); - return this.intersectsSphere( sphere ); + this.specularMap = source.specularMap; - }, - size: function ( optionalTarget ) { + this.alphaMap = source.alphaMap; - console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' ); - return this.getSize( optionalTarget ); + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + 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; -Line3.prototype.center = function ( optionalTarget ) { + this.flatShading = source.flatShading; - console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); + this.fog = source.fog; -}; + return this; -Object.assign( _Math, { + } - random16: function () { +} - console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' ); - return Math.random(); +// converts an array to a specific type +function convertArray( array, type, forceClone ) { - }, + if ( ! array || // let 'undefined' and 'null' pass + ! forceClone && array.constructor === type ) return array; - nearestPowerOfTwo: function ( value ) { + if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { - console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' ); - return _Math.floorPowerOfTwo( value ); + return new type( array ); // create typed array - }, + } - nextPowerOfTwo: function ( value ) { + return Array.prototype.slice.call( array ); // create Array - console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' ); - return _Math.ceilPowerOfTwo( value ); +} - } +function isTypedArray( object ) { -} ); + return ArrayBuffer.isView( object ) && + ! ( object instanceof DataView ); -Object.assign( Matrix3.prototype, { +} - flattenToArrayOffset: function ( array, offset ) { +// returns an array by which times and values can be sorted +function getKeyframeOrder( times ) { - console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); - return this.toArray( array, offset ); + function compareTime( i, j ) { - }, - multiplyVector3: function ( vector ) { + return times[ i ] - times[ j ]; - console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' ); - return vector.applyMatrix3( this ); + } - }, - multiplyVector3Array: function ( /* a */ ) { + const n = times.length; + const result = new Array( n ); + for ( let i = 0; i !== n; ++ i ) result[ i ] = i; - console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' ); + result.sort( compareTime ); - }, - applyToBuffer: function ( buffer /*, offset, length */ ) { + return result; - console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); - return this.applyToBufferAttribute( buffer ); +} - }, - applyToVector3Array: function ( /* array, offset, length */ ) { +// uses the array previously returned by 'getKeyframeOrder' to sort data +function sortedArray( values, stride, order ) { - console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' ); + 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 ) { -Object.assign( Matrix4.prototype, { + result[ dstOffset ++ ] = values[ srcOffset + j ]; + + } + + } - extractPosition: function ( m ) { + return result; - console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' ); - return this.copyPosition( m ); +} - }, - flattenToArrayOffset: function ( array, offset ) { +// function for parsing AOS keyframe formats +function flattenJSON( jsonKeys, times, values, valuePropertyName ) { - console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); - return this.toArray( array, offset ); + let i = 1, key = jsonKeys[ 0 ]; - }, - getPosition: function () { + while ( key !== undefined && key[ valuePropertyName ] === undefined ) { - var v1; + key = jsonKeys[ i ++ ]; - return function getPosition() { + } - if ( v1 === undefined ) { v1 = new Vector3(); } - console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); - return v1.setFromMatrixColumn( this, 3 ); + if ( key === undefined ) return; // no data - }; + let value = key[ valuePropertyName ]; + if ( value === undefined ) return; // no data - }(), - setRotationFromQuaternion: function ( q ) { + if ( Array.isArray( value ) ) { - console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); - return this.makeRotationFromQuaternion( q ); + do { - }, - multiplyToArray: function () { + value = key[ valuePropertyName ]; - console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' ); + if ( value !== undefined ) { - }, - multiplyVector3: function ( vector ) { + times.push( key.time ); + values.push.apply( values, value ); // push all elements - console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); + } - }, - multiplyVector4: function ( vector ) { + key = jsonKeys[ i ++ ]; - console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); + } while ( key !== undefined ); - }, - multiplyVector3Array: function ( /* a */ ) { + } else if ( value.toArray !== undefined ) { - console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' ); + // ...assume THREE.Math-ish - }, - rotateAxis: function ( v ) { + do { - console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); - v.transformDirection( this ); + value = key[ valuePropertyName ]; - }, - crossVector: function ( vector ) { + if ( value !== undefined ) { - console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); + times.push( key.time ); + value.toArray( values, values.length ); - }, - translate: function () { + } - console.error( 'THREE.Matrix4: .translate() has been removed.' ); + key = jsonKeys[ i ++ ]; - }, - rotateX: function () { + } while ( key !== undefined ); - console.error( 'THREE.Matrix4: .rotateX() has been removed.' ); + } else { - }, - rotateY: function () { + // otherwise push as-is - console.error( 'THREE.Matrix4: .rotateY() has been removed.' ); + do { - }, - rotateZ: function () { + value = key[ valuePropertyName ]; - console.error( 'THREE.Matrix4: .rotateZ() has been removed.' ); + if ( value !== undefined ) { - }, - rotateByAxis: function () { + times.push( key.time ); + values.push( value ); - console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); + } - }, - applyToBuffer: function ( buffer /*, offset, length */ ) { + key = jsonKeys[ i ++ ]; - console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); - return this.applyToBufferAttribute( buffer ); + } while ( key !== undefined ); - }, - applyToVector3Array: function ( /* array, offset, length */ ) { + } - console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' ); +} - }, - makeFrustum: function ( left, right, bottom, top, near, far ) { +/** + * Abstract base class of interpolants over parametric samples. + * + * The parameter domain is one dimensional, typically the time or a path + * along a curve defined by the data. + * + * The sample values can have any dimensionality and derived classes may + * apply special interpretations to the data. + * + * This class provides the interval seek in a Template Method, deferring + * the actual interpolation to derived classes. + * + * Time complexity is O(1) for linear access crossing at most two points + * and O(log N) for random access, where N is the number of positions. + * + * References: + * + * http://www.oodesign.com/template-method-pattern.html + * + */ - console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' ); - return this.makePerspective( left, right, top, bottom, near, far ); +class Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { -} ); + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; -Plane.prototype.isIntersectionLine = function ( line ) { + this.resultBuffer = resultBuffer !== undefined ? + resultBuffer : new sampleValues.constructor( sampleSize ); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; - console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' ); - return this.intersectsLine( line ); + this.settings = null; + this.DefaultSettings_ = {}; -}; + } -Quaternion.prototype.multiplyVector3 = function ( vector ) { + evaluate( t ) { - console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' ); - return vector.applyQuaternion( this ); + const pp = this.parameterPositions; + let i1 = this._cachedIndex, + t1 = pp[ i1 ], + t0 = pp[ i1 - 1 ]; -}; + validate_interval: { -Object.assign( Ray.prototype, { + seek: { - isIntersectionBox: function ( box ) { + let right; - console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); + linear_scan: { - }, - isIntersectionPlane: function ( plane ) { + //- See http://jsperf.com/comparison-to-undefined/3 + //- slower code: + //- + //- if ( t >= t1 || t1 === undefined ) { + forward_scan: if ( ! ( t < t1 ) ) { - console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' ); - return this.intersectsPlane( plane ); + for ( let giveUpAt = i1 + 2; ; ) { - }, - isIntersectionSphere: function ( sphere ) { + if ( t1 === undefined ) { - console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); - return this.intersectsSphere( sphere ); + if ( t < t0 ) break forward_scan; - } + // after end -} ); + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); -Object.assign( Shape.prototype, { + } - extractAllPoints: function ( divisions ) { + if ( i1 === giveUpAt ) break; // this loop - console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' ); - return this.extractPoints( divisions ); + t0 = t1; + t1 = pp[ ++ i1 ]; - }, - extrude: function ( options ) { + if ( t < t1 ) { - console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' ); - return new ExtrudeGeometry( this, options ); + // we have arrived at the sought interval + break seek; - }, - makeGeometry: function ( options ) { + } - console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' ); - return new ShapeGeometry( this, options ); + } - } + // prepare binary search on the right side of the index + right = pp.length; + break linear_scan; -} ); + } -Object.assign( Vector2.prototype, { + //- slower code: + //- if ( t < t0 || t0 === undefined ) { + if ( ! ( t >= t0 ) ) { - fromAttribute: function ( attribute, index, offset ) { + // looping? - console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); + const t1global = pp[ 1 ]; - }, - distanceToManhattan: function ( v ) { + if ( t < t1global ) { - console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); - return this.manhattanDistanceTo( v ); + i1 = 2; // + 1, using the scan for the details + t0 = t1global; - }, - lengthManhattan: function () { + } - console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); + // linear reverse scan - } + for ( let giveUpAt = i1 - 2; ; ) { -} ); + if ( t0 === undefined ) { -Object.assign( Vector3.prototype, { + // before start - setEulerFromRotationMatrix: function () { + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); - console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' ); + } - }, - setEulerFromQuaternion: function () { + if ( i1 === giveUpAt ) break; // this loop - console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' ); + t1 = t0; + t0 = pp[ -- i1 - 1 ]; - }, - getPositionFromMatrix: function ( m ) { + if ( t >= t0 ) { - console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' ); - return this.setFromMatrixPosition( m ); + // we have arrived at the sought interval + break seek; - }, - getScaleFromMatrix: function ( m ) { + } - console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' ); - return this.setFromMatrixScale( m ); + } - }, - getColumnFromMatrix: function ( index, matrix ) { + // prepare binary search on the left side of the index + right = i1; + i1 = 0; + break linear_scan; - console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' ); - return this.setFromMatrixColumn( matrix, index ); + } - }, - applyProjection: function ( m ) { + // the interval is valid - console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' ); - return this.applyMatrix4( m ); + break validate_interval; - }, - fromAttribute: function ( attribute, index, offset ) { + } // linear scan - console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); + // binary search - }, - distanceToManhattan: function ( v ) { + while ( i1 < right ) { - console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); - return this.manhattanDistanceTo( v ); + const mid = ( i1 + right ) >>> 1; - }, - lengthManhattan: function () { + if ( t < pp[ mid ] ) { - console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); + right = mid; - } + } else { -} ); + i1 = mid + 1; -Object.assign( Vector4.prototype, { + } - fromAttribute: function ( attribute, index, offset ) { + } - console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); + t1 = pp[ i1 ]; + t0 = pp[ i1 - 1 ]; - }, - lengthManhattan: function () { + // check boundary cases, again - console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); + if ( t0 === undefined ) { - } + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); -} ); + } -// + if ( t1 === undefined ) { -Geometry.prototype.computeTangents = function () { + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); - console.warn( 'THREE.Geometry: .computeTangents() has been removed.' ); + } -}; + } // seek -Object.assign( Object3D.prototype, { + this._cachedIndex = i1; - getChildByName: function ( name ) { + this.intervalChanged_( i1, t0, t1 ); - console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' ); - return this.getObjectByName( name ); + } // validate_interval - }, - renderDepth: function () { + return this.interpolate_( i1, t0, t, t1 ); - console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' ); + } - }, - translate: function ( distance, axis ) { + getSettings_() { - console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' ); - return this.translateOnAxis( axis, distance ); + return this.settings || this.DefaultSettings_; } -} ); + copySampleValue_( index ) { -Object.defineProperties( Object3D.prototype, { - - eulerOrder: { - get: function () { + // copies a sample value to the result buffer - console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); - return this.rotation.order; + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + offset = index * stride; - }, - set: function ( value ) { + for ( let i = 0; i !== stride; ++ i ) { - console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); - this.rotation.order = value; + result[ i ] = values[ offset + i ]; } - }, - useQuaternion: { - get: function () { - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); + return result; - }, - set: function () { + } - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); + // Template methods for derived classes: - } - } + interpolate_( /* i1, t0, t, t1 */ ) { -} ); + throw new Error( 'call to abstract method' ); + // implementations shall return this.resultBuffer -Object.defineProperties( LOD.prototype, { + } - objects: { - get: function () { + intervalChanged_( /* i1, t0, t1 */ ) { - console.warn( 'THREE.LOD: .objects has been renamed to .levels.' ); - return this.levels; + // empty - } } -} ); +} + +/** + * Fast and simple cubic spline interpolant. + * + * It was derived from a Hermitian construction setting the first derivative + * at each sample position to the linear slope between neighboring positions + * over their parameter interval. + */ -Object.defineProperty( Skeleton.prototype, 'useVertexTexture', { +class CubicInterpolant extends Interpolant { - get: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - }, - set: function () { + this._weightPrev = - 0; + this._offsetPrev = - 0; + this._weightNext = - 0; + this._offsetNext = - 0; - console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); + this.DefaultSettings_ = { - } + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding -} ); + }; -Object.defineProperty( Curve.prototype, '__arcLengthDivisions', { + } - get: function () { + intervalChanged_( i1, t0, t1 ) { - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - return this.arcLengthDivisions; + const pp = this.parameterPositions; + let iPrev = i1 - 2, + iNext = i1 + 1, - }, - set: function ( value ) { + tPrev = pp[ iPrev ], + tNext = pp[ iNext ]; - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - this.arcLengthDivisions = value; + if ( tPrev === undefined ) { - } + switch ( this.getSettings_().endingStart ) { -} ); + case ZeroSlopeEnding: -// + // f'(t0) = 0 + iPrev = i1; + tPrev = 2 * t0 - t1; -PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) { + break; - console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " + - "Use .setFocalLength and .filmGauge for a photographic setup." ); + case WrapAroundEnding: - if ( filmGauge !== undefined ) { this.filmGauge = filmGauge; } - this.setFocalLength( focalLength ); + // use the other end of the curve + iPrev = pp.length - 2; + tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; -}; + break; -// + default: // ZeroCurvatureEnding -Object.defineProperties( Light.prototype, { - onlyShadow: { - set: function () { + // f''(t0) = 0 a.k.a. Natural Spline + iPrev = i1; + tPrev = t1; - console.warn( 'THREE.Light: .onlyShadow has been removed.' ); + } } - }, - shadowCameraFov: { - set: function ( value ) { - console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' ); - this.shadow.camera.fov = value; + if ( tNext === undefined ) { - } - }, - shadowCameraLeft: { - set: function ( value ) { + switch ( this.getSettings_().endingEnd ) { - console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' ); - this.shadow.camera.left = value; + case ZeroSlopeEnding: - } - }, - shadowCameraRight: { - set: function ( value ) { + // f'(tN) = 0 + iNext = i1; + tNext = 2 * t1 - t0; - console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' ); - this.shadow.camera.right = value; + break; - } - }, - shadowCameraTop: { - set: function ( value ) { + case WrapAroundEnding: - console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' ); - this.shadow.camera.top = value; + // use the other end of the curve + iNext = 1; + tNext = t1 + pp[ 1 ] - pp[ 0 ]; - } - }, - shadowCameraBottom: { - set: function ( value ) { + break; - console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' ); - this.shadow.camera.bottom = value; + default: // ZeroCurvatureEnding - } - }, - shadowCameraNear: { - set: function ( value ) { + // f''(tN) = 0, a.k.a. Natural Spline + iNext = i1 - 1; + tNext = t0; - console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' ); - this.shadow.camera.near = value; + } } - }, - shadowCameraFar: { - set: function ( value ) { - console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' ); - this.shadow.camera.far = value; + const halfDt = ( t1 - t0 ) * 0.5, + stride = this.valueSize; - } - }, - shadowCameraVisible: { - set: function () { + 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, - console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' ); + o1 = i1 * stride, o0 = o1 - stride, + oP = this._offsetPrev, oN = this._offsetNext, + wP = this._weightPrev, wN = this._weightNext, - } - }, - shadowBias: { - set: function ( value ) { + p = ( t - t0 ) / ( t1 - t0 ), + pp = p * p, + ppp = pp * p; - console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' ); - this.shadow.bias = value; + // evaluate polynomials - } - }, - shadowDarkness: { - set: function () { + 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; - console.warn( 'THREE.Light: .shadowDarkness has been removed.' ); + // combine data linearly - } - }, - shadowMapWidth: { - set: function ( value ) { + for ( let i = 0; i !== stride; ++ i ) { - console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' ); - this.shadow.mapSize.width = value; + result[ i ] = + sP * values[ oP + i ] + + s0 * values[ o0 + i ] + + s1 * values[ o1 + i ] + + sN * values[ oN + i ]; } - }, - shadowMapHeight: { - set: function ( value ) { - console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' ); - this.shadow.mapSize.height = value; + return result; - } } -} ); -// +} -Object.defineProperties( BufferAttribute.prototype, { +class LinearInterpolant extends Interpolant { - length: { - get: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' ); - return this.array.length; + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - } } -} ); + interpolate_( i1, t0, t, t1 ) { -Object.assign( BufferGeometry.prototype, { - - addIndex: function ( index ) { + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, - console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' ); - this.setIndex( index ); + offset1 = i1 * stride, + offset0 = offset1 - stride, - }, - addDrawCall: function ( start, count, indexOffset ) { + weight1 = ( t - t0 ) / ( t1 - t0 ), + weight0 = 1 - weight1; - if ( indexOffset !== undefined ) { + for ( let i = 0; i !== stride; ++ i ) { - console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' ); + result[ i ] = + values[ offset0 + i ] * weight0 + + values[ offset1 + i ] * weight1; } - console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' ); - this.addGroup( start, count ); - }, - clearDrawCalls: function () { + return result; + + } - console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' ); - this.clearGroups(); +} - }, - computeTangents: function () { +/** + * + * Interpolant that evaluates to the sample value at the position preceding + * the parameter. + */ - console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' ); +class DiscreteInterpolant extends Interpolant { - }, - computeOffsets: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' ); + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); } -} ); + interpolate_( i1 /*, t0, t, t1 */ ) { -Object.defineProperties( BufferGeometry.prototype, { + return this.copySampleValue_( i1 - 1 ); - drawcalls: { - get: function () { + } - console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' ); - return this.groups; +} - } - }, - offsets: { - get: function () { +class KeyframeTrack { - console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' ); - return this.groups; + constructor( name, times, values, interpolation ) { - } - } + if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); + if ( times === undefined || 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 ); -Object.defineProperties( Uniform.prototype, { + this.setInterpolation( interpolation || this.DefaultInterpolation ); - dynamic: { - set: function () { + } - console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' ); + // Serialization (in static context, because of constructor invocation + // and automatic invocation of .toJSON): - } - }, - onUpdate: { - value: function () { + static toJSON( track ) { - console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' ); - return this; + const trackType = track.constructor; - } - } + let json; -} ); + // derived classes can define a static toJSON method + if ( trackType.toJSON !== this.toJSON ) { -// + json = trackType.toJSON( track ); -Object.defineProperties( Material.prototype, { + } else { - wrapAround: { - get: function () { + // by default, we assume the data can be serialized as-is + json = { - console.warn( 'THREE.Material: .wrapAround has been removed.' ); + 'name': track.name, + 'times': convertArray( track.times, Array ), + 'values': convertArray( track.values, Array ) - }, - set: function () { + }; - console.warn( 'THREE.Material: .wrapAround has been removed.' ); + const interpolation = track.getInterpolation(); - } - }, - wrapRGB: { - get: function () { + if ( interpolation !== track.DefaultInterpolation ) { - console.warn( 'THREE.Material: .wrapRGB has been removed.' ); - return new Color(); + json.interpolation = interpolation; + + } } - }, - shading: { - get: function () { + json.type = track.ValueTypeName; // mandatory - console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + return json; - }, - set: function ( value ) { + } - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( value === FlatShading ); + InterpolantFactoryMethodDiscrete( result ) { - } - } + return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); -} ); + } -Object.defineProperties( MeshPhongMaterial.prototype, { + InterpolantFactoryMethodLinear( result ) { - metal: { - get: function () { + return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); - console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' ); - return false; + } - }, - set: function () { + InterpolantFactoryMethodSmooth( result ) { - console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' ); + return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); - } } -} ); + setInterpolation( interpolation ) { -Object.defineProperties( ShaderMaterial.prototype, { + let factoryMethod; - derivatives: { - get: function () { + switch ( interpolation ) { - console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); - return this.extensions.derivatives; + case InterpolateDiscrete: - }, - set: function ( value ) { + factoryMethod = this.InterpolantFactoryMethodDiscrete; - console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); - this.extensions.derivatives = value; + break; - } - } + case InterpolateLinear: -} ); + factoryMethod = this.InterpolantFactoryMethodLinear; -// + break; -Object.assign( WebGLRenderer.prototype, { + case InterpolateSmooth: - getCurrentRenderTarget: function () { + factoryMethod = this.InterpolantFactoryMethodSmooth; - console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' ); - return this.getRenderTarget(); + break; - }, + } - getMaxAnisotropy: function () { + if ( factoryMethod === undefined ) { - console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' ); - return this.capabilities.getMaxAnisotropy(); + const message = 'unsupported interpolation for ' + + this.ValueTypeName + ' keyframe track named ' + this.name; - }, + if ( this.createInterpolant === undefined ) { - getPrecision: function () { + // fall back to default, unless the default itself is messed up + if ( interpolation !== this.DefaultInterpolation ) { - console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' ); - return this.capabilities.precision; + this.setInterpolation( this.DefaultInterpolation ); - }, + } else { - resetGLState: function () { + throw new Error( message ); // fatal, in this case - console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' ); - return this.state.reset(); + } - }, + } - supportsFloatTextures: function () { + console.warn( 'THREE.KeyframeTrack:', message ); + return this; - console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' ); - return this.extensions.get( 'OES_texture_float' ); + } - }, - supportsHalfFloatTextures: function () { + this.createInterpolant = factoryMethod; - console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' ); - return this.extensions.get( 'OES_texture_half_float' ); + return this; - }, - supportsStandardDerivatives: function () { + } - console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' ); - return this.extensions.get( 'OES_standard_derivatives' ); + getInterpolation() { - }, - supportsCompressedTextureS3TC: function () { + switch ( this.createInterpolant ) { - console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' ); - return this.extensions.get( 'WEBGL_compressed_texture_s3tc' ); + case this.InterpolantFactoryMethodDiscrete: - }, - supportsCompressedTexturePVRTC: function () { + return InterpolateDiscrete; - console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' ); - return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + case this.InterpolantFactoryMethodLinear: - }, - supportsBlendMinMax: function () { + return InterpolateLinear; - console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' ); - return this.extensions.get( 'EXT_blend_minmax' ); + case this.InterpolantFactoryMethodSmooth: - }, - supportsVertexTextures: function () { + return InterpolateSmooth; - console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' ); - return this.capabilities.vertexTextures; + } - }, - supportsInstancedArrays: function () { + } - console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' ); - return this.extensions.get( 'ANGLE_instanced_arrays' ); + getValueSize() { - }, - enableScissorTest: function ( boolean ) { + return this.values.length / this.times.length; - console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' ); - this.setScissorTest( boolean ); + } - }, - initMaterial: function () { + // move all keyframes either forwards or backwards in time + shift( timeOffset ) { - console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' ); + if ( timeOffset !== 0.0 ) { - }, - addPrePlugin: function () { + const times = this.times; - console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' ); + for ( let i = 0, n = times.length; i !== n; ++ i ) { - }, - addPostPlugin: function () { + times[ i ] += timeOffset; - console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' ); + } - }, - updateShadowMap: function () { + } - console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' ); + return this; } -} ); + // scale all keyframe times by a factor (useful for frame <-> seconds conversions) + scale( timeScale ) { -Object.defineProperties( WebGLRenderer.prototype, { + if ( timeScale !== 1.0 ) { - shadowMapEnabled: { - get: function () { + const times = this.times; - return this.shadowMap.enabled; + for ( let i = 0, n = times.length; i !== n; ++ i ) { - }, - set: function ( value ) { + times[ i ] *= timeScale; - console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' ); - this.shadowMap.enabled = value; + } } - }, - shadowMapType: { - get: function () { - return this.shadowMap.type; + return this; - }, - set: function ( value ) { + } - console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' ); - this.shadowMap.type = value; + // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. + // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values + trim( startTime, endTime ) { - } - }, - shadowMapCullFace: { - get: function () { + const times = this.times, + nKeys = times.length; - return this.shadowMap.cullFace; + let from = 0, + to = nKeys - 1; - }, - set: function ( value ) { + while ( from !== nKeys && times[ from ] < startTime ) { - console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' ); - this.shadowMap.cullFace = value; + ++ from; } - } -} ); -Object.defineProperties( WebGLShadowMap.prototype, { - - cullFace: { - get: function () { + while ( to !== - 1 && times[ to ] > endTime ) { - return this.renderReverseSided ? CullFaceFront : CullFaceBack; + -- to; - }, - set: function ( cullFace ) { + } - var value = ( cullFace !== CullFaceBack ); - console.warn( "WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to " + value + "." ); - this.renderReverseSided = value; + ++ to; // inclusive -> exclusive bound - } - } + if ( from !== 0 || to !== nKeys ) { -} ); + // empty tracks are forbidden, so keep at least one keyframe + if ( from >= to ) { -// + to = Math.max( to, 1 ); + from = to - 1; -Object.defineProperties( WebGLRenderTarget.prototype, { + } - wrapS: { - get: function () { + const stride = this.getValueSize(); + this.times = times.slice( from, to ); + this.values = this.values.slice( from * stride, to * stride ); - console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); - return this.texture.wrapS; + } - }, - set: function ( value ) { + return this; - console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); - this.texture.wrapS = value; + } - } - }, - wrapT: { - get: function () { + // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable + validate() { - console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); - return this.texture.wrapT; + let valid = true; - }, - set: function ( value ) { + const valueSize = this.getValueSize(); + if ( valueSize - Math.floor( valueSize ) !== 0 ) { - console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); - this.texture.wrapT = value; + console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); + valid = false; } - }, - magFilter: { - get: function () { - console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); - return this.texture.magFilter; + const times = this.times, + values = this.values, - }, - set: function ( value ) { + nKeys = times.length; - console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); - this.texture.magFilter = value; + if ( nKeys === 0 ) { - } - }, - minFilter: { - get: function () { + console.error( 'THREE.KeyframeTrack: Track is empty.', this ); + valid = false; - console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); - return this.texture.minFilter; + } - }, - set: function ( value ) { + let prevTime = null; - console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); - this.texture.minFilter = value; + for ( let i = 0; i !== nKeys; i ++ ) { - } - }, - anisotropy: { - get: function () { + const currTime = times[ i ]; - console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); - return this.texture.anisotropy; + if ( typeof currTime === 'number' && isNaN( currTime ) ) { - }, - set: function ( value ) { + console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); + valid = false; + break; - console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); - this.texture.anisotropy = value; + } - } - }, - offset: { - get: function () { + if ( prevTime !== null && prevTime > currTime ) { - console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); - return this.texture.offset; + console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); + valid = false; + break; - }, - set: function ( value ) { + } - console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); - this.texture.offset = value; + prevTime = currTime; } - }, - repeat: { - get: function () { - console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); - return this.texture.repeat; + if ( values !== undefined ) { - }, - set: function ( value ) { + if ( isTypedArray( values ) ) { - console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); - this.texture.repeat = value; + for ( let i = 0, n = values.length; i !== n; ++ i ) { - } - }, - format: { - get: function () { + const value = values[ i ]; - console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); - return this.texture.format; + if ( isNaN( value ) ) { - }, - set: function ( value ) { + console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); + valid = false; + break; + + } + + } - console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); - this.texture.format = value; + } } - }, - type: { - get: function () { - console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); - return this.texture.type; + return valid; + + } - }, - set: function ( value ) { + // removes equivalent sequential keys as common in morph target sequences + // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) + optimize() { - console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); - this.texture.type = value; + // times or values may be shared with other tracks, so overwriting is unsafe + const times = this.times.slice(), + values = this.values.slice(), + stride = this.getValueSize(), - } - }, - generateMipmaps: { - get: function () { + smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + + lastIndex = times.length - 1; + + let writeIndex = 1; - console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); - return this.texture.generateMipmaps; + for ( let i = 1; i < lastIndex; ++ i ) { - }, - set: function ( value ) { + let keep = false; - console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); - this.texture.generateMipmaps = value; + const time = times[ i ]; + const timeNext = times[ i + 1 ]; - } - } + // remove adjacent keyframes scheduled at the same time -} ); + if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { -// + if ( ! smoothInterpolation ) { -Object.assign( WebVRManager.prototype, { + // remove unnecessary keyframes same as their neighbors - getStandingMatrix: function () { + const offset = i * stride, + offsetP = offset - stride, + offsetN = offset + stride; - console.warn( 'THREE.WebVRManager: .getStandingMatrix() has been removed.' ); + for ( let j = 0; j !== stride; ++ j ) { - } + const value = values[ offset + j ]; -} ); + if ( value !== values[ offsetP + j ] || + value !== values[ offsetN + j ] ) { -Object.defineProperties( WebVRManager.prototype, { + keep = true; + break; - standing: { - set: function ( /* value */ ) { + } - console.warn( 'THREE.WebVRManager: .standing has been removed.' ); + } - } - } + } else { -} ); + keep = true; -// + } -Audio.prototype.load = function ( file ) { + } - console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' ); - var scope = this; - var audioLoader = new AudioLoader(); - audioLoader.load( file, function ( buffer ) { + // in-place compaction - scope.setBuffer( buffer ); + if ( keep ) { - } ); - return this; + if ( i !== writeIndex ) { -}; + times[ writeIndex ] = times[ i ]; -AudioAnalyser.prototype.getData = function () { + const readOffset = i * stride, + writeOffset = writeIndex * stride; - console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' ); - return this.getFrequencyData(); + for ( let j = 0; j !== stride; ++ j ) { -}; + values[ writeOffset + j ] = values[ readOffset + j ]; -// + } -CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) { + } - console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' ); - return this.update( renderer, scene ); + ++ writeIndex; -}; + } -// + } + + // flush last keyframe (compaction looks ahead) -var GeometryUtils = { + if ( lastIndex > 0 ) { - merge: function ( geometry1, geometry2, materialIndexOffset ) { + times[ writeIndex ] = times[ lastIndex ]; - console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); - var matrix; + for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { - if ( geometry2.isMesh ) { + values[ writeOffset + j ] = values[ readOffset + j ]; - geometry2.matrixAutoUpdate && geometry2.updateMatrix(); + } - matrix = geometry2.matrix; - geometry2 = geometry2.geometry; + ++ writeIndex; } - geometry1.merge( geometry2, matrix, materialIndexOffset ); + if ( writeIndex !== times.length ) { - }, + this.times = times.slice( 0, writeIndex ); + this.values = values.slice( 0, writeIndex * stride ); + + } else { - center: function ( geometry ) { + this.times = times; + this.values = values; - console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); - return geometry.center(); + } + + return this; } -}; + clone() { -var ImageUtils = { + const times = this.times.slice(); + const values = this.values.slice(); - crossOrigin: undefined, + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack( this.name, times, values ); - loadTexture: function ( url, mapping, onLoad, onError ) { + // Interpolant argument to constructor is not saved, so copy the factory method directly. + track.createInterpolant = this.createInterpolant; - console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' ); + return track; - var loader = new TextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); + } - var texture = loader.load( url, onLoad, undefined, onError ); +} - if ( mapping ) { texture.mapping = mapping; } +KeyframeTrack.prototype.TimeBufferType = Float32Array; +KeyframeTrack.prototype.ValueBufferType = Float32Array; +KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; - return texture; +/** + * A Track of Boolean keyframe values. + */ +class BooleanKeyframeTrack extends KeyframeTrack { - }, + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { - loadTextureCube: function ( urls, mapping, onLoad, onError ) { + super( name, times, values ); - console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' ); + } - var loader = new CubeTextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); +} - var texture = loader.load( urls, onLoad, undefined, onError ); +BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; +BooleanKeyframeTrack.prototype.ValueBufferType = Array; +BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - if ( mapping ) { texture.mapping = mapping; } +/** + * A Track of keyframe values that represent color. + */ +class ColorKeyframeTrack extends KeyframeTrack {} - return texture; +ColorKeyframeTrack.prototype.ValueTypeName = 'color'; - }, +/** + * A Track of numeric keyframe values. + */ +class NumberKeyframeTrack extends KeyframeTrack {} - loadCompressedTexture: function () { +NumberKeyframeTrack.prototype.ValueTypeName = 'number'; - console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ); +/** + * Spherical linear unit quaternion interpolant. + */ - }, +class QuaternionLinearInterpolant extends Interpolant { - loadCompressedTextureCube: function () { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ); + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); } -}; + interpolate_( i1, t0, t, t1 ) { -// + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, -function Projector() { + alpha = ( t - t0 ) / ( t1 - t0 ); - console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' ); + let offset = i1 * stride; - this.projectVector = function ( vector, camera ) { + for ( let end = offset + stride; offset !== end; offset += 4 ) { - console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); - vector.project( camera ); + Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); - }; + } - this.unprojectVector = function ( vector, camera ) { + return result; - console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); - vector.unproject( camera ); + } - }; +} - this.pickingRay = function () { +/** + * A Track of quaternion keyframe values. + */ +class QuaternionKeyframeTrack extends KeyframeTrack { - console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' ); + InterpolantFactoryMethodLinear( result ) { - }; + return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); + + } } -// +QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; +// ValueBufferType is inherited +// DefaultInterpolation is inherited; +QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; -function CanvasRenderer() { - - console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' ); - - this.domElement = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - this.clear = function () {}; - this.render = function () {}; - this.setClearColor = function () {}; - this.setSize = function () {}; - -} - -var THREE$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - WebGLRenderTargetCube: WebGLRenderTargetCube, - WebGLRenderTarget: WebGLRenderTarget, - WebGLRenderer: WebGLRenderer, - ShaderLib: ShaderLib, - UniformsLib: UniformsLib, - UniformsUtils: UniformsUtils, - ShaderChunk: ShaderChunk, - FogExp2: FogExp2, - Fog: Fog, - Scene: Scene, - LensFlare: LensFlare, - Sprite: Sprite, - LOD: LOD, - SkinnedMesh: SkinnedMesh, - Skeleton: Skeleton, - Bone: Bone, - Mesh: Mesh, - LineSegments: LineSegments, - LineLoop: LineLoop, - Line: Line, - Points: Points$1, - Group: Group, - VideoTexture: VideoTexture, - DataTexture: DataTexture, - CompressedTexture: CompressedTexture, - CubeTexture: CubeTexture, - CanvasTexture: CanvasTexture, - DepthTexture: DepthTexture, - Texture: Texture, - CompressedTextureLoader: CompressedTextureLoader, - DataTextureLoader: DataTextureLoader, - CubeTextureLoader: CubeTextureLoader, - TextureLoader: TextureLoader, - ObjectLoader: ObjectLoader, - MaterialLoader: MaterialLoader, - BufferGeometryLoader: BufferGeometryLoader, - DefaultLoadingManager: DefaultLoadingManager, - LoadingManager: LoadingManager, - JSONLoader: JSONLoader, - ImageLoader: ImageLoader, - ImageBitmapLoader: ImageBitmapLoader, - FontLoader: FontLoader, - FileLoader: FileLoader, - Loader: Loader, - LoaderUtils: LoaderUtils, - Cache: Cache, - AudioLoader: AudioLoader, - SpotLightShadow: SpotLightShadow, - SpotLight: SpotLight, - PointLight: PointLight, - RectAreaLight: RectAreaLight, - HemisphereLight: HemisphereLight, - DirectionalLightShadow: DirectionalLightShadow, - DirectionalLight: DirectionalLight, - AmbientLight: AmbientLight, - LightShadow: LightShadow, - Light: Light, - StereoCamera: StereoCamera, - PerspectiveCamera: PerspectiveCamera, - OrthographicCamera: OrthographicCamera, - CubeCamera: CubeCamera, - ArrayCamera: ArrayCamera, - Camera: Camera, - AudioListener: AudioListener, - PositionalAudio: PositionalAudio, - AudioContext: AudioContext, - AudioAnalyser: AudioAnalyser, - Audio: Audio, - VectorKeyframeTrack: VectorKeyframeTrack, - StringKeyframeTrack: StringKeyframeTrack, - QuaternionKeyframeTrack: QuaternionKeyframeTrack, - NumberKeyframeTrack: NumberKeyframeTrack, - ColorKeyframeTrack: ColorKeyframeTrack, - BooleanKeyframeTrack: BooleanKeyframeTrack, - PropertyMixer: PropertyMixer, - PropertyBinding: PropertyBinding, - KeyframeTrack: KeyframeTrack, - AnimationUtils: AnimationUtils, - AnimationObjectGroup: AnimationObjectGroup, - AnimationMixer: AnimationMixer, - AnimationClip: AnimationClip, - Uniform: Uniform, - InstancedBufferGeometry: InstancedBufferGeometry, - BufferGeometry: BufferGeometry, - Geometry: Geometry, - InterleavedBufferAttribute: InterleavedBufferAttribute, - InstancedInterleavedBuffer: InstancedInterleavedBuffer, - InterleavedBuffer: InterleavedBuffer, - InstancedBufferAttribute: InstancedBufferAttribute, - Face3: Face3, - Object3D: Object3D, - Raycaster: Raycaster, - Layers: Layers, - EventDispatcher: EventDispatcher, - Clock: Clock, - QuaternionLinearInterpolant: QuaternionLinearInterpolant, - LinearInterpolant: LinearInterpolant, - DiscreteInterpolant: DiscreteInterpolant, - CubicInterpolant: CubicInterpolant, - Interpolant: Interpolant, - Triangle: Triangle, - Math: _Math, - Spherical: Spherical, - Cylindrical: Cylindrical, - Plane: Plane, - Frustum: Frustum, - Sphere: Sphere, - Ray: Ray, - Matrix4: Matrix4, - Matrix3: Matrix3, - Box3: Box3, - Box2: Box2, - Line3: Line3, - Euler: Euler, - Vector4: Vector4, - Vector3: Vector3, - Vector2: Vector2, - Quaternion: Quaternion, - Color: Color, - ImmediateRenderObject: ImmediateRenderObject, - VertexNormalsHelper: VertexNormalsHelper, - SpotLightHelper: SpotLightHelper, - SkeletonHelper: SkeletonHelper, - PointLightHelper: PointLightHelper, - RectAreaLightHelper: RectAreaLightHelper, - HemisphereLightHelper: HemisphereLightHelper, - GridHelper: GridHelper, - PolarGridHelper: PolarGridHelper, - FaceNormalsHelper: FaceNormalsHelper, - DirectionalLightHelper: DirectionalLightHelper, - CameraHelper: CameraHelper, - BoxHelper: BoxHelper, - Box3Helper: Box3Helper, - PlaneHelper: PlaneHelper, - ArrowHelper: ArrowHelper, - AxesHelper: AxesHelper, - Shape: Shape, - Path: Path$1, - ShapePath: ShapePath, - Font: Font, - CurvePath: CurvePath, - Curve: Curve, - ShapeUtils: ShapeUtils, - SceneUtils: SceneUtils, - WebGLUtils: WebGLUtils, - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry, - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material, - Float64BufferAttribute: Float64BufferAttribute, - Float32BufferAttribute: Float32BufferAttribute, - Uint32BufferAttribute: Uint32BufferAttribute, - Int32BufferAttribute: Int32BufferAttribute, - Uint16BufferAttribute: Uint16BufferAttribute, - Int16BufferAttribute: Int16BufferAttribute, - Uint8ClampedBufferAttribute: Uint8ClampedBufferAttribute, - Uint8BufferAttribute: Uint8BufferAttribute, - Int8BufferAttribute: Int8BufferAttribute, - BufferAttribute: BufferAttribute, - ArcCurve: ArcCurve, - CatmullRomCurve3: CatmullRomCurve3, - CubicBezierCurve: CubicBezierCurve, - CubicBezierCurve3: CubicBezierCurve3, - EllipseCurve: EllipseCurve, - LineCurve: LineCurve, - LineCurve3: LineCurve3, - QuadraticBezierCurve: QuadraticBezierCurve, - QuadraticBezierCurve3: QuadraticBezierCurve3, - SplineCurve: SplineCurve, - REVISION: REVISION, - MOUSE: MOUSE, - CullFaceNone: CullFaceNone, - CullFaceBack: CullFaceBack, - CullFaceFront: CullFaceFront, - CullFaceFrontBack: CullFaceFrontBack, - FrontFaceDirectionCW: FrontFaceDirectionCW, - FrontFaceDirectionCCW: FrontFaceDirectionCCW, - BasicShadowMap: BasicShadowMap, - PCFShadowMap: PCFShadowMap, - PCFSoftShadowMap: PCFSoftShadowMap, - FrontSide: FrontSide, - BackSide: BackSide, - DoubleSide: DoubleSide, - FlatShading: FlatShading, - SmoothShading: SmoothShading, - NoColors: NoColors, - FaceColors: FaceColors, - VertexColors: VertexColors, - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending, - AddEquation: AddEquation, - SubtractEquation: SubtractEquation, - ReverseSubtractEquation: ReverseSubtractEquation, - MinEquation: MinEquation, - MaxEquation: MaxEquation, - ZeroFactor: ZeroFactor, - OneFactor: OneFactor, - SrcColorFactor: SrcColorFactor, - OneMinusSrcColorFactor: OneMinusSrcColorFactor, - SrcAlphaFactor: SrcAlphaFactor, - OneMinusSrcAlphaFactor: OneMinusSrcAlphaFactor, - DstAlphaFactor: DstAlphaFactor, - OneMinusDstAlphaFactor: OneMinusDstAlphaFactor, - DstColorFactor: DstColorFactor, - OneMinusDstColorFactor: OneMinusDstColorFactor, - SrcAlphaSaturateFactor: SrcAlphaSaturateFactor, - NeverDepth: NeverDepth, - AlwaysDepth: AlwaysDepth, - LessDepth: LessDepth, - LessEqualDepth: LessEqualDepth, - EqualDepth: EqualDepth, - GreaterEqualDepth: GreaterEqualDepth, - GreaterDepth: GreaterDepth, - NotEqualDepth: NotEqualDepth, - MultiplyOperation: MultiplyOperation, - MixOperation: MixOperation, - AddOperation: AddOperation, - NoToneMapping: NoToneMapping, - LinearToneMapping: LinearToneMapping, - ReinhardToneMapping: ReinhardToneMapping, - Uncharted2ToneMapping: Uncharted2ToneMapping, - CineonToneMapping: CineonToneMapping, - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping, - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping, - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter, - UnsignedByteType: UnsignedByteType, - ByteType: ByteType, - ShortType: ShortType, - UnsignedShortType: UnsignedShortType, - IntType: IntType, - UnsignedIntType: UnsignedIntType, - FloatType: FloatType, - HalfFloatType: HalfFloatType, - UnsignedShort4444Type: UnsignedShort4444Type, - UnsignedShort5551Type: UnsignedShort5551Type, - UnsignedShort565Type: UnsignedShort565Type, - UnsignedInt248Type: UnsignedInt248Type, - AlphaFormat: AlphaFormat, - RGBFormat: RGBFormat, - RGBAFormat: RGBAFormat, - LuminanceFormat: LuminanceFormat, - LuminanceAlphaFormat: LuminanceAlphaFormat, - RGBEFormat: RGBEFormat, - DepthFormat: DepthFormat, - DepthStencilFormat: DepthStencilFormat, - RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format, - RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format, - RGBA_S3TC_DXT3_Format: RGBA_S3TC_DXT3_Format, - RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format, - RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format, - RGB_PVRTC_2BPPV1_Format: RGB_PVRTC_2BPPV1_Format, - RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format, - RGBA_PVRTC_2BPPV1_Format: RGBA_PVRTC_2BPPV1_Format, - RGB_ETC1_Format: RGB_ETC1_Format, - LoopOnce: LoopOnce, - LoopRepeat: LoopRepeat, - LoopPingPong: LoopPingPong, - InterpolateDiscrete: InterpolateDiscrete, - InterpolateLinear: InterpolateLinear, - InterpolateSmooth: InterpolateSmooth, - ZeroCurvatureEnding: ZeroCurvatureEnding, - ZeroSlopeEnding: ZeroSlopeEnding, - WrapAroundEnding: WrapAroundEnding, - TrianglesDrawMode: TrianglesDrawMode, - TriangleStripDrawMode: TriangleStripDrawMode, - TriangleFanDrawMode: TriangleFanDrawMode, - LinearEncoding: LinearEncoding, - sRGBEncoding: sRGBEncoding, - GammaEncoding: GammaEncoding, - RGBEEncoding: RGBEEncoding, - LogLuvEncoding: LogLuvEncoding, - RGBM7Encoding: RGBM7Encoding, - RGBM16Encoding: RGBM16Encoding, - RGBDEncoding: RGBDEncoding, - BasicDepthPacking: BasicDepthPacking, - RGBADepthPacking: RGBADepthPacking, - CubeGeometry: BoxGeometry, - Face4: Face4, - LineStrip: LineStrip, - LinePieces: LinePieces, - MeshFaceMaterial: MeshFaceMaterial, - MultiMaterial: MultiMaterial, - PointCloud: PointCloud, - Particle: Particle, - ParticleSystem: ParticleSystem, - PointCloudMaterial: PointCloudMaterial, - ParticleBasicMaterial: ParticleBasicMaterial, - ParticleSystemMaterial: ParticleSystemMaterial, - Vertex: Vertex, - DynamicBufferAttribute: DynamicBufferAttribute, - Int8Attribute: Int8Attribute, - Uint8Attribute: Uint8Attribute, - Uint8ClampedAttribute: Uint8ClampedAttribute, - Int16Attribute: Int16Attribute, - Uint16Attribute: Uint16Attribute, - Int32Attribute: Int32Attribute, - Uint32Attribute: Uint32Attribute, - Float32Attribute: Float32Attribute, - Float64Attribute: Float64Attribute, - ClosedSplineCurve3: ClosedSplineCurve3, - SplineCurve3: SplineCurve3, - Spline: Spline, - AxisHelper: AxisHelper, - BoundingBoxHelper: BoundingBoxHelper, - EdgesHelper: EdgesHelper, - WireframeHelper: WireframeHelper, - XHRLoader: XHRLoader, - BinaryTextureLoader: BinaryTextureLoader, - GeometryUtils: GeometryUtils, - ImageUtils: ImageUtils, - Projector: Projector, - CanvasRenderer: CanvasRenderer -}); +/** + * A Track that interpolates Strings + */ +class StringKeyframeTrack extends KeyframeTrack { -var THREE = Object.assign({}, THREE$1); + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { -// Marker types -var MARKER_ARROW = 0; -var MARKER_CUBE = 1; -var MARKER_SPHERE = 2; -var MARKER_CYLINDER = 3; -var MARKER_LINE_STRIP = 4; -var MARKER_LINE_LIST = 5; -var MARKER_CUBE_LIST = 6; -var MARKER_SPHERE_LIST = 7; -var MARKER_POINTS = 8; -var MARKER_TEXT_VIEW_FACING = 9; -var MARKER_MESH_RESOURCE = 10; -var MARKER_TRIANGLE_LIST = 11; + super( name, times, values ); -// Interactive marker feedback types -var INTERACTIVE_MARKER_KEEP_ALIVE = 0; -var INTERACTIVE_MARKER_POSE_UPDATE = 1; -var INTERACTIVE_MARKER_MENU_SELECT = 2; -var INTERACTIVE_MARKER_BUTTON_CLICK = 3; -var INTERACTIVE_MARKER_MOUSE_DOWN = 4; -var INTERACTIVE_MARKER_MOUSE_UP = 5; + } -// Interactive marker control types -var INTERACTIVE_MARKER_NONE = 0; -var INTERACTIVE_MARKER_MENU = 1; -var INTERACTIVE_MARKER_BUTTON = 2; -var INTERACTIVE_MARKER_MOVE_AXIS = 3; -var INTERACTIVE_MARKER_MOVE_PLANE = 4; -var INTERACTIVE_MARKER_ROTATE_AXIS = 5; -var INTERACTIVE_MARKER_MOVE_ROTATE = 6; -var INTERACTIVE_MARKER_MOVE_3D = 7; -var INTERACTIVE_MARKER_ROTATE_3D = 8; -var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; +} -// Interactive marker rotation behavior -var INTERACTIVE_MARKER_INHERIT = 0; -var INTERACTIVE_MARKER_FIXED = 1; -var INTERACTIVE_MARKER_VIEW_FACING = 2; +StringKeyframeTrack.prototype.ValueTypeName = 'string'; +StringKeyframeTrack.prototype.ValueBufferType = Array; +StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; /** - * @function makeColorMaterial - * @description Create a THREE material based on the given RGBA values. - * - * @param r - the red value - * @param g - the green value - * @param b - the blue value - * @param a - the alpha value - * @returns the THREE material + * A Track of vectored keyframe values. */ -var makeColorMaterial = function(r, g, b, a) { - var color = new THREE.Color(); - color.setRGB(r, g, b); - if (a <= 0.99) { - return new THREE.MeshBasicMaterial({ - color : color.getHex(), - opacity : a + 0.1, - transparent : true, - depthWrite : true, - blendSrc : THREE.SrcAlphaFactor, - blendDst : THREE.OneMinusSrcAlphaFactor, - blendEquation : THREE.ReverseSubtractEquation, - blending : THREE.NormalBlending - }); - } else { - return new THREE.MeshPhongMaterial({ - color : color.getHex(), - opacity : a, - blending : THREE.NormalBlending - }); - } -}; +class VectorKeyframeTrack extends KeyframeTrack {} -/** - * @function intersectPlane - * @description Return the intersection between the mouseray and the plane. - * - * @param mouseRay - the mouse ray - * @param planeOrigin - the origin of the plane - * @param planeNormal - the normal of the plane - * @returns the intersection point - */ -var intersectPlane = function(mouseRay, planeOrigin, planeNormal) { - var vector = new THREE.Vector3(); - var intersectPoint = new THREE.Vector3(); - vector.subVectors(planeOrigin, mouseRay.origin); - var dot = mouseRay.direction.dot(planeNormal); +VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; - // bail if ray and plane are parallel - if (Math.abs(dot) < mouseRay.precision) { - return undefined; - } +class AnimationClip { - // calc distance to plane - var scalar = planeNormal.dot(vector) / dot; + constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { - intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); - return intersectPoint; -}; + this.name = name; + this.tracks = tracks; + this.duration = duration; + this.blendMode = blendMode; -/** - * @function findClosestPoint - * @description Find the closest point on targetRay to any point on mouseRay. Math taken from - * http://paulbourke.net/geometry/lineline3d/ - * - * @param targetRay - the target ray to use - * @param mouseRay - the mouse ray - * @param the closest point between the two rays - */ -var findClosestPoint = function(targetRay, mouseRay) { - var v13 = new THREE.Vector3(); - v13.subVectors(targetRay.origin, mouseRay.origin); - var v43 = mouseRay.direction.clone(); - var v21 = targetRay.direction.clone(); - var d1343 = v13.dot(v43); - var d4321 = v43.dot(v21); - var d1321 = v13.dot(v21); - var d4343 = v43.dot(v43); - var d2121 = v21.dot(v21); + this.uuid = generateUUID(); - var denom = d2121 * d4343 - d4321 * d4321; - // check within a delta - if (Math.abs(denom) <= 0.0001) { - return undefined; - } - var numer = d1343 * d4321 - d1321 * d4343; + // this means it should figure out its duration by scanning the tracks + if ( this.duration < 0 ) { - var mua = numer / denom; - return mua; -}; + this.resetDuration(); -/** - * @function closestAxisPoint - * @description Find the closest point between the axis and the mouse. - * - * @param axisRay - the ray from the axis - * @param camera - the camera to project from - * @param mousePos - the mouse position - * @returns the closest axis point - */ -var closestAxisPoint = function(axisRay, camera, mousePos) { - // project axis onto screen - var o = axisRay.origin.clone(); - o.project(camera); - var o2 = axisRay.direction.clone().add(axisRay.origin); - o2.project(camera); + } - // d is the axis vector in screen space (d = o2-o) - var d = o2.clone().sub(o); + } - // t is the 2d ray param of perpendicular projection of mousePos onto o - var tmp = new THREE.Vector2(); - // (t = (mousePos - o) * d / (d*d)) - var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); - // mp is the final 2d-projected mouse pos (mp = o + d*t) - var mp = new THREE.Vector2(); - mp.addVectors(o, d.clone().multiplyScalar(t)); + static parse( json ) { - // go back to 3d by shooting a ray - var vector = new THREE.Vector3(mp.x, mp.y, 0.5); - vector.unproject(camera); - var mpRay = new THREE.Ray(camera.position, vector.sub(camera.position).normalize()); + const tracks = [], + jsonTracks = json.tracks, + frameTime = 1.0 / ( json.fps || 1.0 ); - return findClosestPoint(axisRay, mpRay); -}; + for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { -/** - * @fileOverview - * @author Julius Kammerl - jkammerl@willowgarage.com - */ + tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); -var DepthCloud = /*@__PURE__*/(function (superclass) { - function DepthCloud(options) { - superclass.call(this); - options = options || {}; + } - this.url = options.url; - this.streamType = options.streamType || 'vp8'; - this.f = options.f || 526; - this.maxDepthPerTile = options.maxDepthPerTile || 1.0; - this.pointSize = options.pointSize || 3; - this.width = options.width || 1024; - this.height = options.height || 1024; - this.resolutionFactor = Math.max(this.width, this.height) / 1024; - this.whiteness = options.whiteness || 0; - this.varianceThreshold = options.varianceThreshold || 0.000016667; - - this.isMjpeg = this.streamType.toLowerCase() === 'mjpeg'; - - this.video = document.createElement(this.isMjpeg ? 'img' : 'video'); - this.video.crossOrigin = 'Anonymous'; - this.video.addEventListener(this.isMjpeg ? 'load' : 'loadedmetadata', this.metaLoaded.bind(this), false); - - if (!this.isMjpeg) { - this.video.loop = true; - } + const clip = new this( json.name, json.duration, tracks, json.blendMode ); + clip.uuid = json.uuid; - this.video.src = this.url; - this.video.setAttribute('crossorigin', 'Anonymous'); + return clip; - // define custom shaders - this.vertex_shader = [ - 'uniform sampler2D map;', - '', - 'uniform float width;', - 'uniform float height;', - 'uniform float nearClipping, farClipping;', - '', - 'uniform float pointSize;', - 'uniform float zOffset;', - '', - 'uniform float focallength;', - 'uniform float maxDepthPerTile;', - 'uniform float resolutionFactor;', - '', - 'varying vec2 vUvP;', - 'varying vec2 colorP;', - '', - 'varying float depthVariance;', - 'varying float maskVal;', - '', - 'float sampleDepth(vec2 pos)', - ' {', - ' float depth;', - ' ', - ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', - ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', - ' ', - ' vec4 depthColor = texture2D( map, vUv );', - ' ', - ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', - ' ', - ' if (depth>0.99)', - ' {', - ' vec4 depthColor2 = texture2D( map, vUv2 );', - ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', - ' depth = 0.99+depth2;', - ' }', - ' ', - ' return depth;', - ' }', - '', - 'float median(float a, float b, float c)', - ' {', - ' float r=a;', - ' ', - ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', - ' {', - ' vec2 smp = decodeDepth(vec2(position.x, position.y));', - ' float depth = smp.x;', - ' depthVariance = smp.y;', - ' ', - ' float z = -depth;', - ' ', - ' pos = vec4(', - ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', - ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', - ' (- z + zOffset / 1000.0) * maxDepthPerTile,', - ' 1.0);', - ' ', - ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', - ' vec4 maskColor = texture2D( map, maskP );', - ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', - ' }', - ' ', - ' gl_PointSize = pointSize;', - ' gl_Position = projectionMatrix * modelViewMatrix * pos;', - ' ', - '}' - ].join('\n'); - - this.fragment_shader = [ - 'uniform sampler2D map;', - 'uniform float varianceThreshold;', - 'uniform float whiteness;', - '', - 'varying vec2 vUvP;', - 'varying vec2 colorP;', - '', - 'varying float depthVariance;', - 'varying float maskVal;', - '', - '', - 'void main() {', - ' ', - ' vec4 color;', - ' ', - ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', - ' { ', - ' discard;', - ' }', - ' else ', - ' {', - ' color = texture2D( map, colorP );', - ' ', - ' float fader = whiteness /100.0;', - ' ', - ' color.r = color.r * (1.0-fader)+ fader;', - ' ', - ' color.g = color.g * (1.0-fader)+ fader;', - ' ', - ' color.b = color.b * (1.0-fader)+ fader;', - ' ', - ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', - ' }', - ' ', - ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', - ' ', - '}' - ].join('\n'); - } + } - if ( superclass ) DepthCloud.__proto__ = superclass; - DepthCloud.prototype = Object.create( superclass && superclass.prototype ); - DepthCloud.prototype.constructor = DepthCloud; - /** - * Callback called when video metadata is ready - */ - DepthCloud.prototype.metaLoaded = function metaLoaded () { - this.metaLoaded = true; - this.initStreamer(); - }; - /** - * Callback called when video metadata is ready - */ - DepthCloud.prototype.initStreamer = function initStreamer () { - var this$1$1 = this; + 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 ) { - if (this.metaLoaded) { - this.texture = new THREE.Texture(this.video); - this.geometry = new THREE.Geometry(); + tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); - for (var i = 0, l = this.width * this.height; i < l; i++) { + } - var vertex = new THREE.Vector3(); - vertex.x = (i % this.width); - vertex.y = Math.floor(i / this.width); + return json; - this.geometry.vertices.push(vertex); - } + } - this.material = new THREE.ShaderMaterial({ - uniforms : { - 'map' : { - type : 't', - value : this.texture - }, - 'width' : { - type : 'f', - value : this.width - }, - 'height' : { - type : 'f', - value : this.height - }, - 'focallength' : { - type : 'f', - value : this.f - }, - 'pointSize' : { - type : 'f', - value : this.pointSize - }, - 'zOffset' : { - type : 'f', - value : 0 - }, - 'whiteness' : { - type : 'f', - value : this.whiteness - }, - 'varianceThreshold' : { - type : 'f', - value : this.varianceThreshold - }, - 'maxDepthPerTile': { - type : 'f', - value : this.maxDepthPerTile - }, - 'resolutionFactor': { - type : 'f', - value : this.resolutionFactor - }, - }, - vertexShader : this.vertex_shader, - fragmentShader : this.fragment_shader - }); + static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { - this.mesh = new THREE.ParticleSystem(this.geometry, this.material); - this.mesh.position.x = 0; - this.mesh.position.y = 0; - this.add(this.mesh); + const numMorphTargets = morphTargetSequence.length; + const tracks = []; - setInterval(function () { - if (this$1$1.isMjpeg || this$1$1.video.readyState === this$1$1.video.HAVE_ENOUGH_DATA) { - this$1$1.texture.needsUpdate = true; - } - }, 1000 / 30); - } - }; - /** - * Start video playback - */ - DepthCloud.prototype.startStream = function startStream () { - if (!this.isMjpeg) { - this.video.play(); - } - }; - /** - * Stop video playback - */ - DepthCloud.prototype.stopStream = function stopStream () { - if (!this.isMjpeg) { - this.video.pause(); - } - }; + for ( let i = 0; i < numMorphTargets; i ++ ) { - return DepthCloud; -}(THREE.Object3D)); + let times = []; + let values = []; -/** - * @fileOverview - * @author David Gossow - dgossow@willowgarage.com - */ + times.push( + ( i + numMorphTargets - 1 ) % numMorphTargets, + i, + ( i + 1 ) % numMorphTargets ); -var Arrow = /*@__PURE__*/(function (superclass) { - function Arrow(options) { - options = options || {}; - var origin = options.origin || new THREE.Vector3(0, 0, 0); - var direction = options.direction || new THREE.Vector3(1, 0, 0); - var length = options.length || 1; - var headLength = options.headLength || 0.2; - var shaftDiameter = options.shaftDiameter || 0.05; - var headDiameter = options.headDiameter || 0.1; - var material = options.material || new THREE.MeshBasicMaterial(); + values.push( 0, 1, 0 ); - var shaftLength = length - headLength; + const order = getKeyframeOrder( times ); + times = sortedArray( times, 1, order ); + values = sortedArray( values, 1, order ); - // create and merge geometry - var geometry = new THREE.CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, - 12, 1); - var m = new THREE.Matrix4(); - m.setPosition(new THREE.Vector3(0, shaftLength * 0.5, 0)); - geometry.applyMatrix(m); + // if there is a key at the first frame, duplicate it as the + // last frame as well for perfect loop. + if ( ! noLoop && times[ 0 ] === 0 ) { - // create the head - var coneGeometry = new THREE.CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); - m.setPosition(new THREE.Vector3(0, shaftLength + (headLength * 0.5), 0)); - coneGeometry.applyMatrix(m); + times.push( numMorphTargets ); + values.push( values[ 0 ] ); - // put the arrow together - geometry.merge(coneGeometry); + } - superclass.call(this, geometry, material); + tracks.push( + new NumberKeyframeTrack( + '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', + times, values + ).scale( 1.0 / fps ) ); - this.position.copy(origin); - this.setDirection(direction); - } + } - if ( superclass ) Arrow.__proto__ = superclass; - Arrow.prototype = Object.create( superclass && superclass.prototype ); - Arrow.prototype.constructor = Arrow; - /** - * Set the direction of this arrow to that of the given vector. - * - * @param direction - the direction to set this arrow - */ - Arrow.prototype.setDirection = function setDirection (direction) { - var axis = new THREE.Vector3(); - if(direction.x === 0 && direction.z === 0){ - axis.set(1, 0, 0); - } else { - axis.set(0, 1, 0).cross(direction); - } - var radians = Math.acos(new THREE.Vector3(0, 1, 0).dot(direction.clone().normalize())); - this.matrix = new THREE.Matrix4().makeRotationAxis(axis.normalize(), radians); - this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); - }; - /** - * Set this arrow to be the given length. - * - * @param length - the new length of the arrow - */ - Arrow.prototype.setLength = function setLength (length) { - this.scale.set(length, length, length); - }; - /** - * Set the color of this arrow to the given hex value. - * - * @param hex - the hex value of the color to use - */ - Arrow.prototype.setColor = function setColor (hex) { - this.material.color.setHex(hex); - }; - /* - * Free memory of elements in this marker. - */ - Arrow.prototype.dispose = function dispose () { - if (this.geometry !== undefined) { - this.geometry.dispose(); - } - if (this.material !== undefined) { - this.material.dispose(); - } - }; + return new this( name, - 1, tracks ); - return Arrow; -}(THREE.Mesh)); + } -/** - * @fileOverview - * @author aleeper / http://adamleeper.com/ - * @author mrdoob / http://mrdoob.com/ - * @author gero3 / https://github.com/gero3 - * @author Mugen87 / https://github.com/Mugen87 - * - * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. - * - * Supports both binary and ASCII encoded files, with automatic detection of type. - * - * The loader returns a non-indexed buffer geometry. - * - * Limitations: - * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). - * There is perhaps some question as to how valid it is to always assume little-endian-ness. - * ASCII decoding assumes file is UTF-8. - * - * Usage: - * var loader = new THREE.STLLoader(); - * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { - * scene.add( new THREE.Mesh( geometry ) ); - * }); - * - * For binary STLs geometry might contain colors for vertices. To use it: - * // use the same code to load STL as above - * if (geometry.hasColors) { - * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors }); - * } else { .... } - * var mesh = new THREE.Mesh( geometry, material ); - */ + static findByName( objectOrClipArray, name ) { -THREE.STLLoader = function (manager) { + let clipArray = objectOrClipArray; - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; + if ( ! Array.isArray( objectOrClipArray ) ) { -}; + const o = objectOrClipArray; + clipArray = o.geometry && o.geometry.animations || o.animations; -THREE.STLLoader.prototype = { + } - constructor: THREE.STLLoader, + for ( let i = 0; i < clipArray.length; i ++ ) { - load: function (url, onLoad, onProgress, onError) { + if ( clipArray[ i ].name === name ) { - var scope = this; + return clipArray[ i ]; - var loader = new THREE.FileLoader(scope.manager); - loader.setResponseType('arraybuffer'); - loader.load(url, function (text) { + } - onLoad(scope.parse(text)); + } - }, onProgress, onError); + return null; - }, + } - parse: function (data) { + static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { - function isBinary(data) { + const animationToMorphTargets = {}; - var expect, face_size, n_faces, reader; - reader = new DataView(data); - face_size = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8); - n_faces = reader.getUint32(80, true); - expect = 80 + (32 / 8) + (n_faces * face_size); + // tested with https://regex101.com/ on trick sequences + // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 + const pattern = /^([\w-]*?)([\d]+)$/; + + // sort morph target names into animation groups based + // patterns like Walk_001, Walk_002, Run_001, Run_002 + for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { - if (expect === reader.byteLength) { + const morphTarget = morphTargets[ i ]; + const parts = morphTarget.name.match( pattern ); - return true; + if ( parts && parts.length > 1 ) { - } + const name = parts[ 1 ]; - // An ASCII STL data must begin with 'solid ' as the first six bytes. - // However, ASCII STLs lacking the SPACE after the 'd' are known to be - // plentiful. So, check the first 5 bytes for 'solid'. + let animationMorphTargets = animationToMorphTargets[ name ]; - // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' + if ( ! animationMorphTargets ) { - var solid = [115, 111, 108, 105, 100]; + animationToMorphTargets[ name ] = animationMorphTargets = []; - for (var i = 0; i < 5; i++) { + } - // If solid[ i ] does not match the i-th byte, then it is not an - // ASCII STL; hence, it is binary and return true. + animationMorphTargets.push( morphTarget ); - if (solid[i] != reader.getUint8(i, false)) { return true; } + } - } + } - // First 5 bytes read "solid"; declare it to be an ASCII STL + const clips = []; - return false; + for ( const name in animationToMorphTargets ) { - } + clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); - function parseBinary(data) { + } - var reader = new DataView(data); - var faces = reader.getUint32(80, true); + return clips; - var r, g, b, hasColors = false, colors; - var defaultR, defaultG, defaultB, alpha; + } - // process STL header - // check for default color in header ("COLOR=rgba" sequence). + // parse the animation.hierarchy format + static parseAnimation( animation, bones ) { - for (var index = 0; index < 80 - 10; index++) { + if ( ! animation ) { - if ((reader.getUint32(index, false) == 0x434F4C4F /*COLO*/) && - (reader.getUint8(index + 4) == 0x52 /*'R'*/) && - (reader.getUint8(index + 5) == 0x3D /*'='*/)) { + console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); + return null; - hasColors = true; - colors = []; + } - defaultR = reader.getUint8(index + 6) / 255; - defaultG = reader.getUint8(index + 7) / 255; - defaultB = reader.getUint8(index + 8) / 255; - alpha = reader.getUint8(index + 9) / 255; + const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { - } + // only return track if there are actually keys. + if ( animationKeys.length !== 0 ) { - } + const times = []; + const values = []; - var dataOffset = 84; - var faceLength = 12 * 4 + 2; + flattenJSON( animationKeys, times, values, propertyName ); - var geometry = new THREE.BufferGeometry(); + // empty keys are filtered out, so check again + if ( times.length !== 0 ) { - var vertices = []; - var normals = []; + destTracks.push( new trackType( trackName, times, values ) ); - for (var face = 0; face < faces; face++) { + } - var start = dataOffset + face * faceLength; - var normalX = reader.getFloat32(start, true); - var normalY = reader.getFloat32(start + 4, true); - var normalZ = reader.getFloat32(start + 8, true); + } - if (hasColors) { + }; - var packedColor = reader.getUint16(start + 48, true); + const tracks = []; - if ((packedColor & 0x8000) === 0) { + const clipName = animation.name || 'default'; + const fps = animation.fps || 30; + const blendMode = animation.blendMode; - // facet has its own unique color + // automatic length determination in AnimationClip. + let duration = animation.length || - 1; - r = (packedColor & 0x1F) / 31; - g = ((packedColor >> 5) & 0x1F) / 31; - b = ((packedColor >> 10) & 0x1F) / 31; + const hierarchyTracks = animation.hierarchy || []; - } else { + for ( let h = 0; h < hierarchyTracks.length; h ++ ) { - r = defaultR; - g = defaultG; - b = defaultB; + const animationKeys = hierarchyTracks[ h ].keys; - } + // skip empty tracks + if ( ! animationKeys || animationKeys.length === 0 ) continue; - } + // process morph targets + if ( animationKeys[ 0 ].morphTargets ) { - for (var i = 1; i <= 3; i++) { + // figure out all morph targets used in this track + const morphTargetNames = {}; - var vertexstart = start + i * 12; + let k; - vertices.push(reader.getFloat32(vertexstart, true)); - vertices.push(reader.getFloat32(vertexstart + 4, true)); - vertices.push(reader.getFloat32(vertexstart + 8, true)); + for ( k = 0; k < animationKeys.length; k ++ ) { - normals.push(normalX, normalY, normalZ); + if ( animationKeys[ k ].morphTargets ) { - if (hasColors) { + for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { - colors.push(r, g, b); + morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; - } + } - } + } - } + } + + // create a track for each morph target with all zero + // morphTargetInfluences except for the keys in which + // the morphTarget is named. + for ( const morphTargetName in morphTargetNames ) { - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); + const times = []; + const values = []; - if (hasColors) { + for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); - geometry.hasColors = true; - geometry.alpha = alpha; + const animationKey = animationKeys[ k ]; - } + times.push( animationKey.time ); + values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); - return geometry; + } - } + tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); - function parseASCII(data) { + } - var geometry = new THREE.BufferGeometry(); - var patternFace = /facet([\s\S]*?)endfacet/g; - var faceCounter = 0; + duration = morphTargetNames.length * fps; - var patternFloat = /[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source; - var patternVertex = new RegExp('vertex' + patternFloat + patternFloat + patternFloat, 'g'); - var patternNormal = new RegExp('normal' + patternFloat + patternFloat + patternFloat, 'g'); + } else { - var vertices = []; - var normals = []; + // ...assume skeletal animation - var normal = new THREE.Vector3(); + const boneName = '.bones[' + bones[ h ].name + ']'; - var result; + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.position', + animationKeys, 'pos', tracks ); - while ((result = patternFace.exec(data)) !== null) { + addNonemptyTrack( + QuaternionKeyframeTrack, boneName + '.quaternion', + animationKeys, 'rot', tracks ); - var vertexCountPerFace = 0; - var normalCountPerFace = 0; + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.scale', + animationKeys, 'scl', tracks ); - var text = result[0]; + } - while ((result = patternNormal.exec(text)) !== null) { + } - normal.x = parseFloat(result[1]); - normal.y = parseFloat(result[2]); - normal.z = parseFloat(result[3]); - normalCountPerFace++; + if ( tracks.length === 0 ) { - } + return null; - while ((result = patternVertex.exec(text)) !== null) { + } - vertices.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])); - normals.push(normal.x, normal.y, normal.z); - vertexCountPerFace++; + const clip = new this( clipName, duration, tracks, blendMode ); - } + return clip; - // every face have to own ONE valid normal + } - if (normalCountPerFace !== 1) { + resetDuration() { - console.error('THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter); + const tracks = this.tracks; + let duration = 0; - } + for ( let i = 0, n = tracks.length; i !== n; ++ i ) { - // each face have to own THREE valid vertices + const track = this.tracks[ i ]; - if (vertexCountPerFace !== 3) { + duration = Math.max( duration, track.times[ track.times.length - 1 ] ); - console.error('THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter); + } - } + this.duration = duration; - faceCounter++; + return this; - } + } - geometry.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); - geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normals, 3)); + trim() { - return geometry; + for ( let i = 0; i < this.tracks.length; i ++ ) { - } + this.tracks[ i ].trim( 0, this.duration ); - function ensureString(buffer) { + } - if (typeof buffer !== 'string') { + return this; - var array_buffer = new Uint8Array(buffer); + } - if (window.TextDecoder !== undefined) { + validate() { - return new TextDecoder().decode(array_buffer); + let valid = true; - } + for ( let i = 0; i < this.tracks.length; i ++ ) { - var str = ''; + valid = valid && this.tracks[ i ].validate(); - for (var i = 0, il = buffer.byteLength; i < il; i++) { + } - str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian + return valid; - } + } - return str; + optimize() { - } else { + for ( let i = 0; i < this.tracks.length; i ++ ) { - return buffer; + this.tracks[ i ].optimize(); - } + } - } + return this; - function ensureBinary(buffer) { + } - if (typeof buffer === 'string') { + clone() { - var array_buffer = new Uint8Array(buffer.length); - for (var i = 0; i < buffer.length; i++) { + const tracks = []; - array_buffer[i] = buffer.charCodeAt(i) & 0xff; // implicitly assumes little-endian + for ( let i = 0; i < this.tracks.length; i ++ ) { - } - return array_buffer.buffer || array_buffer; + tracks.push( this.tracks[ i ].clone() ); - } else { + } - return buffer; + return new this.constructor( this.name, this.duration, tracks, this.blendMode ); - } + } - } + toJSON() { - // start + return this.constructor.toJSON( this ); - var binData = ensureBinary(data); + } - return isBinary(binData) ? parseBinary(binData) : parseASCII(ensureString(data)); +} - } +function getTrackTypeForValueTypeName( typeName ) { -}; + switch ( typeName.toLowerCase() ) { -/** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * - * @Modified by Jose Rojas from OBJLoader.js@r106 - * - */ + case 'scalar': + case 'double': + case 'float': + case 'number': + case 'integer': -// o object_name | g group_name -var object_pattern = /^[og]\s*(.+)?/; -// mtllib file_reference -var material_library_pattern = /^mtllib /; -// usemtl material_name -var material_use_pattern = /^usemtl /; + return NumberKeyframeTrack; -function ParserState() { + case 'vector': + case 'vector2': + case 'vector3': + case 'vector4': - var state = { - objects: [], - object: {}, + return VectorKeyframeTrack; - vertices: [], - normals: [], - colors: [], - uvs: [], + case 'color': - materialLibraries: [], + return ColorKeyframeTrack; - startObject: function ( name, fromDeclaration ) { + case 'quaternion': - // If the current object (initial from reset) is not from a g/o declaration in the parsed - // file. We need to use it for the first parsed g/o to keep things in sync. - if ( this.object && this.object.fromDeclaration === false ) { + return QuaternionKeyframeTrack; - this.object.name = name; - this.object.fromDeclaration = ( fromDeclaration !== false ); - return; + case 'bool': + case 'boolean': - } + return BooleanKeyframeTrack; - var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); + case 'string': - if ( this.object && typeof this.object._finalize === 'function' ) { + return StringKeyframeTrack; - this.object._finalize( true ); + } - } + throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); - this.object = { - name: name || '', - fromDeclaration: ( fromDeclaration !== false ), +} - geometry: { - vertices: [], - normals: [], - colors: [], - uvs: [] - }, - materials: [], - smooth: true, +function parseKeyframeTrack( json ) { - startMaterial: function ( name, libraries ) { + if ( json.type === undefined ) { - var previous = this._finalize( false ); + throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); - // New usemtl declaration overwrites an inherited material, except if faces were declared - // after the material, then it must be preserved for proper MultiMaterial continuation. - if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { + } - this.materials.splice( previous.index, 1 ); + const trackType = getTrackTypeForValueTypeName( json.type ); - } + if ( json.times === undefined ) { - var material = { - index: this.materials.length, - name: name || '', - mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), - smooth: ( previous !== undefined ? previous.smooth : this.smooth ), - groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), - groupEnd: - 1, - groupCount: - 1, - inherited: false, - - clone: function ( index ) { - - var cloned = { - index: ( typeof index === 'number' ? index : this.index ), - name: this.name, - mtllib: this.mtllib, - smooth: this.smooth, - groupStart: 0, - groupEnd: - 1, - groupCount: - 1, - inherited: false - }; - cloned.clone = this.clone.bind( cloned ); - return cloned; + const times = [], values = []; - } - }; + flattenJSON( json.keys, times, values, 'value' ); - this.materials.push( material ); + json.times = times; + json.values = values; - return material; + } - }, + // derived classes can define a static parse method + if ( trackType.parse !== undefined ) { - currentMaterial: function () { + return trackType.parse( json ); - if ( this.materials.length > 0 ) { + } else { - return this.materials[ this.materials.length - 1 ]; + // by default, we assume a constructor compatible with the base + return new trackType( json.name, json.times, json.values, json.interpolation ); - } + } - return undefined; +} - }, +const Cache = { - _finalize: function ( end ) { + enabled: false, - var lastMultiMaterial = this.currentMaterial(); - if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { + files: {}, - lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; - lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; - lastMultiMaterial.inherited = false; + add: function ( key, file ) { - } + if ( this.enabled === false ) return; - // Ignore objects tail materials if no face declarations followed them before a new o/g started. - if ( end && this.materials.length > 1 ) { + // console.log( 'THREE.Cache', 'Adding key:', key ); - for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { + this.files[ key ] = file; - if ( this.materials[ mi ].groupCount <= 0 ) { + }, - this.materials.splice( mi, 1 ); + get: function ( key ) { - } + if ( this.enabled === false ) return; - } + // console.log( 'THREE.Cache', 'Checking key:', key ); - } + return this.files[ key ]; - // Guarantee at least one empty material, this makes the creation later more straight forward. - if ( end && this.materials.length === 0 ) { + }, - this.materials.push( { - name: '', - smooth: this.smooth - } ); + remove: function ( key ) { - } + delete this.files[ key ]; - return lastMultiMaterial; + }, - } - }; + clear: function () { - // Inherit previous objects material. - // Spec tells us that a declared material must be set to all objects until a new material is declared. - // If a usemtl declaration is encountered while this new object is being parsed, it will - // overwrite the inherited material. Exception being that there was already face declarations - // to the inherited material, then it will be preserved for proper MultiMaterial continuation. + this.files = {}; - if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { + } - var declared = previousMaterial.clone( 0 ); - declared.inherited = true; - this.object.materials.push( declared ); +}; - } +class LoadingManager { - this.objects.push( this.object ); + constructor( onLoad, onProgress, onError ) { - }, + const scope = this; - finalize: function () { + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; - if ( this.object && typeof this.object._finalize === 'function' ) { + // Refer to #5689 for the reason why we don't set .onStart + // in the constructor - this.object._finalize( true ); + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; - } + this.itemStart = function ( url ) { - }, + itemsTotal ++; - parseVertexIndex: function ( value, len ) { + if ( isLoading === false ) { - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + if ( scope.onStart !== undefined ) { - }, + scope.onStart( url, itemsLoaded, itemsTotal ); - parseNormalIndex: function ( value, len ) { + } - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + } - }, + isLoading = true; - parseUVIndex: function ( value, len ) { + }; - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; + this.itemEnd = function ( url ) { - }, + itemsLoaded ++; - addVertex: function ( a, b, c ) { + if ( scope.onProgress !== undefined ) { - var src = this.vertices; - var dst = this.object.geometry.vertices; + scope.onProgress( url, itemsLoaded, itemsTotal ); - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + } - }, + if ( itemsLoaded === itemsTotal ) { - addVertexPoint: function ( a ) { + isLoading = false; - var src = this.vertices; - var dst = this.object.geometry.vertices; + if ( scope.onLoad !== undefined ) { - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + scope.onLoad(); - }, + } - addVertexLine: function ( a ) { + } - var src = this.vertices; - var dst = this.object.geometry.vertices; + }; - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + this.itemError = function ( url ) { - }, + if ( scope.onError !== undefined ) { - addNormal: function ( a, b, c ) { + scope.onError( url ); - var src = this.normals; - var dst = this.object.geometry.normals; + } - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + }; - }, + this.resolveURL = function ( url ) { - addColor: function ( a, b, c ) { + if ( urlModifier ) { - var src = this.colors; - var dst = this.object.geometry.colors; + return urlModifier( url ); - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + } - }, + return url; - addUV: function ( a, b, c ) { + }; - var src = this.uvs; - var dst = this.object.geometry.uvs; + this.setURLModifier = function ( transform ) { - dst.push( src[ a + 0 ], src[ a + 1 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ] ); + urlModifier = transform; - }, + return this; - addUVLine: function ( a ) { + }; - var src = this.uvs; - var dst = this.object.geometry.uvs; + this.addHandler = function ( regex, loader ) { - dst.push( src[ a + 0 ], src[ a + 1 ] ); + handlers.push( regex, loader ); - }, + return this; - addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { + }; - var vLen = this.vertices.length; + this.removeHandler = function ( regex ) { - var ia = this.parseVertexIndex( a, vLen ); - var ib = this.parseVertexIndex( b, vLen ); - var ic = this.parseVertexIndex( c, vLen ); + const index = handlers.indexOf( regex ); - this.addVertex( ia, ib, ic ); + if ( index !== - 1 ) { - if ( ua !== undefined && ua !== '' ) { + handlers.splice( index, 2 ); - var uvLen = this.uvs.length; - ia = this.parseUVIndex( ua, uvLen ); - ib = this.parseUVIndex( ub, uvLen ); - ic = this.parseUVIndex( uc, uvLen ); - this.addUV( ia, ib, ic ); + } - } + return this; - if ( na !== undefined && na !== '' ) { + }; - // Normals are many times the same. If so, skip function call and parseInt. - var nLen = this.normals.length; - ia = this.parseNormalIndex( na, nLen ); + this.getHandler = function ( file ) { - ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); - ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); + for ( let i = 0, l = handlers.length; i < l; i += 2 ) { - this.addNormal( ia, ib, ic ); + const regex = handlers[ i ]; + const loader = handlers[ i + 1 ]; - } + if ( regex.global ) regex.lastIndex = 0; // see #17920 - if ( this.colors.length > 0 ) { + if ( regex.test( file ) ) { - this.addColor( ia, ib, ic ); + return loader; - } + } - }, + } - addPointGeometry: function ( vertices ) { + return null; - this.object.geometry.type = 'Points'; + }; - var vLen = this.vertices.length; + } - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { +} - this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); +const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); - } +class Loader { - }, + constructor( manager ) { - addLineGeometry: function ( vertices, uvs ) { + this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.object.geometry.type = 'Line'; + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; - var vLen = this.vertices.length; - var uvLen = this.uvs.length; + } - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { + load( /* url, onLoad, onProgress, onError */ ) {} - this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); + loadAsync( url, onProgress ) { - } + const scope = this; - for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { + return new Promise( function ( resolve, reject ) { - this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); + scope.load( url, resolve, onProgress, reject ); - } + } ); - } + } - }; + parse( /* data */ ) {} - state.startObject( '', false ); + setCrossOrigin( crossOrigin ) { - return state; + this.crossOrigin = crossOrigin; + return this; -} + } -THREE.OBJLoader = function( manager ) { + setWithCredentials( value ) { - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + this.withCredentials = value; + return this; - this.materials = null; + } -}; + setPath( path ) { -THREE.OBJLoader.prototype = { + this.path = path; + return this; - constructor: THREE.OBJLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + setResourcePath( resourcePath ) { - var scope = this; + this.resourcePath = resourcePath; + return this; - var loader = new THREE.FileLoader( scope.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { + } - onLoad( scope.parse( text ) ); + setRequestHeader( requestHeader ) { - }, onProgress, onError ); + this.requestHeader = requestHeader; + return this; - }, + } - setPath: function ( value ) { +} - this.path = value; +Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; - return this; +const loading = {}; - }, +class HttpError extends Error { - setMaterials: function ( materials ) { + constructor( message, response ) { - this.materials = materials; + super( message ); + this.response = response; - return this; + } - }, +} - parse: function ( text ) { +class FileLoader extends Loader { - console.time( 'OBJLoader' ); + constructor( manager ) { - var state = new ParserState(); + super( manager ); - if ( text.indexOf( '\r\n' ) !== - 1 ) { + } - // This is faster than String.split with regex that splits on both - text = text.replace( /\r\n/g, '\n' ); + load( url, onLoad, onProgress, onError ) { - } + if ( url === undefined ) url = ''; - if ( text.indexOf( '\\\n' ) !== - 1 ) { + if ( this.path !== undefined ) url = this.path + url; - // join lines separated by a line continuation character (\) - text = text.replace( /\\\n/g, '' ); + url = this.manager.resolveURL( url ); - } + const cached = Cache.get( url ); - var lines = text.split( '\n' ); - var line = '', lineFirstChar = ''; - var lineLength = 0; - var result = []; + if ( cached !== undefined ) { - // Faster to just trim left side of the line. Use if available. - var trimLeft = ( typeof ''.trimLeft === 'function' ); + this.manager.itemStart( url ); - for ( var i = 0, l = lines.length; i < l; i ++ ) { + setTimeout( () => { - line = lines[ i ]; + if ( onLoad ) onLoad( cached ); - line = trimLeft ? line.trimLeft() : line.trim(); + this.manager.itemEnd( url ); - lineLength = line.length; + }, 0 ); - if ( lineLength === 0 ) { continue; } + return cached; - lineFirstChar = line.charAt( 0 ); + } - // @todo invoke passed in handler if any - if ( lineFirstChar === '#' ) { continue; } + // Check if request is duplicate - if ( lineFirstChar === 'v' ) { + if ( loading[ url ] !== undefined ) { - var data = line.split( /\s+/ ); + loading[ url ].push( { - switch ( data[ 0 ] ) { + onLoad: onLoad, + onProgress: onProgress, + onError: onError - case 'v': - state.vertices.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - if ( data.length === 8 ) { + } ); - state.colors.push( - parseFloat( data[ 4 ] ), - parseFloat( data[ 5 ] ), - parseFloat( data[ 6 ] ) + return; - ); + } - } - break; - case 'vn': - state.normals.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - break; - case 'vt': - state.uvs.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ) - ); - break; + // Initialise array for duplicate requests + loading[ url ] = []; - } + loading[ url ].push( { + onLoad: onLoad, + onProgress: onProgress, + onError: onError, + } ); - } else if ( lineFirstChar === 'f' ) { + // create request + const req = new Request( url, { + headers: new Headers( this.requestHeader ), + credentials: this.withCredentials ? 'include' : 'same-origin', + // An abort controller could be added within a future PR + } ); - var lineData = line.substr( 1 ).trim(); - var vertexData = lineData.split( /\s+/ ); - var faceVertices = []; + // record states ( avoid data race ) + const mimeType = this.mimeType; + const responseType = this.responseType; - // Parse the face vertex data into an easy to work with format + // start the fetch + fetch( req ) + .then( response => { - for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { + if ( response.status === 200 || response.status === 0 ) { - var vertex = vertexData[ j ]; + // Some browsers return HTTP Status 0 when using non-http protocol + // e.g. 'file://' or 'data://'. Handle as success. - if ( vertex.length > 0 ) { + if ( response.status === 0 ) { - var vertexParts = vertex.split( '/' ); - faceVertices.push( vertexParts ); + console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); } - } + // Workaround: Checking if response.body === undefined for Alipay browser #23548 - // Draw an edge between the first vertex and all subsequent vertices to form an n-gon + if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { - var v1 = faceVertices[ 0 ]; + return response; - for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { + } - var v2 = faceVertices[ j ]; - var v3 = faceVertices[ j + 1 ]; + const callbacks = loading[ url ]; + const reader = response.body.getReader(); - state.addFace( - v1[ 0 ], v2[ 0 ], v3[ 0 ], - v1[ 1 ], v2[ 1 ], v3[ 1 ], - v1[ 2 ], v2[ 2 ], v3[ 2 ] - ); + // Nginx needs X-File-Size check + // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content + const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); + const total = contentLength ? parseInt( contentLength ) : 0; + const lengthComputable = total !== 0; + let loaded = 0; - } + // periodically read data into the new stream tracking while download progress + const stream = new ReadableStream( { + start( controller ) { - } else if ( lineFirstChar === 'l' ) { + readData(); - var lineParts = line.substring( 1 ).trim().split( " " ); - var lineVertices = [], lineUVs = []; + function readData() { - if ( line.indexOf( "/" ) === - 1 ) { + reader.read().then( ( { done, value } ) => { - lineVertices = lineParts; + if ( done ) { - } else { + controller.close(); - for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { + } else { - var parts = lineParts[ li ].split( "/" ); + loaded += value.byteLength; - if ( parts[ 0 ] !== "" ) { lineVertices.push( parts[ 0 ] ); } - if ( parts[ 1 ] !== "" ) { lineUVs.push( parts[ 1 ] ); } + 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 ); - } - state.addLineGeometry( lineVertices, lineUVs ); + } - } else if ( lineFirstChar === 'p' ) { + controller.enqueue( value ); + readData(); - var lineData = line.substr( 1 ).trim(); - var pointData = lineData.split( " " ); + } - state.addPointGeometry( pointData ); + }, ( e ) => { - } else if ( ( result = object_pattern.exec( line ) ) !== null ) { + controller.error( e ); - // o object_name - // or - // g group_name + } ); - // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 - // var name = result[ 0 ].substr( 1 ).trim(); - var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); + } - state.startObject( name ); + } - } else if ( material_use_pattern.test( line ) ) { + } ); - // material + return new Response( stream ); - state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); + } else { - } else if ( material_library_pattern.test( line ) ) { + throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); - // mtl file + } - state.materialLibraries.push( line.substring( 7 ).trim() ); + } ) + .then( response => { - } else if ( lineFirstChar === 's' ) { + switch ( responseType ) { - result = line.split( ' ' ); + case 'arraybuffer': - // smooth shading + return response.arrayBuffer(); - // @todo Handle files that have varying smooth values for a set of faces inside one geometry, - // but does not define a usemtl for each face set. - // This should be detected and a dummy material created (later MultiMaterial and geometry groups). - // This requires some care to not create extra material on each smooth value for "normal" obj files. - // where explicit usemtl defines geometry groups. - // Example asset: examples/models/obj/cerberus/Cerberus.obj + case 'blob': - /* - * http://paulbourke.net/dataformats/obj/ - * or - * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf - * - * From chapter "Grouping" Syntax explanation "s group_number": - * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. - * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form - * surfaces, smoothing groups are either turned on or off; there is no difference between values greater - * than 0." - */ - if ( result.length > 1 ) { + return response.blob(); - var value = result[ 1 ].trim().toLowerCase(); - state.object.smooth = ( value !== '0' && value !== 'off' ); + case 'document': - } else { + return response.text() + .then( text => { - // ZBrush can produce "s" lines #11707 - state.object.smooth = true; + const parser = new DOMParser(); + return parser.parseFromString( text, mimeType ); - } - var material = state.object.currentMaterial(); - if ( material ) { material.smooth = state.object.smooth; } + } ); - } else { + case 'json': - // Handle null terminated files without exception - if ( line === '\0' ) { continue; } + return response.json(); - throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); + default: - } + if ( mimeType === undefined ) { - } + return response.text(); - state.finalize(); + } else { - var container = new THREE.Object3D(); - container.materialLibraries = [].concat( state.materialLibraries ); + // sniff encoding + const re = /charset="?([^;"\s]*)"?/i; + const exec = re.exec( mimeType ); + const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; + const decoder = new TextDecoder( label ); + return response.arrayBuffer().then( ab => decoder.decode( ab ) ); + + } - for ( var i = 0, l = state.objects.length; i < l; i ++ ) { + } - var object = state.objects[ i ]; - var geometry = object.geometry; - var materials = object.materials; - var isLine = ( geometry.type === 'Line' ); - var isPoints = ( geometry.type === 'Points' ); - var hasVertexColors = false; + } ) + .then( data => { - // Skip o/g line declarations that did not follow with any faces - if ( geometry.vertices.length === 0 ) { continue; } + // Add to cache only on HTTP success, so that we do not cache + // error response bodies as proper responses to requests. + Cache.add( url, data ); - var buffergeometry = new THREE.BufferGeometry(); + const callbacks = loading[ url ]; + delete loading[ url ]; - buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - if ( geometry.normals.length > 0 ) { + const callback = callbacks[ i ]; + if ( callback.onLoad ) callback.onLoad( data ); - buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); + } - } else { + } ) + .catch( err => { - buffergeometry.computeVertexNormals(); + // Abort errors and other errors are handled the same - } + const callbacks = loading[ url ]; - if ( geometry.colors.length > 0 ) { + if ( callbacks === undefined ) { - hasVertexColors = true; - buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); + // When onLoad was called and url was deleted in `loading` + this.manager.itemError( url ); + throw err; - } + } - if ( geometry.uvs.length > 0 ) { + delete loading[ url ]; - buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - } + const callback = callbacks[ i ]; + if ( callback.onError ) callback.onError( err ); - // Create materials + } - var createdMaterials = []; + this.manager.itemError( url ); - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + } ) + .finally( () => { - var sourceMaterial = materials[ mi ]; - var material = undefined; + this.manager.itemEnd( url ); - if ( this.materials !== null ) { + } ); - material = this.materials.create( sourceMaterial.name ); + this.manager.itemStart( url ); - // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. - if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { + } - var materialLine = new THREE.LineBasicMaterial(); - THREE.Material.prototype.copy.call( materialLine, material ); - materialLine.color.copy( material.color ); - materialLine.lights = false; - material = materialLine; + setResponseType( value ) { - } else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { + this.responseType = value; + return this; - var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); - THREE.Material.prototype.copy.call( materialPoints, material ); - materialPoints.color.copy( material.color ); - materialPoints.map = material.map; - materialPoints.lights = false; - material = materialPoints; + } - } + setMimeType( value ) { - } + this.mimeType = value; + return this; - if ( ! material ) { + } - if ( isLine ) { +} - material = new THREE.LineBasicMaterial(); +class ImageLoader extends Loader { - } else if ( isPoints ) { + constructor( manager ) { - material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); + super( manager ); - } else { + } - material = new THREE.MeshPhongMaterial(); + load( url, onLoad, onProgress, onError ) { - } + if ( this.path !== undefined ) url = this.path + url; - material.name = sourceMaterial.name; + url = this.manager.resolveURL( url ); - } + const scope = this; - material.flatShading = sourceMaterial.smooth ? false : true; - material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; + const cached = Cache.get( url ); - createdMaterials.push( material ); + if ( cached !== undefined ) { - } + scope.manager.itemStart( url ); - // Create mesh + setTimeout( function () { - var mesh; + if ( onLoad ) onLoad( cached ); - if ( createdMaterials.length > 1 ) { + scope.manager.itemEnd( url ); - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + }, 0 ); - var sourceMaterial = materials[ mi ]; - buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); + return cached; - } + } - if ( isLine ) { + const image = createElementNS( 'img' ); - mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); + function onImageLoad() { - } else if ( isPoints ) { + removeEventListeners(); - mesh = new THREE.Points( buffergeometry, createdMaterials ); + Cache.add( url, this ); - } else { + if ( onLoad ) onLoad( this ); - mesh = new THREE.Mesh( buffergeometry, createdMaterials ); + scope.manager.itemEnd( url ); - } + } - } else { + function onImageError( event ) { - if ( isLine ) { + removeEventListeners(); - mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); + if ( onError ) onError( event ); - } else if ( isPoints ) { + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); + } - } else { + function removeEventListeners() { - mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); + image.removeEventListener( 'load', onImageLoad, false ); + image.removeEventListener( 'error', onImageError, false ); - } + } - } + image.addEventListener( 'load', onImageLoad, false ); + image.addEventListener( 'error', onImageError, false ); - mesh.name = object.name; + if ( url.slice( 0, 5 ) !== 'data:' ) { - container.add( mesh ); + if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; } - console.timeEnd( 'OBJLoader' ); + scope.manager.itemStart( url ); + + image.src = url; - return container; + return image; } -}; +} /** - * @fileOverview - * Loads a Wavefront .mtl file specifying materials + * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) * - * @author angelxuanchang + * Sub classes have to implement the parse() method which will be used in load(). */ -THREE.MTLLoader = function ( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - -}; +class DataTextureLoader extends Loader { -THREE.MTLLoader.prototype = { + constructor( manager ) { - constructor: THREE.MTLLoader, + super( manager ); - crossOrigin: 'anonymous', + } - /** - * Loads and parses a MTL asset from a URL. - * - * @param {String} url - URL to the MTL file. - * @param {Function} [onLoad] - Callback invoked with the loaded object. - * @param {Function} [onProgress] - Callback for download progress. - * @param {Function} [onError] - Callback for download errors. - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to load. - */ - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var path = ( this.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path; + const texture = new DataTexture(); - var loader = new THREE.FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); loader.setPath( this.path ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text, path ) ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( buffer ) { - }, onProgress, onError ); + let texData; - }, + try { - /** - * Set base path for resolving references. - * If set this path will be prepended to each loaded and found reference. - * - * @see setResourcePath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setPath: function ( path ) { + texData = scope.parse( buffer ); - this.path = path; - return this; + } catch ( error ) { - }, + if ( onError !== undefined ) { - /** - * Set base path for additional resources like textures. - * - * @see setPath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.setResourcePath( 'assets/textures/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setResourcePath: function ( path ) { + onError( error ); - this.resourcePath = path; - return this; + } else { - }, + console.error( error ); + return; - setTexturePath: function ( path ) { + } - console.warn( 'THREE.MTLLoader: .setTexturePath() has been renamed to .setResourcePath().' ); - return this.setResourcePath( path ); + } - }, + if ( texData.image !== undefined ) { - setCrossOrigin: function ( value ) { + texture.image = texData.image; - this.crossOrigin = value; - return this; + } else if ( texData.data !== undefined ) { - }, + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; - setMaterialOptions: function ( value ) { + } - this.materialOptions = value; - return this; + texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; + texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; - }, + texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; + texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; - /** - * Parses a MTL file. - * - * @param {String} text - Content of MTL file - * @return {THREE.MTLLoader.MaterialCreator} - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to parse. - */ - parse: function ( text, path ) { + texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - var lines = text.split( '\n' ); - var info = {}; - var delimiter_pattern = /\s+/; - var materialsInfo = {}; + if ( texData.colorSpace !== undefined ) { - for ( var i = 0; i < lines.length; i ++ ) { + texture.colorSpace = texData.colorSpace; - var line = lines[ i ]; - line = line.trim(); + } - if ( line.length === 0 || line.charAt( 0 ) === '#' ) { + if ( texData.flipY !== undefined ) { - // Blank line or comment ignore - continue; + texture.flipY = texData.flipY; } - var pos = line.indexOf( ' ' ); - - var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; - key = key.toLowerCase(); + if ( texData.format !== undefined ) { - var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; - value = value.trim(); + texture.format = texData.format; - if ( key === 'newmtl' ) { + } - // New material + if ( texData.type !== undefined ) { - info = { name: value }; - materialsInfo[ value ] = info; + texture.type = texData.type; - } else { + } - if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { + if ( texData.mipmaps !== undefined ) { - var ss = value.split( delimiter_pattern, 3 ); - info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; + texture.mipmaps = texData.mipmaps; + texture.minFilter = LinearMipmapLinearFilter; // presumably... - } else { + } - info[ key ] = value; + if ( texData.mipmapCount === 1 ) { - } + texture.minFilter = LinearFilter; } - } - - var materialCreator = new THREE.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions ); - materialCreator.setCrossOrigin( this.crossOrigin ); - materialCreator.setManager( this.manager ); - materialCreator.setMaterials( materialsInfo ); - return materialCreator; + if ( texData.generateMipmaps !== undefined ) { - } + texture.generateMipmaps = texData.generateMipmaps; -}; + } -/** - * Create a new THREE-MTLLoader.MaterialCreator - * @param baseUrl - Url relative to which textures are loaded - * @param options - Set of options on how to construct the materials - * side: Which side to apply the material - * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide - * wrap: What type of wrapping to apply for textures - * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping - * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 - * Default: false, assumed to be already normalized - * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's - * Default: false - * @constructor - */ + texture.needsUpdate = true; -THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) { + if ( onLoad ) onLoad( texture, texData ); - this.baseUrl = baseUrl || ''; - this.options = options; - this.materialsInfo = {}; - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; + }, onProgress, onError ); - this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide; - this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping; -}; + return texture; -THREE.MTLLoader.MaterialCreator.prototype = { + } - constructor: THREE.MTLLoader.MaterialCreator, +} - crossOrigin: 'anonymous', +class TextureLoader extends Loader { - setCrossOrigin: function ( value ) { + constructor( manager ) { - this.crossOrigin = value; - return this; + super( manager ); - }, + } - setManager: function ( value ) { + load( url, onLoad, onProgress, onError ) { - this.manager = value; + const texture = new Texture(); - }, + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); - setMaterials: function ( materialsInfo ) { + loader.load( url, function ( image ) { - this.materialsInfo = this.convert( materialsInfo ); - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; + texture.image = image; + texture.needsUpdate = true; - }, + if ( onLoad !== undefined ) { - convert: function ( materialsInfo ) { + onLoad( texture ); - if ( ! this.options ) { return materialsInfo; } + } - var converted = {}; + }, onProgress, onError ); - for ( var mn in materialsInfo ) { + return texture; - // Convert materials info into normalized form based on options + } - var mat = materialsInfo[ mn ]; +} - var covmat = {}; +class Light extends Object3D { - converted[ mn ] = covmat; + constructor( color, intensity = 1 ) { - for ( var prop in mat ) { + super(); - var save = true; - var value = mat[ prop ]; - var lprop = prop.toLowerCase(); + this.isLight = true; - switch ( lprop ) { + this.type = 'Light'; - case 'kd': - case 'ka': - case 'ks': + this.color = new Color( color ); + this.intensity = intensity; - // Diffuse color (color under white light) using RGB values + } - if ( this.options && this.options.normalizeRGB ) { + dispose() { - value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; + // Empty here in base class; some subclasses override. - } + } - if ( this.options && this.options.ignoreZeroRGBs ) { + copy( source, recursive ) { - if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { + super.copy( source, recursive ); - // ignore + this.color.copy( source.color ); + this.intensity = source.intensity; - save = false; + return this; - } + } - } + toJSON( meta ) { - break; + const data = super.toJSON( meta ); - } + data.object.color = this.color.getHex(); + data.object.intensity = this.intensity; - if ( save ) { + if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); - covmat[ lprop ] = value; + if ( this.distance !== undefined ) data.object.distance = this.distance; + if ( this.angle !== undefined ) data.object.angle = this.angle; + if ( this.decay !== undefined ) data.object.decay = this.decay; + if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - } + if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); + if ( this.target !== undefined ) data.object.target = this.target.uuid; - } + return data; - } + } - return converted; +} - }, +const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); +const _lookTarget$1 = /*@__PURE__*/ new Vector3(); - preload: function () { +class LightShadow { - for ( var mn in this.materialsInfo ) { + constructor( camera ) { - this.create( mn ); + this.camera = camera; - } + this.intensity = 1; - }, + this.bias = 0; + this.normalBias = 0; + this.radius = 1; + this.blurSamples = 8; - getIndex: function ( materialName ) { + this.mapSize = new Vector2( 512, 512 ); - return this.nameLookup[ materialName ]; + this.map = null; + this.mapPass = null; + this.matrix = new Matrix4(); - }, + this.autoUpdate = true; + this.needsUpdate = false; - getAsArray: function () { + this._frustum = new Frustum(); + this._frameExtents = new Vector2( 1, 1 ); - var index = 0; + this._viewportCount = 1; - for ( var mn in this.materialsInfo ) { + this._viewports = [ - this.materialsArray[ index ] = this.create( mn ); - this.nameLookup[ mn ] = index; - index ++; + new Vector4( 0, 0, 1, 1 ) - } + ]; - return this.materialsArray; + } - }, + getViewportCount() { - create: function ( materialName ) { + return this._viewportCount; - if ( this.materials[ materialName ] === undefined ) { + } - this.createMaterial_( materialName ); + getFrustum() { - } + return this._frustum; - return this.materials[ materialName ]; + } - }, + updateMatrices( light ) { - createMaterial_: function ( materialName ) { + const shadowCamera = this.camera; + const shadowMatrix = this.matrix; - // Create material + _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld$1 ); - var scope = this; - var mat = this.materialsInfo[ materialName ]; - var params = { + _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget$1 ); + shadowCamera.updateMatrixWorld(); - name: materialName, - side: this.side + _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); - }; + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - function resolveURL( baseUrl, url ) { + shadowMatrix.multiply( _projScreenMatrix$1 ); - if ( typeof url !== 'string' || url === '' ) - { return ''; } + } - // Absolute URL - if ( /^https?:\/\//i.test( url ) ) { return url; } + getViewport( viewportIndex ) { - return baseUrl + url; + return this._viewports[ viewportIndex ]; - } + } - function setMapForType( mapType, value ) { + getFrameExtents() { - if ( params[ mapType ] ) { return; } // Keep the first encountered texture + return this._frameExtents; - var texParams = scope.getTextureParams( value, params ); - var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); + } - map.repeat.copy( texParams.scale ); - map.offset.copy( texParams.offset ); + dispose() { - map.wrapS = scope.wrap; - map.wrapT = scope.wrap; + if ( this.map ) { - params[ mapType ] = map; + this.map.dispose(); } - for ( var prop in mat ) { - - var value = mat[ prop ]; - var n; - - if ( value === '' ) { continue; } - - switch ( prop.toLowerCase() ) { - - // Ns is material specular exponent - - case 'kd': - - // Diffuse color (color under white light) using RGB values - - params.color = new THREE.Color().fromArray( value ); + if ( this.mapPass ) { - break; + this.mapPass.dispose(); - case 'ks': + } - // Specular color (color when light is reflected from shiny surface) using RGB values - params.specular = new THREE.Color().fromArray( value ); + } - break; + copy( source ) { - case 'ke': + this.camera = source.camera.clone(); - // Emissive using RGB values - params.emissive = new THREE.Color().fromArray( value ); + this.intensity = source.intensity; - break; + this.bias = source.bias; + this.radius = source.radius; - case 'map_kd': + this.mapSize.copy( source.mapSize ); - // Diffuse texture map + return this; - setMapForType( "map", value ); + } - break; + clone() { - case 'map_ks': + return new this.constructor().copy( this ); - // Specular map + } - setMapForType( "specularMap", value ); + toJSON() { - break; + const object = {}; - case 'map_ke': + if ( this.intensity !== 1 ) object.intensity = this.intensity; + 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(); - // Emissive map + object.camera = this.camera.toJSON( false ).object; + delete object.camera.matrix; - setMapForType( "emissiveMap", value ); + return object; - break; + } - case 'norm': +} - setMapForType( "normalMap", value ); +class SpotLightShadow extends LightShadow { - break; + constructor() { - case 'map_bump': - case 'bump': + super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); - // Bump texture map + this.isSpotLightShadow = true; - setMapForType( "bumpMap", value ); + this.focus = 1; - break; + } - case 'map_d': + updateMatrices( light ) { - // Alpha map + const camera = this.camera; - setMapForType( "alphaMap", value ); - params.transparent = true; + const fov = RAD2DEG * 2 * light.angle * this.focus; + const aspect = this.mapSize.width / this.mapSize.height; + const far = light.distance || camera.far; - break; + if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { - case 'ns': + camera.fov = fov; + camera.aspect = aspect; + camera.far = far; + camera.updateProjectionMatrix(); - // The specular exponent (defines the focus of the specular highlight) - // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. + } - params.shininess = parseFloat( value ); + super.updateMatrices( light ); - break; + } - case 'd': - n = parseFloat( value ); + copy( source ) { - if ( n < 1 ) { + super.copy( source ); - params.opacity = n; - params.transparent = true; + this.focus = source.focus; - } + return this; - break; + } - case 'tr': - n = parseFloat( value ); +} - if ( this.options && this.options.invertTrProperty ) { n = 1 - n; } +class SpotLight extends Light { - if ( n > 0 ) { + constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { - params.opacity = 1 - n; - params.transparent = true; + super( color, intensity ); - } + this.isSpotLight = true; - break; + this.type = 'SpotLight'; - } + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - } + this.target = new Object3D(); - this.materials[ materialName ] = new THREE.MeshPhongMaterial( params ); - return this.materials[ materialName ]; + this.distance = distance; + this.angle = angle; + this.penumbra = penumbra; + this.decay = decay; - }, + this.map = null; - getTextureParams: function ( value, matParams ) { + this.shadow = new SpotLightShadow(); - var texParams = { + } - scale: new THREE.Vector2( 1, 1 ), - offset: new THREE.Vector2( 0, 0 ) + get power() { - }; + // compute the light's luminous power (in lumens) from its intensity (in candela) + // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd) + return this.intensity * Math.PI; - var items = value.split( /\s+/ ); - var pos; + } - pos = items.indexOf( '-bm' ); + set power( power ) { - if ( pos >= 0 ) { + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / Math.PI; - matParams.bumpScale = parseFloat( items[ pos + 1 ] ); - items.splice( pos, 2 ); + } - } + dispose() { - pos = items.indexOf( '-s' ); + this.shadow.dispose(); - if ( pos >= 0 ) { + } - texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! + copy( source, recursive ) { - } + super.copy( source, recursive ); - pos = items.indexOf( '-o' ); + this.distance = source.distance; + this.angle = source.angle; + this.penumbra = source.penumbra; + this.decay = source.decay; - if ( pos >= 0 ) { + this.target = source.target.clone(); - texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! + this.shadow = source.shadow.clone(); - } + return this; - texParams.url = items.join( ' ' ).trim(); - return texParams; + } - }, +} - loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { +const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld = /*@__PURE__*/ new Vector3(); +const _lookTarget = /*@__PURE__*/ new Vector3(); - var texture; - var loader = THREE.Loader.Handlers.get( url ); - var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager; +class PointLightShadow extends LightShadow { - if ( loader === null ) { + constructor() { - loader = new THREE.TextureLoader( manager ); + super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); - } + this.isPointLightShadow = true; - if ( loader.setCrossOrigin ) { loader.setCrossOrigin( this.crossOrigin ); } - texture = loader.load( url, onLoad, onProgress, onError ); + this._frameExtents = new Vector2( 4, 2 ); - if ( mapping !== undefined ) { texture.mapping = mapping; } + this._viewportCount = 6; - return texture; + this._viewports = [ + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction + + // positive X + new Vector4( 2, 1, 1, 1 ), + // negative X + new Vector4( 0, 1, 1, 1 ), + // positive Z + new Vector4( 3, 1, 1, 1 ), + // negative Z + new Vector4( 1, 1, 1, 1 ), + // positive Y + new Vector4( 3, 0, 1, 1 ), + // negative Y + new Vector4( 1, 0, 1, 1 ) + ]; - } + this._cubeDirections = [ + new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), + new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) + ]; -}; + this._cubeUps = [ + new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), + new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) + ]; -/** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - * @Modified by Jihoon Lee from ColladerLoader.js@r88 - * To support rviz compatible collada viewing. - * See: #202 why it is forked. - * - * It is a fork from ColladerLoader.js in three.js. It follows three.js license. - */ + } -THREE.ColladaLoader = function (manager) { + updateMatrices( light, viewportIndex = 0 ) { - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; + const camera = this.camera; + const shadowMatrix = this.matrix; -}; + const far = light.distance || camera.far; -THREE.ColladaLoader.prototype = { + if ( far !== camera.far ) { - constructor: THREE.ColladaLoader, + camera.far = far; + camera.updateProjectionMatrix(); - crossOrigin: 'Anonymous', + } - load: function (url, onLoad, onProgress, onError) { + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + camera.position.copy( _lightPositionWorld ); - var scope = this; + _lookTarget.copy( camera.position ); + _lookTarget.add( this._cubeDirections[ viewportIndex ] ); + camera.up.copy( this._cubeUps[ viewportIndex ] ); + camera.lookAt( _lookTarget ); + camera.updateMatrixWorld(); - var path = THREE.Loader.prototype.extractUrlBase(url); + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - var loader = new THREE.FileLoader(scope.manager); - loader.load(url, function (text) { + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix ); - onLoad(scope.parse(text, path)); + } - }, onProgress, onError); +} - }, +class PointLight extends Light { - options: { + constructor( color, intensity, distance = 0, decay = 2 ) { - set convertUpAxis(value) { + super( color, intensity ); - console.warn('THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.'); + this.isPointLight = true; - } + this.type = 'PointLight'; - }, + this.distance = distance; + this.decay = decay; - setCrossOrigin: function (value) { + this.shadow = new PointLightShadow(); - this.crossOrigin = value; + } - }, + get power() { - parse: function (text, path) { + // compute the light's luminous power (in lumens) from its intensity (in candela) + // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd) + return this.intensity * 4 * Math.PI; - function getElementsByTagName(xml, name) { + } - // Non recursive xml.getElementsByTagName() ... + set power( power ) { - var array = []; - var childNodes = xml.childNodes; + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / ( 4 * Math.PI ); - for (var i = 0, l = childNodes.length; i < l; i++) { + } - var child = childNodes[i]; + dispose() { - if (child.nodeName === name) { + this.shadow.dispose(); - array.push(child); + } - } + copy( source, recursive ) { - } + super.copy( source, recursive ); - return array; + this.distance = source.distance; + this.decay = source.decay; - } + this.shadow = source.shadow.clone(); - function parseStrings(text) { + return this; - if (text.length === 0) { return []; } + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); +} - for (var i = 0, l = parts.length; i < l; i++) { +class DirectionalLightShadow extends LightShadow { - array[i] = parts[i]; + constructor() { - } + super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); - return array; + this.isDirectionalLightShadow = true; - } + } - function parseFloats(text) { +} - if (text.length === 0) { return []; } +class DirectionalLight extends Light { - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + constructor( color, intensity ) { - for (var i = 0, l = parts.length; i < l; i++) { + super( color, intensity ); - array[i] = parseFloat(parts[i]); + this.isDirectionalLight = true; - } + this.type = 'DirectionalLight'; - return array; + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - } + this.target = new Object3D(); - function parseInts(text) { + this.shadow = new DirectionalLightShadow(); - if (text.length === 0) { return []; } + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + dispose() { - for (var i = 0, l = parts.length; i < l; i++) { + this.shadow.dispose(); - array[i] = parseInt(parts[i]); + } - } + copy( source ) { - return array; + super.copy( source ); - } + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); - function parseId(text) { + return this; - return text.substring(1); + } - } +} - function generateId() { +class AmbientLight extends Light { - return 'three_default_' + (count++); + constructor( color, intensity ) { - } + super( color, intensity ); - function isEmpty(object) { + this.isAmbientLight = true; - return Object.keys(object).length === 0; + this.type = 'AmbientLight'; - } + } - // asset +} - function parseAsset(xml) { +class LoaderUtils { - return { - unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), - upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) - }; + static decodeText( array ) { // @deprecated, r165 - } + console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); - function parseAssetUnit(xml) { + if ( typeof TextDecoder !== 'undefined' ) { - return xml !== undefined ? parseFloat(xml.getAttribute('meter')) : 1; + return new TextDecoder().decode( array ); - } + } - function parseAssetUpAxis(xml) { + // Avoid the String.fromCharCode.apply(null, array) shortcut, which + // throws a "maximum call stack size exceeded" error for large arrays. - return xml !== undefined ? xml.textContent : 'Y_UP'; + let s = ''; - } + for ( let i = 0, il = array.length; i < il; i ++ ) { - // library + // Implicitly assumes little-endian. + s += String.fromCharCode( array[ i ] ); - function parseLibrary(xml, libraryName, nodeName, parser) { + } - var library = getElementsByTagName(xml, libraryName)[0]; + try { - if (library !== undefined) { + // merges multi-byte utf-8 characters. - var elements = getElementsByTagName(library, nodeName); + return decodeURIComponent( escape( s ) ); - for (var i = 0; i < elements.length; i++) { + } catch ( e ) { // see #16358 - parser(elements[i]); + return s; - } + } - } + } - } + static extractUrlBase( url ) { - function buildLibrary(data, builder) { + const index = url.lastIndexOf( '/' ); - for (var name in data) { + if ( index === - 1 ) return './'; - var object = data[name]; - object.build = builder(data[name]); + return url.slice( 0, index + 1 ); - } + } - } + static resolveURL( url, path ) { - // get + // Invalid URL + if ( typeof url !== 'string' || url === '' ) return ''; - function getBuild(data, builder) { + // Host Relative URL + if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { - if (data.build !== undefined) { return data.build; } + path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); - data.build = builder(data); + } - return data.build; + // Absolute URL http://,https://,// + if ( /^(https?:)?\/\//i.test( url ) ) return url; - } + // Data URI + if ( /^data:.*,.*$/i.test( url ) ) return url; - // animation + // Blob URL + if ( /^blob:.*$/i.test( url ) ) return url; - function parseAnimation(xml) { + // Relative URL + return path + url; - var data = { - sources: {}, - samplers: {}, - channels: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { +} - var child = xml.childNodes[i]; +const _matrix = /*@__PURE__*/ new Matrix4(); - if (child.nodeType !== 1) { continue; } +class Raycaster { - var id; + constructor( origin, direction, near = 0, far = Infinity ) { - switch (child.nodeName) { + this.ray = new Ray( origin, direction ); + // direction is assumed to be normalized (for accurate distance calculations) - case 'source': - id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); + + this.params = { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + }; - case 'sampler': - id = child.getAttribute('id'); - data.samplers[id] = parseAnimationSampler(child); - break; + } - case 'channel': - id = child.getAttribute('target'); - data.channels[id] = parseAnimationChannel(child); - break; + set( origin, direction ) { - default: - console.log(child); + // direction is assumed to be normalized (for accurate distance calculations) - } + this.ray.set( origin, direction ); - } + } - library.animations[xml.getAttribute('id')] = data; + setFromCamera( coords, camera ) { - } + if ( camera.isPerspectiveCamera ) { - function parseAnimationSampler(xml) { + 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; - var data = { - inputs: {}, - }; + } else if ( camera.isOrthographicCamera ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera + this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + this.camera = camera; - var child = xml.childNodes[i]; + } else { - if (child.nodeType !== 1) { continue; } + console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); - switch (child.nodeName) { + } - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - data.inputs[semantic] = id; - break; + } - } + setFromXRController( controller ) { - } + _matrix.identity().extractRotation( controller.matrixWorld ); - return data; + this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); - } + return this; - function parseAnimationChannel(xml) { + } - var data = {}; + intersectObject( object, recursive = true, intersects = [] ) { - var target = xml.getAttribute('target'); + intersect( object, this, intersects, recursive ); - // parsing SID Addressing Syntax + intersects.sort( ascSort ); - var parts = target.split('/'); + return intersects; - var id = parts.shift(); - var sid = parts.shift(); + } - // check selection syntax + intersectObjects( objects, recursive = true, intersects = [] ) { - var arraySyntax = (sid.indexOf('(') !== - 1); - var memberSyntax = (sid.indexOf('.') !== - 1); + for ( let i = 0, l = objects.length; i < l; i ++ ) { - if (memberSyntax) { + intersect( objects[ i ], this, intersects, recursive ); - // member selection access + } - parts = sid.split('.'); - sid = parts.shift(); - data.member = parts.shift(); + intersects.sort( ascSort ); - } else if (arraySyntax) { + return intersects; - // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. + } - var indices = sid.split('('); - sid = indices.shift(); +} - for (var i = 0; i < indices.length; i++) { +function ascSort( a, b ) { - indices[i] = parseInt(indices[i].replace(/\)/, '')); + return a.distance - b.distance; - } +} - data.indices = indices; +function intersect( object, raycaster, intersects, recursive ) { - } + let propagate = true; - data.id = id; - data.sid = sid; + if ( object.layers.test( raycaster.layers ) ) { - data.arraySyntax = arraySyntax; - data.memberSyntax = memberSyntax; + const result = object.raycast( raycaster, intersects ); - data.sampler = parseId(xml.getAttribute('source')); + if ( result === false ) propagate = false; - return data; + } - } + if ( propagate === true && recursive === true ) { - function buildAnimation(data) { + const children = object.children; - var tracks = []; + for ( let i = 0, l = children.length; i < l; i ++ ) { - var channels = data.channels; - var samplers = data.samplers; - var sources = data.sources; + intersect( children[ i ], raycaster, intersects, true ); - for (var target in channels) { + } - if (channels.hasOwnProperty(target)) { + } - var channel = channels[target]; - var sampler = samplers[channel.sampler]; +} - var inputId = sampler.inputs.INPUT; - var outputId = sampler.inputs.OUTPUT; +const _axis = /*@__PURE__*/ new Vector3(); +let _lineGeometry, _coneGeometry; - var inputSource = sources[inputId]; - var outputSource = sources[outputId]; +class ArrowHelper extends Object3D { - var animation = buildAnimationChannel(channel, inputSource, outputSource); + // dir is assumed to be normalized - createKeyframeTracks(animation, tracks); + constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - } + super(); - } + this.type = 'ArrowHelper'; - return tracks; + if ( _lineGeometry === undefined ) { - } + _lineGeometry = new BufferGeometry(); + _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); - function getAnimation(id) { + _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); + _coneGeometry.translate( 0, - 0.5, 0 ); - return getBuild(library.animations[id], buildAnimation); + } - } + this.position.copy( origin ); - function buildAnimationChannel(channel, inputSource, outputSource) { + this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + this.line.matrixAutoUpdate = false; + this.add( this.line ); - var node = library.nodes[channel.id]; - var object3D = getNode(node.id); + this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); + this.cone.matrixAutoUpdate = false; + this.add( this.cone ); - var transform = node.transforms[channel.sid]; - var defaultMatrix = node.matrix.clone().transpose(); + this.setDirection( dir ); + this.setLength( length, headLength, headWidth ); - var time, stride; - var i, il, j, jl; + } - var data = {}; + setDirection( dir ) { - // the collada spec allows the animation of data in various ways. - // depending on the transform type (matrix, translate, rotate, scale), we execute different logic + // dir is assumed to be normalized - switch (transform) { + if ( dir.y > 0.99999 ) { - case 'matrix': + this.quaternion.set( 0, 0, 0, 1 ); - for (i = 0, il = inputSource.array.length; i < il; i++) { + } else if ( dir.y < - 0.99999 ) { - time = inputSource.array[i]; - stride = i * outputSource.stride; + this.quaternion.set( 1, 0, 0, 0 ); - if (data[time] === undefined) { data[time] = {}; } + } else { - if (channel.arraySyntax === true) { + _axis.set( dir.z, 0, - dir.x ).normalize(); - var value = outputSource.array[stride]; - var index = channel.indices[0] + 4 * channel.indices[1]; + const radians = Math.acos( dir.y ); - data[time][index] = value; + this.quaternion.setFromAxisAngle( _axis, radians ); - } else { + } - for (j = 0, jl = outputSource.stride; j < jl; j++) { + } - data[time][j] = outputSource.array[stride + j]; + setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - } + this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 + this.line.updateMatrix(); - } + this.cone.scale.set( headWidth, headLength, headWidth ); + this.cone.position.y = length; + this.cone.updateMatrix(); - } + } - break; + setColor( color ) { - case 'translate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + this.line.material.color.set( color ); + this.cone.material.color.set( color ); - case 'rotate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + } - case 'scale': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + copy( source ) { - } + super.copy( source, false ); - var keyframes = prepareAnimationData(data, defaultMatrix); + this.line.copy( source.line ); + this.cone.copy( source.cone ); - var animation = { - name: object3D.uuid, - keyframes: keyframes - }; + return this; - return animation; + } - } + dispose() { - function prepareAnimationData(data, defaultMatrix) { + this.line.geometry.dispose(); + this.line.material.dispose(); + this.cone.geometry.dispose(); + this.cone.material.dispose(); - var keyframes = []; + } - // transfer data into a sortable array +} - for (var time in data) { +if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - keyframes.push({ time: parseFloat(time), value: data[time] }); + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { + revision: REVISION, + } } ) ); - } +} - // ensure keyframes are sorted by time +if ( typeof window !== 'undefined' ) { - keyframes.sort(ascending); + if ( window.__THREE__ ) { - // now we clean up all animation data, so we can use them for keyframe tracks + console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); - for (var i = 0; i < 16; i++) { + } else { - transformAnimationData(keyframes, i, defaultMatrix.elements[i]); + window.__THREE__ = REVISION; - } + } - return keyframes; +} - // array sort function +// Marker types +var MARKER_ARROW = 0; +var MARKER_CUBE = 1; +var MARKER_SPHERE = 2; +var MARKER_CYLINDER = 3; +var MARKER_LINE_STRIP = 4; +var MARKER_LINE_LIST = 5; +var MARKER_CUBE_LIST = 6; +var MARKER_SPHERE_LIST = 7; +var MARKER_POINTS = 8; +var MARKER_TEXT_VIEW_FACING = 9; +var MARKER_MESH_RESOURCE = 10; +var MARKER_TRIANGLE_LIST = 11; - function ascending(a, b) { +// Interactive marker feedback types +var INTERACTIVE_MARKER_KEEP_ALIVE = 0; +var INTERACTIVE_MARKER_POSE_UPDATE = 1; +var INTERACTIVE_MARKER_MENU_SELECT = 2; +var INTERACTIVE_MARKER_BUTTON_CLICK = 3; +var INTERACTIVE_MARKER_MOUSE_DOWN = 4; +var INTERACTIVE_MARKER_MOUSE_UP = 5; - return a.time - b.time; +// Interactive marker control types +var INTERACTIVE_MARKER_NONE = 0; +var INTERACTIVE_MARKER_MENU = 1; +var INTERACTIVE_MARKER_BUTTON = 2; +var INTERACTIVE_MARKER_MOVE_AXIS = 3; +var INTERACTIVE_MARKER_MOVE_PLANE = 4; +var INTERACTIVE_MARKER_ROTATE_AXIS = 5; +var INTERACTIVE_MARKER_MOVE_ROTATE = 6; +var INTERACTIVE_MARKER_MOVE_3D = 7; +var INTERACTIVE_MARKER_ROTATE_3D = 8; +var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; - } +// Interactive marker rotation behavior +var INTERACTIVE_MARKER_INHERIT = 0; +var INTERACTIVE_MARKER_FIXED = 1; +var INTERACTIVE_MARKER_VIEW_FACING = 2; - } +/** + * @function makeColorMaterial + * @description Create a THREE material based on the given RGBA values. + * + * @param r - the red value + * @param g - the green value + * @param b - the blue value + * @param a - the alpha value + * @returns the THREE material + */ +var makeColorMaterial = function makeColorMaterial(r, g, b, a) { + var color = new Color(); + color.setRGB(r, g, b); + if (a <= 0.99) { + return new MeshBasicMaterial({ + color: color.getHex(), + opacity: a + 0.1, + transparent: true, + depthWrite: true, + blendSrc: SrcAlphaFactor, + blendDst: OneMinusSrcAlphaFactor, + blendEquation: ReverseSubtractEquation, + blending: NormalBlending + }); + } else { + return new MeshPhongMaterial({ + color: color.getHex(), + opacity: a, + blending: NormalBlending + }); + } +}; - var position = new THREE.Vector3(); - var scale = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); +/** + * @function intersectPlane + * @description Return the intersection between the mouseray and the plane. + * + * @param mouseRay - the mouse ray + * @param planeOrigin - the origin of the plane + * @param planeNormal - the normal of the plane + * @returns the intersection point + */ +var intersectPlane = function intersectPlane(mouseRay, planeOrigin, planeNormal) { + var vector = new Vector3(); + var intersectPoint = new Vector3(); + vector.subVectors(planeOrigin, mouseRay.origin); + var dot = mouseRay.direction.dot(planeNormal); - function createKeyframeTracks(animation, tracks) { + // bail if ray and plane are parallel + if (Math.abs(dot) < mouseRay.precision) { + return undefined; + } - var keyframes = animation.keyframes; - var name = animation.name; + // calc distance to plane + var scalar = planeNormal.dot(vector) / dot; + intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); + return intersectPoint; +}; - var times = []; - var positionData = []; - var quaternionData = []; - var scaleData = []; +/** + * @function findClosestPoint + * @description Find the closest point on targetRay to any point on mouseRay. Math taken from + * http://paulbourke.net/geometry/lineline3d/ + * + * @param targetRay - the target ray to use + * @param mouseRay - the mouse ray + * @param the closest point between the two rays + */ +var findClosestPoint = function findClosestPoint(targetRay, mouseRay) { + var v13 = new Vector3(); + v13.subVectors(targetRay.origin, mouseRay.origin); + var v43 = mouseRay.direction.clone(); + var v21 = targetRay.direction.clone(); + var d1343 = v13.dot(v43); + var d4321 = v43.dot(v21); + var d1321 = v13.dot(v21); + var d4343 = v43.dot(v43); + var d2121 = v21.dot(v21); + var denom = d2121 * d4343 - d4321 * d4321; + // check within a delta + if (Math.abs(denom) <= 0.0001) { + return undefined; + } + var numer = d1343 * d4321 - d1321 * d4343; + var mua = numer / denom; + return mua; +}; - for (var i = 0, l = keyframes.length; i < l; i++) { +/** + * @function closestAxisPoint + * @description Find the closest point between the axis and the mouse. + * + * @param axisRay - the ray from the axis + * @param camera - the camera to project from + * @param mousePos - the mouse position + * @returns the closest axis point + */ +var closestAxisPoint = function closestAxisPoint(axisRay, camera, mousePos) { + // project axis onto screen + var o = axisRay.origin.clone(); + o.project(camera); + var o2 = axisRay.direction.clone().add(axisRay.origin); + o2.project(camera); - var keyframe = keyframes[i]; + // d is the axis vector in screen space (d = o2-o) + var d = o2.clone().sub(o); - var time = keyframe.time; - var value = keyframe.value; + // t is the 2d ray param of perpendicular projection of mousePos onto o + var tmp = new Vector2(); + // (t = (mousePos - o) * d / (d*d)) + var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); - matrix.fromArray(value).transpose(); - matrix.decompose(position, quaternion, scale); + // mp is the final 2d-projected mouse pos (mp = o + d*t) + var mp = new Vector2(); + mp.addVectors(o, d.clone().multiplyScalar(t)); - times.push(time); - positionData.push(position.x, position.y, position.z); - quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); - scaleData.push(scale.x, scale.y, scale.z); + // go back to 3d by shooting a ray + var vector = new Vector3(mp.x, mp.y, 0.5); + vector.unproject(camera); + var mpRay = new Ray(camera.position, vector.sub(camera.position).normalize()); + return findClosestPoint(axisRay, mpRay); +}; - } +function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); +} - if (positionData.length > 0) { tracks.push(new THREE.VectorKeyframeTrack(name + '.position', times, positionData)); } - if (quaternionData.length > 0) { tracks.push(new THREE.QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); } - if (scaleData.length > 0) { tracks.push(new THREE.VectorKeyframeTrack(name + '.scale', times, scaleData)); } +function _typeof(o) { + "@babel/helpers - typeof"; - return tracks; + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); +} - } +function toPrimitive(t, r) { + if ("object" != _typeof(t) || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r || "default"); + if ("object" != _typeof(i)) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return ("string" === r ? String : Number)(t); +} - function transformAnimationData(keyframes, property, defaultValue) { +function toPropertyKey(t) { + var i = toPrimitive(t, "string"); + return "symbol" == _typeof(i) ? i : i + ""; +} - var keyframe; +function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, toPropertyKey(o.key), o); + } +} +function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { + writable: !1 + }), e; +} - var empty = true; - var i, l; +function _assertThisInitialized(e) { + if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return e; +} - // check, if values of a property are missing in our keyframes +function _possibleConstructorReturn(t, e) { + if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; + if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); + return _assertThisInitialized(t); +} - for (i = 0, l = keyframes.length; i < l; i++) { +function _getPrototypeOf(t) { + return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { + return t.__proto__ || Object.getPrototypeOf(t); + }, _getPrototypeOf(t); +} - keyframe = keyframes[i]; +function _setPrototypeOf(t, e) { + return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { + return t.__proto__ = e, t; + }, _setPrototypeOf(t, e); +} - if (keyframe.value[property] === undefined) { +function _inherits(t, e) { + if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); + t.prototype = Object.create(e && e.prototype, { + constructor: { + value: t, + writable: !0, + configurable: !0 + } + }), Object.defineProperty(t, "prototype", { + writable: !1 + }), e && _setPrototypeOf(t, e); +} - keyframe.value[property] = null; // mark as missing +function _callSuper$z(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$z() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$z() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$z = function _isNativeReflectConstruct() { return !!t; })(); } - } else { +/** + * @fileOverview + * @author Julius Kammerl - jkammerl@willowgarage.com + */ - empty = false; +var DepthCloud = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The DepthCloud object. + * + * @constructor + * @param options - object with following keys: + * + * * url - the URL of the stream + * * streamType (optional) - the stream type: mjpeg or vp8 video (defaults to vp8) + * * f (optional) - the camera's focal length (defaults to standard Kinect calibration) + * * maxDepthPerTile (optional) - the factor with which we control the desired depth range (defaults to 1.0) + * * pointSize (optional) - point size (pixels) for rendered point cloud + * * width (optional) - width of the video stream + * * height (optional) - height of the video stream + * * whiteness (optional) - blends rgb values to white (0..100) + * * varianceThreshold (optional) - threshold for variance filter, used for compression artifact removal + */ + function DepthCloud(options) { + var _this; + _classCallCheck(this, DepthCloud); + _this = _callSuper$z(this, DepthCloud); + options = options || {}; + _this.url = options.url; + _this.streamType = options.streamType || 'vp8'; + _this.f = options.f || 526; + _this.maxDepthPerTile = options.maxDepthPerTile || 1.0; + _this.pointSize = options.pointSize || 3; + _this.width = options.width || 1024; + _this.height = options.height || 1024; + _this.resolutionFactor = Math.max(_this.width, _this.height) / 1024; + _this.whiteness = options.whiteness || 0; + _this.varianceThreshold = options.varianceThreshold || 0.000016667; + _this.isMjpeg = _this.streamType.toLowerCase() === 'mjpeg'; + _this.video = document.createElement(_this.isMjpeg ? 'img' : 'video'); + _this.video.crossOrigin = 'Anonymous'; + _this.video.addEventListener(_this.isMjpeg ? 'load' : 'loadedmetadata', _this.metaLoaded.bind(_this), false); + if (!_this.isMjpeg) { + _this.video.loop = true; + } + _this.video.src = _this.url; + _this.video.setAttribute('crossorigin', 'Anonymous'); + // define custom shaders + _this.vertex_shader = ['uniform sampler2D map;', '', 'uniform float width;', 'uniform float height;', 'uniform float nearClipping, farClipping;', '', 'uniform float pointSize;', 'uniform float zOffset;', '', 'uniform float focallength;', 'uniform float maxDepthPerTile;', 'uniform float resolutionFactor;', '', 'varying vec2 vUvP;', 'varying vec2 colorP;', '', 'varying float depthVariance;', 'varying float maskVal;', '', 'float sampleDepth(vec2 pos)', ' {', ' float depth;', ' ', ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', ' ', ' vec4 depthColor = texture2D( map, vUv );', ' ', ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', ' ', ' if (depth>0.99)', ' {', ' vec4 depthColor2 = texture2D( map, vUv2 );', ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', ' depth = 0.99+depth2;', ' }', ' ', ' return depth;', ' }', '', 'float median(float a, float b, float c)', ' {', ' float r=a;', ' ', ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', ' {', ' vec2 smp = decodeDepth(vec2(position.x, position.y));', ' float depth = smp.x;', ' depthVariance = smp.y;', ' ', ' float z = -depth;', ' ', ' pos = vec4(', ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', ' (- z + zOffset / 1000.0) * maxDepthPerTile,', ' 1.0);', ' ', ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', ' vec4 maskColor = texture2D( map, maskP );', ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', ' }', ' ', ' gl_PointSize = pointSize;', ' gl_Position = projectionMatrix * modelViewMatrix * pos;', ' ', '}'].join('\n'); + _this.fragment_shader = ['uniform sampler2D map;', 'uniform float varianceThreshold;', 'uniform float whiteness;', '', 'varying vec2 vUvP;', 'varying vec2 colorP;', '', 'varying float depthVariance;', 'varying float maskVal;', '', '', 'void main() {', ' ', ' vec4 color;', ' ', ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', ' { ', ' discard;', ' }', ' else ', ' {', ' color = texture2D( map, colorP );', ' ', ' float fader = whiteness /100.0;', ' ', ' color.r = color.r * (1.0-fader)+ fader;', ' ', ' color.g = color.g * (1.0-fader)+ fader;', ' ', ' color.b = color.b * (1.0-fader)+ fader;', ' ', ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', ' }', ' ', ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', ' ', '}'].join('\n'); + return _this; + } + _inherits(DepthCloud, _THREE$Object3D); + return _createClass(DepthCloud, [{ + key: "metaLoaded", + value: + /** + * Callback called when video metadata is ready + */ + function metaLoaded() { + this.metaLoaded = true; + this.initStreamer(); + } + }, { + key: "initStreamer", + value: + /** + * Callback called when video metadata is ready + */ + function initStreamer() { + var _this2 = this; + if (this.metaLoaded) { + this.texture = new Texture(this.video); + this.geometry = new BufferGeometry(); + for (var i = 0, l = this.width * this.height; i < l; i++) { + var vertex = new Vector3(); + vertex.x = i % this.width; + vertex.y = Math.floor(i / this.width); + this.geometry.vertices.push(vertex); } - + this.material = new ShaderMaterial({ + uniforms: { + 'map': { + type: 't', + value: this.texture + }, + 'width': { + type: 'f', + value: this.width + }, + 'height': { + type: 'f', + value: this.height + }, + 'focallength': { + type: 'f', + value: this.f + }, + 'pointSize': { + type: 'f', + value: this.pointSize + }, + 'zOffset': { + type: 'f', + value: 0 + }, + 'whiteness': { + type: 'f', + value: this.whiteness + }, + 'varianceThreshold': { + type: 'f', + value: this.varianceThreshold + }, + 'maxDepthPerTile': { + type: 'f', + value: this.maxDepthPerTile + }, + 'resolutionFactor': { + type: 'f', + value: this.resolutionFactor + } + }, + vertexShader: this.vertex_shader, + fragmentShader: this.fragment_shader + }); + this.mesh = new Points$1(this.geometry, this.material); + this.mesh.position.x = 0; + this.mesh.position.y = 0; + this.add(this.mesh); + setInterval(function () { + if (_this2.isMjpeg || _this2.video.readyState === _this2.video.HAVE_ENOUGH_DATA) { + _this2.texture.needsUpdate = true; + } + }, 1000 / 30); + } + } + }, { + key: "startStream", + value: + /** + * Start video playback + */ + function startStream() { + if (!this.isMjpeg) { + this.video.play(); } + } + }, { + key: "stopStream", + value: + /** + * Stop video playback + */ + function stopStream() { + if (!this.isMjpeg) { + this.video.pause(); + } + } + }]); +}(Object3D); - if (empty === true) { +function _superPropBase(t, o) { + for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); + return t; +} - // no values at all, so we set a default value +function _get() { + return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { + var p = _superPropBase(e, t); + if (p) { + var n = Object.getOwnPropertyDescriptor(p, t); + return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; + } + }, _get.apply(null, arguments); +} - for (i = 0, l = keyframes.length; i < l; i++) { +function _callSuper$y(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$y() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$y() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$y = function _isNativeReflectConstruct() { return !!t; })(); } - keyframe = keyframes[i]; +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ - keyframe.value[property] = defaultValue; +var Arrow = /*#__PURE__*/function (_THREE$Mesh) { + /** + * A Arrow is a THREE object that can be used to display an arrow model. + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ + function Arrow(options) { + var _this; + _classCallCheck(this, Arrow); + options = options || {}; + var origin = options.origin || new Vector3(0, 0, 0); + var direction = options.direction || new Vector3(1, 0, 0); + var length = options.length || 1; + var headLength = options.headLength || 0.2; + var shaftDiameter = options.shaftDiameter || 0.05; + var headDiameter = options.headDiameter || 0.1; + var material = options.material || new MeshBasicMaterial(); + var shaftLength = length - headLength; - } + // create and merge geometry + var geometry = new CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, 12, 1); + var m = new Matrix4(); + m.setPosition(new Vector3(0, shaftLength * 0.5, 0)); + geometry.applyMatrix(m); - } else { + // create the head + var coneGeometry = new CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); + m.setPosition(new Vector3(0, shaftLength + headLength * 0.5, 0)); + coneGeometry.applyMatrix(m); - // filling gaps + // put the arrow together + geometry.merge(coneGeometry); + _this = _callSuper$y(this, Arrow, [geometry, material]); + _this.position.copy(origin); + _this.setDirection(direction); + return _this; + } + _inherits(Arrow, _THREE$Mesh); + return _createClass(Arrow, [{ + key: "setDirection", + value: + /** + * Set the direction of this arrow to that of the given vector. + * + * @param direction - the direction to set this arrow + */ + function setDirection(direction) { + var axis = new Vector3(); + if (direction.x === 0 && direction.z === 0) { + axis.set(1, 0, 0); + } else { + axis.set(0, 1, 0).cross(direction); + } + var radians = Math.acos(new Vector3(0, 1, 0).dot(direction.clone().normalize())); + this.matrix = new Matrix4().makeRotationAxis(axis.normalize(), radians); + this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); + } + }, { + key: "setLength", + value: + /** + * Set this arrow to be the given length. + * + * @param length - the new length of the arrow + */ + function setLength(length) { + this.scale.set(length, length, length); + } + }, { + key: "setColor", + value: + /** + * Set the color of this arrow to the given hex value. + * + * @param hex - the hex value of the color to use + */ + function setColor(hex) { + this.material.color.setHex(hex); + } + }, { + key: "dispose", + value: + /* + * Free memory of elements in this marker. + */ + function dispose() { + if (this.geometry !== undefined) { + this.geometry.dispose(); + } + if (this.material !== undefined) { + this.material.dispose(); + } + } + }]); +}(Mesh); - createMissingKeyframes(keyframes, property); +class TGALoader extends DataTextureLoader { - } + constructor( manager ) { - } + super( manager ); - function createMissingKeyframes(keyframes, property) { + } - var prev, next; + parse( buffer ) { - for (var i = 0, l = keyframes.length; i < l; i++) { + // reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js - var keyframe = keyframes[i]; + function tgaCheckHeader( header ) { - if (keyframe.value[property] === null) { + switch ( header.image_type ) { - prev = getPrev(keyframes, i, property); - next = getNext(keyframes, i, property); + // check indexed type - if (prev === null) { + case TGA_TYPE_INDEXED: + case TGA_TYPE_RLE_INDEXED: + if ( header.colormap_length > 256 || header.colormap_size !== 24 || header.colormap_type !== 1 ) { - keyframe.value[property] = next.value[property]; - continue; + throw new Error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' ); - } + } - if (next === null) { + break; - keyframe.value[property] = prev.value[property]; - continue; + // check colormap type - } + case TGA_TYPE_RGB: + case TGA_TYPE_GREY: + case TGA_TYPE_RLE_RGB: + case TGA_TYPE_RLE_GREY: + if ( header.colormap_type ) { - interpolate(keyframe, prev, next, property); + throw new Error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' ); - } + } - } + break; - } + // What the need of a file without data ? - function getPrev(keyframes, i, property) { + case TGA_TYPE_NO_DATA: + throw new Error( 'THREE.TGALoader: No data.' ); - while (i >= 0) { + // Invalid type ? - var keyframe = keyframes[i]; + default: + throw new Error( 'THREE.TGALoader: Invalid type ' + header.image_type ); - if (keyframe.value[property] !== null) { return keyframe; } + } - i--; + // check image width and height - } + if ( header.width <= 0 || header.height <= 0 ) { - return null; + throw new Error( 'THREE.TGALoader: Invalid image size.' ); - } + } - function getNext(keyframes, i, property) { + // check image pixel size - while (i < keyframes.length) { + if ( header.pixel_size !== 8 && header.pixel_size !== 16 && + header.pixel_size !== 24 && header.pixel_size !== 32 ) { - var keyframe = keyframes[i]; + throw new Error( 'THREE.TGALoader: Invalid pixel size ' + header.pixel_size ); - if (keyframe.value[property] !== null) { return keyframe; } + } - i++; + } - } + // parse tga image buffer - return null; + function tgaParse( use_rle, use_pal, header, offset, data ) { - } + let pixel_data, + palettes; - function interpolate(key, prev, next, property) { + const pixel_size = header.pixel_size >> 3; + const pixel_total = header.width * header.height * pixel_size; - if ((next.time - prev.time) === 0) { + // read palettes - key.value[property] = prev.value[property]; - return; + if ( use_pal ) { - } + palettes = data.subarray( offset, offset += header.colormap_length * ( header.colormap_size >> 3 ) ); - key.value[property] = ((key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time)) + prev.value[property]; + } - } + // read RLE - // animation clips + if ( use_rle ) { - function parseAnimationClip(xml) { + pixel_data = new Uint8Array( pixel_total ); - var data = { - name: xml.getAttribute('id') || 'default', - start: parseFloat(xml.getAttribute('start') || 0), - end: parseFloat(xml.getAttribute('end') || 0), - animations: [] - }; + let c, count, i; + let shift = 0; + const pixels = new Uint8Array( pixel_size ); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + while ( shift < pixel_total ) { - var child = xml.childNodes[i]; + c = data[ offset ++ ]; + count = ( c & 0x7f ) + 1; - if (child.nodeType !== 1) { continue; } + // RLE pixels - switch (child.nodeName) { + if ( c & 0x80 ) { - case 'instance_animation': - data.animations.push(parseId(child.getAttribute('url'))); - break; + // bind pixel tmp array - } + for ( i = 0; i < pixel_size; ++ i ) { - } + pixels[ i ] = data[ offset ++ ]; - library.clips[xml.getAttribute('id')] = data; + } - } + // copy pixel array - function buildAnimationClip(data) { + for ( i = 0; i < count; ++ i ) { - var tracks = []; + pixel_data.set( pixels, shift + i * pixel_size ); - var name = data.name; - var duration = (data.end - data.start) || - 1; - var animations = data.animations; + } - for (var i = 0, il = animations.length; i < il; i++) { + shift += pixel_size * count; - var animationTracks = getAnimation(animations[i]); + } else { - for (var j = 0, jl = animationTracks.length; j < jl; j++) { + // raw pixels - tracks.push(animationTracks[j]); + count *= pixel_size; - } + for ( i = 0; i < count; ++ i ) { - } + pixel_data[ shift + i ] = data[ offset ++ ]; - return new THREE.AnimationClip(name, duration, tracks); + } - } + shift += count; - function getAnimationClip(id) { + } - return getBuild(library.clips[id], buildAnimationClip); + } - } + } else { - // controller + // raw pixels - function parseController(xml) { + pixel_data = data.subarray( + offset, offset += ( use_pal ? header.width * header.height : pixel_total ) + ); - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + return { + pixel_data: pixel_data, + palettes: palettes + }; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) { continue; } + function tgaGetImageData8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes ) { - switch (child.nodeName) { + const colormap = palettes; + let color, i = 0, x, y; + const width = header.width; - case 'skin': - // there is exactly one skin per controller - data.id = parseId(child.getAttribute('source')); - data.skin = parseSkin(child); - break; + for ( y = y_start; y !== y_end; y += y_step ) { - case 'morph': - data.id = parseId(child.getAttribute('source')); - console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); - break; + for ( x = x_start; x !== x_end; x += x_step, i ++ ) { - } + color = image[ i ]; + imageData[ ( x + width * y ) * 4 + 3 ] = 255; + imageData[ ( x + width * y ) * 4 + 2 ] = colormap[ ( color * 3 ) + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = colormap[ ( color * 3 ) + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = colormap[ ( color * 3 ) + 2 ]; - } + } - library.controllers[xml.getAttribute('id')] = data; + } - } + return imageData; - function parseSkin(xml) { + } - var data = { - sources: {} - }; + function tgaGetImageData16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + let color, i = 0, x, y; + const width = header.width; - var child = xml.childNodes[i]; + for ( y = y_start; y !== y_end; y += y_step ) { - if (child.nodeType !== 1) { continue; } + for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { - switch (child.nodeName) { + color = image[ i + 0 ] + ( image[ i + 1 ] << 8 ); + imageData[ ( x + width * y ) * 4 + 0 ] = ( color & 0x7C00 ) >> 7; + imageData[ ( x + width * y ) * 4 + 1 ] = ( color & 0x03E0 ) >> 2; + imageData[ ( x + width * y ) * 4 + 2 ] = ( color & 0x001F ) << 3; + imageData[ ( x + width * y ) * 4 + 3 ] = ( color & 0x8000 ) ? 0 : 255; - case 'bind_shape_matrix': - data.bindShapeMatrix = parseFloats(child.textContent); - break; + } - case 'source': - var id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; + } - case 'joints': - data.joints = parseJoints(child); - break; + return imageData; - case 'vertex_weights': - data.vertexWeights = parseVertexWeights(child); - break; + } - } + function tgaGetImageData24bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - } + let i = 0, x, y; + const width = header.width; - return data; + for ( y = y_start; y !== y_end; y += y_step ) { - } + for ( x = x_start; x !== x_end; x += x_step, i += 3 ) { - function parseJoints(xml) { + imageData[ ( x + width * y ) * 4 + 3 ] = 255; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; - var data = { - inputs: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + return imageData; - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + function tgaGetImageData32bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - data.inputs[semantic] = id; - break; + let i = 0, x, y; + const width = header.width; - } + for ( y = y_start; y !== y_end; y += y_step ) { - } + for ( x = x_start; x !== x_end; x += x_step, i += 4 ) { - return data; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; + imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 3 ]; - } + } - function parseVertexWeights(xml) { + } - var data = { - inputs: {} - }; + return imageData; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + function tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - if (child.nodeType !== 1) { continue; } + let color, i = 0, x, y; + const width = header.width; - switch (child.nodeName) { + for ( y = y_start; y !== y_end; y += y_step ) { - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - var offset = parseInt(child.getAttribute('offset')); - data.inputs[semantic] = { id: id, offset: offset }; - break; + for ( x = x_start; x !== x_end; x += x_step, i ++ ) { - case 'vcount': - data.vcount = parseInts(child.textContent); - break; + color = image[ i ]; + imageData[ ( x + width * y ) * 4 + 0 ] = color; + imageData[ ( x + width * y ) * 4 + 1 ] = color; + imageData[ ( x + width * y ) * 4 + 2 ] = color; + imageData[ ( x + width * y ) * 4 + 3 ] = 255; - case 'v': - data.v = parseInts(child.textContent); - break; + } - } + } - } + return imageData; - return data; + } - } + function tgaGetImageDataGrey16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - function buildController(data) { + let i = 0, x, y; + const width = header.width; - var build = { - id: data.id - }; + for ( y = y_start; y !== y_end; y += y_step ) { - var geometry = library.geometries[build.id]; + for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { - if (data.skin !== undefined) { + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 1 ]; - build.skin = buildSkin(data.skin); + } - // we enhance the 'sources' property of the corresponding geometry with our skin data + } - geometry.sources.skinIndices = build.skin.indices; - geometry.sources.skinWeights = build.skin.weights; + return imageData; - } + } - return build; + function getTgaRGBA( data, width, height, image, palette ) { - } + let x_start, + y_start, + x_step, + y_step, + x_end, + y_end; - function buildSkin(data) { + switch ( ( header.flags & TGA_ORIGIN_MASK ) >> TGA_ORIGIN_SHIFT ) { - var BONE_LIMIT = 4; + default: + case TGA_ORIGIN_UL: + x_start = 0; + x_step = 1; + x_end = width; + y_start = 0; + y_step = 1; + y_end = height; + break; - var build = { - joints: [], // this must be an array to preserve the joint order - indices: { - array: [], - stride: BONE_LIMIT - }, - weights: { - array: [], - stride: BONE_LIMIT - } - }; + case TGA_ORIGIN_BL: + x_start = 0; + x_step = 1; + x_end = width; + y_start = height - 1; + y_step = - 1; + y_end = - 1; + break; - var sources = data.sources; - var vertexWeights = data.vertexWeights; + case TGA_ORIGIN_UR: + x_start = width - 1; + x_step = - 1; + x_end = - 1; + y_start = 0; + y_step = 1; + y_end = height; + break; - var vcount = vertexWeights.vcount; - var v = vertexWeights.v; - var jointOffset = vertexWeights.inputs.JOINT.offset; - var weightOffset = vertexWeights.inputs.WEIGHT.offset; + case TGA_ORIGIN_BR: + x_start = width - 1; + x_step = - 1; + x_end = - 1; + y_start = height - 1; + y_step = - 1; + y_end = - 1; + break; - var jointSource = data.sources[data.joints.inputs.JOINT]; - var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; + } - var weights = sources[vertexWeights.inputs.WEIGHT.id].array; - var stride = 0; + if ( use_grey ) { - var i, j, l; + switch ( header.pixel_size ) { - // procces skin data for each vertex + case 8: + tgaGetImageDataGrey8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - for (i = 0, l = vcount.length; i < l; i++) { + case 16: + tgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex - var vertexSkinData = []; + default: + throw new Error( 'THREE.TGALoader: Format not supported.' ); - for (j = 0; j < jointCount; j++) { + } - var skinIndex = v[stride + jointOffset]; - var weightId = v[stride + weightOffset]; - var skinWeight = weights[weightId]; + } else { - vertexSkinData.push({ index: skinIndex, weight: skinWeight }); + switch ( header.pixel_size ) { - stride += 2; + case 8: + tgaGetImageData8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image, palette ); + break; - } + case 16: + tgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - // we sort the joints in descending order based on the weights. - // this ensures, we only procced the most important joints of the vertex + case 24: + tgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - vertexSkinData.sort(descending); + case 32: + tgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - // now we provide for each vertex a set of four index and weight values. - // the order of the skin data matches the order of vertices + default: + throw new Error( 'THREE.TGALoader: Format not supported.' ); - for (j = 0; j < BONE_LIMIT; j++) { + } - var d = vertexSkinData[j]; + } - if (d !== undefined) { + // Load image data according to specific method + // let func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits'; + // func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette ); + return data; - build.indices.array.push(d.index); - build.weights.array.push(d.weight); + } - } else { + // TGA constants + + const TGA_TYPE_NO_DATA = 0, + TGA_TYPE_INDEXED = 1, + TGA_TYPE_RGB = 2, + TGA_TYPE_GREY = 3, + TGA_TYPE_RLE_INDEXED = 9, + TGA_TYPE_RLE_RGB = 10, + TGA_TYPE_RLE_GREY = 11, + + TGA_ORIGIN_MASK = 0x30, + TGA_ORIGIN_SHIFT = 0x04, + TGA_ORIGIN_BL = 0x00, + TGA_ORIGIN_BR = 0x01, + TGA_ORIGIN_UL = 0x02, + TGA_ORIGIN_UR = 0x03; + + if ( buffer.length < 19 ) throw new Error( 'THREE.TGALoader: Not enough data to contain header.' ); + + let offset = 0; + + const content = new Uint8Array( buffer ), + header = { + id_length: content[ offset ++ ], + colormap_type: content[ offset ++ ], + image_type: content[ offset ++ ], + colormap_index: content[ offset ++ ] | content[ offset ++ ] << 8, + colormap_length: content[ offset ++ ] | content[ offset ++ ] << 8, + colormap_size: content[ offset ++ ], + origin: [ + content[ offset ++ ] | content[ offset ++ ] << 8, + content[ offset ++ ] | content[ offset ++ ] << 8 + ], + width: content[ offset ++ ] | content[ offset ++ ] << 8, + height: content[ offset ++ ] | content[ offset ++ ] << 8, + pixel_size: content[ offset ++ ], + flags: content[ offset ++ ] + }; - build.indices.array.push(0); - build.weights.array.push(0); + // check tga if it is valid format - } + tgaCheckHeader( header ); - } + if ( header.id_length + offset > buffer.length ) { - } + throw new Error( 'THREE.TGALoader: No data.' ); - // setup bind matrix + } - build.bindMatrix = new THREE.Matrix4().fromArray(data.bindShapeMatrix).transpose(); + // skip the needn't data - // process bones and inverse bind matrix data + offset += header.id_length; - for (i = 0, l = jointSource.array.length; i < l; i++) { + // get targa information about RLE compression and palette - var name = jointSource.array[i]; - var boneInverse = new THREE.Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); + let use_rle = false, + use_pal = false, + use_grey = false; - build.joints.push({ name: name, boneInverse: boneInverse }); + switch ( header.image_type ) { - } + case TGA_TYPE_RLE_INDEXED: + use_rle = true; + use_pal = true; + break; - return build; + case TGA_TYPE_INDEXED: + use_pal = true; + break; - // array sort function + case TGA_TYPE_RLE_RGB: + use_rle = true; + break; - function descending(a, b) { + case TGA_TYPE_RGB: + break; - return b.weight - a.weight; + case TGA_TYPE_RLE_GREY: + use_rle = true; + use_grey = true; + break; - } + case TGA_TYPE_GREY: + use_grey = true; + break; - } + } - function getController(id) { + // - return getBuild(library.controllers[id], buildController); + const imageData = new Uint8Array( header.width * header.height * 4 ); + const result = tgaParse( use_rle, use_pal, header, offset, content ); + getTgaRGBA( imageData, header.width, header.height, result.pixel_data, result.palettes ); - } + return { - // image + data: imageData, + width: header.width, + height: header.height, + flipY: true, + generateMipmaps: true, + minFilter: LinearMipmapLinearFilter, - function parseImage(xml) { + }; - var data = { - init_from: getElementsByTagName(xml, 'init_from')[0].textContent - }; + } - library.images[xml.getAttribute('id')] = data; +} +function _callSuper$x(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$x() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$x() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$x = function _isNativeReflectConstruct() { return !!t; })(); } +var ColladaLoader = /*#__PURE__*/function (_Loader) { + function ColladaLoader() { + _classCallCheck(this, ColladaLoader); + return _callSuper$x(this, ColladaLoader, arguments); + } + _inherits(ColladaLoader, _Loader); + return _createClass(ColladaLoader, [{ + key: "load", + value: function load(url, onLoad, onProgress, onError) { + var scope = this; + var path = scope.path === '' ? LoaderUtils.extractUrlBase(url) : scope.path; + var 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(text, path)); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); } + }, { + key: "parse", + value: function parse(text, path) { + function getElementsByTagName(xml, name) { + // Non recursive xml.getElementsByTagName() ... + + var array = []; + var childNodes = xml.childNodes; + for (var i = 0, l = childNodes.length; i < l; i++) { + var child = childNodes[i]; + if (child.nodeName === name) { + array.push(child); + } + } + return array; + } + function parseStrings(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parts[i]; + } + return array; + } + function parseFloats(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parseFloat(parts[i]); + } + return array; + } + function parseInts(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parseInt(parts[i]); + } + return array; + } + function parseId(text) { + return text.substring(1); + } + function generateId() { + return 'three_default_' + count++; + } + function isEmpty(object) { + return Object.keys(object).length === 0; + } - function buildImage(data) { - - if (data.build !== undefined) { return data.build; } + // asset - return data.init_from; + function parseAsset(xml) { + return { + unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), + upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) + }; + } + function parseAssetUnit(xml) { + if (xml !== undefined && xml.hasAttribute('meter') === true) { + return parseFloat(xml.getAttribute('meter')); + } else { + return 1; // default 1 meter + } + } + function parseAssetUpAxis(xml) { + return xml !== undefined ? xml.textContent : 'Y_UP'; + } - } + // library - function getImage(id) { + function parseLibrary(xml, libraryName, nodeName, parser) { + var library = getElementsByTagName(xml, libraryName)[0]; + if (library !== undefined) { + var elements = getElementsByTagName(library, nodeName); + for (var i = 0; i < elements.length; i++) { + parser(elements[i]); + } + } + } + function buildLibrary(data, builder) { + for (var name in data) { + var object = data[name]; + object.build = builder(data[name]); + } + } - return getBuild(library.images[id], buildImage); + // get - } + function getBuild(data, builder) { + if (data.build !== undefined) return data.build; + data.build = builder(data); + return data.build; + } - // effect + // animation + + function parseAnimation(xml) { + var data = { + sources: {}, + samplers: {}, + channels: {} + }; + var hasChildren = false; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var id = void 0; + switch (child.nodeName) { + case 'source': + id = child.getAttribute('id'); + data.sources[id] = parseSource(child); + break; + case 'sampler': + id = child.getAttribute('id'); + data.samplers[id] = parseAnimationSampler(child); + break; + case 'channel': + id = child.getAttribute('target'); + data.channels[id] = parseAnimationChannel(child); + break; + case 'animation': + // hierarchy of related animations + parseAnimation(child); + hasChildren = true; + break; + default: + console.log(child); + } + } + if (hasChildren === false) { + // since 'id' attributes can be optional, it's necessary to generate a UUID for unqiue assignment - function parseEffect(xml) { + library.animations[xml.getAttribute('id') || MathUtils.generateUUID()] = data; + } + } + function parseAnimationSampler(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var id = parseId(child.getAttribute('source')); + var semantic = child.getAttribute('semantic'); + data.inputs[semantic] = id; + break; + } + } + return data; + } + function parseAnimationChannel(xml) { + var data = {}; + var target = xml.getAttribute('target'); - var data = {}; + // parsing SID Addressing Syntax - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var parts = target.split('/'); + var id = parts.shift(); + var sid = parts.shift(); - var child = xml.childNodes[i]; + // check selection syntax - if (child.nodeType !== 1) { continue; } + var arraySyntax = sid.indexOf('(') !== -1; + var memberSyntax = sid.indexOf('.') !== -1; + if (memberSyntax) { + // member selection access - switch (child.nodeName) { + parts = sid.split('.'); + sid = parts.shift(); + data.member = parts.shift(); + } else if (arraySyntax) { + // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. - case 'profile_COMMON': - data.profile = parseEffectProfileCOMMON(child); + var indices = sid.split('('); + sid = indices.shift(); + for (var i = 0; i < indices.length; i++) { + indices[i] = parseInt(indices[i].replace(/\)/, '')); + } + data.indices = indices; + } + data.id = id; + data.sid = sid; + data.arraySyntax = arraySyntax; + data.memberSyntax = memberSyntax; + data.sampler = parseId(xml.getAttribute('source')); + return data; + } + function buildAnimation(data) { + var tracks = []; + var channels = data.channels; + var samplers = data.samplers; + var sources = data.sources; + for (var target in channels) { + if (channels.hasOwnProperty(target)) { + var channel = channels[target]; + var sampler = samplers[channel.sampler]; + var inputId = sampler.inputs.INPUT; + var outputId = sampler.inputs.OUTPUT; + var inputSource = sources[inputId]; + var outputSource = sources[outputId]; + var animation = buildAnimationChannel(channel, inputSource, outputSource); + createKeyframeTracks(animation, tracks); + } + } + return tracks; + } + function getAnimation(id) { + return getBuild(library.animations[id], buildAnimation); + } + function buildAnimationChannel(channel, inputSource, outputSource) { + var node = library.nodes[channel.id]; + var object3D = getNode(node.id); + var transform = node.transforms[channel.sid]; + var defaultMatrix = node.matrix.clone().transpose(); + var time, stride; + var i, il, j, jl; + var data = {}; + + // the collada spec allows the animation of data in various ways. + // depending on the transform type (matrix, translate, rotate, scale), we execute different logic + + switch (transform) { + case 'matrix': + for (i = 0, il = inputSource.array.length; i < il; i++) { + time = inputSource.array[i]; + stride = i * outputSource.stride; + if (data[time] === undefined) data[time] = {}; + if (channel.arraySyntax === true) { + var value = outputSource.array[stride]; + var index = channel.indices[0] + 4 * channel.indices[1]; + data[time][index] = value; + } else { + for (j = 0, jl = outputSource.stride; j < jl; j++) { + data[time][j] = outputSource.array[stride + j]; + } + } + } + break; + case 'translate': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + case 'rotate': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + case 'scale': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); break; - } - + var keyframes = prepareAnimationData(data, defaultMatrix); + var animation = { + name: object3D.uuid, + keyframes: keyframes + }; + return animation; } + function prepareAnimationData(data, defaultMatrix) { + var keyframes = []; - library.effects[xml.getAttribute('id')] = data; + // transfer data into a sortable array - } + for (var time in data) { + keyframes.push({ + time: parseFloat(time), + value: data[time] + }); + } - function parseEffectProfileCOMMON(xml) { + // ensure keyframes are sorted by time - var data = { - surfaces: {}, - samplers: {} - }; + keyframes.sort(ascending); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // now we clean up all animation data, so we can use them for keyframe tracks - var child = xml.childNodes[i]; + for (var i = 0; i < 16; i++) { + transformAnimationData(keyframes, i, defaultMatrix.elements[i]); + } + return keyframes; - if (child.nodeType !== 1) { continue; } + // array sort function - switch (child.nodeName) { + function ascending(a, b) { + return a.time - b.time; + } + } + var position = new Vector3(); + var scale = new Vector3(); + var quaternion = new Quaternion(); + function createKeyframeTracks(animation, tracks) { + var keyframes = animation.keyframes; + var name = animation.name; + var times = []; + var positionData = []; + var quaternionData = []; + var scaleData = []; + for (var i = 0, l = keyframes.length; i < l; i++) { + var keyframe = keyframes[i]; + var time = keyframe.time; + var value = keyframe.value; + matrix.fromArray(value).transpose(); + matrix.decompose(position, quaternion, scale); + times.push(time); + positionData.push(position.x, position.y, position.z); + quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); + scaleData.push(scale.x, scale.y, scale.z); + } + if (positionData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.position', times, positionData)); + if (quaternionData.length > 0) tracks.push(new QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); + if (scaleData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.scale', times, scaleData)); + return tracks; + } + function transformAnimationData(keyframes, property, defaultValue) { + var keyframe; + var empty = true; + var i, l; - case 'newparam': - parseEffectNewparam(child, data); - break; + // check, if values of a property are missing in our keyframes - case 'technique': - data.technique = parseEffectTechnique(child); - break; + for (i = 0, l = keyframes.length; i < l; i++) { + keyframe = keyframes[i]; + if (keyframe.value[property] === undefined) { + keyframe.value[property] = null; // mark as missing + } else { + empty = false; + } + } + if (empty === true) { + // no values at all, so we set a default value + + for (i = 0, l = keyframes.length; i < l; i++) { + keyframe = keyframes[i]; + keyframe.value[property] = defaultValue; + } + } else { + // filling gaps + + createMissingKeyframes(keyframes, property); + } + } + function createMissingKeyframes(keyframes, property) { + var prev, next; + for (var i = 0, l = keyframes.length; i < l; i++) { + var keyframe = keyframes[i]; + if (keyframe.value[property] === null) { + prev = getPrev(keyframes, i, property); + next = getNext(keyframes, i, property); + if (prev === null) { + keyframe.value[property] = next.value[property]; + continue; + } + if (next === null) { + keyframe.value[property] = prev.value[property]; + continue; + } + interpolate(keyframe, prev, next, property); + } + } + } + function getPrev(keyframes, i, property) { + while (i >= 0) { + var keyframe = keyframes[i]; + if (keyframe.value[property] !== null) return keyframe; + i--; + } + return null; + } + function getNext(keyframes, i, property) { + while (i < keyframes.length) { + var keyframe = keyframes[i]; + if (keyframe.value[property] !== null) return keyframe; + i++; + } + return null; + } + function interpolate(key, prev, next, property) { + if (next.time - prev.time === 0) { + key.value[property] = prev.value[property]; + return; + } + key.value[property] = (key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time) + prev.value[property]; + } + // animation clips + + function parseAnimationClip(xml) { + var data = { + name: xml.getAttribute('id') || 'default', + start: parseFloat(xml.getAttribute('start') || 0), + end: parseFloat(xml.getAttribute('end') || 0), + animations: [] + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'instance_animation': + data.animations.push(parseId(child.getAttribute('url'))); + break; + } + } + library.clips[xml.getAttribute('id')] = data; + } + function buildAnimationClip(data) { + var tracks = []; + var name = data.name; + var duration = data.end - data.start || -1; + var animations = data.animations; + for (var i = 0, il = animations.length; i < il; i++) { + var animationTracks = getAnimation(animations[i]); + for (var j = 0, jl = animationTracks.length; j < jl; j++) { + tracks.push(animationTracks[j]); + } } + return new AnimationClip(name, duration, tracks); + } + function getAnimationClip(id) { + return getBuild(library.clips[id], buildAnimationClip); + } + // controller + + function parseController(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'skin': + // there is exactly one skin per controller + data.id = parseId(child.getAttribute('source')); + data.skin = parseSkin(child); + break; + case 'morph': + data.id = parseId(child.getAttribute('source')); + console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); + break; + } + } + library.controllers[xml.getAttribute('id')] = data; + } + function parseSkin(xml) { + var data = { + sources: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'bind_shape_matrix': + data.bindShapeMatrix = parseFloats(child.textContent); + break; + case 'source': + var id = child.getAttribute('id'); + data.sources[id] = parseSource(child); + break; + case 'joints': + data.joints = parseJoints(child); + break; + case 'vertex_weights': + data.vertexWeights = parseVertexWeights(child); + break; + } + } + return data; + } + function parseJoints(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var semantic = child.getAttribute('semantic'); + var id = parseId(child.getAttribute('source')); + data.inputs[semantic] = id; + break; + } + } + return data; + } + function parseVertexWeights(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var semantic = child.getAttribute('semantic'); + var id = parseId(child.getAttribute('source')); + var offset = parseInt(child.getAttribute('offset')); + data.inputs[semantic] = { + id: id, + offset: offset + }; + break; + case 'vcount': + data.vcount = parseInts(child.textContent); + break; + case 'v': + data.v = parseInts(child.textContent); + break; + } + } + return data; + } + function buildController(data) { + var build = { + id: data.id + }; + var geometry = library.geometries[build.id]; + if (data.skin !== undefined) { + build.skin = buildSkin(data.skin); + + // we enhance the 'sources' property of the corresponding geometry with our skin data + + geometry.sources.skinIndices = build.skin.indices; + geometry.sources.skinWeights = build.skin.weights; + } + return build; } + function buildSkin(data) { + var BONE_LIMIT = 4; + var build = { + joints: [], + // this must be an array to preserve the joint order + indices: { + array: [], + stride: BONE_LIMIT + }, + weights: { + array: [], + stride: BONE_LIMIT + } + }; + var sources = data.sources; + var vertexWeights = data.vertexWeights; + var vcount = vertexWeights.vcount; + var v = vertexWeights.v; + var jointOffset = vertexWeights.inputs.JOINT.offset; + var weightOffset = vertexWeights.inputs.WEIGHT.offset; + var jointSource = data.sources[data.joints.inputs.JOINT]; + var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; + var weights = sources[vertexWeights.inputs.WEIGHT.id].array; + var stride = 0; + var i, j, l; + + // process skin data for each vertex + + for (i = 0, l = vcount.length; i < l; i++) { + var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex + var vertexSkinData = []; + for (j = 0; j < jointCount; j++) { + var skinIndex = v[stride + jointOffset]; + var weightId = v[stride + weightOffset]; + var skinWeight = weights[weightId]; + vertexSkinData.push({ + index: skinIndex, + weight: skinWeight + }); + stride += 2; + } - return data; - - } + // we sort the joints in descending order based on the weights. + // this ensures, we only procced the most important joints of the vertex - function parseEffectNewparam(xml, data) { + vertexSkinData.sort(descending); - var sid = xml.getAttribute('sid'); + // now we provide for each vertex a set of four index and weight values. + // the order of the skin data matches the order of vertices - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + for (j = 0; j < BONE_LIMIT; j++) { + var d = vertexSkinData[j]; + if (d !== undefined) { + build.indices.array.push(d.index); + build.weights.array.push(d.weight); + } else { + build.indices.array.push(0); + build.weights.array.push(0); + } + } + } - var child = xml.childNodes[i]; + // setup bind matrix - if (child.nodeType !== 1) { continue; } + if (data.bindShapeMatrix) { + build.bindMatrix = new Matrix4().fromArray(data.bindShapeMatrix).transpose(); + } else { + build.bindMatrix = new Matrix4().identity(); + } - switch (child.nodeName) { + // process bones and inverse bind matrix data - case 'surface': - data.surfaces[sid] = parseEffectSurface(child); - break; + for (i = 0, l = jointSource.array.length; i < l; i++) { + var name = jointSource.array[i]; + var boneInverse = new Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); + build.joints.push({ + name: name, + boneInverse: boneInverse + }); + } + return build; - case 'sampler2D': - data.samplers[sid] = parseEffectSampler(child); - break; + // array sort function + function descending(a, b) { + return b.weight - a.weight; } - + } + function getController(id) { + return getBuild(library.controllers[id], buildController); } - } - - function parseEffectSurface(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'init_from': - data.init_from = child.textContent; - break; + // image + function parseImage(xml) { + var data = { + init_from: getElementsByTagName(xml, 'init_from')[0].textContent + }; + library.images[xml.getAttribute('id')] = data; + } + function buildImage(data) { + if (data.build !== undefined) return data.build; + return data.init_from; + } + function getImage(id) { + var data = library.images[id]; + if (data !== undefined) { + return getBuild(data, buildImage); } - + console.warn('THREE.ColladaLoader: Couldn\'t find image with ID:', id); + return null; } - return data; - - } - - function parseEffectSampler(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // effect - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { + function parseEffect(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'profile_COMMON': + data.profile = parseEffectProfileCOMMON(child); + break; + } + } + library.effects[xml.getAttribute('id')] = data; + } + function parseEffectProfileCOMMON(xml) { + var data = { + surfaces: {}, + samplers: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'newparam': + parseEffectNewparam(child, data); + break; + case 'technique': + data.technique = parseEffectTechnique(child); + break; + case 'extra': + data.extra = parseEffectExtra(child); + break; + } + } + return data; + } + function parseEffectNewparam(xml, data) { + var sid = xml.getAttribute('sid'); + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'surface': + data.surfaces[sid] = parseEffectSurface(child); + break; + case 'sampler2D': + data.samplers[sid] = parseEffectSampler(child); + break; + } + } + } + function parseEffectSurface(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'init_from': + data.init_from = child.textContent; + break; + } + } + return data; + } + function parseEffectSampler(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'source': + data.source = child.textContent; + break; + } + } + return data; + } + function parseEffectTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'constant': + case 'lambert': + case 'blinn': + case 'phong': + data.type = child.nodeName; + data.parameters = parseEffectParameters(child); + break; + case 'extra': + data.extra = parseEffectExtra(child); + break; + } + } + return data; + } + function parseEffectParameters(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'emission': + case 'diffuse': + case 'specular': + case 'bump': + case 'ambient': + case 'shininess': + case 'transparency': + data[child.nodeName] = parseEffectParameter(child); + break; + case 'transparent': + data[child.nodeName] = { + opaque: child.hasAttribute('opaque') ? child.getAttribute('opaque') : 'A_ONE', + data: parseEffectParameter(child) + }; + break; + } + } + return data; + } + function parseEffectParameter(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'color': + data[child.nodeName] = parseFloats(child.textContent); + break; + case 'float': + data[child.nodeName] = parseFloat(child.textContent); + break; + case 'texture': + data[child.nodeName] = { + id: child.getAttribute('texture'), + extra: parseEffectParameterTexture(child) + }; + break; + } + } + return data; + } + function parseEffectParameterTexture(xml) { + var data = { + technique: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'extra': + parseEffectParameterTextureExtra(child, data); + break; + } + } + return data; + } + function parseEffectParameterTextureExtra(xml, data) { + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique': + parseEffectParameterTextureExtraTechnique(child, data); + break; + } + } + } + function parseEffectParameterTextureExtraTechnique(xml, data) { + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'repeatU': + case 'repeatV': + case 'offsetU': + case 'offsetV': + data.technique[child.nodeName] = parseFloat(child.textContent); + break; + case 'wrapU': + case 'wrapV': + // some files have values for wrapU/wrapV which become NaN via parseInt + + if (child.textContent.toUpperCase() === 'TRUE') { + data.technique[child.nodeName] = 1; + } else if (child.textContent.toUpperCase() === 'FALSE') { + data.technique[child.nodeName] = 0; + } else { + data.technique[child.nodeName] = parseInt(child.textContent); + } + break; + case 'bump': + data[child.nodeName] = parseEffectExtraTechniqueBump(child); + break; + } + } + } + function parseEffectExtra(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique': + data.technique = parseEffectExtraTechnique(child); + break; + } + } + return data; + } + function parseEffectExtraTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'double_sided': + data[child.nodeName] = parseInt(child.textContent); + break; + case 'bump': + data[child.nodeName] = parseEffectExtraTechniqueBump(child); + break; + } + } + return data; + } + function parseEffectExtraTechniqueBump(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'texture': + data[child.nodeName] = { + id: child.getAttribute('texture'), + texcoord: child.getAttribute('texcoord'), + extra: parseEffectParameterTexture(child) + }; + break; + } + } + return data; + } + function buildEffect(data) { + return data; + } + function getEffect(id) { + return getBuild(library.effects[id], buildEffect); + } - case 'source': - data.source = child.textContent; + // material + + function parseMaterial(xml) { + var data = { + name: xml.getAttribute('name') + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'instance_effect': + data.url = parseId(child.getAttribute('url')); + break; + } + } + library.materials[xml.getAttribute('id')] = data; + } + function getTextureLoader(image) { + var loader; + var extension = image.slice((image.lastIndexOf('.') - 1 >>> 0) + 2); // http://www.jstips.co/en/javascript/get-file-extension/ + extension = extension.toLowerCase(); + switch (extension) { + case 'tga': + loader = tgaLoader; break; - + default: + loader = textureLoader; } - + return loader; } - - return data; - - } - - function parseEffectTechnique(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'constant': - case 'lambert': - case 'blinn': + function buildMaterial(data) { + var effect = getEffect(data.url); + var technique = effect.profile.technique; + var material; + switch (technique.type) { case 'phong': - data.type = child.nodeName; - data.parameters = parseEffectParameters(child); + case 'blinn': + material = new MeshPhongMaterial(); + break; + case 'lambert': + material = new MeshLambertMaterial(); + break; + default: + material = new MeshBasicMaterial(); break; - } + material.name = data.name || ''; + function getTexture(textureObject) { + var colorSpace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var sampler = effect.profile.samplers[textureObject.id]; + var image = null; - } + // get image - return data; + if (sampler !== undefined) { + var surface = effect.profile.surfaces[sampler.source]; + image = getImage(surface.init_from); + } else { + console.warn('THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530).'); + image = getImage(textureObject.id); + } - } + // create texture if image is avaiable + + if (image !== null) { + var loader = getTextureLoader(image); + if (loader !== undefined) { + var texture = loader.load(image); + var extra = textureObject.extra; + if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { + var _technique = extra.technique; + texture.wrapS = _technique.wrapU ? RepeatWrapping : ClampToEdgeWrapping; + texture.wrapT = _technique.wrapV ? RepeatWrapping : ClampToEdgeWrapping; + texture.offset.set(_technique.offsetU || 0, _technique.offsetV || 0); + texture.repeat.set(_technique.repeatU || 1, _technique.repeatV || 1); + } else { + texture.wrapS = RepeatWrapping; + texture.wrapT = RepeatWrapping; + } + if (colorSpace !== null) { + texture.colorSpace = colorSpace; + } + return texture; + } else { + console.warn('THREE.ColladaLoader: Loader for texture %s not found.', image); + return null; + } + } else { + console.warn('THREE.ColladaLoader: Couldn\'t create texture with ID:', textureObject.id); + return null; + } + } + var parameters = technique.parameters; + for (var key in parameters) { + var parameter = parameters[key]; + switch (key) { + case 'diffuse': + if (parameter.color) material.color.fromArray(parameter.color); + if (parameter.texture) material.map = getTexture(parameter.texture, SRGBColorSpace); + break; + case 'specular': + if (parameter.color && material.specular) material.specular.fromArray(parameter.color); + if (parameter.texture) material.specularMap = getTexture(parameter.texture); + break; + case 'bump': + if (parameter.texture) material.normalMap = getTexture(parameter.texture); + break; + case 'ambient': + if (parameter.texture) material.lightMap = getTexture(parameter.texture, SRGBColorSpace); + break; + case 'shininess': + if (parameter["float"] && material.shininess) material.shininess = parameter["float"]; + break; + case 'emission': + if (parameter.color && material.emissive) material.emissive.fromArray(parameter.color); + if (parameter.texture) material.emissiveMap = getTexture(parameter.texture, SRGBColorSpace); + break; + } + } + material.color.convertSRGBToLinear(); + if (material.specular) material.specular.convertSRGBToLinear(); + if (material.emissive) material.emissive.convertSRGBToLinear(); - function parseEffectParameters(xml) { + // - var data = {}; + var transparent = parameters['transparent']; + var transparency = parameters['transparency']; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // does not exist but - var child = xml.childNodes[i]; + if (transparency === undefined && transparent) { + transparency = { + "float": 1 + }; + } - if (child.nodeType !== 1) { continue; } + // does not exist but - switch (child.nodeName) { + if (transparent === undefined && transparency) { + transparent = { + opaque: 'A_ONE', + data: { + color: [1, 1, 1, 1] + } + }; + } + if (transparent && transparency) { + // handle case if a texture exists but no color - case 'emission': - case 'diffuse': - case 'specular': - case 'shininess': - case 'transparent': - case 'transparency': - data[child.nodeName] = parseEffectParameter(child); - break; + if (transparent.data.texture) { + // we do not set an alpha map (see #13792) + material.transparent = true; + } else { + var color = transparent.data.color; + switch (transparent.opaque) { + case 'A_ONE': + material.opacity = color[3] * transparency["float"]; + break; + case 'RGB_ZERO': + material.opacity = 1 - color[0] * transparency["float"]; + break; + case 'A_ZERO': + material.opacity = 1 - color[3] * transparency["float"]; + break; + case 'RGB_ONE': + material.opacity = color[0] * transparency["float"]; + break; + default: + console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.', transparent.opaque); + } + if (material.opacity < 1) material.transparent = true; + } } + // + + if (technique.extra !== undefined && technique.extra.technique !== undefined) { + var techniques = technique.extra.technique; + for (var k in techniques) { + var v = techniques[k]; + switch (k) { + case 'double_sided': + material.side = v === 1 ? DoubleSide : FrontSide; + break; + case 'bump': + material.normalMap = getTexture(v.texture); + material.normalScale = new Vector2(1, 1); + break; + } + } + } + return material; + } + function getMaterial(id) { + return getBuild(library.materials[id], buildMaterial); } - return data; - - } - - function parseEffectParameter(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } + // camera + + function parseCamera(xml) { + var data = { + name: xml.getAttribute('name') + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'optics': + data.optics = parseCameraOptics(child); + break; + } + } + library.cameras[xml.getAttribute('id')] = data; + } + function parseCameraOptics(xml) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'technique_common': + return parseCameraTechnique(child); + } + } + return {}; + } + function parseCameraTechnique(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'perspective': + case 'orthographic': + data.technique = child.nodeName; + data.parameters = parseCameraParameters(child); + break; + } + } + return data; + } + function parseCameraParameters(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'xfov': + case 'yfov': + case 'xmag': + case 'ymag': + case 'znear': + case 'zfar': + case 'aspect_ratio': + data[child.nodeName] = parseFloat(child.textContent); + break; + } + } + return data; + } + function buildCamera(data) { + var camera; + switch (data.optics.technique) { + case 'perspective': + camera = new PerspectiveCamera(data.optics.parameters.yfov, data.optics.parameters.aspect_ratio, data.optics.parameters.znear, data.optics.parameters.zfar); + break; + case 'orthographic': + var ymag = data.optics.parameters.ymag; + var xmag = data.optics.parameters.xmag; + var aspectRatio = data.optics.parameters.aspect_ratio; + xmag = xmag === undefined ? ymag * aspectRatio : xmag; + ymag = ymag === undefined ? xmag / aspectRatio : ymag; + xmag *= 0.5; + ymag *= 0.5; + camera = new OrthographicCamera(-xmag, xmag, ymag, -ymag, + // left, right, top, bottom + data.optics.parameters.znear, data.optics.parameters.zfar); + break; + default: + camera = new PerspectiveCamera(); + break; + } + camera.name = data.name || ''; + return camera; + } + function getCamera(id) { + var data = library.cameras[id]; + if (data !== undefined) { + return getBuild(data, buildCamera); + } + console.warn('THREE.ColladaLoader: Couldn\'t find camera with ID:', id); + return null; + } - switch (child.nodeName) { + // light - case 'color': - data[child.nodeName] = parseFloats(child.textContent); + function parseLight(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + data = parseLightTechnique(child); + break; + } + } + library.lights[xml.getAttribute('id')] = data; + } + function parseLightTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'directional': + case 'point': + case 'spot': + case 'ambient': + data.technique = child.nodeName; + data.parameters = parseLightParameters(child); + } + } + return data; + } + function parseLightParameters(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'color': + var array = parseFloats(child.textContent); + data.color = new Color().fromArray(array).convertSRGBToLinear(); + break; + case 'falloff_angle': + data.falloffAngle = parseFloat(child.textContent); + break; + case 'quadratic_attenuation': + var f = parseFloat(child.textContent); + data.distance = f ? Math.sqrt(1 / f) : 0; + break; + } + } + return data; + } + function buildLight(data) { + var light; + switch (data.technique) { + case 'directional': + light = new DirectionalLight(); break; - - case 'float': - data[child.nodeName] = parseFloat(child.textContent); + case 'point': + light = new PointLight(); break; - - case 'texture': - data[child.nodeName] = { id: child.getAttribute('texture'), extra: parseEffectParameterTexture(child) }; + case 'spot': + light = new SpotLight(); + break; + case 'ambient': + light = new AmbientLight(); break; + } + if (data.parameters.color) light.color.copy(data.parameters.color); + if (data.parameters.distance) light.distance = data.parameters.distance; + return light; + } + function getLight(id) { + var data = library.lights[id]; + if (data !== undefined) { + return getBuild(data, buildLight); + } + console.warn('THREE.ColladaLoader: Couldn\'t find light with ID:', id); + return null; + } + // geometry + + function parseGeometry(xml) { + var data = { + name: xml.getAttribute('name'), + sources: {}, + vertices: {}, + primitives: [] + }; + var mesh = getElementsByTagName(xml, 'mesh')[0]; + + // the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep + if (mesh === undefined) return; + for (var i = 0; i < mesh.childNodes.length; i++) { + var child = mesh.childNodes[i]; + if (child.nodeType !== 1) continue; + var id = child.getAttribute('id'); + switch (child.nodeName) { + case 'source': + data.sources[id] = parseSource(child); + break; + case 'vertices': + // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; + data.vertices = parseGeometryVertices(child); + break; + case 'polygons': + console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); + break; + case 'lines': + case 'linestrips': + case 'polylist': + case 'triangles': + data.primitives.push(parseGeometryPrimitive(child)); + break; + default: + console.log(child); + } + } + library.geometries[xml.getAttribute('id')] = data; + } + function parseSource(xml) { + var data = { + array: [], + stride: 3 + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'float_array': + data.array = parseFloats(child.textContent); + break; + case 'Name_array': + data.array = parseStrings(child.textContent); + break; + case 'technique_common': + var accessor = getElementsByTagName(child, 'accessor')[0]; + if (accessor !== undefined) { + data.stride = parseInt(accessor.getAttribute('stride')); + } + break; + } + } + return data; + } + function parseGeometryVertices(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + } + return data; + } + function parseGeometryPrimitive(xml) { + var primitive = { + type: xml.nodeName, + material: xml.getAttribute('material'), + count: parseInt(xml.getAttribute('count')), + inputs: {}, + stride: 0, + hasUV: false + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var id = parseId(child.getAttribute('source')); + var semantic = child.getAttribute('semantic'); + var offset = parseInt(child.getAttribute('offset')); + var set = parseInt(child.getAttribute('set')); + var inputname = set > 0 ? semantic + set : semantic; + primitive.inputs[inputname] = { + id: id, + offset: offset + }; + primitive.stride = Math.max(primitive.stride, offset + 1); + if (semantic === 'TEXCOORD') primitive.hasUV = true; + break; + case 'vcount': + primitive.vcount = parseInts(child.textContent); + break; + case 'p': + primitive.p = parseInts(child.textContent); + break; + } + } + return primitive; + } + function groupPrimitives(primitives) { + var build = {}; + for (var i = 0; i < primitives.length; i++) { + var primitive = primitives[i]; + if (build[primitive.type] === undefined) build[primitive.type] = []; + build[primitive.type].push(primitive); + } + return build; + } + function checkUVCoordinates(primitives) { + var count = 0; + for (var i = 0, l = primitives.length; i < l; i++) { + var primitive = primitives[i]; + if (primitive.hasUV === true) { + count++; + } + } + if (count > 0 && count < primitives.length) { + primitives.uvsNeedsFix = true; } - } + function buildGeometry(data) { + var build = {}; + var sources = data.sources; + var vertices = data.vertices; + var primitives = data.primitives; + if (primitives.length === 0) return {}; - return data; - - } - - function parseEffectParameterTexture(xml) { + // our goal is to create one buffer geometry for a single type of primitives + // first, we group all primitives by their type - var data = { - technique: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var groupedPrimitives = groupPrimitives(primitives); + for (var type in groupedPrimitives) { + var primitiveType = groupedPrimitives[type]; - var child = xml.childNodes[i]; + // second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines) - if (child.nodeType !== 1) { continue; } + checkUVCoordinates(primitiveType); - switch (child.nodeName) { - - case 'extra': - parseEffectParameterTextureExtra(child, data); - break; + // third, create a buffer geometry for each type of primitives + build[type] = buildGeometryType(primitiveType, sources, vertices); } - + return build; } + function buildGeometryType(primitives, sources, vertices) { + var build = {}; + var position = { + array: [], + stride: 0 + }; + var normal = { + array: [], + stride: 0 + }; + var uv = { + array: [], + stride: 0 + }; + var uv1 = { + array: [], + stride: 0 + }; + var color = { + array: [], + stride: 0 + }; + var skinIndex = { + array: [], + stride: 4 + }; + var skinWeight = { + array: [], + stride: 4 + }; + var geometry = new BufferGeometry(); + var materialKeys = []; + var start = 0; + for (var p = 0; p < primitives.length; p++) { + var primitive = primitives[p]; + var inputs = primitive.inputs; + + // groups + + var _count = 0; + switch (primitive.type) { + case 'lines': + case 'linestrips': + _count = primitive.count * 2; + break; + case 'triangles': + _count = primitive.count * 3; + break; + case 'polylist': + for (var g = 0; g < primitive.count; g++) { + var vc = primitive.vcount[g]; + switch (vc) { + case 3: + _count += 3; // single triangle + break; + case 4: + _count += 6; // quad, subdivided into two triangles + break; + default: + _count += (vc - 2) * 3; // polylist with more than four vertices + break; + } + } + break; + default: + console.warn('THREE.ColladaLoader: Unknow primitive type:', primitive.type); + } + geometry.addGroup(start, _count, p); + start += _count; - return data; - - } - - function parseEffectParameterTextureExtra(xml, data) { - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { + // material - case 'technique': - parseEffectParameterTextureExtraTechnique(child, data); - break; + if (primitive.material) { + materialKeys.push(primitive.material); + } + // geometry data + + for (var name in inputs) { + var input = inputs[name]; + switch (name) { + case 'VERTEX': + for (var key in vertices) { + var id = vertices[key]; + switch (key) { + case 'POSITION': + var prevLength = position.array.length; + buildGeometryData(primitive, sources[id], input.offset, position.array); + position.stride = sources[id].stride; + if (sources.skinWeights && sources.skinIndices) { + buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); + buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + } + + // see #3803 + + if (primitive.hasUV === false && primitives.uvsNeedsFix === true) { + var _count2 = (position.array.length - prevLength) / position.stride; + for (var i = 0; i < _count2; i++) { + // fill missing uv coordinates + + uv.array.push(0, 0); + } + } + break; + case 'NORMAL': + buildGeometryData(primitive, sources[id], input.offset, normal.array); + normal.stride = sources[id].stride; + break; + case 'COLOR': + buildGeometryData(primitive, sources[id], input.offset, color.array); + color.stride = sources[id].stride; + break; + case 'TEXCOORD': + buildGeometryData(primitive, sources[id], input.offset, uv.array); + uv.stride = sources[id].stride; + break; + case 'TEXCOORD1': + buildGeometryData(primitive, sources[id], input.offset, uv1.array); + uv.stride = sources[id].stride; + break; + default: + console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + } + } + break; + case 'NORMAL': + buildGeometryData(primitive, sources[input.id], input.offset, normal.array); + normal.stride = sources[input.id].stride; + break; + case 'COLOR': + buildGeometryData(primitive, sources[input.id], input.offset, color.array, true); + color.stride = sources[input.id].stride; + break; + case 'TEXCOORD': + buildGeometryData(primitive, sources[input.id], input.offset, uv.array); + uv.stride = sources[input.id].stride; + break; + case 'TEXCOORD1': + buildGeometryData(primitive, sources[input.id], input.offset, uv1.array); + uv1.stride = sources[input.id].stride; + break; + } + } } + // build geometry + + if (position.array.length > 0) geometry.setAttribute('position', new Float32BufferAttribute(position.array, position.stride)); + if (normal.array.length > 0) geometry.setAttribute('normal', new Float32BufferAttribute(normal.array, normal.stride)); + if (color.array.length > 0) geometry.setAttribute('color', new Float32BufferAttribute(color.array, color.stride)); + if (uv.array.length > 0) geometry.setAttribute('uv', new Float32BufferAttribute(uv.array, uv.stride)); + if (uv1.array.length > 0) geometry.setAttribute('uv1', new Float32BufferAttribute(uv1.array, uv1.stride)); + if (skinIndex.array.length > 0) geometry.setAttribute('skinIndex', new Float32BufferAttribute(skinIndex.array, skinIndex.stride)); + if (skinWeight.array.length > 0) geometry.setAttribute('skinWeight', new Float32BufferAttribute(skinWeight.array, skinWeight.stride)); + build.data = geometry; + build.type = primitives[0].type; + build.materialKeys = materialKeys; + return build; } - - } - - function parseEffectParameterTextureExtraTechnique(xml, data) { - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'repeatU': - case 'repeatV': - case 'offsetU': - case 'offsetV': - data.technique[child.nodeName] = parseFloat(child.textContent); - break; - - case 'wrapU': - case 'wrapV': - - // some files have values for wrapU/wrapV which become NaN via parseInt - - if (child.textContent.toUpperCase() === 'TRUE') { - - data.technique[child.nodeName] = 1; - - } else if (child.textContent.toUpperCase() === 'FALSE') { - - data.technique[child.nodeName] = 0; - - } else { - - data.technique[child.nodeName] = parseInt(child.textContent); - + function buildGeometryData(primitive, source, offset, array) { + var isColor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + var indices = primitive.p; + var stride = primitive.stride; + var vcount = primitive.vcount; + function pushVector(i) { + var index = indices[i + offset] * sourceStride; + var length = index + sourceStride; + for (; index < length; index++) { + array.push(sourceArray[index]); + } + if (isColor) { + // convert the vertex colors from srgb to linear if present + var startIndex = array.length - sourceStride - 1; + tempColor.setRGB(array[startIndex + 0], array[startIndex + 1], array[startIndex + 2]).convertSRGBToLinear(); + array[startIndex + 0] = tempColor.r; + array[startIndex + 1] = tempColor.g; + array[startIndex + 2] = tempColor.b; + } + } + var sourceArray = source.array; + var sourceStride = source.stride; + if (primitive.vcount !== undefined) { + var index = 0; + for (var i = 0, l = vcount.length; i < l; i++) { + var _count3 = vcount[i]; + if (_count3 === 4) { + var a = index + stride * 0; + var b = index + stride * 1; + var c = index + stride * 2; + var d = index + stride * 3; + pushVector(a); + pushVector(b); + pushVector(d); + pushVector(b); + pushVector(c); + pushVector(d); + } else if (_count3 === 3) { + var _a = index + stride * 0; + var _b = index + stride * 1; + var _c = index + stride * 2; + pushVector(_a); + pushVector(_b); + pushVector(_c); + } else if (_count3 > 4) { + for (var k = 1, kl = _count3 - 2; k <= kl; k++) { + var _a2 = index + stride * 0; + var _b2 = index + stride * k; + var _c2 = index + stride * (k + 1); + pushVector(_a2); + pushVector(_b2); + pushVector(_c2); + } } - - break; - + index += stride * _count3; + } + } else { + for (var _i = 0, _l = indices.length; _i < _l; _i += stride) { + pushVector(_i); + } } - + } + function getGeometry(id) { + return getBuild(library.geometries[id], buildGeometry); } - } - - function buildEffect(data) { - - return data; - - } - - function getEffect(id) { - - return getBuild(library.effects[id], buildEffect); - - } - - // material - - function parseMaterial(xml) { - - var data = { - name: xml.getAttribute('name') - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) { continue; } - - switch (child.nodeName) { - - case 'instance_effect': - data.url = parseId(child.getAttribute('url')); - break; - + // kinematics + + function parseKinematicsModel(xml) { + var data = { + name: xml.getAttribute('name') || '', + joints: {}, + links: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + parseKinematicsTechniqueCommon(child, data); + break; + } } - + library.kinematicsModels[xml.getAttribute('id')] = data; } - - library.materials[xml.getAttribute('id')] = data; - - } - - function buildMaterial(data) { - - var effect = getEffect(data.url); - var technique = effect.profile.technique; - - var material; - - switch (technique.type) { - - case 'phong': - case 'blinn': - material = new THREE.MeshPhongMaterial(); - break; - - case 'lambert': - material = new THREE.MeshLambertMaterial(); - break; - - default: - material = new THREE.MeshBasicMaterial(); - break; - + function buildKinematicsModel(data) { + if (data.build !== undefined) return data.build; + return data; } - - material.name = data.name; - - function getTexture(textureObject) { - - var sampler = effect.profile.samplers[textureObject.id]; - - if (sampler !== undefined) { - - var surface = effect.profile.surfaces[sampler.source]; - - var texture = textureLoader.load(getImage(surface.init_from)); - - var extra = textureObject.extra; - - if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { - - var technique = extra.technique; - - texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; - texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; - - texture.offset.set(technique.offsetU || 0, technique.offsetV || 0); - texture.repeat.set(technique.repeatU || 1, technique.repeatV || 1); - - } else { - - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; - + function getKinematicsModel(id) { + return getBuild(library.kinematicsModels[id], buildKinematicsModel); + } + function parseKinematicsTechniqueCommon(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'joint': + data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); + break; + case 'link': + data.links.push(parseKinematicsLink(child)); + break; } - - return texture; - } - - console.error('THREE.ColladaLoader: Undefined sampler', textureObject.id); - - return null; - } + function parseKinematicsJoint(xml) { + var data; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'prismatic': + case 'revolute': + data = parseKinematicsJointParameter(child); + break; + } + } + return data; + } + function parseKinematicsJointParameter(xml) { + var data = { + sid: xml.getAttribute('sid'), + name: xml.getAttribute('name') || '', + axis: new Vector3(), + limits: { + min: 0, + max: 0 + }, + type: xml.nodeName, + "static": false, + zeroPosition: 0, + middlePosition: 0 + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'axis': + var array = parseFloats(child.textContent); + data.axis.fromArray(array); + break; + case 'limits': + var max = child.getElementsByTagName('max')[0]; + var min = child.getElementsByTagName('min')[0]; + data.limits.max = parseFloat(max.textContent); + data.limits.min = parseFloat(min.textContent); + break; + } + } - var parameters = technique.parameters; - - for (var key in parameters) { + // if min is equal to or greater than max, consider the joint static - var parameter = parameters[key]; + if (data.limits.min >= data.limits.max) { + data["static"] = true; + } - switch (key) { + // calculate middle position - case 'diffuse': - if (parameter.color) { material.color.fromArray(parameter.color); } - if (parameter.texture) { material.map = getTexture(parameter.texture); } - break; - case 'specular': - if (parameter.color && material.specular) { material.specular.fromArray(parameter.color); } - if (parameter.texture) { material.specularMap = getTexture(parameter.texture); } - break; - case 'shininess': - if (parameter.float && material.shininess) - { material.shininess = parameter.float; } - break; - case 'emission': - if (parameter.color && material.emissive) - { material.emissive.fromArray(parameter.color); } + data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + return data; + } + function parseKinematicsLink(xml) { + var data = { + sid: xml.getAttribute('sid'), + name: xml.getAttribute('name') || '', + attachments: [], + transforms: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'attachment_full': + data.attachments.push(parseKinematicsAttachment(child)); + break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push(parseKinematicsTransform(child)); + break; + } + } + return data; + } + function parseKinematicsAttachment(xml) { + var data = { + joint: xml.getAttribute('joint').split('/').pop(), + transforms: [], + links: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'link': + data.links.push(parseKinematicsLink(child)); + break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push(parseKinematicsTransform(child)); + break; + } + } + return data; + } + function parseKinematicsTransform(xml) { + var data = { + type: xml.nodeName + }; + var array = parseFloats(xml.textContent); + switch (data.type) { + case 'matrix': + data.obj = new Matrix4(); + data.obj.fromArray(array).transpose(); break; - case 'transparent': - // if ( parameter.texture ) material.alphaMap = getTexture( parameter.texture ); - material.transparent = true; + case 'translate': + data.obj = new Vector3(); + data.obj.fromArray(array); break; - case 'transparency': - if (parameter.float !== undefined) { material.opacity = parameter.float; } - material.transparent = true; + case 'rotate': + data.obj = new Vector3(); + data.obj.fromArray(array); + data.angle = MathUtils.degToRad(array[3]); break; - } - + return data; } - return material; - - } - - function getMaterial(id) { + // physics + + function parsePhysicsModel(xml) { + var data = { + name: xml.getAttribute('name') || '', + rigidBodies: {} + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'rigid_body': + data.rigidBodies[child.getAttribute('name')] = {}; + parsePhysicsRigidBody(child, data.rigidBodies[child.getAttribute('name')]); + break; + } + } + library.physicsModels[xml.getAttribute('id')] = data; + } + function parsePhysicsRigidBody(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + parsePhysicsTechniqueCommon(child, data); + break; + } + } + } + function parsePhysicsTechniqueCommon(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'inertia': + data.inertia = parseFloats(child.textContent); + break; + case 'mass': + data.mass = parseFloats(child.textContent)[0]; + break; + } + } + } - return getBuild(library.materials[id], buildMaterial); + // scene + + function parseKinematicsScene(xml) { + var data = { + bindJointAxis: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'bind_joint_axis': + data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); + break; + } + } + library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + } + function parseKinematicsBindJointAxis(xml) { + var data = { + target: xml.getAttribute('target').split('/').pop() + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'axis': + var param = child.getElementsByTagName('param')[0]; + data.axis = param.textContent; + var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; + data.jointIndex = tmpJointIndex.substring(0, tmpJointIndex.length - 1); + break; + } + } + return data; + } + function buildKinematicsScene(data) { + if (data.build !== undefined) return data.build; + return data; + } + function getKinematicsScene(id) { + return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + } + function setupKinematics() { + var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; + var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; + var visualSceneId = Object.keys(library.visualScenes)[0]; + if (kinematicsModelId === undefined || kinematicsSceneId === undefined) return; + var kinematicsModel = getKinematicsModel(kinematicsModelId); + var kinematicsScene = getKinematicsScene(kinematicsSceneId); + var visualScene = getVisualScene(visualSceneId); + var bindJointAxis = kinematicsScene.bindJointAxis; + var jointMap = {}; + for (var i = 0, l = bindJointAxis.length; i < l; i++) { + var axis = bindJointAxis[i]; + + // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' + + var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); + if (targetElement) { + // get the parent of the transform element + + var parentVisualElement = targetElement.parentElement; + + // connect the joint of the kinematics model with the element in the visual scene + + connect(axis.jointIndex, parentVisualElement); + } + } + function connect(jointIndex, visualElement) { + var visualElementName = visualElement.getAttribute('name'); + var joint = kinematicsModel.joints[jointIndex]; + visualScene.traverse(function (object) { + if (object.name === visualElementName) { + jointMap[jointIndex] = { + object: object, + transforms: buildTransformList(visualElement), + joint: joint, + position: joint.zeroPosition + }; + } + }); + } + var m0 = new Matrix4(); + kinematics = { + joints: kinematicsModel && kinematicsModel.joints, + getJointValue: function getJointValue(jointIndex) { + var jointData = jointMap[jointIndex]; + if (jointData) { + return jointData.position; + } else { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); + } + }, + setJointValue: function setJointValue(jointIndex, value) { + var jointData = jointMap[jointIndex]; + if (jointData) { + var joint = jointData.joint; + if (value > joint.limits.max || value < joint.limits.min) { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + } else if (joint["static"]) { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + } else { + var object = jointData.object; + var _axis = joint.axis; + var transforms = jointData.transforms; + matrix.identity(); + + // each update, we have to apply all transforms in the correct order + + for (var _i2 = 0; _i2 < transforms.length; _i2++) { + var transform = transforms[_i2]; + + // if there is a connection of the transform node with a joint, apply the joint value + + if (transform.sid && transform.sid.indexOf(jointIndex) !== -1) { + switch (joint.type) { + case 'revolute': + matrix.multiply(m0.makeRotationAxis(_axis, MathUtils.degToRad(value))); + break; + case 'prismatic': + matrix.multiply(m0.makeTranslation(_axis.x * value, _axis.y * value, _axis.z * value)); + break; + default: + console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); + break; + } + } else { + switch (transform.type) { + case 'matrix': + matrix.multiply(transform.obj); + break; + case 'translate': + matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); + break; + case 'scale': + matrix.scale(transform.obj); + break; + case 'rotate': + matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); + break; + } + } + } + object.matrix.copy(matrix); + object.matrix.decompose(object.position, object.quaternion, object.scale); + jointMap[jointIndex].position = value; + } + } else { + console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + } + } + }; + } + function buildTransformList(node) { + var transforms = []; + var xml = collada.querySelector('[id="' + node.id + '"]'); + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var array = void 0, + _vector = void 0; + switch (child.nodeName) { + case 'matrix': + array = parseFloats(child.textContent); + var _matrix = new Matrix4().fromArray(array).transpose(); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _matrix + }); + break; + case 'translate': + case 'scale': + array = parseFloats(child.textContent); + _vector = new Vector3().fromArray(array); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _vector + }); + break; + case 'rotate': + array = parseFloats(child.textContent); + _vector = new Vector3().fromArray(array); + var angle = MathUtils.degToRad(array[3]); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _vector, + angle: angle + }); + break; + } + } + return transforms; + } - } + // nodes - // camera + function prepareNodes(xml) { + var elements = xml.getElementsByTagName('node'); - function parseCamera(xml) { + // ensure all node elements have id attributes - var data = { - name: xml.getAttribute('name') - }; + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (element.hasAttribute('id') === false) { + element.setAttribute('id', generateId()); + } + } + } + var matrix = new Matrix4(); + var vector = new Vector3(); + function parseNode(xml) { + var data = { + name: xml.getAttribute('name') || '', + type: xml.getAttribute('type'), + id: xml.getAttribute('id'), + sid: xml.getAttribute('sid'), + matrix: new Matrix4(), + nodes: [], + instanceCameras: [], + instanceControllers: [], + instanceLights: [], + instanceGeometries: [], + instanceNodes: [], + transforms: {} + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var array = void 0; + switch (child.nodeName) { + case 'node': + data.nodes.push(child.getAttribute('id')); + parseNode(child); + break; + case 'instance_camera': + data.instanceCameras.push(parseId(child.getAttribute('url'))); + break; + case 'instance_controller': + data.instanceControllers.push(parseNodeInstance(child)); + break; + case 'instance_light': + data.instanceLights.push(parseId(child.getAttribute('url'))); + break; + case 'instance_geometry': + data.instanceGeometries.push(parseNodeInstance(child)); + break; + case 'instance_node': + data.instanceNodes.push(parseId(child.getAttribute('url'))); + break; + case 'matrix': + array = parseFloats(child.textContent); + data.matrix.multiply(matrix.fromArray(array).transpose()); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'translate': + array = parseFloats(child.textContent); + vector.fromArray(array); + data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'rotate': + array = parseFloats(child.textContent); + var angle = MathUtils.degToRad(array[3]); + data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'scale': + array = parseFloats(child.textContent); + data.matrix.scale(vector.fromArray(array)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'extra': + break; + default: + console.log(child); + } + } + if (hasNode(data.id)) { + console.warn('THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id); + } else { + library.nodes[data.id] = data; + } + return data; + } + function parseNodeInstance(xml) { + var data = { + id: parseId(xml.getAttribute('url')), + materials: {}, + skeletons: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'bind_material': + var instances = child.getElementsByTagName('instance_material'); + for (var j = 0; j < instances.length; j++) { + var instance = instances[j]; + var symbol = instance.getAttribute('symbol'); + var target = instance.getAttribute('target'); + data.materials[symbol] = parseId(target); + } + break; + case 'skeleton': + data.skeletons.push(parseId(child.textContent)); + break; + } + } + return data; + } + function buildSkeleton(skeletons, joints) { + var boneData = []; + var sortedBoneData = []; + var i, j, data; + + // a skeleton can have multiple root bones. collada expresses this + // situtation with multiple "skeleton" tags per controller instance + + for (i = 0; i < skeletons.length; i++) { + var skeleton = skeletons[i]; + var root = void 0; + if (hasNode(skeleton)) { + root = getNode(skeleton); + buildBoneHierarchy(root, joints, boneData); + } else if (hasVisualScene(skeleton)) { + // handle case where the skeleton refers to the visual scene (#13335) + + var visualScene = library.visualScenes[skeleton]; + var children = visualScene.children; + for (var _j = 0; _j < children.length; _j++) { + var child = children[_j]; + if (child.type === 'JOINT') { + var _root = getNode(child.id); + buildBoneHierarchy(_root, joints, boneData); + } + } + } else { + console.error('THREE.ColladaLoader: Unable to find root bone of skeleton with ID:', skeleton); + } + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // sort bone data (the order is defined in the corresponding controller) - var child = xml.childNodes[i]; + for (i = 0; i < joints.length; i++) { + for (j = 0; j < boneData.length; j++) { + data = boneData[j]; + if (data.bone.name === joints[i].name) { + sortedBoneData[i] = data; + data.processed = true; + break; + } + } + } - if (child.nodeType !== 1) { continue; } + // add unprocessed bone data at the end of the list - switch (child.nodeName) { + for (i = 0; i < boneData.length; i++) { + data = boneData[i]; + if (data.processed === false) { + sortedBoneData.push(data); + data.processed = true; + } + } - case 'optics': - data.optics = parseCameraOptics(child); - break; + // setup arrays for skeleton creation + var bones = []; + var boneInverses = []; + for (i = 0; i < sortedBoneData.length; i++) { + data = sortedBoneData[i]; + bones.push(data.bone); + boneInverses.push(data.boneInverse); } - + return new Skeleton(bones, boneInverses); } + function buildBoneHierarchy(root, joints, boneData) { + // setup bone data from visual scene - library.cameras[xml.getAttribute('id')] = data; - - } - - function parseCameraOptics(xml) { + root.traverse(function (object) { + if (object.isBone === true) { + var boneInverse; - for (var i = 0; i < xml.childNodes.length; i++) { + // retrieve the boneInverse from the controller data - var child = xml.childNodes[i]; + for (var i = 0; i < joints.length; i++) { + var joint = joints[i]; + if (joint.name === object.name) { + boneInverse = joint.boneInverse; + break; + } + } + if (boneInverse === undefined) { + // Unfortunately, there can be joints in the visual scene that are not part of the + // corresponding controller. In this case, we have to create a dummy boneInverse matrix + // for the respective bone. This bone won't affect any vertices, because there are no skin indices + // and weights defined for it. But we still have to add the bone to the sorted bone list in order to + // ensure a correct animation of the model. + + boneInverse = new Matrix4(); + } + boneData.push({ + bone: object, + boneInverse: boneInverse, + processed: false + }); + } + }); + } + function buildNode(data) { + var objects = []; + var matrix = data.matrix; + var nodes = data.nodes; + var type = data.type; + var instanceCameras = data.instanceCameras; + var instanceControllers = data.instanceControllers; + var instanceLights = data.instanceLights; + var instanceGeometries = data.instanceGeometries; + var instanceNodes = data.instanceNodes; + + // nodes + + for (var i = 0, l = nodes.length; i < l; i++) { + objects.push(getNode(nodes[i])); + } - switch (child.nodeName) { + // instance cameras - case 'technique_common': - return parseCameraTechnique(child); + for (var _i3 = 0, _l2 = instanceCameras.length; _i3 < _l2; _i3++) { + var instanceCamera = getCamera(instanceCameras[_i3]); + if (instanceCamera !== null) { + objects.push(instanceCamera.clone()); + } + } + // instance controllers + + for (var _i4 = 0, _l3 = instanceControllers.length; _i4 < _l3; _i4++) { + var instance = instanceControllers[_i4]; + var controller = getController(instance.id); + var geometries = getGeometry(controller.id); + var newObjects = buildObjects(geometries, instance.materials); + var skeletons = instance.skeletons; + var joints = controller.skin.joints; + var skeleton = buildSkeleton(skeletons, joints); + for (var j = 0, jl = newObjects.length; j < jl; j++) { + var _object = newObjects[j]; + if (_object.isSkinnedMesh) { + _object.bind(skeleton, controller.skin.bindMatrix); + _object.normalizeSkinWeights(); + } + objects.push(_object); + } } - } + // instance lights - return {}; + for (var _i5 = 0, _l4 = instanceLights.length; _i5 < _l4; _i5++) { + var instanceLight = getLight(instanceLights[_i5]); + if (instanceLight !== null) { + objects.push(instanceLight.clone()); + } + } - } + // instance geometries - function parseCameraTechnique(xml) { + for (var _i6 = 0, _l5 = instanceGeometries.length; _i6 < _l5; _i6++) { + var _instance = instanceGeometries[_i6]; - var data = {}; + // a single geometry instance in collada can lead to multiple object3Ds. + // this is the case when primitives are combined like triangles and lines - for (var i = 0; i < xml.childNodes.length; i++) { + var _geometries = getGeometry(_instance.id); + var _newObjects = buildObjects(_geometries, _instance.materials); + for (var _j2 = 0, _jl = _newObjects.length; _j2 < _jl; _j2++) { + objects.push(_newObjects[_j2]); + } + } - var child = xml.childNodes[i]; + // instance nodes - switch (child.nodeName) { + for (var _i7 = 0, _l6 = instanceNodes.length; _i7 < _l6; _i7++) { + objects.push(getNode(instanceNodes[_i7]).clone()); + } + var object; + if (nodes.length === 0 && objects.length === 1) { + object = objects[0]; + } else { + object = type === 'JOINT' ? new Bone() : new Group(); + for (var _i8 = 0; _i8 < objects.length; _i8++) { + object.add(objects[_i8]); + } + } + object.name = type === 'JOINT' ? data.sid : data.name; + object.matrix.copy(matrix); + object.matrix.decompose(object.position, object.quaternion, object.scale); + return object; + } + var fallbackMaterial = new MeshBasicMaterial({ + name: Loader.DEFAULT_MATERIAL_NAME, + color: 0xff00ff + }); + function resolveMaterialBinding(keys, instanceMaterials) { + var materials = []; + for (var i = 0, l = keys.length; i < l; i++) { + var id = instanceMaterials[keys[i]]; + if (id === undefined) { + console.warn('THREE.ColladaLoader: Material with key %s not found. Apply fallback material.', keys[i]); + materials.push(fallbackMaterial); + } else { + materials.push(getMaterial(id)); + } + } + return materials; + } + function buildObjects(geometries, instanceMaterials) { + var objects = []; + for (var type in geometries) { + var geometry = geometries[type]; + var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); - case 'perspective': - case 'orthographic': + // handle case if no materials are defined - data.technique = child.nodeName; - data.parameters = parseCameraParameters(child); + if (materials.length === 0) { + if (type === 'lines' || type === 'linestrips') { + materials.push(new LineBasicMaterial()); + } else { + materials.push(new MeshPhongMaterial()); + } + } - break; + // Collada allows to use phong and lambert materials with lines. Replacing these cases with LineBasicMaterial. - } + if (type === 'lines' || type === 'linestrips') { + for (var i = 0, l = materials.length; i < l; i++) { + var _material = materials[i]; + if (_material.isMeshPhongMaterial === true || _material.isMeshLambertMaterial === true) { + var lineMaterial = new LineBasicMaterial(); - } + // copy compatible properties - return data; + lineMaterial.color.copy(_material.color); + lineMaterial.opacity = _material.opacity; + lineMaterial.transparent = _material.transparent; - } + // replace material - function parseCameraParameters(xml) { + materials[i] = lineMaterial; + } + } + } - var data = {}; + // regard skinning - for (var i = 0; i < xml.childNodes.length; i++) { + var skinning = geometry.data.attributes.skinIndex !== undefined; - var child = xml.childNodes[i]; + // choose between a single or multi materials (material array) - switch (child.nodeName) { + var material = materials.length === 1 ? materials[0] : materials; - case 'xfov': - case 'yfov': - case 'xmag': - case 'ymag': - case 'znear': - case 'zfar': - case 'aspect_ratio': - data[child.nodeName] = parseFloat(child.textContent); - break; + // now create a specific 3D object + var object = void 0; + switch (type) { + case 'lines': + object = new LineSegments(geometry.data, material); + break; + case 'linestrips': + object = new Line(geometry.data, material); + break; + case 'triangles': + case 'polylist': + if (skinning) { + object = new SkinnedMesh(geometry.data, material); + } else { + object = new Mesh(geometry.data, material); + } + break; + } + objects.push(object); } - + return objects; + } + function hasNode(id) { + return library.nodes[id] !== undefined; + } + function getNode(id) { + return getBuild(library.nodes[id], buildNode); } - return data; - - } - - function buildCamera(data) { + // visual scenes - var camera; + function parseVisualScene(xml) { + var data = { + name: xml.getAttribute('name'), + children: [] + }; + prepareNodes(xml); + var elements = getElementsByTagName(xml, 'node'); + for (var i = 0; i < elements.length; i++) { + data.children.push(parseNode(elements[i])); + } + library.visualScenes[xml.getAttribute('id')] = data; + } + function buildVisualScene(data) { + var group = new Group(); + group.name = data.name; + var children = data.children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + group.add(getNode(child.id)); + } + return group; + } + function hasVisualScene(id) { + return library.visualScenes[id] !== undefined; + } + function getVisualScene(id) { + return getBuild(library.visualScenes[id], buildVisualScene); + } - switch (data.optics.technique) { + // scenes - case 'perspective': - camera = new THREE.PerspectiveCamera( - data.optics.parameters.yfov, - data.optics.parameters.aspect_ratio, - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + function parseScene(xml) { + var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; + return getVisualScene(parseId(instance.getAttribute('url'))); + } + function setupAnimations() { + var clips = library.clips; + if (isEmpty(clips) === true) { + if (isEmpty(library.animations) === false) { + // if there are animations but no clips, we create a default clip for playback + + var tracks = []; + for (var id in library.animations) { + var animationTracks = getAnimation(id); + for (var i = 0, l = animationTracks.length; i < l; i++) { + tracks.push(animationTracks[i]); + } + } + animations.push(new AnimationClip('default', -1, tracks)); + } + } else { + for (var _id in clips) { + animations.push(getAnimationClip(_id)); + } + } + } - case 'orthographic': - var ymag = data.optics.parameters.ymag; - var xmag = data.optics.parameters.xmag; - var aspectRatio = data.optics.parameters.aspect_ratio; + // convert the parser error element into text with each child elements text + // separated by new lines. - xmag = (xmag === undefined) ? (ymag * aspectRatio) : xmag; - ymag = (ymag === undefined) ? (xmag / aspectRatio) : ymag; + function parserErrorToText(parserError) { + var result = ''; + var stack = [parserError]; + while (stack.length) { + var node = stack.shift(); + if (node.nodeType === Node.TEXT_NODE) { + result += node.textContent; + } else { + result += '\n'; + stack.push.apply(stack, node.childNodes); + } + } + return result.trim(); + } + if (text.length === 0) { + return { + scene: new Scene() + }; + } + var xml = new DOMParser().parseFromString(text, 'application/xml'); + var collada = getElementsByTagName(xml, 'COLLADA')[0]; + var parserError = xml.getElementsByTagName('parsererror')[0]; + if (parserError !== undefined) { + // Chrome will return parser error with a div in it + + var errorElement = getElementsByTagName(parserError, 'div')[0]; + var errorText; + if (errorElement) { + errorText = errorElement.textContent; + } else { + errorText = parserErrorToText(parserError); + } + console.error('THREE.ColladaLoader: Failed to parse collada file.\n', errorText); + return null; + } - xmag *= 0.5; - ymag *= 0.5; + // metadata + + var version = collada.getAttribute('version'); + console.debug('THREE.ColladaLoader: File version', version); + var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); + var textureLoader = new TextureLoader(this.manager); + textureLoader.setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin); + var tgaLoader; + if (TGALoader) { + tgaLoader = new TGALoader(this.manager); + tgaLoader.setPath(this.resourcePath || path); + } - camera = new THREE.OrthographicCamera( - - xmag, xmag, ymag, - ymag, // left, right, top, bottom - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + // - default: - camera = new THREE.PerspectiveCamera(); - break; + var tempColor = new Color(); + var animations = []; + var kinematics = {}; + var count = 0; - } + // - camera.name = data.name; + var library = { + animations: {}, + clips: {}, + controllers: {}, + images: {}, + effects: {}, + materials: {}, + cameras: {}, + lights: {}, + geometries: {}, + nodes: {}, + visualScenes: {}, + kinematicsModels: {}, + physicsModels: {}, + kinematicsScenes: {} + }; + parseLibrary(collada, 'library_animations', 'animation', parseAnimation); + parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); + parseLibrary(collada, 'library_controllers', 'controller', parseController); + parseLibrary(collada, 'library_images', 'image', parseImage); + parseLibrary(collada, 'library_effects', 'effect', parseEffect); + parseLibrary(collada, 'library_materials', 'material', parseMaterial); + parseLibrary(collada, 'library_cameras', 'camera', parseCamera); + parseLibrary(collada, 'library_lights', 'light', parseLight); + parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); + parseLibrary(collada, 'library_nodes', 'node', parseNode); + parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); + parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); + parseLibrary(collada, 'library_physics_models', 'physics_model', parsePhysicsModel); + parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + buildLibrary(library.animations, buildAnimation); + buildLibrary(library.clips, buildAnimationClip); + buildLibrary(library.controllers, buildController); + buildLibrary(library.images, buildImage); + buildLibrary(library.effects, buildEffect); + buildLibrary(library.materials, buildMaterial); + buildLibrary(library.cameras, buildCamera); + buildLibrary(library.lights, buildLight); + buildLibrary(library.geometries, buildGeometry); + buildLibrary(library.visualScenes, buildVisualScene); + setupAnimations(); + setupKinematics(); + var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + scene.animations = animations; + + // if ( asset.upAxis === 'Z_UP' ) { + + // console.warn( 'THREE.ColladaLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted, see #24289.' ); + // scene.rotation.set( - Math.PI / 2, 0, 0 ); + + // } + + scene.scale.multiplyScalar(asset.unit); + return { + get animations() { + console.warn('THREE.ColladaLoader: Please access animations over scene.animations now.'); + return animations; + }, + kinematics: kinematics, + library: library, + scene: scene + }; + } + }]); +}(Loader); - return camera; +// o object_name | g group_name +const _object_pattern = /^[og]\s*(.+)?/; +// mtllib file_reference +const _material_library_pattern = /^mtllib /; +// usemtl material_name +const _material_use_pattern = /^usemtl /; +// usemap map_name +const _map_use_pattern = /^usemap /; +const _face_vertex_data_separator_pattern = /\s+/; - } +const _vA = new Vector3(); +const _vB = new Vector3(); +const _vC = new Vector3(); - function getCamera(id) { - var data = library.cameras[id]; - if (data !== undefined) { - return getBuild(data, buildCamera); - } - return null; - } +const _ab = new Vector3(); +const _cb = new Vector3(); - // light +const _color = new Color(); - function parseLight(xml) { +function ParserState() { - var data = {}; + const state = { + objects: [], + object: {}, - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + vertices: [], + normals: [], + colors: [], + uvs: [], - var child = xml.childNodes[i]; + materials: {}, + materialLibraries: [], - if (child.nodeType !== 1) { continue; } + startObject: function ( name, fromDeclaration ) { - switch (child.nodeName) { + // If the current object (initial from reset) is not from a g/o declaration in the parsed + // file. We need to use it for the first parsed g/o to keep things in sync. + if ( this.object && this.object.fromDeclaration === false ) { - case 'technique_common': - data = parseLightTechnique(child); - break; + this.object.name = name; + this.object.fromDeclaration = ( fromDeclaration !== false ); + return; - } + } - } + const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); - library.lights[xml.getAttribute('id')] = data; + if ( this.object && typeof this.object._finalize === 'function' ) { - } + this.object._finalize( true ); - function parseLightTechnique(xml) { + } - var data = {}; + this.object = { + name: name || '', + fromDeclaration: ( fromDeclaration !== false ), - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + geometry: { + vertices: [], + normals: [], + colors: [], + uvs: [], + hasUVIndices: false + }, + materials: [], + smooth: true, - var child = xml.childNodes[i]; + startMaterial: function ( name, libraries ) { - if (child.nodeType !== 1) { continue; } + const previous = this._finalize( false ); - switch (child.nodeName) { + // New usemtl declaration overwrites an inherited material, except if faces were declared + // after the material, then it must be preserved for proper MultiMaterial continuation. + if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { - case 'directional': - case 'point': - case 'spot': - case 'ambient': + this.materials.splice( previous.index, 1 ); - data.technique = child.nodeName; - data.parameters = parseLightParameters(child); + } - } + const material = { + index: this.materials.length, + name: name || '', + mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), + smooth: ( previous !== undefined ? previous.smooth : this.smooth ), + groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), + groupEnd: - 1, + groupCount: - 1, + inherited: false, + + clone: function ( index ) { + + const cloned = { + index: ( typeof index === 'number' ? index : this.index ), + name: this.name, + mtllib: this.mtllib, + smooth: this.smooth, + groupStart: 0, + groupEnd: - 1, + groupCount: - 1, + inherited: false + }; + cloned.clone = this.clone.bind( cloned ); + return cloned; - } + } + }; - return data; + this.materials.push( material ); - } + return material; - function parseLightParameters(xml) { + }, - var data = {}; + currentMaterial: function () { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + if ( this.materials.length > 0 ) { - var child = xml.childNodes[i]; + return this.materials[ this.materials.length - 1 ]; - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + return undefined; - case 'color': - var array = parseFloats(child.textContent); - data.color = new THREE.Color().fromArray(array); - break; + }, - case 'falloff_angle': - data.falloffAngle = parseFloat(child.textContent); - break; + _finalize: function ( end ) { - case 'quadratic_attenuation': - var f = parseFloat(child.textContent); - data.distance = f ? Math.sqrt(1 / f) : 0; - break; + const lastMultiMaterial = this.currentMaterial(); + if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { - } + lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; + lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; + lastMultiMaterial.inherited = false; - } + } - return data; + // Ignore objects tail materials if no face declarations followed them before a new o/g started. + if ( end && this.materials.length > 1 ) { - } + for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) { - function buildLight(data) { + if ( this.materials[ mi ].groupCount <= 0 ) { - var light; + this.materials.splice( mi, 1 ); - switch (data.technique) { + } - case 'directional': - light = new THREE.DirectionalLight(); - break; + } - case 'point': - light = new THREE.PointLight(); - break; + } - case 'spot': - light = new THREE.SpotLight(); - break; + // Guarantee at least one empty material, this makes the creation later more straight forward. + if ( end && this.materials.length === 0 ) { - case 'ambient': - light = new THREE.AmbientLight(); - break; + this.materials.push( { + name: '', + smooth: this.smooth + } ); - } + } - if (data.parameters.color) { light.color.copy(data.parameters.color); } - if (data.parameters.distance) { light.distance = data.parameters.distance; } + return lastMultiMaterial; - return light; + } + }; - } + // Inherit previous objects material. + // Spec tells us that a declared material must be set to all objects until a new material is declared. + // If a usemtl declaration is encountered while this new object is being parsed, it will + // overwrite the inherited material. Exception being that there was already face declarations + // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - // geometry + if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - function parseGeometry(xml) { + const declared = previousMaterial.clone( 0 ); + declared.inherited = true; + this.object.materials.push( declared ); - var data = { - name: xml.getAttribute('name'), - sources: {}, - vertices: {}, - primitives: [] - }; + } - var mesh = getElementsByTagName(xml, 'mesh')[0]; + this.objects.push( this.object ); - for (var i = 0; i < mesh.childNodes.length; i++) { + }, - var child = mesh.childNodes[i]; + finalize: function () { - if (child.nodeType !== 1) { continue; } + if ( this.object && typeof this.object._finalize === 'function' ) { - var id = child.getAttribute('id'); + this.object._finalize( true ); - switch (child.nodeName) { + } - case 'source': - data.sources[id] = parseSource(child); - break; + }, - case 'vertices': - // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; - data.vertices = parseGeometryVertices(child); - break; + parseVertexIndex: function ( value, len ) { - case 'polygons': - console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); - break; + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - case 'lines': - case 'linestrips': - case 'polylist': - case 'triangles': - data.primitives.push(parseGeometryPrimitive(child)); - break; + }, - default: - console.log(child); + parseNormalIndex: function ( value, len ) { - } + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - } + }, - library.geometries[xml.getAttribute('id')] = data; + parseUVIndex: function ( value, len ) { - } + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; - function parseSource(xml) { + }, - var data = { - array: [], - stride: 3 - }; + addVertex: function ( a, b, c ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const src = this.vertices; + const dst = this.object.geometry.vertices; - var child = xml.childNodes[i]; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - if (child.nodeType !== 1) { continue; } + }, - switch (child.nodeName) { + addVertexPoint: function ( a ) { - case 'float_array': - data.array = parseFloats(child.textContent); - break; + const src = this.vertices; + const dst = this.object.geometry.vertices; - case 'Name_array': - data.array = parseStrings(child.textContent); - break; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - case 'technique_common': - var accessor = getElementsByTagName(child, 'accessor')[0]; + }, - if (accessor !== undefined) { + addVertexLine: function ( a ) { - data.stride = parseInt(accessor.getAttribute('stride')); + const src = this.vertices; + const dst = this.object.geometry.vertices; - } - break; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - } + }, - } + addNormal: function ( a, b, c ) { - return data; + const src = this.normals; + const dst = this.object.geometry.normals; - } + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - function parseGeometryVertices(xml) { + }, - var data = {}; + addFaceNormal: function ( a, b, c ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const src = this.vertices; + const dst = this.object.geometry.normals; - var child = xml.childNodes[i]; + _vA.fromArray( src, a ); + _vB.fromArray( src, b ); + _vC.fromArray( src, c ); - if (child.nodeType !== 1) { continue; } + _cb.subVectors( _vC, _vB ); + _ab.subVectors( _vA, _vB ); + _cb.cross( _ab ); - data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + _cb.normalize(); - } + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); - return data; + }, - } + addColor: function ( a, b, c ) { - function parseGeometryPrimitive(xml) { + const src = this.colors; + const dst = this.object.geometry.colors; - var primitive = { - type: xml.nodeName, - material: xml.getAttribute('material'), - count: parseInt(xml.getAttribute('count')), - inputs: {}, - stride: 0 - }; + if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + }, - var child = xml.childNodes[i]; + addUV: function ( a, b, c ) { - if (child.nodeType !== 1) { continue; } + const src = this.uvs; + const dst = this.object.geometry.uvs; - switch (child.nodeName) { + dst.push( src[ a + 0 ], src[ a + 1 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ] ); - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - var offset = parseInt(child.getAttribute('offset')); - primitive.inputs[semantic] = { id: id, offset: offset }; - primitive.stride = Math.max(primitive.stride, offset + 1); - break; + }, - case 'vcount': - primitive.vcount = parseInts(child.textContent); - break; + addDefaultUV: function () { - case 'p': - primitive.p = parseInts(child.textContent); - break; + const dst = this.object.geometry.uvs; - } + dst.push( 0, 0 ); + dst.push( 0, 0 ); + dst.push( 0, 0 ); - } + }, - return primitive; + addUVLine: function ( a ) { - } + const src = this.uvs; + const dst = this.object.geometry.uvs; - function groupPrimitives(primitives) { + dst.push( src[ a + 0 ], src[ a + 1 ] ); - var build = {}; + }, - for (var i = 0; i < primitives.length; i++) { + addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { - var primitive = primitives[i]; + const vLen = this.vertices.length; - if (build[primitive.type] === undefined) { build[primitive.type] = []; } + let ia = this.parseVertexIndex( a, vLen ); + let ib = this.parseVertexIndex( b, vLen ); + let ic = this.parseVertexIndex( c, vLen ); - build[primitive.type].push(primitive); + this.addVertex( ia, ib, ic ); + this.addColor( ia, ib, ic ); - } + // normals - return build; + if ( na !== undefined && na !== '' ) { - } + const nLen = this.normals.length; - function buildGeometry(data) { + ia = this.parseNormalIndex( na, nLen ); + ib = this.parseNormalIndex( nb, nLen ); + ic = this.parseNormalIndex( nc, nLen ); - var build = {}; + this.addNormal( ia, ib, ic ); - var sources = data.sources; - var vertices = data.vertices; - var primitives = data.primitives; + } else { - if (primitives.length === 0) { return {}; } + this.addFaceNormal( ia, ib, ic ); - // our goal is to create one buffer geoemtry for a single type of primitives - // first, we group all primitives by their type + } - var groupedPrimitives = groupPrimitives(primitives); + // uvs - for (var type in groupedPrimitives) { + if ( ua !== undefined && ua !== '' ) { - // second, we create for each type of primitives (polylist,triangles or lines) a buffer geometry + const uvLen = this.uvs.length; - build[type] = buildGeometryType(groupedPrimitives[type], sources, vertices); + ia = this.parseUVIndex( ua, uvLen ); + ib = this.parseUVIndex( ub, uvLen ); + ic = this.parseUVIndex( uc, uvLen ); - } + this.addUV( ia, ib, ic ); - return build; + this.object.geometry.hasUVIndices = true; - } + } else { - function buildGeometryType(primitives, sources, vertices) { + // add placeholder values (for inconsistent face definitions) - var build = {}; + this.addDefaultUV(); - var position = { array: [], stride: 0 }; - var normal = { array: [], stride: 0 }; - var uv = { array: [], stride: 0 }; - var color = { array: [], stride: 0 }; + } - var skinIndex = { array: [], stride: 4 }; - var skinWeight = { array: [], stride: 4 }; + }, - var geometry = new THREE.BufferGeometry(); + addPointGeometry: function ( vertices ) { - var materialKeys = []; + this.object.geometry.type = 'Points'; - var start = 0, count = 0; + const vLen = this.vertices.length; - for (var p = 0; p < primitives.length; p++) { + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - var primitive = primitives[p]; - var inputs = primitive.inputs; - var triangleCount = 1; + const index = this.parseVertexIndex( vertices[ vi ], vLen ); - if (primitive.vcount && primitive.vcount[0] === 4) { + this.addVertexPoint( index ); + this.addColor( index ); - triangleCount = 2; // one quad -> two triangles + } - } + }, - // groups + addLineGeometry: function ( vertices, uvs ) { - if (primitive.type === 'lines' || primitive.type === 'linestrips') { + this.object.geometry.type = 'Line'; - count = primitive.count * 2; + const vLen = this.vertices.length; + const uvLen = this.uvs.length; - } else { + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - count = primitive.count * 3 * triangleCount; + this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); - } + } - geometry.addGroup(start, count, p); - start += count; + for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { - // material + this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); - if (primitive.material) { + } - materialKeys.push(primitive.material); + } - } + }; - // geometry data + state.startObject( '', false ); - for (var name in inputs) { + return state; - var input = inputs[name]; +} - switch (name) { +// - case 'VERTEX': - for (var key in vertices) { +class OBJLoader extends Loader { - var id = vertices[key]; + constructor( manager ) { - switch (key) { + super( manager ); - case 'POSITION': - buildGeometryData(primitive, sources[id], input.offset, position.array); - position.stride = sources[id].stride; + this.materials = null; - if (sources.skinWeights && sources.skinIndices) { + } - buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); - buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + load( url, onLoad, onProgress, onError ) { - } - break; + const scope = this; - case 'NORMAL': - buildGeometryData(primitive, sources[id], input.offset, normal.array); - normal.stride = sources[id].stride; - break; + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - case 'COLOR': - buildGeometryData(primitive, sources[id], input.offset, color.array); - color.stride = sources[id].stride; - break; + try { - case 'TEXCOORD': - buildGeometryData(primitive, sources[id], input.offset, uv.array); - uv.stride = sources[id].stride; - break; + onLoad( scope.parse( text ) ); - default: - console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + } catch ( e ) { - } + if ( onError ) { - } - break; + onError( e ); - case 'NORMAL': - buildGeometryData(primitive, sources[input.id], input.offset, normal.array); - normal.stride = sources[input.id].stride; - break; + } else { - case 'COLOR': - buildGeometryData(primitive, sources[input.id], input.offset, color.array); - color.stride = sources[input.id].stride; - break; + console.error( e ); - case 'TEXCOORD': - buildGeometryData(primitive, sources[input.id], input.offset, uv.array); - uv.stride = sources[input.id].stride; - break; + } - } + scope.manager.itemError( url ); - } + } - } + }, onProgress, onError ); - // build geometry + } - if (position.array.length > 0) { geometry.addAttribute('position', new THREE.Float32BufferAttribute(position.array, position.stride)); } - if (normal.array.length > 0) { geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normal.array, normal.stride)); } - if (color.array.length > 0) { geometry.addAttribute('color', new THREE.Float32BufferAttribute(color.array, color.stride)); } - if (uv.array.length > 0) { geometry.addAttribute('uv', new THREE.Float32BufferAttribute(uv.array, uv.stride)); } + setMaterials( materials ) { - if (skinIndex.array.length > 0) { geometry.addAttribute('skinIndex', new THREE.Float32BufferAttribute(skinIndex.array, skinIndex.stride)); } - if (skinWeight.array.length > 0) { geometry.addAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeight.array, skinWeight.stride)); } + this.materials = materials; - build.data = geometry; - build.type = primitives[0].type; - build.materialKeys = materialKeys; + return this; - return build; + } - } + parse( text ) { - function buildGeometryData(primitive, source, offset, array) { + const state = new ParserState(); - var indices = primitive.p; - var stride = primitive.stride; - var vcount = primitive.vcount; + if ( text.indexOf( '\r\n' ) !== - 1 ) { - function pushVector(i) { + // This is faster than String.split with regex that splits on both + text = text.replace( /\r\n/g, '\n' ); - var index = indices[i + offset] * sourceStride; - var length = index + sourceStride; + } - for (; index < length; index++) { + if ( text.indexOf( '\\\n' ) !== - 1 ) { - array.push(sourceArray[index]); + // join lines separated by a line continuation character (\) + text = text.replace( /\\\n/g, '' ); - } + } - } + const lines = text.split( '\n' ); + let result = []; - var maxcount = 0; + for ( let i = 0, l = lines.length; i < l; i ++ ) { - var sourceArray = source.array; - var sourceStride = source.stride; + const line = lines[ i ].trimStart(); - if (primitive.vcount !== undefined) { + if ( line.length === 0 ) continue; - var index = 0; + const lineFirstChar = line.charAt( 0 ); - for (var i = 0, l = vcount.length; i < l; i++) { + // @todo invoke passed in handler if any + if ( lineFirstChar === '#' ) continue; // skip comments - var count = vcount[i]; + if ( lineFirstChar === 'v' ) { - if (count === 4) { + const data = line.split( _face_vertex_data_separator_pattern ); - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; - var d = index + stride * 3; + switch ( data[ 0 ] ) { - pushVector(a); pushVector(b); pushVector(d); - pushVector(b); pushVector(c); pushVector(d); + case 'v': + state.vertices.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + if ( data.length >= 7 ) { - } else if (count === 3) { + _color.setRGB( + parseFloat( data[ 4 ] ), + parseFloat( data[ 5 ] ), + parseFloat( data[ 6 ] ) + ).convertSRGBToLinear(); - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; + state.colors.push( _color.r, _color.g, _color.b ); - pushVector(a); pushVector(b); pushVector(c); + } else { - } else { + // if no colors are defined, add placeholders so color and vertex indices match - maxcount = Math.max(maxcount, count); + state.colors.push( undefined, undefined, undefined ); - } + } - index += stride * count; + break; + case 'vn': + state.normals.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + break; + case 'vt': + state.uvs.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ) + ); + break; - } + } - if (maxcount > 0) { + } else if ( lineFirstChar === 'f' ) { - console.log('THREE.ColladaLoader: Geometry has faces with more than 4 vertices.'); + const lineData = line.slice( 1 ).trim(); + const vertexData = lineData.split( _face_vertex_data_separator_pattern ); + const faceVertices = []; - } + // Parse the face vertex data into an easy to work with format - } else { + for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) { - for (var i = 0, l = indices.length; i < l; i += stride) { + const vertex = vertexData[ j ]; - pushVector(i); + if ( vertex.length > 0 ) { - } + const vertexParts = vertex.split( '/' ); + faceVertices.push( vertexParts ); - } + } - } + } - function getGeometry(id) { + // Draw an edge between the first vertex and all subsequent vertices to form an n-gon - return getBuild(library.geometries[id], buildGeometry); + const v1 = faceVertices[ 0 ]; - } + for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { - // kinematics + const v2 = faceVertices[ j ]; + const v3 = faceVertices[ j + 1 ]; - function parseKinematicsModel(xml) { + state.addFace( + v1[ 0 ], v2[ 0 ], v3[ 0 ], + v1[ 1 ], v2[ 1 ], v3[ 1 ], + v1[ 2 ], v2[ 2 ], v3[ 2 ] + ); - var data = { - name: xml.getAttribute('name') || '', - joints: {}, - links: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + } else if ( lineFirstChar === 'l' ) { - var child = xml.childNodes[i]; + const lineParts = line.substring( 1 ).trim().split( ' ' ); + let lineVertices = []; + const lineUVs = []; - if (child.nodeType !== 1) { continue; } + if ( line.indexOf( '/' ) === - 1 ) { - switch (child.nodeName) { + lineVertices = lineParts; - case 'technique_common': - parseKinematicsTechniqueCommon(child, data); - break; + } else { - } + for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) { - } + const parts = lineParts[ li ].split( '/' ); - library.kinematicsModels[xml.getAttribute('id')] = data; + if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] ); + if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] ); - } + } - function buildKinematicsModel(data) { + } - if (data.build !== undefined) { return data.build; } + state.addLineGeometry( lineVertices, lineUVs ); - return data; + } else if ( lineFirstChar === 'p' ) { - } + const lineData = line.slice( 1 ).trim(); + const pointData = lineData.split( ' ' ); - function getKinematicsModel(id) { + state.addPointGeometry( pointData ); - return getBuild(library.kinematicsModels[id], buildKinematicsModel); + } else if ( ( result = _object_pattern.exec( line ) ) !== null ) { - } + // o object_name + // or + // g group_name - function parseKinematicsTechniqueCommon(xml, data) { + // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 + // let name = result[ 0 ].slice( 1 ).trim(); + const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 ); - for (var i = 0; i < xml.childNodes.length; i++) { + state.startObject( name ); - var child = xml.childNodes[i]; + } else if ( _material_use_pattern.test( line ) ) { - if (child.nodeType !== 1) { continue; } + // material - switch (child.nodeName) { + state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); - case 'joint': - data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); - break; + } else if ( _material_library_pattern.test( line ) ) { - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + // mtl file - } + state.materialLibraries.push( line.substring( 7 ).trim() ); - } + } else if ( _map_use_pattern.test( line ) ) { - } + // the line is parsed but ignored since the loader assumes textures are defined MTL files + // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) - function parseKinematicsJoint(xml) { + console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); - var data; + } else if ( lineFirstChar === 's' ) { - for (var i = 0; i < xml.childNodes.length; i++) { + result = line.split( ' ' ); - var child = xml.childNodes[i]; + // smooth shading - if (child.nodeType !== 1) { continue; } + // @todo Handle files that have varying smooth values for a set of faces inside one geometry, + // but does not define a usemtl for each face set. + // This should be detected and a dummy material created (later MultiMaterial and geometry groups). + // This requires some care to not create extra material on each smooth value for "normal" obj files. + // where explicit usemtl defines geometry groups. + // Example asset: examples/models/obj/cerberus/Cerberus.obj - switch (child.nodeName) { + /* + * http://paulbourke.net/dataformats/obj/ + * + * From chapter "Grouping" Syntax explanation "s group_number": + * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. + * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form + * surfaces, smoothing groups are either turned on or off; there is no difference between values greater + * than 0." + */ + if ( result.length > 1 ) { - case 'prismatic': - case 'revolute': - data = parseKinematicsJointParameter(child); - break; + const value = result[ 1 ].trim().toLowerCase(); + state.object.smooth = ( value !== '0' && value !== 'off' ); - } + } else { - } + // ZBrush can produce "s" lines #11707 + state.object.smooth = true; - return data; + } - } + const material = state.object.currentMaterial(); + if ( material ) material.smooth = state.object.smooth; - function parseKinematicsJointParameter(xml, data) { + } else { - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - axis: new THREE.Vector3(), - limits: { - min: 0, - max: 0 - }, - type: xml.nodeName, - static: false, - zeroPosition: 0, - middlePosition: 0 - }; + // Handle null terminated files without exception + if ( line === '\0' ) continue; - for (var i = 0; i < xml.childNodes.length; i++) { + console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + state.finalize(); - case 'axis': - var array = parseFloats(child.textContent); - data.axis.fromArray(array); - break; - case 'limits': - var max = child.getElementsByTagName('max')[0]; - var min = child.getElementsByTagName('min')[0]; + const container = new Group(); + container.materialLibraries = [].concat( state.materialLibraries ); - data.limits.max = parseFloat(max.textContent); - data.limits.min = parseFloat(min.textContent); - break; + const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); - } + if ( hasPrimitives === true ) { - } + for ( let i = 0, l = state.objects.length; i < l; i ++ ) { - // if min is equal to or greater than max, consider the joint static + const object = state.objects[ i ]; + const geometry = object.geometry; + const materials = object.materials; + const isLine = ( geometry.type === 'Line' ); + const isPoints = ( geometry.type === 'Points' ); + let hasVertexColors = false; - if (data.limits.min >= data.limits.max) { + // Skip o/g line declarations that did not follow with any faces + if ( geometry.vertices.length === 0 ) continue; - data.static = true; + const buffergeometry = new BufferGeometry(); - } + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) ); - // calculate middle position + if ( geometry.normals.length > 0 ) { - data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) ); - return data; + } - } + if ( geometry.colors.length > 0 ) { - function parseKinematicsLink(xml) { + hasVertexColors = true; + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) ); - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - attachments: [], - transforms: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( geometry.hasUVIndices === true ) { - var child = xml.childNodes[i]; + buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) ); - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + // Create materials - case 'attachment_full': - data.attachments.push(parseKinematicsAttachment(child)); - break; + const createdMaterials = []; - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - } + const sourceMaterial = materials[ mi ]; + const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors; + let material = state.materials[ materialHash ]; - } + if ( this.materials !== null ) { - return data; + material = this.materials.create( sourceMaterial.name ); - } + // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. + if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) { - function parseKinematicsAttachment(xml) { + const materialLine = new LineBasicMaterial(); + Material.prototype.copy.call( materialLine, material ); + materialLine.color.copy( material.color ); + material = materialLine; - var data = { - joint: xml.getAttribute('joint').split('/').pop(), - transforms: [], - links: [] - }; + } else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } ); + Material.prototype.copy.call( materialPoints, material ); + materialPoints.color.copy( material.color ); + materialPoints.map = material.map; + material = materialPoints; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) { continue; } + } - switch (child.nodeName) { + if ( material === undefined ) { - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + if ( isLine ) { - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + material = new LineBasicMaterial(); - } + } else if ( isPoints ) { - } + material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - return data; + } else { - } + material = new MeshPhongMaterial(); - function parseKinematicsTransform(xml) { + } - var data = { - type: xml.nodeName - }; + material.name = sourceMaterial.name; + material.flatShading = sourceMaterial.smooth ? false : true; + material.vertexColors = hasVertexColors; - var array = parseFloats(xml.textContent); + state.materials[ materialHash ] = material; - switch (data.type) { + } - case 'matrix': - data.obj = new THREE.Matrix4(); - data.obj.fromArray(array).transpose(); - break; + createdMaterials.push( material ); - case 'translate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - break; + } - case 'rotate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - data.angle = THREE.Math.degToRad(array[3]); - break; + // Create mesh - } + let mesh; - return data; + if ( createdMaterials.length > 1 ) { - } + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - function parseKinematicsScene(xml) { + const sourceMaterial = materials[ mi ]; + buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); - var data = { - bindJointAxis: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( isLine ) { - var child = xml.childNodes[i]; + mesh = new LineSegments( buffergeometry, createdMaterials ); - if (child.nodeType !== 1) { continue; } + } else if ( isPoints ) { - switch (child.nodeName) { + mesh = new Points$1( buffergeometry, createdMaterials ); - case 'bind_joint_axis': - data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); - break; + } else { - } + mesh = new Mesh( buffergeometry, createdMaterials ); - } + } - library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + } else { - } + if ( isLine ) { - function parseKinematicsBindJointAxis(xml) { + mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] ); - var data = { - target: xml.getAttribute('target').split('/').pop() - }; + } else if ( isPoints ) { - for (var i = 0; i < xml.childNodes.length; i++) { + mesh = new Points$1( buffergeometry, createdMaterials[ 0 ] ); - var child = xml.childNodes[i]; + } else { - if (child.nodeType !== 1) { continue; } + mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] ); - switch (child.nodeName) { + } - case 'axis': - var param = child.getElementsByTagName('param')[0]; - data.axis = param.textContent; - var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; - data.jointIndex = tmpJointIndex.substr(0, tmpJointIndex.length - 1); - break; + } - } + mesh.name = object.name; - } + container.add( mesh ); - return data; + } - } + } else { - function buildKinematicsScene(data) { + // if there is only the default parser state object with no geometry data, interpret data as point cloud - if (data.build !== undefined) { return data.build; } + if ( state.vertices.length > 0 ) { - return data; + const material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - } + const buffergeometry = new BufferGeometry(); - function getKinematicsScene(id) { + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) ); - return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { - } + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) ); + material.vertexColors = true; - function setupKinematics() { + } - var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; - var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; - var visualSceneId = Object.keys(library.visualScenes)[0]; + const points = new Points$1( buffergeometry, material ); + container.add( points ); - if (kinematicsModelId === undefined || kinematicsSceneId === undefined) { return; } + } - var kinematicsModel = getKinematicsModel(kinematicsModelId); - var kinematicsScene = getKinematicsScene(kinematicsSceneId); - var visualScene = getVisualScene(visualSceneId); + } - var bindJointAxis = kinematicsScene.bindJointAxis; - var jointMap = {}; + return container; - for (var i = 0, l = bindJointAxis.length; i < l; i++) { + } - var axis = bindJointAxis[i]; +} - // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' +/** + * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. + * + * Supports both binary and ASCII encoded files, with automatic detection of type. + * + * The loader returns a non-indexed buffer geometry. + * + * Limitations: + * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). + * There is perhaps some question as to how valid it is to always assume little-endian-ness. + * ASCII decoding assumes file is UTF-8. + * + * Usage: + * const loader = new STLLoader(); + * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { + * scene.add( new THREE.Mesh( geometry ) ); + * }); + * + * For binary STLs geometry might contain colors for vertices. To use it: + * // use the same code to load STL as above + * if (geometry.hasColors) { + * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true }); + * } else { .... } + * const mesh = new THREE.Mesh( geometry, material ); + * + * For ASCII STLs containing multiple solids, each solid is assigned to a different group. + * Groups can be used to assign a different color by defining an array of materials with the same length of + * geometry.groups and passing it to the Mesh constructor: + * + * const mesh = new THREE.Mesh( geometry, material ); + * + * For example: + * + * const materials = []; + * const nGeometryGroups = geometry.groups.length; + * + * const colorMap = ...; // Some logic to index colors. + * + * for (let i = 0; i < nGeometryGroups; i++) { + * + * const material = new THREE.MeshPhongMaterial({ + * color: colorMap[i], + * wireframe: false + * }); + * + * } + * + * materials.push(material); + * const mesh = new THREE.Mesh(geometry, materials); + */ - var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); - if (targetElement) { +class STLLoader extends Loader { - // get the parent of the transfrom element + constructor( manager ) { - var parentVisualElement = targetElement.parentElement; + super( manager ); - // connect the joint of the kinematics model with the element in the visual scene + } - connect(axis.jointIndex, parentVisualElement); + load( url, onLoad, onProgress, onError ) { - } + const scope = this; - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); - function connect(jointIndex, visualElement) { + loader.load( url, function ( text ) { - var visualElementName = visualElement.getAttribute('name'); - var joint = kinematicsModel.joints[jointIndex]; + try { - visualScene.traverse(function (object) { + onLoad( scope.parse( text ) ); - if (object.name === visualElementName) { + } catch ( e ) { - jointMap[jointIndex] = { - object: object, - transforms: buildTransformList(visualElement), - joint: joint, - position: joint.zeroPosition - }; + if ( onError ) { - } + onError( e ); - }); + } else { - } + console.error( e ); - var m0 = new THREE.Matrix4(); + } - kinematics = { + scope.manager.itemError( url ); - joints: kinematicsModel && kinematicsModel.joints, + } - getJointValue: function (jointIndex) { + }, onProgress, onError ); - var jointData = jointMap[jointIndex]; + } - if (jointData) { + parse( data ) { - return jointData.position; + function isBinary( data ) { - } else { + const reader = new DataView( data ); + const face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 ); + const n_faces = reader.getUint32( 80, true ); + const expect = 80 + ( 32 / 8 ) + ( n_faces * face_size ); - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); + if ( expect === reader.byteLength ) { - } + return true; - }, + } - setJointValue: function (jointIndex, value) { + // An ASCII STL data must begin with 'solid ' as the first six bytes. + // However, ASCII STLs lacking the SPACE after the 'd' are known to be + // plentiful. So, check the first 5 bytes for 'solid'. - var jointData = jointMap[jointIndex]; + // Several encodings, such as UTF-8, precede the text with up to 5 bytes: + // https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding + // Search for "solid" to start anywhere after those prefixes. - if (jointData) { + // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' - var joint = jointData.joint; + const solid = [ 115, 111, 108, 105, 100 ]; - if (value > joint.limits.max || value < joint.limits.min) { + for ( let off = 0; off < 5; off ++ ) { - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + // If "solid" text is matched to the current offset, declare it to be an ASCII STL. - } else if (joint.static) { + if ( matchDataViewAt( solid, reader, off ) ) return false; - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + } - } else { + // Couldn't find "solid" text at the beginning; it is binary STL. - var object = jointData.object; - var axis = joint.axis; - var transforms = jointData.transforms; + return true; - matrix.identity(); + } - // each update, we have to apply all transforms in the correct order + function matchDataViewAt( query, reader, offset ) { - for (var i = 0; i < transforms.length; i++) { + // Check if each byte in query matches the corresponding byte from the current offset - var transform = transforms[i]; + for ( let i = 0, il = query.length; i < il; i ++ ) { - // if there is a connection of the transform node with a joint, apply the joint value + if ( query[ i ] !== reader.getUint8( offset + i ) ) return false; - if (transform.sid && transform.sid.indexOf(jointIndex) !== - 1) { + } - switch (joint.type) { + return true; - case 'revolute': - matrix.multiply(m0.makeRotationAxis(axis, THREE.Math.degToRad(value))); - break; + } - case 'prismatic': - matrix.multiply(m0.makeTranslation(axis.x * value, axis.y * value, axis.z * value)); - break; + function parseBinary( data ) { - default: - console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); - break; + const reader = new DataView( data ); + const faces = reader.getUint32( 80, true ); - } + let r, g, b, hasColors = false, colors; + let defaultR, defaultG, defaultB, alpha; - } else { + // process STL header + // check for default color in header ("COLOR=rgba" sequence). - switch (transform.type) { + for ( let index = 0; index < 80 - 10; index ++ ) { - case 'matrix': - matrix.multiply(transform.obj); - break; + if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) && + ( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) && + ( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) { - case 'translate': - matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); - break; + hasColors = true; + colors = new Float32Array( faces * 3 * 3 ); - case 'scale': - matrix.scale(transform.obj); - break; + defaultR = reader.getUint8( index + 6 ) / 255; + defaultG = reader.getUint8( index + 7 ) / 255; + defaultB = reader.getUint8( index + 8 ) / 255; + alpha = reader.getUint8( index + 9 ) / 255; - case 'rotate': - matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); - break; + } - } + } - } + const dataOffset = 84; + const faceLength = 12 * 4 + 2; - } + const geometry = new BufferGeometry(); - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + const vertices = new Float32Array( faces * 3 * 3 ); + const normals = new Float32Array( faces * 3 * 3 ); - jointMap[jointIndex].position = value; + const color = new Color(); - } + for ( let face = 0; face < faces; face ++ ) { - } else { + const start = dataOffset + face * faceLength; + const normalX = reader.getFloat32( start, true ); + const normalY = reader.getFloat32( start + 4, true ); + const normalZ = reader.getFloat32( start + 8, true ); - console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + if ( hasColors ) { - } + const packedColor = reader.getUint16( start + 48, true ); - } + if ( ( packedColor & 0x8000 ) === 0 ) { - }; + // facet has its own unique color - } + r = ( packedColor & 0x1F ) / 31; + g = ( ( packedColor >> 5 ) & 0x1F ) / 31; + b = ( ( packedColor >> 10 ) & 0x1F ) / 31; - function buildTransformList(node) { + } else { - var transforms = []; + r = defaultR; + g = defaultG; + b = defaultB; - var xml = collada.querySelector('[id="' + node.id + '"]'); + } - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + for ( let i = 1; i <= 3; i ++ ) { - if (child.nodeType !== 1) { continue; } + const vertexstart = start + i * 12; + const componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 ); - switch (child.nodeName) { + vertices[ componentIdx ] = reader.getFloat32( vertexstart, true ); + vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true ); + vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true ); - case 'matrix': - var array = parseFloats(child.textContent); - var matrix = new THREE.Matrix4().fromArray(array).transpose(); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: matrix - }); - break; + normals[ componentIdx ] = normalX; + normals[ componentIdx + 1 ] = normalY; + normals[ componentIdx + 2 ] = normalZ; - case 'translate': - case 'scale': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector - }); - break; + if ( hasColors ) { - case 'rotate': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - var angle = THREE.Math.degToRad(array[3]); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector, - angle: angle - }); - break; + color.set( r, g, b ).convertSRGBToLinear(); - } + colors[ componentIdx ] = color.r; + colors[ componentIdx + 1 ] = color.g; + colors[ componentIdx + 2 ] = color.b; - } + } - return transforms; + } - } + } - // nodes + geometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) ); - function prepareNodes(xml) { + if ( hasColors ) { - var elements = xml.getElementsByTagName('node'); + geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); + geometry.hasColors = true; + geometry.alpha = alpha; - // ensure all node elements have id attributes + } - for (var i = 0; i < elements.length; i++) { + return geometry; - var element = elements[i]; + } - if (element.hasAttribute('id') === false) { + function parseASCII( data ) { - element.setAttribute('id', generateId()); + const geometry = new BufferGeometry(); + const patternSolid = /solid([\s\S]*?)endsolid/g; + const patternFace = /facet([\s\S]*?)endfacet/g; + const patternName = /solid\s(.+)/; + let faceCounter = 0; - } + const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source; + const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' ); + const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' ); - } + const vertices = []; + const normals = []; + const groupNames = []; - } + const normal = new Vector3(); - var matrix = new THREE.Matrix4(); - var vector = new THREE.Vector3(); - - function parseNode(xml) { - - var data = { - name: xml.getAttribute('name') || '', - type: xml.getAttribute('type'), - id: xml.getAttribute('id'), - sid: xml.getAttribute('sid'), - matrix: new THREE.Matrix4(), - nodes: [], - instanceCameras: [], - instanceControllers: [], - instanceLights: [], - instanceGeometries: [], - instanceNodes: [], - transforms: {} - }; + let result; - for (var i = 0; i < xml.childNodes.length; i++) { + let groupCount = 0; + let startVertex = 0; + let endVertex = 0; - var child = xml.childNodes[i]; + while ( ( result = patternSolid.exec( data ) ) !== null ) { - if (child.nodeType !== 1) { continue; } + startVertex = endVertex; - switch (child.nodeName) { + const solid = result[ 0 ]; - case 'node': - data.nodes.push(child.getAttribute('id')); - parseNode(child); - break; + const name = ( result = patternName.exec( solid ) ) !== null ? result[ 1 ] : ''; + groupNames.push( name ); - case 'instance_camera': - data.instanceCameras.push(parseId(child.getAttribute('url'))); - break; + while ( ( result = patternFace.exec( solid ) ) !== null ) { - case 'instance_controller': - data.instanceControllers.push(parseNodeInstance(child)); - break; + let vertexCountPerFace = 0; + let normalCountPerFace = 0; - case 'instance_light': - data.instanceLights.push(parseId(child.getAttribute('url'))); - break; + const text = result[ 0 ]; - case 'instance_geometry': - data.instanceGeometries.push(parseNodeInstance(child)); - break; + while ( ( result = patternNormal.exec( text ) ) !== null ) { - case 'instance_node': - data.instanceNodes.push(parseId(child.getAttribute('url'))); - break; + normal.x = parseFloat( result[ 1 ] ); + normal.y = parseFloat( result[ 2 ] ); + normal.z = parseFloat( result[ 3 ] ); + normalCountPerFace ++; - case 'matrix': - var array = parseFloats(child.textContent); - data.matrix.multiply(matrix.fromArray(array).transpose()); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + } - case 'translate': - var array = parseFloats(child.textContent); - vector.fromArray(array); - data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + while ( ( result = patternVertex.exec( text ) ) !== null ) { - case 'rotate': - var array = parseFloats(child.textContent); - var angle = THREE.Math.degToRad(array[3]); - data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) ); + normals.push( normal.x, normal.y, normal.z ); + vertexCountPerFace ++; + endVertex ++; - case 'scale': - var array = parseFloats(child.textContent); - data.matrix.scale(vector.fromArray(array)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + } - case 'extra': - break; + // every face have to own ONE valid normal - default: - console.log(child); + if ( normalCountPerFace !== 1 ) { - } + console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter ); - } + } - library.nodes[data.id] = data; + // each face have to own THREE valid vertices - return data; + if ( vertexCountPerFace !== 3 ) { - } + console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter ); - function parseNodeInstance(xml) { + } - var data = { - id: parseId(xml.getAttribute('url')), - materials: {}, - skeletons: [] - }; + faceCounter ++; - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + const start = startVertex; + const count = endVertex - startVertex; - switch (child.nodeName) { + geometry.userData.groupNames = groupNames; - case 'bind_material': - var instances = child.getElementsByTagName('instance_material'); + geometry.addGroup( start, count, groupCount ); + groupCount ++; - for (var j = 0; j < instances.length; j++) { + } - var instance = instances[j]; - var symbol = instance.getAttribute('symbol'); - var target = instance.getAttribute('target'); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - data.materials[symbol] = parseId(target); + return geometry; - } + } - break; + function ensureString( buffer ) { - case 'skeleton': - data.skeletons.push(parseId(child.textContent)); - break; + if ( typeof buffer !== 'string' ) { - } + return new TextDecoder().decode( buffer ); - } + } - return data; + return buffer; - } + } - function buildSkeleton(skeletons, joints) { + function ensureBinary( buffer ) { - var boneData = []; - var sortedBoneData = []; + if ( typeof buffer === 'string' ) { - var i, j, data; + const array_buffer = new Uint8Array( buffer.length ); + for ( let i = 0; i < buffer.length; i ++ ) { - // a skeleton can have multiple root bones. collada expresses this - // situtation with multiple "skeleton" tags per controller instance + array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian - for (i = 0; i < skeletons.length; i++) { + } - var skeleton = skeletons[i]; - var root = getNode(skeleton); + return array_buffer.buffer || array_buffer; - // setup bone data for a single bone hierarchy + } else { - buildBoneHierarchy(root, joints, boneData); + return buffer; - } + } - // sort bone data (the order is defined in the corresponding controller) + } - for (i = 0; i < joints.length; i++) { + // start - for (j = 0; j < boneData.length; j++) { + const binData = ensureBinary( data ); - data = boneData[j]; + return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) ); - if (data.bone.name === joints[i].name) { + } - sortedBoneData[i] = data; - data.processed = true; - break; +} - } +/** + * Loads a Wavefront .mtl file specifying materials + */ - } +class MTLLoader extends Loader { - } + constructor( manager ) { - // add unprocessed bone data at the end of the list + super( manager ); - for (i = 0; i < boneData.length; i++) { + } - data = boneData[i]; + /** + * Loads and parses a MTL asset from a URL. + * + * @param {String} url - URL to the MTL file. + * @param {Function} [onLoad] - Callback invoked with the loaded object. + * @param {Function} [onProgress] - Callback for download progress. + * @param {Function} [onError] - Callback for download errors. + * + * @see setPath setResourcePath + * + * @note In order for relative texture references to resolve correctly + * you must call setResourcePath() explicitly prior to load. + */ + load( url, onLoad, onProgress, onError ) { - if (data.processed === false) { + const scope = this; - sortedBoneData.push(data); - data.processed = true; + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - } + try { - // setup arrays for skeleton creation + onLoad( scope.parse( text, path ) ); - var bones = []; - var boneInverses = []; + } catch ( e ) { - for (i = 0; i < sortedBoneData.length; i++) { + if ( onError ) { - data = sortedBoneData[i]; + onError( e ); - bones.push(data.bone); - boneInverses.push(data.boneInverse); + } else { - } + console.error( e ); - return new THREE.Skeleton(bones, boneInverses); + } - } + scope.manager.itemError( url ); - function buildBoneHierarchy(root, joints, boneData) { + } - // setup bone data from visual scene + }, onProgress, onError ); - root.traverse(function (object) { + } - if (object.isBone === true) { + setMaterialOptions( value ) { - var boneInverse; + this.materialOptions = value; + return this; - // retrieve the boneInverse from the controller data + } - for (var i = 0; i < joints.length; i++) { + /** + * Parses a MTL file. + * + * @param {String} text - Content of MTL file + * @return {MaterialCreator} + * + * @see setPath setResourcePath + * + * @note In order for relative texture references to resolve correctly + * you must call setResourcePath() explicitly prior to parse. + */ + parse( text, path ) { - var joint = joints[i]; + const lines = text.split( '\n' ); + let info = {}; + const delimiter_pattern = /\s+/; + const materialsInfo = {}; - if (joint.name === object.name) { + for ( let i = 0; i < lines.length; i ++ ) { - boneInverse = joint.boneInverse; - break; + let line = lines[ i ]; + line = line.trim(); - } + if ( line.length === 0 || line.charAt( 0 ) === '#' ) { - } + // Blank line or comment ignore + continue; - if (boneInverse === undefined) { + } - // Unfortunately, there can be joints in the visual scene that are not part of the - // corresponding controller. In this case, we have to create a dummy boneInverse matrix - // for the respective bone. This bone won't affect any vertices, because there are no skin indices - // and weights defined for it. But we still have to add the bone to the sorted bone list in order to - // ensure a correct animation of the model. + const pos = line.indexOf( ' ' ); - boneInverse = new THREE.Matrix4(); + let key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; + key = key.toLowerCase(); - } + let value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; + value = value.trim(); - boneData.push({ bone: object, boneInverse: boneInverse, processed: false }); + if ( key === 'newmtl' ) { - } + // New material - }); + info = { name: value }; + materialsInfo[ value ] = info; - } + } else { - function buildNode(data) { + if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { - var objects = []; + const ss = value.split( delimiter_pattern, 3 ); + info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; - var matrix = data.matrix; - var nodes = data.nodes; - var type = data.type; - var instanceCameras = data.instanceCameras; - var instanceControllers = data.instanceControllers; - var instanceLights = data.instanceLights; - var instanceGeometries = data.instanceGeometries; - var instanceNodes = data.instanceNodes; + } else { - // nodes + info[ key ] = value; - for (var i = 0, l = nodes.length; i < l; i++) { + } - objects.push(getNode(nodes[i])); + } - } + } - // instance cameras + const materialCreator = new MaterialCreator( this.resourcePath || path, this.materialOptions ); + materialCreator.setCrossOrigin( this.crossOrigin ); + materialCreator.setManager( this.manager ); + materialCreator.setMaterials( materialsInfo ); + return materialCreator; - for (var i = 0, l = instanceCameras.length; i < l; i++) { + } - var instanceCamera = getCamera(instanceCameras[i]); +} - if (instanceCamera !== null) { +/** + * Create a new MTLLoader.MaterialCreator + * @param baseUrl - Url relative to which textures are loaded + * @param options - Set of options on how to construct the materials + * side: Which side to apply the material + * FrontSide (default), THREE.BackSide, THREE.DoubleSide + * wrap: What type of wrapping to apply for textures + * RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping + * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 + * Default: false, assumed to be already normalized + * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's + * Default: false + * @constructor + */ - objects.push(instanceCamera.clone()); +class MaterialCreator { - } + constructor( baseUrl = '', options = {} ) { + this.baseUrl = baseUrl; + this.options = options; + this.materialsInfo = {}; + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; - } + this.crossOrigin = 'anonymous'; - // instance controllers + this.side = ( this.options.side !== undefined ) ? this.options.side : FrontSide; + this.wrap = ( this.options.wrap !== undefined ) ? this.options.wrap : RepeatWrapping; - for (var i = 0, l = instanceControllers.length; i < l; i++) { + } - var instance = instanceControllers[i]; - var controller = getController(instance.id); - var geometries = getGeometry(controller.id); - var newObjects = buildObjects(geometries, instance.materials); + setCrossOrigin( value ) { - var skeletons = instance.skeletons; - var joints = controller.skin.joints; + this.crossOrigin = value; + return this; - var skeleton = buildSkeleton(skeletons, joints); + } - for (var j = 0, jl = newObjects.length; j < jl; j++) { + setManager( value ) { - var object = newObjects[j]; + this.manager = value; - if (object.isSkinnedMesh) { + } - object.bind(skeleton, controller.skin.bindMatrix); - object.normalizeSkinWeights(); + setMaterials( materialsInfo ) { - } + this.materialsInfo = this.convert( materialsInfo ); + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; - objects.push(object); + } - } + convert( materialsInfo ) { - } + if ( ! this.options ) return materialsInfo; - // instance lights + const converted = {}; - for (var i = 0, l = instanceLights.length; i < l; i++) { - var instanceCamera = getCamera(instanceCameras[i]); + for ( const mn in materialsInfo ) { - if (instanceCamera !== null) { + // Convert materials info into normalized form based on options - objects.push(instanceCamera.clone()); + const mat = materialsInfo[ mn ]; - } + const covmat = {}; - } + converted[ mn ] = covmat; - // instance geometries + for ( const prop in mat ) { - for (var i = 0, l = instanceGeometries.length; i < l; i++) { + let save = true; + let value = mat[ prop ]; + const lprop = prop.toLowerCase(); - var instance = instanceGeometries[i]; + switch ( lprop ) { - // a single geometry instance in collada can lead to multiple object3Ds. - // this is the case when primitives are combined like triangles and lines + case 'kd': + case 'ka': + case 'ks': - var geometries = getGeometry(instance.id); - var newObjects = buildObjects(geometries, instance.materials); + // Diffuse color (color under white light) using RGB values - for (var j = 0, jl = newObjects.length; j < jl; j++) { + if ( this.options && this.options.normalizeRGB ) { - objects.push(newObjects[j]); + value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; - } + } - } + if ( this.options && this.options.ignoreZeroRGBs ) { - // instance nodes + if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { - for (var i = 0, l = instanceNodes.length; i < l; i++) { + // ignore - objects.push(getNode(instanceNodes[i]).clone()); + save = false; - } + } - var object; + } - if (nodes.length === 0 && objects.length === 1) { + break; - object = objects[0]; + } - } else { + if ( save ) { - object = (type === 'JOINT') ? new THREE.Bone() : new THREE.Object3D(); + covmat[ lprop ] = value; - for (var i = 0; i < objects.length; i++) { + } - object.add(objects[i]); + } - } + } - } + return converted; - object.name = (type === 'JOINT') ? data.sid : data.name; - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + } - return object; + preload() { - } + for ( const mn in this.materialsInfo ) { - function resolveMaterialBinding(keys, instanceMaterials) { + this.create( mn ); - var materials = []; + } - for (var i = 0, l = keys.length; i < l; i++) { + } - var id = instanceMaterials[keys[i]]; - materials.push(getMaterial(id)); + getIndex( materialName ) { - } + return this.nameLookup[ materialName ]; - return materials; + } - } + getAsArray() { - function buildObjects(geometries, instanceMaterials) { + let index = 0; - var objects = []; + for ( const mn in this.materialsInfo ) { - for (var type in geometries) { + this.materialsArray[ index ] = this.create( mn ); + this.nameLookup[ mn ] = index; + index ++; - var geometry = geometries[type]; + } - var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); + return this.materialsArray; - // handle case if no materials are defined + } - if (materials.length === 0) { + create( materialName ) { - if (type === 'lines' || type === 'linestrips') { + if ( this.materials[ materialName ] === undefined ) { - materials.push(new THREE.LineBasicMaterial()); + this.createMaterial_( materialName ); - } else { + } - materials.push(new THREE.MeshPhongMaterial()); + return this.materials[ materialName ]; - } + } - } + createMaterial_( materialName ) { - // regard skinning + // Create material - var skinning = (geometry.data.attributes.skinIndex !== undefined); + const scope = this; + const mat = this.materialsInfo[ materialName ]; + const params = { - if (skinning) { + name: materialName, + side: this.side - for (var i = 0, l = materials.length; i < l; i++) { + }; - materials[i].skinning = true; + function resolveURL( baseUrl, url ) { - } + if ( typeof url !== 'string' || url === '' ) + return ''; - } + // Absolute URL + if ( /^https?:\/\//i.test( url ) ) return url; - // choose between a single or multi materials (material array) + return baseUrl + url; - var material = (materials.length === 1) ? materials[0] : materials; + } - // now create a specific 3D object + function setMapForType( mapType, value ) { - var object; + if ( params[ mapType ] ) return; // Keep the first encountered texture - switch (type) { + const texParams = scope.getTextureParams( value, params ); + const map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); - case 'lines': - object = new THREE.LineSegments(geometry.data, material); - break; + map.repeat.copy( texParams.scale ); + map.offset.copy( texParams.offset ); - case 'linestrips': - object = new THREE.Line(geometry.data, material); - break; + map.wrapS = scope.wrap; + map.wrapT = scope.wrap; - case 'triangles': - case 'polylist': - if (skinning) { + if ( mapType === 'map' || mapType === 'emissiveMap' ) { - object = new THREE.SkinnedMesh(geometry.data, material); + map.colorSpace = SRGBColorSpace; - } else { + } - object = new THREE.Mesh(geometry.data, material); + params[ mapType ] = map; - } - break; + } - } + for ( const prop in mat ) { - objects.push(object); + const value = mat[ prop ]; + let n; - } + if ( value === '' ) continue; - return objects; + switch ( prop.toLowerCase() ) { - } + // Ns is material specular exponent - function getNode(id) { + case 'kd': - return getBuild(library.nodes[id], buildNode); + // Diffuse color (color under white light) using RGB values - } + params.color = new Color().fromArray( value ).convertSRGBToLinear(); - // visual scenes + break; - function parseVisualScene(xml) { + case 'ks': - var data = { - name: xml.getAttribute('name'), - children: [] - }; + // Specular color (color when light is reflected from shiny surface) using RGB values + params.specular = new Color().fromArray( value ).convertSRGBToLinear(); - prepareNodes(xml); + break; - var elements = getElementsByTagName(xml, 'node'); + case 'ke': - for (var i = 0; i < elements.length; i++) { + // Emissive using RGB values + params.emissive = new Color().fromArray( value ).convertSRGBToLinear(); - data.children.push(parseNode(elements[i])); + break; - } + case 'map_kd': - library.visualScenes[xml.getAttribute('id')] = data; + // Diffuse texture map - } + setMapForType( 'map', value ); - function buildVisualScene(data) { + break; - var group = new THREE.Object3D(); - group.name = data.name; + case 'map_ks': - var children = data.children; + // Specular map - for (var i = 0; i < children.length; i++) { + setMapForType( 'specularMap', value ); - var child = children[i]; + break; - if (child.id === null) { + case 'map_ke': - group.add(buildNode(child)); + // Emissive map - } else { + setMapForType( 'emissiveMap', value ); - // if there is an ID, let's try to get the finished build (e.g. joints are already build) + break; - group.add(getNode(child.id)); + case 'norm': - } + setMapForType( 'normalMap', value ); - } + break; - return group; + case 'map_bump': + case 'bump': - } + // Bump texture map - function getVisualScene(id) { + setMapForType( 'bumpMap', value ); - return getBuild(library.visualScenes[id], buildVisualScene); + break; - } + case 'map_d': - // scenes + // Alpha map - function parseScene(xml) { + setMapForType( 'alphaMap', value ); + params.transparent = true; - var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; - return getVisualScene(parseId(instance.getAttribute('url'))); + break; - } + case 'ns': - function setupAnimations() { + // The specular exponent (defines the focus of the specular highlight) + // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. - var clips = library.clips; + params.shininess = parseFloat( value ); - if (isEmpty(clips) === true) { + break; - if (isEmpty(library.animations) === false) { + case 'd': + n = parseFloat( value ); - // if there are animations but no clips, we create a default clip for playback + if ( n < 1 ) { - var tracks = []; + params.opacity = n; + params.transparent = true; - for (var id in library.animations) { + } - var animationTracks = getAnimation(id); + break; - for (var i = 0, l = animationTracks.length; i < l; i++) { + case 'tr': + n = parseFloat( value ); - tracks.push(animationTracks[i]); + if ( this.options && this.options.invertTrProperty ) n = 1 - n; - } + if ( n > 0 ) { - } + params.opacity = 1 - n; + params.transparent = true; - animations.push(new THREE.AnimationClip('default', - 1, tracks)); + } - } + break; - } else { + } - for (var id in clips) { + } - animations.push(getAnimationClip(id)); + this.materials[ materialName ] = new MeshPhongMaterial( params ); + return this.materials[ materialName ]; - } + } - } + getTextureParams( value, matParams ) { - } + const texParams = { - console.time('THREE.ColladaLoader'); + scale: new Vector2( 1, 1 ), + offset: new Vector2( 0, 0 ) - if (text.length === 0) { + }; - return { scene: new THREE.Scene() }; + const items = value.split( /\s+/ ); + let pos; - } + pos = items.indexOf( '-bm' ); - console.time('THREE.ColladaLoader: DOMParser'); + if ( pos >= 0 ) { - var xml = new DOMParser().parseFromString(text, 'application/xml'); + matParams.bumpScale = parseFloat( items[ pos + 1 ] ); + items.splice( pos, 2 ); - console.timeEnd('THREE.ColladaLoader: DOMParser'); + } - var collada = getElementsByTagName(xml, 'COLLADA')[0]; + pos = items.indexOf( '-s' ); - // metadata + if ( pos >= 0 ) { - var version = collada.getAttribute('version'); - console.log('THREE.ColladaLoader: File version', version); + texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! - var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); - var textureLoader = new THREE.TextureLoader(this.manager); - textureLoader.setPath(path).setCrossOrigin(this.crossOrigin); + } - // + pos = items.indexOf( '-o' ); - var animations = []; - var kinematics = {}; - var count = 0; + if ( pos >= 0 ) { - // + texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! - var library = { - animations: {}, - clips: {}, - controllers: {}, - images: {}, - effects: {}, - materials: {}, - cameras: {}, - lights: {}, - geometries: {}, - nodes: {}, - visualScenes: {}, - kinematicsModels: {}, - kinematicsScenes: {} - }; + } - console.time('THREE.ColladaLoader: Parse'); + texParams.url = items.join( ' ' ).trim(); + return texParams; - parseLibrary(collada, 'library_animations', 'animation', parseAnimation); - parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); - parseLibrary(collada, 'library_controllers', 'controller', parseController); - parseLibrary(collada, 'library_images', 'image', parseImage); - parseLibrary(collada, 'library_effects', 'effect', parseEffect); - parseLibrary(collada, 'library_materials', 'material', parseMaterial); - parseLibrary(collada, 'library_cameras', 'camera', parseCamera); - parseLibrary(collada, 'library_lights', 'light', parseLight); - parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); - parseLibrary(collada, 'library_nodes', 'node', parseNode); - parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); - parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); - parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + } - console.timeEnd('THREE.ColladaLoader: Parse'); + loadTexture( url, mapping, onLoad, onProgress, onError ) { - console.time('THREE.ColladaLoader: Build'); + const manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager; + let loader = manager.getHandler( url ); - buildLibrary(library.animations, buildAnimation); - buildLibrary(library.clips, buildAnimationClip); - buildLibrary(library.controllers, buildController); - buildLibrary(library.images, buildImage); - buildLibrary(library.effects, buildEffect); - buildLibrary(library.materials, buildMaterial); - buildLibrary(library.cameras, buildCamera); - buildLibrary(library.lights, buildLight); - buildLibrary(library.geometries, buildGeometry); - buildLibrary(library.visualScenes, buildVisualScene); + if ( loader === null ) { - console.timeEnd('THREE.ColladaLoader: Build'); + loader = new TextureLoader( manager ); - setupAnimations(); - setupKinematics(); + } - var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); - /* - * up_axis of some robot models in ROS world aren't properly set because - * rviz ignores this field. Thus, ignores Z_UP to show urdfs just like rviz. - * See https://github.com/ros-visualization/rviz/issues/1045 for the detail - if ( asset.upAxis === 'Z_UP' ) { + const texture = loader.load( url, onLoad, onProgress, onError ); - scene.rotation.x = - Math.PI / 2; + if ( mapping !== undefined ) texture.mapping = mapping; - } - */ + return texture; - scene.scale.multiplyScalar(asset.unit); + } - console.timeEnd('THREE.ColladaLoader'); +} - return { - animations: animations, - kinematics: kinematics, - library: library, - scene: scene - }; +var MeshLoader = { + onError: function onError(error) { + console.error(error); + }, + loaders: { + 'dae': function dae(meshRes, uri, options) { + var loader = new ColladaLoader(options.loader); + console.log('Loading collada: ' + uri); + loader.load(uri, function (collada_mesh) { + var model = collada_mesh.scene; + meshRes.add(model); + console.log('Done loading collada'); + }); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + return loader; + }, + 'obj': function obj(meshRes, uri, options) { + options.material; + var loader = new OBJLoader(options.loader); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + //Reload the mesh again after materials have been loaded + // @todo: this should be improved so that the file doesn't need to be + // reloaded however that would involve more changes within the OBJLoader. + function onMaterialsLoaded(loader, materials) { + loader.setMaterials(materials).load(uri, function OBJMaterialsReady(obj) { + // add the container group + meshRes.add(obj); + }, null, MeshLoader.onError); + } + loader.load(uri, function OBJFileReady(obj) { + var baseUri = LoaderUtils.extractUrlBase(uri); + if (obj.materialLibraries.length) { + // load the material libraries + var materialUri = obj.materialLibraries[0]; + new MTLLoader(options.loader).setPath(baseUri).load(materialUri, function (materials) { + materials.preload(); + onMaterialsLoaded(loader, materials); + }, null, MeshLoader.onError); + } else { + // add the container group + meshRes.add(obj); + } + }, /*onProgress=*/null, MeshLoader.onError); + return loader; + }, + 'stl': function stl(meshRes, uri, options) { + var material = options.material; + var loader = new STLLoader(options.loader); + { + loader.load(uri, function (geometry) { + geometry.computeVertexNormals(); + var mesh; + if (material !== null) { + mesh = new Mesh(geometry, material); + } else { + mesh = new Mesh(geometry, new MeshBasicMaterial({ + color: 0x999999 + })); + } + meshRes.add(mesh); + }, /*onProgress=*/null, MeshLoader.onError); + } + return loader; + } } - }; -/** - * @fileOverview - * @author Jose Rojas - jrojas@redlinesolutions.co - */ - - /** - * MeshLoader is a singleton factory class for using various helper classes to - * load mesh files of different types. - * - * It consists of one dictionary property 'loaders'. The dictionary keys consist - * of the file extension for each supported loader type. The dictionary values - * are functions used to construct the loader objects. The functions have the - * following parameters: - * - * * meshRes - the MeshResource that will contain the loaded mesh - * * uri - the uri path to the mesh file - * @returns loader object - */ -var MeshLoader = { - onError: function(error) { - console.error(error); - }, - loaders: { - 'dae': function(meshRes, uri, options) { - var material = options.material; - var loader = new THREE.ColladaLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - loader.load( - uri, - function colladaReady(collada) { - // check for a scale factor in ColladaLoader2 - // add a texture to anything that is missing one - if(material !== null) { - collada.scene.traverse(function(child) { - if(child instanceof THREE.Mesh) { - if(child.material === undefined) { - child.material = material; - } - } - }); - } - - meshRes.add(collada.scene); - }, - /*onProgress=*/null, - MeshLoader.onError); - return loader; - }, - - 'obj': function(meshRes, uri, options) { - options.material; - var loader = new THREE.OBJLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - - //Reload the mesh again after materials have been loaded - // @todo: this should be improved so that the file doesn't need to be - // reloaded however that would involve more changes within the OBJLoader. - function onMaterialsLoaded(loader, materials) { - loader. - setMaterials(materials). - load( - uri, - function OBJMaterialsReady(obj) { - // add the container group - meshRes.add(obj); - }, - null, - MeshLoader.onError); - } - - loader.load( - uri, - function OBJFileReady(obj) { - - var baseUri = THREE.LoaderUtils.extractUrlBase( uri ); - - if (obj.materialLibraries.length) { - // load the material libraries - var materialUri = obj.materialLibraries[0]; - new THREE.MTLLoader(options.loader).setPath(baseUri).load( - materialUri, - function(materials) { - materials.preload(); - onMaterialsLoaded(loader, materials); - }, - null, - MeshLoader.onError - ); - } else { - // add the container group - meshRes.add(obj); - } - - }, - /*onProgress=*/null, - MeshLoader.onError - ); - return loader; - }, - - 'stl': function(meshRes, uri, options) { - var material = options.material; - var loader = new THREE.STLLoader(options.loader); - { - loader.load(uri, - function ( geometry ) { - geometry.computeFaceNormals(); - var mesh; - if(material !== null) { - mesh = new THREE.Mesh( geometry, material ); - } else { - mesh = new THREE.Mesh( geometry, - new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); - } - meshRes.add(mesh); - }, - /*onProgress=*/null, - MeshLoader.onError); - } - return loader; - } - - } - }; +function _callSuper$w(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$w() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$w() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$w = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -51862,114 +42163,149 @@ var MeshLoader = { * @author Russell Toris - rctoris@wpi.edu */ -var MeshResource = /*@__PURE__*/(function (superclass) { +var MeshResource = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A MeshResource is an THREE object that will load from a external mesh file. Currently loads + * Collada files. + * + * @constructor + * @param options - object with following keys: + * + * * path (optional) - the base path to the associated models that will be loaded + * * resource - the resource file name to load + * * material (optional) - the material to use for the object + * * warnings (optional) - if warnings should be printed + */ function MeshResource(options) { - superclass.call(this); + var _this; + _classCallCheck(this, MeshResource); + _this = _callSuper$w(this, MeshResource); options = options || {}; var path = options.path || '/'; var resource = options.resource; options.material || null; - this.warnings = options.warnings; - + _this.warnings = options.warnings; // check for a trailing '/' if (path.substr(path.length - 1) !== '/') { path += '/'; } - var uri = path + resource; var fileType = uri.substr(-3).toLowerCase(); // check the type var loaderFunc = MeshLoader.loaders[fileType]; if (loaderFunc) { - loaderFunc(this, uri, options); + loaderFunc(_this, uri, options); } else { console.warn('Unsupported loader for file type: \'' + fileType + '\''); } + return _this; } + _inherits(MeshResource, _THREE$Object3D); + return _createClass(MeshResource); +}(Object3D); - if ( superclass ) MeshResource.__proto__ = superclass; - MeshResource.prototype = Object.create( superclass && superclass.prototype ); - MeshResource.prototype.constructor = MeshResource; - - return MeshResource; -}(THREE.Object3D)); +function _callSuper$v(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$v() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$v() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$v = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var TriangleList = /*@__PURE__*/(function (superclass) { +var TriangleList = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A TriangleList is a THREE object that can be used to display a list of triangles as a geometry. + * + * @constructor + * @param options - object with following keys: + * + * * material (optional) - the material to use for the object + * * vertices - the array of vertices to use + * * colors - the associated array of colors to use + */ function TriangleList(options) { + var _this; + _classCallCheck(this, TriangleList); options = options || {}; - var material = options.material || new THREE.MeshBasicMaterial(); + var material = options.material || new MeshBasicMaterial(); var vertices = options.vertices; var colors = options.colors; - - superclass.call(this); + _this = _callSuper$v(this, TriangleList); // set the material to be double sided - material.side = THREE.DoubleSide; - - // construct the geometry - var geometry = new THREE.Geometry(); - for (i = 0; i < vertices.length; i++) { - geometry.vertices.push(new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)); + material.side = DoubleSide; + + // Construct the geometry + var geometry = new BufferGeometry(); + var verticesArray = new Float32Array(vertices.length * 3); + for (var _i = 0; _i < vertices.length; _i++) { + verticesArray[_i * 3] = vertices[_i].x; + verticesArray[_i * 3 + 1] = vertices[_i].y; + verticesArray[_i * 3 + 2] = vertices[_i].z; } + geometry.setAttribute('position', new BufferAttribute(verticesArray, 3)); - // set the colors + // Set the colors var i, j; if (colors.length === vertices.length) { - // use per-vertex color - for (i = 0; i < vertices.length; i += 3) { - var faceVert = new THREE.Face3(i, i + 1, i + 2); - for (j = i * 3; j < i * 3 + 3; i++) { - var color = new THREE.Color(); - color.setRGB(colors[i].r, colors[i].g, colors[i].b); - faceVert.vertexColors.push(color); - } - geometry.faces.push(faceVert); + // Use per-vertex color + var vertexColors = new Float32Array(colors.length * 3); + for (i = 0; i < colors.length; i++) { + vertexColors[i * 3] = colors[i].r; + vertexColors[i * 3 + 1] = colors[i].g; + vertexColors[i * 3 + 2] = colors[i].b; } - material.vertexColors = THREE.VertexColors; + geometry.setAttribute('color', new BufferAttribute(vertexColors, 3)); + material.vertexColors = true; } else if (colors.length === vertices.length / 3) { - // use per-triangle color - for (i = 0; i < vertices.length; i += 3) { - var faceTri = new THREE.Face3(i, i + 1, i + 2); - faceTri.color.setRGB(colors[i / 3].r, colors[i / 3].g, colors[i / 3].b); - geometry.faces.push(faceTri); + // Use per-triangle color + var faceColors = new Float32Array(vertices.length); + for (i = 0; i < colors.length; i++) { + var color = new Color(colors[i].r, colors[i].g, colors[i].b); + for (j = 0; j < 9; j += 3) { + faceColors[i * 9 + j] = color.r; + faceColors[i * 9 + j + 1] = color.g; + faceColors[i * 9 + j + 2] = color.b; + } } - material.vertexColors = THREE.FaceColors; + geometry.setAttribute('color', new BufferAttribute(faceColors, 3)); + material.vertexColors = true; } else { - // use marker color + // Use marker color + var defaultColor = new Color(1, 1, 1); // Default color + var _faceColors = new Float32Array(vertices.length); for (i = 0; i < vertices.length; i += 3) { - var face = new THREE.Face3(i, i + 1, i + 2); - geometry.faces.push(face); + _faceColors[i * 3] = defaultColor.r; + _faceColors[i * 3 + 1] = defaultColor.g; + _faceColors[i * 3 + 2] = defaultColor.b; } + geometry.setAttribute('color', new BufferAttribute(_faceColors, 3)); } - geometry.computeBoundingBox(); geometry.computeBoundingSphere(); geometry.computeFaceNormals(); - - this.add(new THREE.Mesh(geometry, material)); + _this.add(new Mesh(geometry, material)); + return _this; } + _inherits(TriangleList, _THREE$Object3D); + return _createClass(TriangleList, [{ + key: "setColor", + value: + /** + * Set the color of this object to the given hex value. + * + * @param hex - the hex value of the color to set + */ + function setColor(hex) { + this.mesh.material.color.setHex(hex); + } + }]); +}(Object3D); - if ( superclass ) TriangleList.__proto__ = superclass; - TriangleList.prototype = Object.create( superclass && superclass.prototype ); - TriangleList.prototype.constructor = TriangleList; - /** - * Set the color of this object to the given hex value. - * - * @param hex - the hex value of the color to set - */ - TriangleList.prototype.setColor = function setColor (hex) { - this.mesh.material.color.setHex(hex); - }; - - return TriangleList; -}(THREE.Object3D)); +function _callSuper$u(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$u() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$u() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$u = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -51977,10 +42313,20 @@ var TriangleList = /*@__PURE__*/(function (superclass) { * @author Russell Toris - rctoris@wpi.edu */ -var Marker = /*@__PURE__*/(function (superclass) { +var Marker = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A Marker can convert a ROS marker message into a THREE object. + * + * @constructor + * @param options - object with following keys: + * + * * path - the base path or URL for any mesh files that will be loaded for this marker + * * message - the marker message + */ function Marker(options) { - superclass.call(this); - + var _this; + _classCallCheck(this, Marker); + _this = _callSuper$u(this, Marker); options = options || {}; var path = options.path || '/'; var message = options.message; @@ -51989,20 +42335,17 @@ var Marker = /*@__PURE__*/(function (superclass) { if (path.substr(path.length - 1) !== '/') { path += '/'; } - - if(message.scale) { - this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; - } - else { - this.msgScale = [1,1,1]; + if (message.scale) { + _this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } else { + _this.msgScale = [1, 1, 1]; } - this.msgColor = message.color; - this.msgMesh = undefined; + _this.msgColor = message.color; + _this.msgMesh = undefined; // set the pose and get the color - this.setPose(message.pose); - var colorMaterial = makeColorMaterial(this.msgColor.r, - this.msgColor.g, this.msgColor.b, this.msgColor.a); + _this.setPose(message.pose); + var colorMaterial = makeColorMaterial(_this.msgColor.r, _this.msgColor.g, _this.msgColor.b, _this.msgColor.a); // create the object based on the type switch (message.type) { @@ -52014,64 +42357,64 @@ var Marker = /*@__PURE__*/(function (superclass) { var shaftDiameter = headDiameter * 0.5; // determine the points - var direction, p1 = null; + var direction, + p1 = null; if (message.points.length === 2) { - p1 = new THREE.Vector3(message.points[0].x, message.points[0].y, message.points[0].z); - var p2 = new THREE.Vector3(message.points[1].x, message.points[1].y, message.points[1].z); + p1 = new Vector3(message.points[0].x, message.points[0].y, message.points[0].z); + var p2 = new Vector3(message.points[1].x, message.points[1].y, message.points[1].z); direction = p1.clone().negate().add(p2); // direction = p2 - p1; len = direction.length(); headDiameter = message.scale.y; shaftDiameter = message.scale.x; - if (message.scale.z !== 0.0) { headLength = message.scale.z; } } // add the marker - this.add(new Arrow({ - direction : direction, - origin : p1, - length : len, - headLength : headLength, - shaftDiameter : shaftDiameter, - headDiameter : headDiameter, - material : colorMaterial + _this.add(new Arrow({ + direction: direction, + origin: p1, + length: len, + headLength: headLength, + shaftDiameter: shaftDiameter, + headDiameter: headDiameter, + material: colorMaterial })); break; case MARKER_CUBE: // set the cube dimensions - var cubeGeom = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); - this.add(new THREE.Mesh(cubeGeom, colorMaterial)); + var cubeGeom = new BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + _this.add(new Mesh(cubeGeom, colorMaterial)); break; case MARKER_SPHERE: // set the sphere dimensions - var sphereGeom = new THREE.SphereGeometry(0.5); - var sphereMesh = new THREE.Mesh(sphereGeom, colorMaterial); + var sphereGeom = new SphereGeometry(0.5); + var sphereMesh = new Mesh(sphereGeom, colorMaterial); sphereMesh.scale.x = message.scale.x; sphereMesh.scale.y = message.scale.y; sphereMesh.scale.z = message.scale.z; - this.add(sphereMesh); + _this.add(sphereMesh); break; case MARKER_CYLINDER: // set the cylinder dimensions - var cylinderGeom = new THREE.CylinderGeometry(0.5, 0.5, 1, 16, 1, false); - var cylinderMesh = new THREE.Mesh(cylinderGeom, colorMaterial); - cylinderMesh.quaternion.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI * 0.5); + var cylinderGeom = new CylinderGeometry(0.5, 0.5, 1, 16, 1, false); + var cylinderMesh = new Mesh(cylinderGeom, colorMaterial); + cylinderMesh.quaternion.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI * 0.5); cylinderMesh.scale.set(message.scale.x, message.scale.z, message.scale.y); - this.add(cylinderMesh); + _this.add(cylinderMesh); break; case MARKER_LINE_STRIP: - var lineStripGeom = new THREE.Geometry(); - var lineStripMaterial = new THREE.LineBasicMaterial({ - linewidth : message.scale.x + var lineStripGeom = new BufferGeometry(); + var lineStripMaterial = new LineBasicMaterial({ + linewidth: message.scale.x }); // add the points var j; - for ( j = 0; j < message.points.length; j++) { - var pt = new THREE.Vector3(); + for (j = 0; j < message.points.length; j++) { + var pt = new Vector3(); pt.x = message.points[j].x; pt.y = message.points[j].y; pt.z = message.points[j].z; @@ -52081,8 +42424,8 @@ var Marker = /*@__PURE__*/(function (superclass) { // determine the colors for each if (message.colors.length === message.points.length) { lineStripMaterial.vertexColors = true; - for ( j = 0; j < message.points.length; j++) { - var clr = new THREE.Color(); + for (j = 0; j < message.points.length; j++) { + var clr = new Color(); clr.setRGB(message.colors[j].r, message.colors[j].g, message.colors[j].b); lineStripGeom.colors.push(clr); } @@ -52091,18 +42434,18 @@ var Marker = /*@__PURE__*/(function (superclass) { } // add the line - this.add(new THREE.Line(lineStripGeom, lineStripMaterial)); + _this.add(new Line(lineStripGeom, lineStripMaterial)); break; case MARKER_LINE_LIST: - var lineListGeom = new THREE.Geometry(); - var lineListMaterial = new THREE.LineBasicMaterial({ - linewidth : message.scale.x + var lineListGeom = new BufferGeometry(); + var lineListMaterial = new LineBasicMaterial({ + linewidth: message.scale.x }); // add the points var k; - for ( k = 0; k < message.points.length; k++) { - var v = new THREE.Vector3(); + for (k = 0; k < message.points.length; k++) { + var v = new Vector3(); v.x = message.points[k].x; v.y = message.points[k].y; v.z = message.points[k].z; @@ -52112,8 +42455,8 @@ var Marker = /*@__PURE__*/(function (superclass) { // determine the colors for each if (message.colors.length === message.points.length) { lineListMaterial.vertexColors = true; - for ( k = 0; k < message.points.length; k++) { - var c = new THREE.Color(); + for (k = 0; k < message.points.length; k++) { + var c = new Color(); c.setRGB(message.colors[k].r, message.colors[k].g, message.colors[k].b); lineListGeom.colors.push(c); } @@ -52122,62 +42465,59 @@ var Marker = /*@__PURE__*/(function (superclass) { } // add the line - this.add(new THREE.LineSegments(lineListGeom, lineListMaterial)); + _this.add(new LineSegments(lineListGeom, lineListMaterial)); break; case MARKER_CUBE_LIST: // holds the main object - var object = new THREE.Object3D(); + var object = new Object3D(); // check if custom colors should be used var numPoints = message.points.length; - var createColors = (numPoints === message.colors.length); + var createColors = numPoints === message.colors.length; // do not render giant lists var stepSize = Math.ceil(numPoints / 1250); // add the points var p, cube, curColor, newMesh; - for (p = 0; p < numPoints; p+=stepSize) { - cube = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + for (p = 0; p < numPoints; p += stepSize) { + cube = new BoxGeometry(message.scale.x, message.scale.y, message.scale.z); // check the color - if(createColors) { + if (createColors) { curColor = makeColorMaterial(message.colors[p].r, message.colors[p].g, message.colors[p].b, message.colors[p].a); } else { curColor = colorMaterial; } - - newMesh = new THREE.Mesh(cube, curColor); + newMesh = new Mesh(cube, curColor); newMesh.position.x = message.points[p].x; newMesh.position.y = message.points[p].y; newMesh.position.z = message.points[p].z; object.add(newMesh); } - - this.add(object); + _this.add(object); break; case MARKER_SPHERE_LIST: // holds the main object - var sphereObject = new THREE.Object3D(); + var sphereObject = new Object3D(); // check if custom colors should be used var numSpherePoints = message.points.length; - var createSphereColors = (numSpherePoints === message.colors.length); + var createSphereColors = numSpherePoints === message.colors.length; // do not render giant lists var sphereStepSize = Math.ceil(numSpherePoints / 1250); // add the points var q, sphere, curSphereColor, newSphereMesh; - for (q = 0; q < numSpherePoints; q+=sphereStepSize) { - sphere = new THREE.SphereGeometry(0.5, 8, 8); + for (q = 0; q < numSpherePoints; q += sphereStepSize) { + sphere = new SphereGeometry(0.5, 8, 8); // check the color - if(createSphereColors) { + if (createSphereColors) { curSphereColor = makeColorMaterial(message.colors[q].r, message.colors[q].g, message.colors[q].b, message.colors[q].a); } else { curSphereColor = colorMaterial; } - - newSphereMesh = new THREE.Mesh(sphere, curSphereColor); + newSphereMesh = new Mesh(sphere, curSphereColor); newSphereMesh.scale.x = message.scale.x; newSphereMesh.scale.y = message.scale.y; newSphereMesh.scale.z = message.scale.z; @@ -52186,19 +42526,19 @@ var Marker = /*@__PURE__*/(function (superclass) { newSphereMesh.position.z = message.points[q].z; sphereObject.add(newSphereMesh); } - this.add(sphereObject); + _this.add(sphereObject); break; case MARKER_POINTS: // for now, use a particle system for the lists - var geometry = new THREE.Geometry(); - var material = new THREE.PointsMaterial({ - size : message.scale.x + var geometry = new BufferGeometry(); + var material = new PointsMaterial({ + size: message.scale.x }); // add the points var i; - for ( i = 0; i < message.points.length; i++) { - var vertex = new THREE.Vector3(); + for (i = 0; i < message.points.length; i++) { + var vertex = new Vector3(); vertex.x = message.points[i].x; vertex.y = message.points[i].y; vertex.z = message.points[i].z; @@ -52208,8 +42548,8 @@ var Marker = /*@__PURE__*/(function (superclass) { // determine the colors for each if (message.colors.length === message.points.length) { material.vertexColors = true; - for ( i = 0; i < message.points.length; i++) { - var color = new THREE.Color(); + for (i = 0; i < message.points.length; i++) { + var color = new Color(); color.setRGB(message.colors[i].r, message.colors[i].g, message.colors[i].b); geometry.colors.push(color); } @@ -52218,23 +42558,21 @@ var Marker = /*@__PURE__*/(function (superclass) { } // add the particle system - this.add(new THREE.Points(geometry, material)); + _this.add(new Points$1(geometry, material)); break; case MARKER_TEXT_VIEW_FACING: // only work on non-empty text if (message.text.length > 0) { // Use a THREE.Sprite to always be view-facing // ( code from http://stackoverflow.com/a/27348780 ) - var textColor = this.msgColor; - + var textColor = _this.msgColor; var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var textHeight = 100; var fontString = 'normal ' + textHeight + 'px sans-serif'; context.font = fontString; - var metrics = context.measureText( message.text ); + var metrics = context.measureText(message.text); var textWidth = metrics.width; - canvas.width = textWidth; // To account for overhang (like the letter 'g'), make the canvas bigger // The non-text portion is transparent anyway @@ -52242,274 +42580,271 @@ var Marker = /*@__PURE__*/(function (superclass) { // this does need to be set again context.font = fontString; - context.fillStyle = 'rgba(' - + Math.round(255 * textColor.r) + ', ' - + Math.round(255 * textColor.g) + ', ' - + Math.round(255 * textColor.b) + ', ' - + textColor.a + ')'; + context.fillStyle = 'rgba(' + Math.round(255 * textColor.r) + ', ' + Math.round(255 * textColor.g) + ', ' + Math.round(255 * textColor.b) + ', ' + textColor.a + ')'; context.textAlign = 'left'; context.textBaseline = 'middle'; - context.fillText( message.text, 0, canvas.height/2); - - var texture = new THREE.Texture(canvas); + context.fillText(message.text, 0, canvas.height / 2); + var texture = new Texture(canvas); texture.needsUpdate = true; - - var spriteMaterial = new THREE.SpriteMaterial({ + var spriteMaterial = new SpriteMaterial({ map: texture, // NOTE: This is needed for THREE.js r61, unused in r70 - useScreenCoordinates: false }); - var sprite = new THREE.Sprite( spriteMaterial ); + useScreenCoordinates: false + }); + var sprite = new Sprite(spriteMaterial); var textSize = message.scale.x; sprite.scale.set(textWidth / canvas.height * textSize, textSize, 1); - - this.add(sprite); } + _this.add(sprite); + } break; case MARKER_MESH_RESOURCE: // load and add the mesh var meshColorMaterial = null; - if(message.color.r !== 0 || message.color.g !== 0 || - message.color.b !== 0 || message.color.a !== 0) { + if (message.color.r !== 0 || message.color.g !== 0 || message.color.b !== 0 || message.color.a !== 0) { meshColorMaterial = colorMaterial; } - this.msgMesh = message.mesh_resource.substr(10); + _this.msgMesh = message.mesh_resource.substr(10); var meshResource = new MeshResource({ - path : path, - resource : this.msgMesh, - material : meshColorMaterial, + path: path, + resource: _this.msgMesh, + material: meshColorMaterial }); - this.add(meshResource); + _this.add(meshResource); break; case MARKER_TRIANGLE_LIST: // create the list of triangles var tri = new TriangleList({ - material : colorMaterial, - vertices : message.points, - colors : message.colors + material: colorMaterial, + vertices: message.points, + colors: message.colors }); tri.scale.set(message.scale.x, message.scale.y, message.scale.z); - this.add(tri); + _this.add(tri); break; default: console.error('Currently unsupported marker type: ' + message.type); break; } + return _this; } + _inherits(Marker, _THREE$Object3D); + return _createClass(Marker, [{ + key: "setPose", + value: + /** + * Set the pose of this marker to the given values. + * + * @param pose - the pose to set for this marker + */ + function setPose(pose) { + // set position information + this.position.x = pose.position.x; + this.position.y = pose.position.y; + this.position.z = pose.position.z; - if ( superclass ) Marker.__proto__ = superclass; - Marker.prototype = Object.create( superclass && superclass.prototype ); - Marker.prototype.constructor = Marker; - /** - * Set the pose of this marker to the given values. - * - * @param pose - the pose to set for this marker - */ - Marker.prototype.setPose = function setPose (pose) { - // set position information - this.position.x = pose.position.x; - this.position.y = pose.position.y; - this.position.z = pose.position.z; - - // set the rotation - this.quaternion.set(pose.orientation.x, pose.orientation.y, - pose.orientation.z, pose.orientation.w); - this.quaternion.normalize(); - - // update the world - this.updateMatrixWorld(); - }; - /** - * Update this marker. - * - * @param message - the marker message - * @return true on success otherwhise false is returned - */ - Marker.prototype.update = function update (message) { - // set the pose and get the color - this.setPose(message.pose); + // set the rotation + this.quaternion.set(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + this.quaternion.normalize(); - // Update color - if(message.color.r !== this.msgColor.r || - message.color.g !== this.msgColor.g || - message.color.b !== this.msgColor.b || - message.color.a !== this.msgColor.a) - { - var colorMaterial = makeColorMaterial( - message.color.r, message.color.g, - message.color.b, message.color.a); + // update the world + this.updateMatrixWorld(); + } + }, { + key: "update", + value: + /** + * Update this marker. + * + * @param message - the marker message + * @return true on success otherwhise false is returned + */ + function update(message) { + // set the pose and get the color + this.setPose(message.pose); + // Update color + if (message.color.r !== this.msgColor.r || message.color.g !== this.msgColor.g || message.color.b !== this.msgColor.b || message.color.a !== this.msgColor.a) { + var colorMaterial = makeColorMaterial(message.color.r, message.color.g, message.color.b, message.color.a); switch (message.type) { - case MARKER_LINE_STRIP: - case MARKER_LINE_LIST: - case MARKER_POINTS: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_POINTS: break; - case MARKER_ARROW: - case MARKER_CUBE: - case MARKER_SPHERE: - case MARKER_CYLINDER: - case MARKER_TRIANGLE_LIST: - case MARKER_TEXT_VIEW_FACING: - this.traverse (function (child){ - if (child instanceof THREE.Mesh) { - child.material = colorMaterial; - } + case MARKER_ARROW: + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + case MARKER_TRIANGLE_LIST: + case MARKER_TEXT_VIEW_FACING: + this.traverse(function (child) { + if (child instanceof Mesh) { + child.material = colorMaterial; + } }); break; - case MARKER_MESH_RESOURCE: + case MARKER_MESH_RESOURCE: var meshColorMaterial = null; - if(message.color.r !== 0 || message.color.g !== 0 || - message.color.b !== 0 || message.color.a !== 0) { - meshColorMaterial = this.colorMaterial; + if (message.color.r !== 0 || message.color.g !== 0 || message.color.b !== 0 || message.color.a !== 0) { + meshColorMaterial = this.colorMaterial; } - this.traverse (function (child){ - if (child instanceof THREE.Mesh) { - child.material = meshColorMaterial; - } + this.traverse(function (child) { + if (child instanceof Mesh) { + child.material = meshColorMaterial; + } }); break; - case MARKER_CUBE_LIST: - case MARKER_SPHERE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: // TODO Support to update color for MARKER_CUBE_LIST & MARKER_SPHERE_LIST return false; - default: + default: return false; } - this.msgColor = message.color; - } - - // Update geometry - var scaleChanged = - Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || - Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || - Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; - this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } - switch (message.type) { - case MARKER_CUBE: - case MARKER_SPHERE: - case MARKER_CYLINDER: - if(scaleChanged) { - return false; + // Update geometry + var scaleChanged = Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; + this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + switch (message.type) { + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + if (scaleChanged) { + return false; } break; - case MARKER_TEXT_VIEW_FACING: - if(scaleChanged || this.text !== message.text) { - return false; + case MARKER_TEXT_VIEW_FACING: + if (scaleChanged || this.text !== message.text) { + return false; } break; - case MARKER_MESH_RESOURCE: + case MARKER_MESH_RESOURCE: var meshResource = message.mesh_resource.substr(10); - if(meshResource !== this.msgMesh) { - return false; - } - if(scaleChanged) { - return false; + if (meshResource !== this.msgMesh) { + return false; } - break; - case MARKER_ARROW: - case MARKER_LINE_STRIP: - case MARKER_LINE_LIST: - case MARKER_CUBE_LIST: - case MARKER_SPHERE_LIST: - case MARKER_POINTS: - case MARKER_TRIANGLE_LIST: + if (scaleChanged) { + return false; + } + break; + case MARKER_ARROW: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: + case MARKER_POINTS: + case MARKER_TRIANGLE_LIST: // TODO: Check if geometry changed return false; + } + return true; } - - return true; - }; - /* - * Free memory of elements in this marker. - */ - Marker.prototype.dispose = function dispose () { - this.children.forEach(function(element) { - if (element instanceof MeshResource) { - element.children.forEach(function(scene) { - if (scene.material !== undefined) { - scene.material.dispose(); - } - scene.children.forEach(function(mesh) { - if (mesh.geometry !== undefined) { - mesh.geometry.dispose(); - } - if (mesh.material !== undefined) { - mesh.material.dispose(); + }, { + key: "dispose", + value: + /* + * Free memory of elements in this marker. + */ + function dispose() { + this.children.forEach(function (element) { + if (element instanceof MeshResource) { + element.children.forEach(function (scene) { + if (scene.material !== undefined) { + scene.material.dispose(); } - scene.remove(mesh); + scene.children.forEach(function (mesh) { + if (mesh.geometry !== undefined) { + mesh.geometry.dispose(); + } + if (mesh.material !== undefined) { + mesh.material.dispose(); + } + scene.remove(mesh); + }); + element.remove(scene); }); - element.remove(scene); - }); - } else { - if (element.geometry !== undefined) { + } else { + if (element.geometry !== undefined) { element.geometry.dispose(); - } - if (element.material !== undefined) { + } + if (element.material !== undefined) { element.material.dispose(); + } } - } - element.parent.remove(element); - }); - }; + element.parent.remove(element); + }); + } + }]); +}(Object3D); - return Marker; -}(THREE.Object3D)); +function _callSuper$t(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$t() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$t() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$t = function _isNativeReflectConstruct() { return !!t; })(); } +function _superPropGet(t, e, r, o) { var p = _get(_getPrototypeOf(1 & o ? t.prototype : t), e, r); return 2 & o ? function (t) { return p.apply(r, t); } : p; } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { +var InteractiveMarkerControl = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The main marker control object for an interactive marker. + * + * @constructor + * @param options - object with following keys: + * + * * parent - the parent of this control + * * message - the interactive marker control message + * * camera - the main camera associated with the viewer for this marker client + * * path (optional) - the base path to any meshes that will be loaded + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ function InteractiveMarkerControl(options) { - superclass.call(this); - var that = this; - + var _this; + _classCallCheck(this, InteractiveMarkerControl); + _this = _callSuper$t(this, InteractiveMarkerControl); + var that = _this; options = options || {}; - this.parent = options.parent; + _this.parent = options.parent; var handle = options.handle; var message = options.message; - this.message = message; - this.name = message.name; - this.camera = options.camera; - this.path = options.path || '/'; - this.loader = options.loader; - this.dragging = false; - this.startMousePos = new THREE.Vector2(); - this.isShift = false; - + _this.message = message; + _this.name = message.name; + _this.camera = options.camera; + _this.path = options.path || '/'; + _this.loader = options.loader; + _this.dragging = false; + _this.startMousePos = new Vector2(); + _this.isShift = false; // orientation for the control - var controlOri = new THREE.Quaternion(message.orientation.x, message.orientation.y, - message.orientation.z, message.orientation.w); + var controlOri = new Quaternion(message.orientation.x, message.orientation.y, message.orientation.z, message.orientation.w); controlOri.normalize(); // transform x axis into local frame - var controlAxis = new THREE.Vector3(1, 0, 0); + var controlAxis = new Vector3(1, 0, 0); controlAxis.applyQuaternion(controlOri); - - this.currentControlOri = new THREE.Quaternion(); + _this.currentControlOri = new Quaternion(); // determine mouse interaction switch (message.interaction_mode) { case INTERACTIVE_MARKER_MOVE_ROTATE_3D: case INTERACTIVE_MARKER_MOVE_3D: - this.addEventListener('mousemove', this.parent.move3d.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.move3d.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_MOVE_AXIS: - this.addEventListener('mousemove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); - this.addEventListener('touchmove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.moveAxis.bind(_this.parent, _this, controlAxis)); + _this.addEventListener('touchmove', _this.parent.moveAxis.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_ROTATE_AXIS: - this - .addEventListener('mousemove', this.parent.rotateAxis.bind(this.parent, this, controlOri)); + _this.addEventListener('mousemove', _this.parent.rotateAxis.bind(_this.parent, _this, controlOri)); break; case INTERACTIVE_MARKER_MOVE_PLANE: - this - .addEventListener('mousemove', this.parent.movePlane.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.movePlane.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_BUTTON: - this.addEventListener('click', this.parent.buttonClick.bind(this.parent, this)); + _this.addEventListener('click', _this.parent.buttonClick.bind(_this.parent, _this)); break; } @@ -52524,38 +42859,38 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { // check the mode if (message.interaction_mode !== INTERACTIVE_MARKER_NONE) { - this.addEventListener('mousedown', this.parent.startDrag.bind(this.parent, this)); - this.addEventListener('mouseup', this.parent.stopDrag.bind(this.parent, this)); - this.addEventListener('contextmenu', this.parent.showMenu.bind(this.parent, this)); - this.addEventListener('mouseup', function(event3d) { + _this.addEventListener('mousedown', _this.parent.startDrag.bind(_this.parent, _this)); + _this.addEventListener('mouseup', _this.parent.stopDrag.bind(_this.parent, _this)); + _this.addEventListener('contextmenu', _this.parent.showMenu.bind(_this.parent, _this)); + _this.addEventListener('mouseup', function (event3d) { if (that.startMousePos.distanceToSquared(event3d.mousePos) === 0) { event3d.type = 'contextmenu'; that.dispatchEvent(event3d); } }); - this.addEventListener('mouseover', stopPropagation); - this.addEventListener('mouseout', stopPropagation); - this.addEventListener('click', stopPropagation); - this.addEventListener('mousedown', function(event3d) { + _this.addEventListener('mouseover', stopPropagation); + _this.addEventListener('mouseout', stopPropagation); + _this.addEventListener('click', stopPropagation); + _this.addEventListener('mousedown', function (event3d) { that.startMousePos = event3d.mousePos; }); // touch support - this.addEventListener('touchstart', function(event3d) { + _this.addEventListener('touchstart', function (event3d) { if (event3d.domEvent.touches.length === 1) { event3d.type = 'mousedown'; event3d.domEvent.button = 0; that.dispatchEvent(event3d); } }); - this.addEventListener('touchmove', function(event3d) { + _this.addEventListener('touchmove', function (event3d) { if (event3d.domEvent.touches.length === 1) { event3d.type = 'mousemove'; event3d.domEvent.button = 0; that.dispatchEvent(event3d); } }); - this.addEventListener('touchend', function(event3d) { + _this.addEventListener('touchend', function (event3d) { if (event3d.domEvent.touches.length === 0) { event3d.domEvent.button = 0; event3d.type = 'mouseup'; @@ -52564,25 +42899,24 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { that.dispatchEvent(event3d); } }); - - window.addEventListener('keydown', function(event){ - if(event.keyCode === 16){ + window.addEventListener('keydown', function (event) { + if (event.keyCode === 16) { that.isShift = true; } }); - window.addEventListener('keyup', function(event){ - if(event.keyCode === 16){ + window.addEventListener('keyup', function (event) { + if (event.keyCode === 16) { that.isShift = false; } }); } // rotation behavior - var rotInv = new THREE.Quaternion(); - var posInv = this.parent.position.clone().multiplyScalar(-1); + var rotInv = new Quaternion(); + var posInv = _this.parent.position.clone().multiplyScalar(-1); switch (message.orientation_mode) { case INTERACTIVE_MARKER_INHERIT: - rotInv = this.parent.quaternion.clone().inverse(); + rotInv = _this.parent.quaternion.clone().inverse(); break; case INTERACTIVE_MARKER_FIXED: break; @@ -52596,26 +42930,26 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { // temporary TFClient to get transformations from InteractiveMarker // frame to potential child Marker frames var localTfClient = new ROSLIB.TFClient({ - ros : handle.tfClient.ros, - fixedFrame : handle.message.header.frame_id, - serverName : handle.tfClient.serverName + ros: handle.tfClient.ros, + fixedFrame: handle.message.header.frame_id, + serverName: handle.tfClient.serverName }); // create visuals (markers) - message.markers.forEach(function(markerMsg) { - var addMarker = function(transformMsg) { + message.markers.forEach(function (markerMsg) { + var addMarker = function addMarker(transformMsg) { var markerHelper = new Marker({ - message : markerMsg, - path : that.path, - loader : that.loader + message: markerMsg, + path: that.path, + loader: that.loader }); // if transformMsg isn't null, this was called by TFClient if (transformMsg !== null) { // get the current pose as a ROSLIB.Pose... var newPose = new ROSLIB.Pose({ - position : markerHelper.position, - orientation : markerHelper.quaternion + position: markerHelper.position, + orientation: markerHelper.quaternion }); // so we can apply the transform provided by the TFClient newPose.applyTransform(new ROSLIB.Transform(transformMsg)); @@ -52624,24 +42958,22 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { // apply it to sub-marker position to get sub-marker position // relative to parent marker var transformMarker = new Marker({ - message : markerMsg, - path : that.path, - loader : that.loader + message: markerMsg, + path: that.path, + loader: that.loader }); transformMarker.position.add(posInv); transformMarker.position.applyQuaternion(rotInv); transformMarker.quaternion.multiplyQuaternions(rotInv, transformMarker.quaternion); - var translation = new THREE.Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); + var translation = new Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); var transform = new ROSLIB.Transform({ - translation : translation, - orientation : transformMarker.quaternion + translation: translation, + orientation: transformMarker.quaternion }); // apply that transform too newPose.applyTransform(transform); - markerHelper.setPose(newPose); - markerHelper.updateMatrixWorld(); // we only need to set the pose once - at least, this is what RViz seems to be doing, might change in the future localTfClient.unsubscribe(markerMsg.header.frame_id); @@ -52662,70 +42994,82 @@ var InteractiveMarkerControl = /*@__PURE__*/(function (superclass) { addMarker(null); } }); + return _this; } - - if ( superclass ) InteractiveMarkerControl.__proto__ = superclass; - InteractiveMarkerControl.prototype = Object.create( superclass && superclass.prototype ); - InteractiveMarkerControl.prototype.constructor = InteractiveMarkerControl; - InteractiveMarkerControl.prototype.updateMatrixWorld = function updateMatrixWorld (force) { - var that = this; - var message = this.message; - switch (message.orientation_mode) { - case INTERACTIVE_MARKER_INHERIT: - superclass.prototype.updateMatrixWorld.call(this, force); - that.currentControlOri.copy(that.quaternion); - that.currentControlOri.normalize(); - break; - case INTERACTIVE_MARKER_FIXED: - that.quaternion.copy(that.parent.quaternion.clone().inverse()); - that.updateMatrix(); - that.matrixWorldNeedsUpdate = true; - superclass.prototype.updateMatrixWorld.call(this, force); - that.currentControlOri.copy(that.quaternion); - break; - case INTERACTIVE_MARKER_VIEW_FACING: - that.camera.updateMatrixWorld(); - var cameraRot = new THREE.Matrix4().extractRotation(that.camera.matrixWorld); - - var ros2Gl = new THREE.Matrix4(); - var r90 = Math.PI * 0.5; - var rv = new THREE.Euler(-r90, 0, r90); - ros2Gl.makeRotationFromEuler(rv); - - var worldToLocal = new THREE.Matrix4(); - worldToLocal.getInverse(that.parent.matrixWorld); - - cameraRot.multiplyMatrices(cameraRot, ros2Gl); - cameraRot.multiplyMatrices(worldToLocal, cameraRot); - - that.currentControlOri.setFromRotationMatrix(cameraRot); - - // check the orientation - if (!message.independent_marker_orientation) { - that.quaternion.copy(that.currentControlOri); + _inherits(InteractiveMarkerControl, _THREE$Object3D); + return _createClass(InteractiveMarkerControl, [{ + key: "updateMatrixWorld", + value: function updateMatrixWorld(force) { + var that = this; + var message = this.message; + switch (message.orientation_mode) { + case INTERACTIVE_MARKER_INHERIT: + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + that.currentControlOri.copy(that.quaternion); + that.currentControlOri.normalize(); + break; + case INTERACTIVE_MARKER_FIXED: + that.quaternion.copy(that.parent.quaternion.clone().inverse()); that.updateMatrix(); that.matrixWorldNeedsUpdate = true; - } - superclass.prototype.updateMatrixWorld.call(this, force); - break; - default: - console.error('Unkown orientation mode: ' + message.orientation_mode); - break; + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + that.currentControlOri.copy(that.quaternion); + break; + case INTERACTIVE_MARKER_VIEW_FACING: + that.camera.updateMatrixWorld(); + var cameraRot = new Matrix4().extractRotation(that.camera.matrixWorld); + var ros2Gl = new Matrix4(); + var r90 = Math.PI * 0.5; + var rv = new Euler(-r90, 0, r90); + ros2Gl.makeRotationFromEuler(rv); + var worldToLocal = new Matrix4(); + worldToLocal.getInverse(that.parent.matrixWorld); + cameraRot.multiplyMatrices(cameraRot, ros2Gl); + cameraRot.multiplyMatrices(worldToLocal, cameraRot); + that.currentControlOri.setFromRotationMatrix(cameraRot); + + // check the orientation + if (!message.independent_marker_orientation) { + that.quaternion.copy(that.currentControlOri); + that.updateMatrix(); + that.matrixWorldNeedsUpdate = true; + } + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + break; + default: + console.error('Unkown orientation mode: ' + message.orientation_mode); + break; + } } - }; + }]); +}(Object3D); - return InteractiveMarkerControl; -}(THREE.Object3D)); +function _callSuper$s(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$s() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$s() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$s = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { +var InteractiveMarkerMenu = /*#__PURE__*/function (_THREE$EventDispatche) { + /** + * A menu for an interactive marker. This will be overlayed on the canvas. + * + * @constructor + * @param options - object with following keys: + * + * * menuEntries - the menu entries to add + * * className (optional) - a custom CSS class for the menu div + * * entryClassName (optional) - a custom CSS class for the menu entry + * * overlayClassName (optional) - a custom CSS class for the menu overlay + * * menuFontSize (optional) - the menu font size + */ function InteractiveMarkerMenu(options) { - superclass.call(this); - var that = this; + var _this; + _classCallCheck(this, InteractiveMarkerMenu); + _this = _callSuper$s(this, InteractiveMarkerMenu); + var that = _this; options = options || {}; var menuEntries = options.menuEntries; var className = options.className || 'default-interactive-marker-menu'; @@ -52736,75 +43080,58 @@ var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { // holds the menu tree var allMenus = []; allMenus[0] = { - children : [] + children: [] }; - // create the CSS for this marker if it has not been created if (document.getElementById('default-interactive-marker-menu-css') === null) { var style = document.createElement('style'); style.id = 'default-interactive-marker-menu-css'; style.type = 'text/css'; - style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' - + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' - + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize +';' + 'z-index: 1002;' - + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' - + 'margin: 0px;' + 'list-style-type: none;' + '}' - + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' - + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' - + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' - + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' - + ' background-color: #666666;' + ' cursor: pointer;' + '}' - + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' - + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' - + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' - + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' - + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; + style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize + ';' + 'z-index: 1002;' + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' + 'margin: 0px;' + 'list-style-type: none;' + '}' + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' + ' background-color: #666666;' + ' cursor: pointer;' + '}' + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; document.getElementsByTagName('head')[0].appendChild(style); } // place the menu in a div - this.menuDomElem = document.createElement('div'); - this.menuDomElem.style.position = 'absolute'; - this.menuDomElem.className = className; - this.menuDomElem.addEventListener('contextmenu', function(event) { + _this.menuDomElem = document.createElement('div'); + _this.menuDomElem.style.position = 'absolute'; + _this.menuDomElem.className = className; + _this.menuDomElem.addEventListener('contextmenu', function (event) { event.preventDefault(); }); // create the overlay DOM - this.overlayDomElem = document.createElement('div'); - this.overlayDomElem.className = overlayClassName; - - this.hideListener = this.hide.bind(this); - this.overlayDomElem.addEventListener('contextmenu', this.hideListener); - this.overlayDomElem.addEventListener('click', this.hideListener); - this.overlayDomElem.addEventListener('touchstart', this.hideListener); + _this.overlayDomElem = document.createElement('div'); + _this.overlayDomElem.className = overlayClassName; + _this.hideListener = _this.hide.bind(_this); + _this.overlayDomElem.addEventListener('contextmenu', _this.hideListener); + _this.overlayDomElem.addEventListener('click', _this.hideListener); + _this.overlayDomElem.addEventListener('touchstart', _this.hideListener); // parse all entries and link children to parents var i, entry, id; - for ( i = 0; i < menuEntries.length; i++) { + for (i = 0; i < menuEntries.length; i++) { entry = menuEntries[i]; id = entry.id; allMenus[id] = { - title : entry.title, - id : id, - children : [] + title: entry.title, + id: id, + children: [] }; } - for ( i = 0; i < menuEntries.length; i++) { + for (i = 0; i < menuEntries.length; i++) { entry = menuEntries[i]; id = entry.id; var menu = allMenus[id]; var parent = allMenus[entry.parent_id]; parent.children.push(menu); } - function emitMenuSelect(menuEntry, domEvent) { this.dispatchEvent({ - type : 'menu-select', - domEvent : domEvent, - id : menuEntry.id, - controlName : this.controlName + type: 'menu-select', + domEvent: domEvent, + id: menuEntry.id, + controlName: this.controlName }); this.hide(domEvent); } @@ -52816,19 +43143,15 @@ var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { * @param parentMenu - the parent menu */ function makeUl(parentDomElem, parentMenu) { - var ulElem = document.createElement('ul'); parentDomElem.appendChild(ulElem); - var children = parentMenu.children; - - for ( var i = 0; i < children.length; i++) { + for (var i = 0; i < children.length; i++) { var liElem = document.createElement('li'); var divElem = document.createElement('div'); divElem.appendChild(document.createTextNode(children[i].title)); ulElem.appendChild(liElem); liElem.appendChild(divElem); - if (children[i].children.length > 0) { makeUl(liElem, children[i]); divElem.addEventListener('click', that.hide.bind(that)); @@ -52839,751 +43162,2505 @@ var InteractiveMarkerMenu = /*@__PURE__*/(function (superclass) { divElem.className = 'default-interactive-marker-menu-entry'; } } - } // construct DOM element - makeUl(this.menuDomElem, allMenus[0]); + makeUl(_this.menuDomElem, allMenus[0]); + return _this; } + _inherits(InteractiveMarkerMenu, _THREE$EventDispatche); + return _createClass(InteractiveMarkerMenu, [{ + key: "show", + value: + /** + * Shoe the menu DOM element. + * + * @param control - the control for the menu + * @param event - the event that caused this + */ + function show(control, event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + this.controlName = control.name; - if ( superclass ) InteractiveMarkerMenu.__proto__ = superclass; - InteractiveMarkerMenu.prototype = Object.create( superclass && superclass.prototype ); - InteractiveMarkerMenu.prototype.constructor = InteractiveMarkerMenu; - /** - * Shoe the menu DOM element. - * - * @param control - the control for the menu - * @param event - the event that caused this - */ - InteractiveMarkerMenu.prototype.show = function show (control, event) { - if (event && event.preventDefault) { - event.preventDefault(); - } - - this.controlName = control.name; - - // position it on the click - if (event.domEvent.changedTouches !== undefined) { - // touch click - this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; - this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; - } else { - // mouse click - this.menuDomElem.style.left = event.domEvent.clientX + 'px'; - this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + // position it on the click + if (event.domEvent.changedTouches !== undefined) { + // touch click + this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; + this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; + } else { + // mouse click + this.menuDomElem.style.left = event.domEvent.clientX + 'px'; + this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + } + document.body.appendChild(this.overlayDomElem); + document.body.appendChild(this.menuDomElem); } - document.body.appendChild(this.overlayDomElem); - document.body.appendChild(this.menuDomElem); - }; - /** - * Hide the menu DOM element. - * - * @param event (optional) - the event that caused this - */ - InteractiveMarkerMenu.prototype.hide = function hide (event) { - if (event && event.preventDefault) { - event.preventDefault(); + }, { + key: "hide", + value: + /** + * Hide the menu DOM element. + * + * @param event (optional) - the event that caused this + */ + function hide(event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + document.body.removeChild(this.overlayDomElem); + document.body.removeChild(this.menuDomElem); } + }]); +}(EventDispatcher); - document.body.removeChild(this.overlayDomElem); - document.body.removeChild(this.menuDomElem); - }; - - return InteractiveMarkerMenu; -}(THREE.EventDispatcher)); +function _callSuper$r(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$r() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$r() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$r = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarker = /*@__PURE__*/(function (superclass) { +var InteractiveMarker = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The main interactive marker object. + * + * @constructor + * @param options - object with following keys: + * + * * handle - the ROS3D.InteractiveMarkerHandle for this marker + * * camera - the main camera associated with the viewer for this marker + * * path (optional) - the base path to any meshes that will be loaded + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ function InteractiveMarker(options) { - superclass.call(this); + var _this; + _classCallCheck(this, InteractiveMarker); + _this = _callSuper$r(this, InteractiveMarker); options = options || {}; var handle = options.handle; - this.name = handle.name; + _this.name = handle.name; var camera = options.camera; var path = options.path || '/'; var loader = options.loader; - this.dragging = false; + _this.dragging = false; // set the initial pose - this.onServerSetPose({ - pose : handle.pose + _this.onServerSetPose({ + pose: handle.pose }); // information on where the drag started - this.dragStart = { - position : new THREE.Vector3(), - orientation : new THREE.Quaternion(), - positionWorld : new THREE.Vector3(), - orientationWorld : new THREE.Quaternion(), - event3d : {} + _this.dragStart = { + position: new Vector3(), + orientation: new Quaternion(), + positionWorld: new Vector3(), + orientationWorld: new Quaternion(), + event3d: {} }; // add each control message - handle.controls.forEach(function(controlMessage) { + handle.controls.forEach(function (controlMessage) { this.add(new InteractiveMarkerControl({ - parent : this, - handle : handle, - message : controlMessage, - camera : camera, - path : path, - loader : loader + parent: this, + handle: handle, + message: controlMessage, + camera: camera, + path: path, + loader: loader })); - }.bind(this)); + }.bind(_this)); // check for any menus if (handle.menuEntries.length > 0) { - this.menu = new InteractiveMarkerMenu({ - menuEntries : handle.menuEntries, - menuFontSize : handle.menuFontSize + _this.menu = new InteractiveMarkerMenu({ + menuEntries: handle.menuEntries, + menuFontSize: handle.menuFontSize }); // forward menu select events - this.menu.addEventListener('menu-select', function(event) { + _this.menu.addEventListener('menu-select', function (event) { this.dispatchEvent(event); - }.bind(this)); + }.bind(_this)); } + return _this; } - - if ( superclass ) InteractiveMarker.__proto__ = superclass; - InteractiveMarker.prototype = Object.create( superclass && superclass.prototype ); - InteractiveMarker.prototype.constructor = InteractiveMarker; - /** - * Show the interactive marker menu associated with this marker. - * - * @param control - the control to use - * @param event - the event that caused this - */ - InteractiveMarker.prototype.showMenu = function showMenu (control, event) { - if (this.menu) { - this.menu.show(control, event); + _inherits(InteractiveMarker, _THREE$Object3D); + return _createClass(InteractiveMarker, [{ + key: "showMenu", + value: + /** + * Show the interactive marker menu associated with this marker. + * + * @param control - the control to use + * @param event - the event that caused this + */ + function showMenu(control, event) { + if (this.menu) { + this.menu.show(control, event); + } } - }; - /** - * Move the axis based on the given event information. - * - * @param control - the control to use - * @param origAxis - the origin of the axis - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.moveAxis = function moveAxis (control, origAxis, event3d) { - if (this.dragging) { - var currentControlOri = control.currentControlOri; - var axis = origAxis.clone().applyQuaternion(currentControlOri); - // get move axis in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); - - var axisRay = new THREE.Ray(originWorld, axisWorld); - - // find closest point to mouse on axis - var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); - - // offset from drag start position - var p = new THREE.Vector3(); - p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation) - .multiplyScalar(t)); - this.setPosition(control, p); - - - event3d.stopPropagation(); + }, { + key: "moveAxis", + value: + /** + * Move the axis based on the given event information. + * + * @param control - the control to use + * @param origAxis - the origin of the axis + * @param event3d - the event that caused this + */ + function moveAxis(control, origAxis, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var axis = origAxis.clone().applyQuaternion(currentControlOri); + // get move axis in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); + var axisRay = new Ray(originWorld, axisWorld); + + // find closest point to mouse on axis + var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); + + // offset from drag start position + var p = new Vector3(); + p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(t)); + this.setPosition(control, p); + event3d.stopPropagation(); + } } - }; + }, { + key: "move3d", + value: + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + function move3d(control, origNormal, event3d) { + // by default, move in a plane + if (this.dragging) { + if (control.isShift) ; else { + // we want to use the origin plane that is closest to the camera + var cameraVector = control.camera.getWorldDirection(); + var x = Math.abs(cameraVector.x); + var y = Math.abs(cameraVector.y); + var z = Math.abs(cameraVector.z); + var controlOri = new Quaternion(1, 0, 0, 1); + if (y > x && y > z) { + // orientation for the control + controlOri = new Quaternion(0, 0, 1, 1); + } else if (z > x && z > y) { + // orientation for the control + controlOri = new Quaternion(0, 1, 0, 1); + } + controlOri.normalize(); - /** - * Move with respect to the plane based on the contorl and event. - * - * @param control - the control to use - * @param origNormal - the normal of the origin - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.move3d = function move3d (control, origNormal, event3d) { - // by default, move in a plane - if (this.dragging) { - - if(control.isShift);else { - // we want to use the origin plane that is closest to the camera - var cameraVector = control.camera.getWorldDirection(); - var x = Math.abs(cameraVector.x); - var y = Math.abs(cameraVector.y); - var z = Math.abs(cameraVector.z); - var controlOri = new THREE.Quaternion(1, 0, 0, 1); - if(y > x && y > z){ - // orientation for the control - controlOri = new THREE.Quaternion(0, 0, 1, 1); - }else if(z > x && z > y){ - // orientation for the control - controlOri = new THREE.Quaternion(0, 1, 0, 1); + // transform x axis into local frame + origNormal = new Vector3(1, 0, 0); + origNormal.applyQuaternion(controlOri); + this.movePlane(control, origNormal, event3d); } - controlOri.normalize(); - - // transform x axis into local frame - origNormal = new THREE.Vector3(1, 0, 0); - origNormal.applyQuaternion(controlOri); - this.movePlane(control, origNormal, event3d); } } - }; - /** - * Move with respect to the plane based on the contorl and event. - * - * @param control - the control to use - * @param origNormal - the normal of the origin - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.movePlane = function movePlane (control, origNormal, event3d) { - if (this.dragging) { - var currentControlOri = control.currentControlOri; - var normal = origNormal.clone().applyQuaternion(currentControlOri); - // get plane params in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); - - // intersect mouse ray with plane - var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); - - // offset from drag start position - var p = new THREE.Vector3(); - p.subVectors(intersection, originWorld); - p.add(this.dragStart.positionWorld); - this.setPosition(control, p); + }, { + key: "movePlane", + value: + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + function movePlane(control, origNormal, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var normal = origNormal.clone().applyQuaternion(currentControlOri); + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset from drag start position + var p = new Vector3(); + p.subVectors(intersection, originWorld); + p.add(this.dragStart.positionWorld); + this.setPosition(control, p); + event3d.stopPropagation(); + } + } + }, { + key: "rotateAxis", + value: + /** + * Rotate based on the control and event given. + * + * @param control - the control to use + * @param origOrientation - the orientation of the origin + * @param event3d - the event that caused this + */ + function rotateAxis(control, origOrientation, event3d) { + if (this.dragging) { + control.updateMatrixWorld(); + var currentControlOri = control.currentControlOri; + var orientation = currentControlOri.clone().multiply(origOrientation.clone()); + var normal = new Vector3(1, 0, 0).applyQuaternion(orientation); + + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset local origin to lie on intersection plane + var normalRay = new Ray(this.dragStart.positionWorld, normalWorld); + var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); + + // rotates from world to plane coords + var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); + var orientationWorldInv = orientationWorld.clone().inverse(); + + // rotate original and current intersection into local coords + intersection.sub(rotOrigin); + intersection.applyQuaternion(orientationWorldInv); + var origIntersection = this.dragStart.event3d.intersection.point.clone(); + origIntersection.sub(rotOrigin); + origIntersection.applyQuaternion(orientationWorldInv); + + // compute relative 2d angle + var a1 = Math.atan2(intersection.y, intersection.z); + var a2 = Math.atan2(origIntersection.y, origIntersection.z); + var a = a2 - a1; + var rot = new Quaternion(); + rot.setFromAxisAngle(normal, a); + + // rotate + this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); + + // offset from drag start position + event3d.stopPropagation(); + } + } + }, { + key: "feedbackEvent", + value: + /** + * Dispatch the given event type. + * + * @param type - the type of event + * @param control - the control to use + */ + function feedbackEvent(type, control) { + this.dispatchEvent({ + type: type, + position: this.position.clone(), + orientation: this.quaternion.clone(), + controlName: control.name + }); + } + }, { + key: "startDrag", + value: + /** + * Start a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function startDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = true; + this.updateMatrixWorld(true); + var scale = new Vector3(); + this.matrixWorld.decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); + this.dragStart.position = this.position.clone(); + this.dragStart.orientation = this.quaternion.clone(); + this.dragStart.event3d = event3d; + this.feedbackEvent('user-mousedown', control); + } + } + }, { + key: "stopDrag", + value: + /** + * Stop a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function stopDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = false; + this.dragStart.event3d = {}; + this.onServerSetPose(this.bufferedPoseEvent); + this.bufferedPoseEvent = undefined; + this.feedbackEvent('user-mouseup', control); + } + } + }, { + key: "buttonClick", + value: + /** + * Handle a button click. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function buttonClick(control, event3d) { event3d.stopPropagation(); + this.feedbackEvent('user-button-click', control); } - }; - /** - * Rotate based on the control and event given. - * - * @param control - the control to use - * @param origOrientation - the orientation of the origin - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.rotateAxis = function rotateAxis (control, origOrientation, event3d) { - if (this.dragging) { - control.updateMatrixWorld(); - - var currentControlOri = control.currentControlOri; - var orientation = currentControlOri.clone().multiply(origOrientation.clone()); - - var normal = (new THREE.Vector3(1, 0, 0)).applyQuaternion(orientation); - - // get plane params in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); - - // intersect mouse ray with plane - var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); - - // offset local origin to lie on intersection plane - var normalRay = new THREE.Ray(this.dragStart.positionWorld, normalWorld); - var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); - - // rotates from world to plane coords - var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); - var orientationWorldInv = orientationWorld.clone().inverse(); - - // rotate original and current intersection into local coords - intersection.sub(rotOrigin); - intersection.applyQuaternion(orientationWorldInv); + }, { + key: "setPosition", + value: + /** + * Handle a user pose change for the position. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function setPosition(control, position) { + this.position.copy(position); + this.feedbackEvent('user-pose-change', control); + } + }, { + key: "setOrientation", + value: + /** + * Handle a user pose change for the orientation. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function setOrientation(control, orientation) { + orientation.normalize(); + this.quaternion.copy(orientation); + this.feedbackEvent('user-pose-change', control); + } + }, { + key: "onServerSetPose", + value: + /** + * Update the marker based when the pose is set from the server. + * + * @param event - the event that caused this + */ + function onServerSetPose(event) { + if (event !== undefined) { + // don't update while dragging + if (this.dragging) { + this.bufferedPoseEvent = event; + } else { + var pose = event.pose; + this.position.copy(pose.position); + this.quaternion.copy(pose.orientation); + this.updateMatrixWorld(true); + } + } + } + }, { + key: "dispose", + value: + /** + * Free memory of elements in this marker. + */ + function dispose() { + this.children.forEach(function (intMarkerControl) { + intMarkerControl.children.forEach(function (marker) { + marker.dispose(); + intMarkerControl.remove(marker); + }); + this.remove(intMarkerControl); + }.bind(this)); + } + }]); +}(Object3D); - var origIntersection = this.dragStart.event3d.intersection.point.clone(); - origIntersection.sub(rotOrigin); - origIntersection.applyQuaternion(orientationWorldInv); +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} - // compute relative 2d angle - var a1 = Math.atan2(intersection.y, intersection.z); - var a2 = Math.atan2(origIntersection.y, origIntersection.z); - var a = a2 - a1; +var eventemitter2 = {exports: {}}; - var rot = new THREE.Quaternion(); - rot.setFromAxisAngle(normal, a); +/*! + * EventEmitter2 + * https://github.com/hij1nx/EventEmitter2 + * + * Copyright (c) 2013 hij1nx + * Licensed under the MIT license. + */ +eventemitter2.exports; + +(function (module, exports) { +!function(undefined$1) { + var hasOwnProperty= Object.hasOwnProperty; + var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + var defaultMaxListeners = 10; + var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; + var symbolsSupported= typeof Symbol==='function'; + var reflectSupported= typeof Reflect === 'object'; + var setImmediateSupported= typeof setImmediate === 'function'; + var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; + var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ + var arr= Object.getOwnPropertyNames(obj); + arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); + return arr; + }) : Object.keys; + + function init() { + this._events = {}; + if (this._conf) { + configure.call(this, this._conf); + } + } + + function configure(conf) { + if (conf) { + this._conf = conf; + + conf.delimiter && (this.delimiter = conf.delimiter); + + if(conf.maxListeners!==undefined$1){ + this._maxListeners= conf.maxListeners; + } + + conf.wildcard && (this.wildcard = conf.wildcard); + conf.newListener && (this._newListener = conf.newListener); + conf.removeListener && (this._removeListener = conf.removeListener); + conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); + conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); + + if (this.wildcard) { + this.listenerTree = {}; + } + } + } + + function logPossibleMemoryLeak(count, eventName) { + var errorMsg = '(node) warning: possible EventEmitter memory ' + + 'leak detected. ' + count + ' listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.'; + + if(this.verboseMemoryLeak){ + errorMsg += ' Event name: ' + eventName + '.'; + } + + if(typeof process !== 'undefined' && process.emitWarning){ + var e = new Error(errorMsg); + e.name = 'MaxListenersExceededWarning'; + e.emitter = this; + e.count = count; + process.emitWarning(e); + } else { + console.error(errorMsg); + + if (console.trace){ + console.trace(); + } + } + } + + var toArray = function (a, b, c) { + var n = arguments.length; + switch (n) { + case 0: + return []; + case 1: + return [a]; + case 2: + return [a, b]; + case 3: + return [a, b, c]; + default: + var arr = new Array(n); + while (n--) { + arr[n] = arguments[n]; + } + return arr; + } + }; + + function toObject(keys, values) { + var obj = {}; + var key; + var len = keys.length; + var valuesCount = values ? value.length : 0; + for (var i = 0; i < len; i++) { + key = keys[i]; + obj[key] = i < valuesCount ? values[i] : undefined$1; + } + return obj; + } + + function TargetObserver(emitter, target, options) { + this._emitter = emitter; + this._target = target; + this._listeners = {}; + this._listenersCount = 0; + + var on, off; + + if (options.on || options.off) { + on = options.on; + off = options.off; + } + + if (target.addEventListener) { + on = target.addEventListener; + off = target.removeEventListener; + } else if (target.addListener) { + on = target.addListener; + off = target.removeListener; + } else if (target.on) { + on = target.on; + off = target.off; + } + + if (!on && !off) { + throw Error('target does not implement any known event API'); + } + + if (typeof on !== 'function') { + throw TypeError('on method must be a function'); + } + + if (typeof off !== 'function') { + throw TypeError('off method must be a function'); + } + + this._on = on; + this._off = off; + + var _observers= emitter._observers; + if(_observers){ + _observers.push(this); + }else { + emitter._observers= [this]; + } + } + + Object.assign(TargetObserver.prototype, { + subscribe: function(event, localEvent, reducer){ + var observer= this; + var target= this._target; + var emitter= this._emitter; + var listeners= this._listeners; + var handler= function(){ + var args= toArray.apply(null, arguments); + var eventObj= { + data: args, + name: localEvent, + original: event + }; + if(reducer){ + var result= reducer.call(target, eventObj); + if(result!==false){ + emitter.emit.apply(emitter, [eventObj.name].concat(args)); + } + return; + } + emitter.emit.apply(emitter, [localEvent].concat(args)); + }; + + + if(listeners[event]){ + throw Error('Event \'' + event + '\' is already listening'); + } + + this._listenersCount++; + + if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ + + this._onNewListener = function (_event) { + if (_event === localEvent && listeners[event] === null) { + listeners[event] = handler; + observer._on.call(target, event, handler); + } + }; + + emitter.on('newListener', this._onNewListener); + + this._onRemoveListener= function(_event){ + if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ + listeners[event]= null; + observer._off.call(target, event, handler); + } + }; + + listeners[event]= null; + + emitter.on('removeListener', this._onRemoveListener); + }else { + listeners[event]= handler; + observer._on.call(target, event, handler); + } + }, + + unsubscribe: function(event){ + var observer= this; + var listeners= this._listeners; + var emitter= this._emitter; + var handler; + var events; + var off= this._off; + var target= this._target; + var i; + + if(event && typeof event!=='string'){ + throw TypeError('event must be a string'); + } + + function clearRefs(){ + if(observer._onNewListener){ + emitter.off('newListener', observer._onNewListener); + emitter.off('removeListener', observer._onRemoveListener); + observer._onNewListener= null; + observer._onRemoveListener= null; + } + var index= findTargetIndex.call(emitter, observer); + emitter._observers.splice(index, 1); + } + + if(event){ + handler= listeners[event]; + if(!handler) return; + off.call(target, event, handler); + delete listeners[event]; + if(!--this._listenersCount){ + clearRefs(); + } + }else { + events= ownKeys(listeners); + i= events.length; + while(i-->0){ + event= events[i]; + off.call(target, event, listeners[event]); + } + this._listeners= {}; + this._listenersCount= 0; + clearRefs(); + } + } + }); + + function resolveOptions(options, schema, reducers, allowUnknown) { + var computedOptions = Object.assign({}, schema); + + if (!options) return computedOptions; + + if (typeof options !== 'object') { + throw TypeError('options must be an object') + } + + var keys = Object.keys(options); + var length = keys.length; + var option, value; + var reducer; + + function reject(reason) { + throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) + } + + for (var i = 0; i < length; i++) { + option = keys[i]; + if (!allowUnknown && !hasOwnProperty.call(schema, option)) { + throw Error('Unknown "' + option + '" option'); + } + value = options[option]; + if (value !== undefined$1) { + reducer = reducers[option]; + computedOptions[option] = reducer ? reducer(value, reject) : value; + } + } + return computedOptions; + } + + function constructorReducer(value, reject) { + if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { + reject('value must be a constructor'); + } + return value; + } + + function makeTypeReducer(types) { + var message= 'value must be type of ' + types.join('|'); + var len= types.length; + var firstType= types[0]; + var secondType= types[1]; + + if (len === 1) { + return function (v, reject) { + if (typeof v === firstType) { + return v; + } + reject(message); + } + } + + if (len === 2) { + return function (v, reject) { + var kind= typeof v; + if (kind === firstType || kind === secondType) return v; + reject(message); + } + } + + return function (v, reject) { + var kind = typeof v; + var i = len; + while (i-- > 0) { + if (kind === types[i]) return v; + } + reject(message); + } + } + + var functionReducer= makeTypeReducer(['function']); + + var objectFunctionReducer= makeTypeReducer(['object', 'function']); + + function makeCancelablePromise(Promise, executor, options) { + var isCancelable; + var callbacks; + var timer= 0; + var subscriptionClosed; + + var promise = new Promise(function (resolve, reject, onCancel) { + options= resolveOptions(options, { + timeout: 0, + overload: false + }, { + timeout: function(value, reject){ + value*= 1; + if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { + reject('timeout must be a positive number'); + } + return value; + } + }); + + isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; + + function cleanup() { + if (callbacks) { + callbacks = null; + } + if (timer) { + clearTimeout(timer); + timer = 0; + } + } + + var _resolve= function(value){ + cleanup(); + resolve(value); + }; + + var _reject= function(err){ + cleanup(); + reject(err); + }; + + if (isCancelable) { + executor(_resolve, _reject, onCancel); + } else { + callbacks = [function(reason){ + _reject(reason || Error('canceled')); + }]; + executor(_resolve, _reject, function (cb) { + if (subscriptionClosed) { + throw Error('Unable to subscribe on cancel event asynchronously') + } + if (typeof cb !== 'function') { + throw TypeError('onCancel callback must be a function'); + } + callbacks.push(cb); + }); + subscriptionClosed= true; + } + + if (options.timeout > 0) { + timer= setTimeout(function(){ + var reason= Error('timeout'); + reason.code = 'ETIMEDOUT'; + timer= 0; + promise.cancel(reason); + reject(reason); + }, options.timeout); + } + }); + + if (!isCancelable) { + promise.cancel = function (reason) { + if (!callbacks) { + return; + } + var length = callbacks.length; + for (var i = 1; i < length; i++) { + callbacks[i](reason); + } + // internal callback to reject the promise + callbacks[0](reason); + callbacks = null; + }; + } + + return promise; + } + + function findTargetIndex(observer) { + var observers = this._observers; + if(!observers){ + return -1; + } + var len = observers.length; + for (var i = 0; i < len; i++) { + if (observers[i]._target === observer) return i; + } + return -1; + } + + // Attention, function return type now is array, always ! + // It has zero elements if no any matches found and one or more + // elements (leafs) if there are matches + // + function searchListenerTree(handlers, type, tree, i, typeLength) { + if (!tree) { + return null; + } + + if (i === 0) { + var kind = typeof type; + if (kind === 'string') { + var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; + if ((n = type.indexOf(delimiter)) !== -1) { + ns = new Array(5); + do { + ns[l++] = type.slice(j, n); + j = n + dl; + } while ((n = type.indexOf(delimiter, j)) !== -1); + + ns[l++] = type.slice(j); + type = ns; + typeLength = l; + } else { + type = [type]; + typeLength = 1; + } + } else if (kind === 'object') { + typeLength = type.length; + } else { + type = [type]; + typeLength = 1; + } + } + + var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], + nextType = type[i + 1], branches, _listeners; + + if (i === typeLength) { + // + // If at the end of the event(s) list and the tree has listeners + // invoke those listeners. + // + + if(tree._listeners) { + if (typeof tree._listeners === 'function') { + handlers && handlers.push(tree._listeners); + listeners = [tree]; + } else { + handlers && handlers.push.apply(handlers, tree._listeners); + listeners = [tree]; + } + } + } else { + + if (currentType === '*') { + // + // If the event emitted is '*' at this part + // or there is a concrete match at this patch + // + branches = ownKeys(tree); + n = branches.length; + while (n-- > 0) { + branch = branches[n]; + if (branch !== '_listeners') { + _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + } + return listeners; + } else if (currentType === '**') { + endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); + if (endReached && tree._listeners) { + // The next element has a _listeners, add it to the handlers. + listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); + } + + branches = ownKeys(tree); + n = branches.length; + while (n-- > 0) { + branch = branches[n]; + if (branch !== '_listeners') { + if (branch === '*' || branch === '**') { + if (tree[branch]._listeners && !endReached) { + _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); + } else if (branch === nextType) { + _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); + } else { + // No match on this one, shift into the tree but not in the type array. + _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); + } + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + } + return listeners; + } else if (tree[currentType]) { + listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); + } + } + + xTree = tree['*']; + if (xTree) { + // + // If the listener tree will allow any match for this part, + // then recursively explore all branches of the tree + // + searchListenerTree(handlers, type, xTree, i + 1, typeLength); + } + + xxTree = tree['**']; + if (xxTree) { + if (i < typeLength) { + if (xxTree._listeners) { + // If we have a listener on a '**', it will catch all, so add its handler. + searchListenerTree(handlers, type, xxTree, typeLength, typeLength); + } + + // Build arrays of matching next branches and others. + branches= ownKeys(xxTree); + n= branches.length; + while(n-->0){ + branch= branches[n]; + if (branch !== '_listeners') { + if (branch === nextType) { + // We know the next element will match, so jump twice. + searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); + } else if (branch === currentType) { + // Current node matches, move into the tree. + searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); + } else { + isolatedBranch = {}; + isolatedBranch[branch] = xxTree[branch]; + searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); + } + } + } + } else if (xxTree._listeners) { + // We have reached the end and still on a '**' + searchListenerTree(handlers, type, xxTree, typeLength, typeLength); + } else if (xxTree['*'] && xxTree['*']._listeners) { + searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); + } + } + + return listeners; + } + + function growListenerTree(type, listener, prepend) { + var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; + + if(typeof type==='string') { + if ((i = type.indexOf(delimiter)) !== -1) { + ns = new Array(5); + do { + ns[len++] = type.slice(j, i); + j = i + dl; + } while ((i = type.indexOf(delimiter, j)) !== -1); + + ns[len++] = type.slice(j); + }else { + ns= [type]; + len= 1; + } + }else { + ns= type; + len= type.length; + } + + // + // Looks for two consecutive '**', if so, don't add the event at all. + // + if (len > 1) { + for (i = 0; i + 1 < len; i++) { + if (ns[i] === '**' && ns[i + 1] === '**') { + return; + } + } + } + + + + var tree = this.listenerTree, name; + + for (i = 0; i < len; i++) { + name = ns[i]; + + tree = tree[name] || (tree[name] = {}); + + if (i === len - 1) { + if (!tree._listeners) { + tree._listeners = listener; + } else { + if (typeof tree._listeners === 'function') { + tree._listeners = [tree._listeners]; + } + + if (prepend) { + tree._listeners.unshift(listener); + } else { + tree._listeners.push(listener); + } + + if ( + !tree._listeners.warned && + this._maxListeners > 0 && + tree._listeners.length > this._maxListeners + ) { + tree._listeners.warned = true; + logPossibleMemoryLeak.call(this, tree._listeners.length, name); + } + } + return true; + } + } + + return true; + } + + function collectTreeEvents(tree, events, root, asArray){ + var branches= ownKeys(tree); + var i= branches.length; + var branch, branchName, path; + var hasListeners= tree['_listeners']; + var isArrayPath; + + while(i-->0){ + branchName= branches[i]; + + branch= tree[branchName]; + + if(branchName==='_listeners'){ + path= root; + }else { + path = root ? root.concat(branchName) : [branchName]; + } + + isArrayPath= asArray || typeof branchName==='symbol'; + + hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); + + if(typeof branch==='object'){ + collectTreeEvents.call(this, branch, events, path, isArrayPath); + } + } + + return events; + } + + function recursivelyGarbageCollect(root) { + var keys = ownKeys(root); + var i= keys.length; + var obj, key, flag; + while(i-->0){ + key = keys[i]; + obj = root[key]; + + if(obj){ + flag= true; + if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ + delete root[key]; + } + } + } + + return flag; + } + + function Listener(emitter, event, listener){ + this.emitter= emitter; + this.event= event; + this.listener= listener; + } + + Listener.prototype.off= function(){ + this.emitter.off(this.event, this.listener); + return this; + }; + + function setupListener(event, listener, options){ + if (options === true) { + promisify = true; + } else if (options === false) { + async = true; + } else { + if (!options || typeof options !== 'object') { + throw TypeError('options should be an object or true'); + } + var async = options.async; + var promisify = options.promisify; + var nextTick = options.nextTick; + var objectify = options.objectify; + } + + if (async || nextTick || promisify) { + var _listener = listener; + var _origin = listener._origin || listener; + + if (nextTick && !nextTickSupported) { + throw Error('process.nextTick is not supported'); + } + + if (promisify === undefined$1) { + promisify = listener.constructor.name === 'AsyncFunction'; + } + + listener = function () { + var args = arguments; + var context = this; + var event = this.event; + + return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { + _setImmediate(resolve); + }).then(function () { + context.event = event; + return _listener.apply(context, args) + })) : (nextTick ? process.nextTick : _setImmediate)(function () { + context.event = event; + _listener.apply(context, args); + }); + }; + + listener._async = true; + listener._origin = _origin; + } + + return [listener, objectify? new Listener(this, event, listener): this]; + } + + function EventEmitter(conf) { + this._events = {}; + this._newListener = false; + this._removeListener = false; + this.verboseMemoryLeak = false; + configure.call(this, conf); + } + + EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property + + EventEmitter.prototype.listenTo= function(target, events, options){ + if(typeof target!=='object'){ + throw TypeError('target musts be an object'); + } + + var emitter= this; + + options = resolveOptions(options, { + on: undefined$1, + off: undefined$1, + reducers: undefined$1 + }, { + on: functionReducer, + off: functionReducer, + reducers: objectFunctionReducer + }); + + function listen(events){ + if(typeof events!=='object'){ + throw TypeError('events must be an object'); + } + + var reducers= options.reducers; + var index= findTargetIndex.call(emitter, target); + var observer; + + if(index===-1){ + observer= new TargetObserver(emitter, target, options); + }else { + observer= emitter._observers[index]; + } + + var keys= ownKeys(events); + var len= keys.length; + var event; + var isSingleReducer= typeof reducers==='function'; + + for(var i=0; i 0) { + observer = observers[i]; + if (!target || observer._target === target) { + observer.unsubscribe(event); + matched= true; + } + } + + return matched; + }; + + // By default EventEmitters will print a warning if more than + // 10 listeners are added to it. This is a useful default which + // helps finding memory leaks. + // + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + + EventEmitter.prototype.delimiter = '.'; + + EventEmitter.prototype.setMaxListeners = function(n) { + if (n !== undefined$1) { + this._maxListeners = n; + if (!this._conf) this._conf = {}; + this._conf.maxListeners = n; + } + }; + + EventEmitter.prototype.getMaxListeners = function() { + return this._maxListeners; + }; + + EventEmitter.prototype.event = ''; + + EventEmitter.prototype.once = function(event, fn, options) { + return this._once(event, fn, false, options); + }; + + EventEmitter.prototype.prependOnceListener = function(event, fn, options) { + return this._once(event, fn, true, options); + }; + + EventEmitter.prototype._once = function(event, fn, prepend, options) { + return this._many(event, 1, fn, prepend, options); + }; + + EventEmitter.prototype.many = function(event, ttl, fn, options) { + return this._many(event, ttl, fn, false, options); + }; + + EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { + return this._many(event, ttl, fn, true, options); + }; + + EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { + var self = this; + + if (typeof fn !== 'function') { + throw new Error('many only accepts instances of Function'); + } + + function listener() { + if (--ttl === 0) { + self.off(event, listener); + } + return fn.apply(this, arguments); + } + + listener._origin = fn; + + return this._on(event, listener, prepend, options); + }; + + EventEmitter.prototype.emit = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0], ns, wildcard= this.wildcard; + var args,l,i,j, containsSymbol; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { + return false; + } + } + + if (wildcard) { + ns= type; + if(type!=='newListener' && type!=='removeListener'){ + if (typeof type === 'object') { + l = type.length; + if (symbolsSupported) { + for (i = 0; i < l; i++) { + if (typeof type[i] === 'symbol') { + containsSymbol = true; + break; + } + } + } + if (!containsSymbol) { + type = type.join(this.delimiter); + } + } + } + } + + var al = arguments.length; + var handler; + + if (this._all && this._all.length) { + handler = this._all.slice(); + + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this, type); + break; + case 2: + handler[i].call(this, type, arguments[1]); + break; + case 3: + handler[i].call(this, type, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, arguments); + } + } + } + + if (wildcard) { + handler = []; + searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); + } else { + handler = this._events[type]; + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + handler.apply(this, args); + } + return true; + } else if (handler) { + // need to make copy of handlers because list can change in the middle + // of emit call + handler = handler.slice(); + } + } + + if (handler && handler.length) { + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this); + break; + case 2: + handler[i].call(this, arguments[1]); + break; + case 3: + handler[i].call(this, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, args); + } + } + return true; + } else if (!this.ignoreErrors && !this._all && type === 'error') { + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + } + + return !!this._all; + }; + + EventEmitter.prototype.emitAsync = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; + var args,l,i,j; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { return Promise.resolve([false]); } + } + + if (wildcard) { + ns= type; + if(type!=='newListener' && type!=='removeListener'){ + if (typeof type === 'object') { + l = type.length; + if (symbolsSupported) { + for (i = 0; i < l; i++) { + if (typeof type[i] === 'symbol') { + containsSymbol = true; + break; + } + } + } + if (!containsSymbol) { + type = type.join(this.delimiter); + } + } + } + } + + var promises= []; + + var al = arguments.length; + var handler; + + if (this._all) { + for (i = 0, l = this._all.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(this._all[i].call(this, type)); + break; + case 2: + promises.push(this._all[i].call(this, type, arguments[1])); + break; + case 3: + promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); + break; + default: + promises.push(this._all[i].apply(this, arguments)); + } + } + } + + if (wildcard) { + handler = []; + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } else { + handler = this._events[type]; + } + + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + promises.push(handler.call(this)); + break; + case 2: + promises.push(handler.call(this, arguments[1])); + break; + case 3: + promises.push(handler.call(this, arguments[1], arguments[2])); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + promises.push(handler.apply(this, args)); + } + } else if (handler && handler.length) { + handler = handler.slice(); + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(handler[i].call(this)); + break; + case 2: + promises.push(handler[i].call(this, arguments[1])); + break; + case 3: + promises.push(handler[i].call(this, arguments[1], arguments[2])); + break; + default: + promises.push(handler[i].apply(this, args)); + } + } + } else if (!this.ignoreErrors && !this._all && type === 'error') { + if (arguments[1] instanceof Error) { + return Promise.reject(arguments[1]); // Unhandled 'error' event + } else { + return Promise.reject("Uncaught, unspecified 'error' event."); + } + } + + return Promise.all(promises); + }; + + EventEmitter.prototype.on = function(type, listener, options) { + return this._on(type, listener, false, options); + }; + + EventEmitter.prototype.prependListener = function(type, listener, options) { + return this._on(type, listener, true, options); + }; + + EventEmitter.prototype.onAny = function(fn) { + return this._onAny(fn, false); + }; + + EventEmitter.prototype.prependAny = function(fn) { + return this._onAny(fn, true); + }; + + EventEmitter.prototype.addListener = EventEmitter.prototype.on; + + EventEmitter.prototype._onAny = function(fn, prepend){ + if (typeof fn !== 'function') { + throw new Error('onAny only accepts instances of Function'); + } + + if (!this._all) { + this._all = []; + } + + // Add the function to the event listener collection. + if(prepend){ + this._all.unshift(fn); + }else { + this._all.push(fn); + } + + return this; + }; + + EventEmitter.prototype._on = function(type, listener, prepend, options) { + if (typeof type === 'function') { + this._onAny(type, listener); + return this; + } + + if (typeof listener !== 'function') { + throw new Error('on only accepts instances of Function'); + } + this._events || init.call(this); + + var returnValue= this, temp; + + if (options !== undefined$1) { + temp = setupListener.call(this, type, listener, options); + listener = temp[0]; + returnValue = temp[1]; + } + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + if (this._newListener) { + this.emit('newListener', type, listener); + } + + if (this.wildcard) { + growListenerTree.call(this, type, listener, prepend); + return returnValue; + } + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } else { + if (typeof this._events[type] === 'function') { + // Change to array. + this._events[type] = [this._events[type]]; + } + + // If we've already got an array, just add + if(prepend){ + this._events[type].unshift(listener); + }else { + this._events[type].push(listener); + } + + // Check for listener leak + if ( + !this._events[type].warned && + this._maxListeners > 0 && + this._events[type].length > this._maxListeners + ) { + this._events[type].warned = true; + logPossibleMemoryLeak.call(this, this._events[type].length, type); + } + } + + return returnValue; + }; + + EventEmitter.prototype.off = function(type, listener) { + if (typeof listener !== 'function') { + throw new Error('removeListener only takes instances of Function'); + } + + var handlers,leafs=[]; + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + if(!leafs) return this; + } else { + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events[type]) return this; + handlers = this._events[type]; + leafs.push({_listeners:handlers}); + } + + for (var iLeaf=0; iLeaf 0) { + fns = this._all; + for(i = 0, l = fns.length; i < l; i++) { + if(fn === fns[i]) { + fns.splice(i, 1); + if (this._removeListener) + this.emit("removeListenerAny", fn); + return this; + } + } + } else { + fns = this._all; + if (this._removeListener) { + for(i = 0, l = fns.length; i < l; i++) + this.emit("removeListenerAny", fns[i]); + } + this._all = []; + } + return this; + }; + + EventEmitter.prototype.removeListener = EventEmitter.prototype.off; + + EventEmitter.prototype.removeAllListeners = function (type) { + if (type === undefined$1) { + !this._events || init.call(this); + return this; + } + + if (this.wildcard) { + var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; + if (!leafs) return this; + for (i = 0; i < leafs.length; i++) { + leaf = leafs[i]; + leaf._listeners = null; + } + this.listenerTree && recursivelyGarbageCollect(this.listenerTree); + } else if (this._events) { + this._events[type] = null; + } + return this; + }; + + EventEmitter.prototype.listeners = function (type) { + var _events = this._events; + var keys, listeners, allListeners; + var i; + var listenerTree; + + if (type === undefined$1) { + if (this.wildcard) { + throw Error('event name required for wildcard emitter'); + } + + if (!_events) { + return []; + } + + keys = ownKeys(_events); + i = keys.length; + allListeners = []; + while (i-- > 0) { + listeners = _events[keys[i]]; + if (typeof listeners === 'function') { + allListeners.push(listeners); + } else { + allListeners.push.apply(allListeners, listeners); + } + } + return allListeners; + } else { + if (this.wildcard) { + listenerTree= this.listenerTree; + if(!listenerTree) return []; + var handlers = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handlers, ns, listenerTree, 0); + return handlers; + } + + if (!_events) { + return []; + } + + listeners = _events[type]; + + if (!listeners) { + return []; + } + return typeof listeners === 'function' ? [listeners] : listeners; + } + }; + + EventEmitter.prototype.eventNames = function(nsAsArray){ + var _events= this._events; + return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); + }; + + EventEmitter.prototype.listenerCount = function(type) { + return this.listeners(type).length; + }; + + EventEmitter.prototype.hasListeners = function (type) { + if (this.wildcard) { + var handlers = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); + return handlers.length > 0; + } + + var _events = this._events; + var _all = this._all; + + return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); + }; + + EventEmitter.prototype.listenersAny = function() { + + if(this._all) { + return this._all; + } + else { + return []; + } + + }; + + EventEmitter.prototype.waitFor = function (event, options) { + var self = this; + var type = typeof options; + if (type === 'number') { + options = {timeout: options}; + } else if (type === 'function') { + options = {filter: options}; + } + + options= resolveOptions(options, { + timeout: 0, + filter: undefined$1, + handleError: false, + Promise: Promise, + overload: false + }, { + filter: functionReducer, + Promise: constructorReducer + }); + + return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { + function listener() { + var filter= options.filter; + if (filter && !filter.apply(self, arguments)) { + return; + } + self.off(event, listener); + if (options.handleError) { + var err = arguments[0]; + err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); + } else { + resolve(toArray.apply(null, arguments)); + } + } + + onCancel(function(){ + self.off(event, listener); + }); + + self._on(event, listener, false); + }, { + timeout: options.timeout, + overload: options.overload + }) + }; + + function once(emitter, name, options) { + options= resolveOptions(options, { + Promise: Promise, + timeout: 0, + overload: false + }, { + Promise: constructorReducer + }); + + var _Promise= options.Promise; + + return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ + var handler; + if (typeof emitter.addEventListener === 'function') { + handler= function () { + resolve(toArray.apply(null, arguments)); + }; + + onCancel(function(){ + emitter.removeEventListener(name, handler); + }); + + emitter.addEventListener( + name, + handler, + {once: true} + ); + return; + } + + var eventListener = function(){ + errorListener && emitter.removeListener('error', errorListener); + resolve(toArray.apply(null, arguments)); + }; + + var errorListener; + + if (name !== 'error') { + errorListener = function (err){ + emitter.removeListener(name, eventListener); + reject(err); + }; + + emitter.once('error', errorListener); + } + + onCancel(function(){ + errorListener && emitter.removeListener('error', errorListener); + emitter.removeListener(name, eventListener); + }); + + emitter.once(name, eventListener); + }, { + timeout: options.timeout, + overload: options.overload + }); + } + + var prototype= EventEmitter.prototype; + + Object.defineProperties(EventEmitter, { + defaultMaxListeners: { + get: function () { + return prototype._maxListeners; + }, + set: function (n) { + if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { + throw TypeError('n must be a non-negative number') + } + prototype._maxListeners = n; + }, + enumerable: true + }, + once: { + value: once, + writable: true, + configurable: true + } + }); + + Object.defineProperties(prototype, { + _maxListeners: { + value: defaultMaxListeners, + writable: true, + configurable: true + }, + _observers: {value: null, writable: true, configurable: true} + }); + + if (typeof undefined$1 === 'function' && undefined$1.amd) { + // AMD. Register as an anonymous module. + undefined$1(function() { + return EventEmitter; + }); + } else { + // CommonJS + module.exports = EventEmitter; + } + }(); +} (eventemitter2, eventemitter2.exports)); + +var eventemitter2Exports = eventemitter2.exports; +var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); + +function _callSuper$q(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$q() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$q() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$q = function _isNativeReflectConstruct() { return !!t; })(); } - // rotate - this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ - // offset from drag start position - event3d.stopPropagation(); - } - }; +var InteractiveMarkerHandle = /*#__PURE__*/function (_EventEmitter) { /** - * Dispatch the given event type. + * Handle with signals for a single interactive marker. * - * @param type - the type of event - * @param control - the control to use - */ - InteractiveMarker.prototype.feedbackEvent = function feedbackEvent (type, control) { - this.dispatchEvent({ - type : type, - position : this.position.clone(), - orientation : this.quaternion.clone(), - controlName : control.name - }); - }; - /** - * Start a drag action. + * Emits the following events: * - * @param control - the control to use - * @param event3d - the event that caused this + * * 'pose' - emitted when a new pose comes from the server + * + * @constructor + * @param options - object with following keys: + * + * * message - the interactive marker message + * * feedbackTopic - the ROSLIB.Topic associated with the feedback + * * tfClient - a handle to the TF client to use + * * menuFontSize (optional) - the menu font size */ - InteractiveMarker.prototype.startDrag = function startDrag (control, event3d) { - if (event3d.domEvent.button === 0) { - event3d.stopPropagation(); + function InteractiveMarkerHandle(options) { + var _this; + _classCallCheck(this, InteractiveMarkerHandle); + _this = _callSuper$q(this, InteractiveMarkerHandle); + options = options || {}; + _this.message = options.message; + _this.feedbackTopic = options.feedbackTopic; + _this.tfClient = options.tfClient; + _this.menuFontSize = options.menuFontSize || '0.8em'; + _this.name = _this.message.name; + _this.header = _this.message.header; + _this.controls = _this.message.controls; + _this.menuEntries = _this.message.menu_entries; + _this.dragging = false; + _this.timeoutHandle = null; + _this.tfTransform = new ROSLIB.Transform(); + _this.pose = new ROSLIB.Pose(); + _this.setPoseFromClientBound = _this.setPoseFromClient.bind(_this); + _this.onMouseDownBound = _this.onMouseDown.bind(_this); + _this.onMouseUpBound = _this.onMouseUp.bind(_this); + _this.onButtonClickBound = _this.onButtonClick.bind(_this); + _this.onMenuSelectBound = _this.onMenuSelect.bind(_this); + + // start by setting the pose + _this.setPoseFromServer(_this.message.pose); + _this.tfUpdateBound = _this.tfUpdate.bind(_this); + return _this; + } + _inherits(InteractiveMarkerHandle, _EventEmitter); + return _createClass(InteractiveMarkerHandle, [{ + key: "subscribeTf", + value: + /** + * Subscribe to the TF associated with this interactive marker. + */ + function subscribeTf() { + // subscribe to tf updates if frame-fixed + if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { + this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + } + } + }, { + key: "unsubscribeTf", + value: function unsubscribeTf() { + this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); + } + }, { + key: "emitServerPoseUpdate", + value: + /** + * Emit the new pose that has come from the server. + */ + function emitServerPoseUpdate() { + var poseTransformed = new ROSLIB.Pose(this.pose); + poseTransformed.applyTransform(this.tfTransform); + this.emit('pose', poseTransformed); + } + }, { + key: "setPoseFromServer", + value: + /** + * Update the pose based on the pose given by the server. + * + * @param poseMsg - the pose given by the server + */ + function setPoseFromServer(poseMsg) { + this.pose = new ROSLIB.Pose(poseMsg); + this.emitServerPoseUpdate(); + } + }, { + key: "tfUpdate", + value: + /** + * Update the pose based on the TF given by the server. + * + * @param transformMsg - the TF given by the server + */ + function tfUpdate(transformMsg) { + this.tfTransform = new ROSLIB.Transform(transformMsg); + this.emitServerPoseUpdate(); + } + }, { + key: "setPoseFromClient", + value: + /** + * Set the pose from the client based on the given event. + * + * @param event - the event to base the change off of + */ + function setPoseFromClient(event) { + // apply the transform + this.pose = new ROSLIB.Pose(event); + var inv = this.tfTransform.clone(); + inv.rotation.invert(); + inv.translation.multiplyQuaternion(inv.rotation); + inv.translation.x *= -1; + inv.translation.y *= -1; + inv.translation.z *= -1; + this.pose.applyTransform(inv); + + // send feedback to the server + this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); + + // keep sending pose feedback until the mouse goes up + if (this.dragging) { + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); + } + this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); + } + } + }, { + key: "onButtonClick", + value: + /** + * Send the button click feedback to the server. + * + * @param event - the event associated with the button click + */ + function onButtonClick(event) { + this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, event.controlName); + } + }, { + key: "onMouseDown", + value: + /** + * Send the mousedown feedback to the server. + * + * @param event - the event associated with the mousedown + */ + function onMouseDown(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); this.dragging = true; - this.updateMatrixWorld(true); - var scale = new THREE.Vector3(); - this.matrixWorld - .decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); - this.dragStart.position = this.position.clone(); - this.dragStart.orientation = this.quaternion.clone(); - this.dragStart.event3d = event3d; - - this.feedbackEvent('user-mousedown', control); } - }; - /** - * Stop a drag action. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.stopDrag = function stopDrag (control, event3d) { - if (event3d.domEvent.button === 0) { - event3d.stopPropagation(); + }, { + key: "onMouseUp", + value: + /** + * Send the mouseup feedback to the server. + * + * @param event - the event associated with the mouseup + */ + function onMouseUp(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); this.dragging = false; - this.dragStart.event3d = {}; - this.onServerSetPose(this.bufferedPoseEvent); - this.bufferedPoseEvent = undefined; - - this.feedbackEvent('user-mouseup', control); - } - }; - /** - * Handle a button click. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.buttonClick = function buttonClick (control, event3d) { - event3d.stopPropagation(); - this.feedbackEvent('user-button-click', control); - }; - /** - * Handle a user pose change for the position. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.setPosition = function setPosition (control, position) { - this.position.copy(position); - this.feedbackEvent('user-pose-change', control); - }; - /** - * Handle a user pose change for the orientation. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - InteractiveMarker.prototype.setOrientation = function setOrientation (control, orientation) { - orientation.normalize(); - this.quaternion.copy(orientation); - this.feedbackEvent('user-pose-change', control); - }; - /** - * Update the marker based when the pose is set from the server. - * - * @param event - the event that caused this - */ - InteractiveMarker.prototype.onServerSetPose = function onServerSetPose (event) { - if (event !== undefined) { - // don't update while dragging - if (this.dragging) { - this.bufferedPoseEvent = event; - } else { - var pose = event.pose; - this.position.copy(pose.position); - this.quaternion.copy(pose.orientation); - this.updateMatrixWorld(true); + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); } } - }; - /** - * Free memory of elements in this marker. - */ - InteractiveMarker.prototype.dispose = function dispose () { - this.children.forEach(function(intMarkerControl) { - intMarkerControl.children.forEach(function(marker) { - marker.dispose(); - intMarkerControl.remove(marker); - }); - this.remove(intMarkerControl); - }.bind(this)); - }; - - return InteractiveMarker; -}(THREE.Object3D)); + }, { + key: "onMenuSelect", + value: + /** + * Send the menu select feedback to the server. + * + * @param event - the event associated with the menu select + */ + function onMenuSelect(event) { + this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); + } + }, { + key: "sendFeedback", + value: + /** + * Send feedback to the interactive marker server. + * + * @param eventType - the type of event that happened + * @param clickPosition (optional) - the position in ROS space the click happened + * @param menuEntryID (optional) - the menu entry ID that is associated + * @param controlName - the name of the control + */ + function sendFeedback(eventType, clickPosition, menuEntryID, controlName) { + // check for the click position + var mousePointValid = clickPosition !== undefined; + clickPosition = clickPosition || { + x: 0, + y: 0, + z: 0 + }; + var feedback = { + header: this.header, + client_id: this.clientID, + marker_name: this.name, + control_name: controlName, + event_type: eventType, + pose: this.pose, + mouse_point: clickPosition, + mouse_point_valid: mousePointValid, + menu_entry_id: menuEntryID + }; + this.feedbackTopic.publish(feedback); + } + }]); +}(EventEmitter2); /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var InteractiveMarkerHandle = /*@__PURE__*/(function (EventEmitter3) { - function InteractiveMarkerHandle(options) { - EventEmitter3.call(this); +var InteractiveMarkerClient = /*#__PURE__*/function () { + /** + * A client for an interactive marker topic. + * + * @constructor + * @param options - object with following keys: + * + * * ros - a handle to the ROS connection + * * tfClient - a handle to the TF client + * * topic (optional) - the topic to subscribe to, like '/basic_controls', if not provided use subscribe() to start message receiving + * * path (optional) - the base path to any meshes that will be loaded + * * camera - the main camera associated with the viewer for this marker client + * * rootObject (optional) - the root THREE 3D object to render to + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + * * menuFontSize (optional) - the menu font size + */ + function InteractiveMarkerClient(options) { + _classCallCheck(this, InteractiveMarkerClient); options = options || {}; - this.message = options.message; - this.feedbackTopic = options.feedbackTopic; + this.ros = options.ros; this.tfClient = options.tfClient; + this.topicName = options.topic; + this.path = options.path || '/'; + this.camera = options.camera; + this.rootObject = options.rootObject || new Object3D(); + this.loader = options.loader; this.menuFontSize = options.menuFontSize || '0.8em'; - this.name = this.message.name; - this.header = this.message.header; - this.controls = this.message.controls; - this.menuEntries = this.message.menu_entries; - this.dragging = false; - this.timeoutHandle = null; - this.tfTransform = new ROSLIB.Transform(); - this.pose = new ROSLIB.Pose(); - - this.setPoseFromClientBound = this.setPoseFromClient.bind(this); - this.onMouseDownBound = this.onMouseDown.bind(this); - this.onMouseUpBound = this.onMouseUp.bind(this); - this.onButtonClickBound = this.onButtonClick.bind(this); - this.onMenuSelectBound = this.onMenuSelect.bind(this); - - // start by setting the pose - this.setPoseFromServer(this.message.pose); - this.tfUpdateBound = this.tfUpdate.bind(this); + this.interactiveMarkers = {}; + this.updateTopic = null; + this.feedbackTopic = null; + this.processUpdateBound = this.processUpdate.bind(this); + + // check for an initial topic + if (this.topicName) { + this.subscribe(this.topicName); + } } - - if ( EventEmitter3 ) InteractiveMarkerHandle.__proto__ = EventEmitter3; - InteractiveMarkerHandle.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - InteractiveMarkerHandle.prototype.constructor = InteractiveMarkerHandle; - /** - * Subscribe to the TF associated with this interactive marker. - */ - InteractiveMarkerHandle.prototype.subscribeTf = function subscribeTf () { - // subscribe to tf updates if frame-fixed - if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { - this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + return _createClass(InteractiveMarkerClient, [{ + key: "subscribe", + value: + /** + * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. + * + * @param topic - the topic to subscribe to, like '/basic_controls' + */ + function subscribe(topic) { + // unsubscribe to the other topics + this.unsubscribe(); + this.updateTopic = new ROSLIB.Topic({ + ros: this.ros, + name: topic + '/tunneled/update', + messageType: 'visualization_msgs/InteractiveMarkerUpdate', + compression: 'png' + }); + this.updateTopic.subscribe(this.processUpdateBound); + this.feedbackTopic = new ROSLIB.Topic({ + ros: this.ros, + name: topic + '/feedback', + messageType: 'visualization_msgs/InteractiveMarkerFeedback', + compression: 'png' + }); + this.feedbackTopic.advertise(); + this.initService = new ROSLIB.Service({ + ros: this.ros, + name: topic + '/tunneled/get_init', + serviceType: 'demo_interactive_markers/GetInit' + }); + var request = new ROSLIB.ServiceRequest({}); + this.initService.callService(request, this.processInit.bind(this)); } - }; - InteractiveMarkerHandle.prototype.unsubscribeTf = function unsubscribeTf () { - this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); - }; - /** - * Emit the new pose that has come from the server. - */ - InteractiveMarkerHandle.prototype.emitServerPoseUpdate = function emitServerPoseUpdate () { - var poseTransformed = new ROSLIB.Pose(this.pose); - poseTransformed.applyTransform(this.tfTransform); - this.emit('pose', poseTransformed); - }; - /** - * Update the pose based on the pose given by the server. - * - * @param poseMsg - the pose given by the server - */ - InteractiveMarkerHandle.prototype.setPoseFromServer = function setPoseFromServer (poseMsg) { - this.pose = new ROSLIB.Pose(poseMsg); - this.emitServerPoseUpdate(); - }; - /** - * Update the pose based on the TF given by the server. - * - * @param transformMsg - the TF given by the server - */ - InteractiveMarkerHandle.prototype.tfUpdate = function tfUpdate (transformMsg) { - this.tfTransform = new ROSLIB.Transform(transformMsg); - this.emitServerPoseUpdate(); - }; - /** - * Set the pose from the client based on the given event. - * - * @param event - the event to base the change off of - */ - InteractiveMarkerHandle.prototype.setPoseFromClient = function setPoseFromClient (event) { - // apply the transform - this.pose = new ROSLIB.Pose(event); - var inv = this.tfTransform.clone(); - inv.rotation.invert(); - inv.translation.multiplyQuaternion(inv.rotation); - inv.translation.x *= -1; - inv.translation.y *= -1; - inv.translation.z *= -1; - this.pose.applyTransform(inv); - - // send feedback to the server - this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); - - // keep sending pose feedback until the mouse goes up - if (this.dragging) { - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); + }, { + key: "unsubscribe", + value: + /** + * Unsubscribe from the current interactive marker topic. + */ + function unsubscribe() { + if (this.updateTopic) { + this.updateTopic.unsubscribe(this.processUpdateBound); } - this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); - } - }; - /** - * Send the button click feedback to the server. - * - * @param event - the event associated with the button click - */ - InteractiveMarkerHandle.prototype.onButtonClick = function onButtonClick (event) { - this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, - event.controlName); - }; - /** - * Send the mousedown feedback to the server. - * - * @param event - the event associated with the mousedown - */ - InteractiveMarkerHandle.prototype.onMouseDown = function onMouseDown (event) { - this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); - this.dragging = true; - }; - /** - * Send the mouseup feedback to the server. - * - * @param event - the event associated with the mouseup - */ - InteractiveMarkerHandle.prototype.onMouseUp = function onMouseUp (event) { - this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); - this.dragging = false; - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); + if (this.feedbackTopic) { + this.feedbackTopic.unadvertise(); + } + // erase all markers + for (var intMarkerName in this.interactiveMarkers) { + this.eraseIntMarker(intMarkerName); + } + this.interactiveMarkers = {}; } - }; - /** - * Send the menu select feedback to the server. - * - * @param event - the event associated with the menu select - */ - InteractiveMarkerHandle.prototype.onMenuSelect = function onMenuSelect (event) { - this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); - }; - /** - * Send feedback to the interactive marker server. - * - * @param eventType - the type of event that happened - * @param clickPosition (optional) - the position in ROS space the click happened - * @param menuEntryID (optional) - the menu entry ID that is associated - * @param controlName - the name of the control - */ - InteractiveMarkerHandle.prototype.sendFeedback = function sendFeedback (eventType, clickPosition, - menuEntryID, controlName) { - - // check for the click position - var mousePointValid = clickPosition !== undefined; - clickPosition = clickPosition || { - x : 0, - y : 0, - z : 0 - }; - - var feedback = { - header : this.header, - client_id : this.clientID, - marker_name : this.name, - control_name : controlName, - event_type : eventType, - pose : this.pose, - mouse_point : clickPosition, - mouse_point_valid : mousePointValid, - menu_entry_id : menuEntryID - }; - this.feedbackTopic.publish(feedback); - }; - - return InteractiveMarkerHandle; -}(EventEmitter3)); - -/** - * @fileOverview - * @author David Gossow - dgossow@willowgarage.com - */ - -var InteractiveMarkerClient = function InteractiveMarkerClient(options) { - options = options || {}; - this.ros = options.ros; - this.tfClient = options.tfClient; - this.topicName = options.topic; - this.path = options.path || '/'; - this.camera = options.camera; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.loader = options.loader; - this.menuFontSize = options.menuFontSize || '0.8em'; + }, { + key: "processInit", + value: + /** + * Process the given interactive marker initialization message. + * + * @param initMessage - the interactive marker initialization message to process + */ + function processInit(initMessage) { + var message = initMessage.msg; - this.interactiveMarkers = {}; - this.updateTopic = null; - this.feedbackTopic = null; - this.processUpdateBound = this.processUpdate.bind(this); + // erase any old markers + message.erases = []; + for (var intMarkerName in this.interactiveMarkers) { + message.erases.push(intMarkerName); + } + message.poses = []; - // check for an initial topic - if (this.topicName) { - this.subscribe(this.topicName); - } -}; -/** - * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. - * - * @param topic - the topic to subscribe to, like '/basic_controls' - */ -InteractiveMarkerClient.prototype.subscribe = function subscribe (topic) { - // unsubscribe to the other topics - this.unsubscribe(); - - this.updateTopic = new ROSLIB.Topic({ - ros : this.ros, - name : topic + '/tunneled/update', - messageType : 'visualization_msgs/InteractiveMarkerUpdate', - compression : 'png' - }); - this.updateTopic.subscribe(this.processUpdateBound); + // treat it as an update + this.processUpdate(message); + } + }, { + key: "processUpdate", + value: + /** + * Process the given interactive marker update message. + * + * @param initMessage - the interactive marker update message to process + */ + function processUpdate(message) { + // erase any markers + message.erases.forEach(function (name) { + this.eraseIntMarker(name); + }); - this.feedbackTopic = new ROSLIB.Topic({ - ros : this.ros, - name : topic + '/feedback', - messageType : 'visualization_msgs/InteractiveMarkerFeedback', - compression : 'png' - }); - this.feedbackTopic.advertise(); + // updates marker poses + message.poses.forEach(function (poseMessage) { + var marker = this.interactiveMarkers[poseMessage.name]; + if (marker) { + marker.setPoseFromServer(poseMessage.pose); + } + }); - this.initService = new ROSLIB.Service({ - ros : this.ros, - name : topic + '/tunneled/get_init', - serviceType : 'demo_interactive_markers/GetInit' - }); - var request = new ROSLIB.ServiceRequest({}); - this.initService.callService(request, this.processInit.bind(this)); -}; -/** - * Unsubscribe from the current interactive marker topic. - */ -InteractiveMarkerClient.prototype.unsubscribe = function unsubscribe () { - if (this.updateTopic) { - this.updateTopic.unsubscribe(this.processUpdateBound); - } - if (this.feedbackTopic) { - this.feedbackTopic.unadvertise(); - } - // erase all markers - for (var intMarkerName in this.interactiveMarkers) { - this.eraseIntMarker(intMarkerName); - } - this.interactiveMarkers = {}; -}; -/** - * Process the given interactive marker initialization message. - * - * @param initMessage - the interactive marker initialization message to process - */ -InteractiveMarkerClient.prototype.processInit = function processInit (initMessage) { - var message = initMessage.msg; + // add new markers + message.markers.forEach(function (msg) { + // get rid of anything with the same name + var oldhandle = this.interactiveMarkers[msg.name]; + if (oldhandle) { + this.eraseIntMarker(oldhandle.name); + } - // erase any old markers - message.erases = []; - for (var intMarkerName in this.interactiveMarkers) { - message.erases.push(intMarkerName); - } - message.poses = []; + // create the handle + var handle = new InteractiveMarkerHandle({ + message: msg, + feedbackTopic: this.feedbackTopic, + tfClient: this.tfClient, + menuFontSize: this.menuFontSize + }); + this.interactiveMarkers[msg.name] = handle; + + // create the actual marker + var intMarker = new InteractiveMarker({ + handle: handle, + camera: this.camera, + path: this.path, + loader: this.loader + }); + // add it to the scene + intMarker.name = msg.name; + this.rootObject.add(intMarker); + + // listen for any pose updates from the server + handle.on('pose', function (pose) { + intMarker.onServerSetPose({ + pose: pose + }); + }); - // treat it as an update - this.processUpdate(message); -}; -/** - * Process the given interactive marker update message. - * - * @param initMessage - the interactive marker update message to process - */ -InteractiveMarkerClient.prototype.processUpdate = function processUpdate (message) { - // erase any markers - message.erases.forEach(function(name) { - this.eraseIntMarker(name); - }); + // add bound versions of UI handlers + intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); + intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); + intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); + intMarker.addEventListener('user-button-click', handle.onButtonClickBound); + intMarker.addEventListener('menu-select', handle.onMenuSelectBound); - // updates marker poses - message.poses.forEach(function(poseMessage) { - var marker = this.interactiveMarkers[poseMessage.name]; - if (marker) { - marker.setPoseFromServer(poseMessage.pose); + // now listen for any TF changes + handle.subscribeTf(); + }); } - }); - - // add new markers - message.markers.forEach(function(msg) { - // get rid of anything with the same name - var oldhandle = this.interactiveMarkers[msg.name]; - if (oldhandle) { - this.eraseIntMarker(oldhandle.name); + }, { + key: "eraseIntMarker", + value: + /** + * Erase the interactive marker with the given name. + * + * @param intMarkerName - the interactive marker name to delete + */ + function eraseIntMarker(intMarkerName) { + if (this.interactiveMarkers[intMarkerName]) { + // remove the object + var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); + this.rootObject.remove(targetIntMarker); + // unsubscribe from TF topic! + var handle = this.interactiveMarkers[intMarkerName]; + handle.unsubscribeTf(); + + // remove all other listeners + + targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); + targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); + targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); + targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); + targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); + + // remove the handle from the map - after leaving this function's scope, there should be no references to the handle + delete this.interactiveMarkers[intMarkerName]; + targetIntMarker.dispose(); + } } + }]); +}(); - // create the handle - var handle = new InteractiveMarkerHandle({ - message : msg, - feedbackTopic : this.feedbackTopic, - tfClient : this.tfClient, - menuFontSize : this.menuFontSize - }); - this.interactiveMarkers[msg.name] = handle; - - // create the actual marker - var intMarker = new InteractiveMarker({ - handle : handle, - camera : this.camera, - path : this.path, - loader : this.loader - }); - // add it to the scene - intMarker.name = msg.name; - this.rootObject.add(intMarker); - - // listen for any pose updates from the server - handle.on('pose', function(pose) { - intMarker.onServerSetPose({ - pose : pose - }); - }); - - // add bound versions of UI handlers - intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); - intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); - intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); - intMarker.addEventListener('user-button-click', handle.onButtonClickBound); - intMarker.addEventListener('menu-select', handle.onMenuSelectBound); - - // now listen for any TF changes - handle.subscribeTf(); - }); -}; -/** - * Erase the interactive marker with the given name. - * - * @param intMarkerName - the interactive marker name to delete - */ -InteractiveMarkerClient.prototype.eraseIntMarker = function eraseIntMarker (intMarkerName) { - if (this.interactiveMarkers[intMarkerName]) { - // remove the object - var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); - this.rootObject.remove(targetIntMarker); - // unsubscribe from TF topic! - var handle = this.interactiveMarkers[intMarkerName]; - handle.unsubscribeTf(); - - // remove all other listeners - - targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); - targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); - targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); - targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); - targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); - - // remove the handle from the map - after leaving this function's scope, there should be no references to the handle - delete this.interactiveMarkers[intMarkerName]; - targetIntMarker.dispose(); - } -}; +function _callSuper$p(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$p() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$p() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$p = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -53591,27 +45668,39 @@ InteractiveMarkerClient.prototype.eraseIntMarker = function eraseIntMarker (intM * @author Russell Toris - rctoris@wpi.edu */ -var SceneNode = /*@__PURE__*/(function (superclass) { +var SceneNode = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A SceneNode can be used to keep track of a 3D object with respect to a ROS frame within a scene. + * + * @constructor + * @param options - object with following keys: + * + * * tfClient - a handle to the TF client + * * frameID - the frame ID this object belongs to + * * pose (optional) - the pose associated with this object + * * object - the THREE 3D object to be rendered + */ function SceneNode(options) { - superclass.call(this); + var _this; + _classCallCheck(this, SceneNode); + _this = _callSuper$p(this, SceneNode); options = options || {}; - this.tfClient = options.tfClient; - this.frameID = options.frameID; + _this.tfClient = options.tfClient; + _this.frameID = options.frameID; var object = options.object; - this.pose = options.pose || new ROSLIB.Pose(); + _this.pose = options.pose || new ROSLIB.Pose(); // Do not render this object until we receive a TF update - this.visible = false; + _this.visible = false; // add the model - this.add(object); + _this.add(object); // set the inital pose - this.updatePose(this.pose); + _this.updatePose(_this.pose); // save the TF handler so we can remove it later - this.tfUpdate = function(msg) { - + _this.tfUpdate = function (msg) { // apply the transform var tf = new ROSLIB.Transform(msg); var poseTransformed = new ROSLIB.Pose(this.pose); @@ -53623,30 +45712,34 @@ var SceneNode = /*@__PURE__*/(function (superclass) { }; // listen for TF updates - this.tfUpdateBound = this.tfUpdate.bind(this); - this.tfClient.subscribe(this.frameID, this.tfUpdateBound); + _this.tfUpdateBound = _this.tfUpdate.bind(_this); + _this.tfClient.subscribe(_this.frameID, _this.tfUpdateBound); + return _this; } + _inherits(SceneNode, _THREE$Object3D); + return _createClass(SceneNode, [{ + key: "updatePose", + value: + /** + * Set the pose of the associated model. + * + * @param pose - the pose to update with + */ + function updatePose(pose) { + this.position.set(pose.position.x, pose.position.y, pose.position.z); + this.quaternion.set(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + this.updateMatrixWorld(true); + } + }, { + key: "unsubscribeTf", + value: function unsubscribeTf() { + this.tfClient.unsubscribe(this.frameID, this.tfUpdateBound); + } + }]); +}(Object3D); - if ( superclass ) SceneNode.__proto__ = superclass; - SceneNode.prototype = Object.create( superclass && superclass.prototype ); - SceneNode.prototype.constructor = SceneNode; - /** - * Set the pose of the associated model. - * - * @param pose - the pose to update with - */ - SceneNode.prototype.updatePose = function updatePose (pose) { - this.position.set( pose.position.x, pose.position.y, pose.position.z ); - this.quaternion.set(pose.orientation.x, pose.orientation.y, - pose.orientation.z, pose.orientation.w); - this.updateMatrixWorld(true); - }; - SceneNode.prototype.unsubscribeTf = function unsubscribeTf () { - this.tfClient.unsubscribe(this.frameID, this.tfUpdateBound); - }; - - return SceneNode; -}(THREE.Object3D)); +function _callSuper$o(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$o() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$o() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$o = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -53654,253 +45747,338 @@ var SceneNode = /*@__PURE__*/(function (superclass) { * @author Nils Berg - berg.nils@gmail.com */ -var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter3) { +var MarkerArrayClient = /*#__PURE__*/function (_EventEmitter) { + /** + * A MarkerArray client that listens to a given topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the MarkerArray + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add the markers to + * * path (optional) - the base path to any meshes that will be loaded + */ function MarkerArrayClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, MarkerArrayClient); + _this = _callSuper$o(this, MarkerArrayClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.path = options.path || '/'; + _this.ros = options.ros; + _this.topicName = options.topic; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.path = options.path || '/'; // Markers that are displayed (Map ns+id--Marker) - this.markers = {}; - this.rosTopic = undefined; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.markers = {}; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) MarkerArrayClient.__proto__ = EventEmitter3; - MarkerArrayClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - MarkerArrayClient.prototype.constructor = MarkerArrayClient; - MarkerArrayClient.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to MarkerArray topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'visualization_msgs/MarkerArray', - compression : 'png' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - MarkerArrayClient.prototype.processMessage = function processMessage (arrayMessage){ - arrayMessage.markers.forEach(function(message) { - var key = message.ns + message.id; - if(message.action === 0) { - var updated = false; - if(key in this.markers) { // "MODIFY" - updated = this.markers[key].children[0].update(message); - if(!updated) { // "REMOVE" - this.removeMarker(key); + _inherits(MarkerArrayClient, _EventEmitter); + return _createClass(MarkerArrayClient, [{ + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to MarkerArray topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'visualization_msgs/MarkerArray', + compression: 'png' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(arrayMessage) { + arrayMessage.markers.forEach(function (message) { + var key = message.ns + message.id; + if (message.action === 0) { + var updated = false; + if (key in this.markers) { + // "MODIFY" + updated = this.markers[key].children[0].update(message); + if (!updated) { + // "REMOVE" + this.removeMarker(key); + } } + if (!updated) { + // "ADD" + var newMarker = new Marker({ + message: message, + path: this.path + }); + this.markers[key] = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newMarker + }); + this.rootObject.add(this.markers[key]); + } + } else if (message.action === 1) { + // "DEPRECATED" + console.warn('Received marker message with deprecated action identifier "1"'); + } else if (message.action === 2) { + // "DELETE" + this.removeMarker(key); + } else if (message.action === 3) { + // "DELETE ALL" + for (var m in this.markers) { + this.removeMarker(m); + } + this.markers = {}; + } else { + console.warn('Received marker message with unknown action identifier "' + message.action + '"'); } - if(!updated) { // "ADD" - var newMarker = new Marker({ - message : message, - path : this.path, - }); - this.markers[key] = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newMarker - }); - this.rootObject.add(this.markers[key]); - } - } - else if(message.action === 1) { // "DEPRECATED" - console.warn('Received marker message with deprecated action identifier "1"'); - } - else if(message.action === 2) { // "DELETE" - this.removeMarker(key); - } - else if(message.action === 3) { // "DELETE ALL" - for (var m in this.markers){ - this.removeMarker(m); - } - this.markers = {}; - } - else { - console.warn('Received marker message with unknown action identifier "'+message.action+'"'); + }.bind(this)); + this.emit('change'); + } + }, { + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); } - }.bind(this)); - - this.emit('change'); - }; - MarkerArrayClient.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); } - }; - MarkerArrayClient.prototype.removeMarker = function removeMarker (key) { - var oldNode = this.markers[key]; - if(!oldNode) { - return; + }, { + key: "removeMarker", + value: function removeMarker(key) { + var oldNode = this.markers[key]; + if (!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(function (child) { + child.dispose(); + }); + delete this.markers[key]; } - oldNode.unsubscribeTf(); - this.rootObject.remove(oldNode); - oldNode.children.forEach(function (child) { - child.dispose(); - }); - delete(this.markers[key]); - }; + }]); +}(EventEmitter2); - return MarkerArrayClient; -}(EventEmitter3)); +function _callSuper$n(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$n() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$n() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$n = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var MarkerClient = /*@__PURE__*/(function (EventEmitter3) { +var MarkerClient = /*#__PURE__*/function (_EventEmitter) { + /** + * A marker client that listens to a given marker topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * path (optional) - the base path to any meshes that will be loaded + * * lifetime - the lifetime of marker + */ function MarkerClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, MarkerClient); + _this = _callSuper$n(this, MarkerClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.path = options.path || '/'; - this.lifetime = options.lifetime || 0; + _this.ros = options.ros; + _this.topicName = options.topic; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.path = options.path || '/'; + _this.lifetime = options.lifetime || 0; // Markers that are displayed (Map ns+id--Marker) - this.markers = {}; - this.rosTopic = undefined; - this.updatedTime = {}; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.markers = {}; + _this.rosTopic = undefined; + _this.updatedTime = {}; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) MarkerClient.__proto__ = EventEmitter3; - MarkerClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - MarkerClient.prototype.constructor = MarkerClient; - MarkerClient.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(MarkerClient, _EventEmitter); + return _createClass(MarkerClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - MarkerClient.prototype.checkTime = function checkTime (name){ + }, { + key: "checkTime", + value: function checkTime(name) { var curTime = new Date().getTime(); if (curTime - this.updatedTime[name] > this.lifetime) { - this.removeMarker(name); - this.emit('change'); + this.removeMarker(name); + this.emit('change'); } else { - var that = this; - setTimeout(function() {that.checkTime(name);}, - 100); + var that = this; + setTimeout(function () { + that.checkTime(name); + }, 100); } - }; - MarkerClient.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'visualization_msgs/Marker', - compression : 'png' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - MarkerClient.prototype.processMessage = function processMessage (message){ - // remove old marker from Three.Object3D children buffer - var key = message.ns + message.id; - var oldNode = this.markers[key]; - this.updatedTime[key] = new Date().getTime(); - if (oldNode) { - this.removeMarker(key); - - } else if (this.lifetime) { - this.checkTime(message.ns + message.id); } - - if (message.action === 0) { // "ADD" or "MODIFY" - var newMarker = new Marker({ - message : message, - path : this.path, - }); - - this.markers[key] = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newMarker + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'visualization_msgs/Marker', + compression: 'png' }); - this.rootObject.add(this.markers[key]); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + // remove old marker from Three.Object3D children buffer + var key = message.ns + message.id; + var oldNode = this.markers[key]; + this.updatedTime[key] = new Date().getTime(); + if (oldNode) { + this.removeMarker(key); + } else if (this.lifetime) { + this.checkTime(message.ns + message.id); + } + if (message.action === 0) { + // "ADD" or "MODIFY" + var newMarker = new Marker({ + message: message, + path: this.path + }); + this.markers[key] = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newMarker + }); + this.rootObject.add(this.markers[key]); + } + this.emit('change'); } - - this.emit('change'); - }; - MarkerClient.prototype.removeMarker = function removeMarker (key) { - var oldNode = this.markers[key]; - if(!oldNode) { - return; + }, { + key: "removeMarker", + value: function removeMarker(key) { + var oldNode = this.markers[key]; + if (!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(function (child) { + child.dispose(); + }); + delete this.markers[key]; } - oldNode.unsubscribeTf(); - this.rootObject.remove(oldNode); - oldNode.children.forEach(function (child) { - child.dispose(); - }); - delete(this.markers[key]); - }; + }]); +}(EventEmitter2); - return MarkerClient; -}(EventEmitter3)); +function _callSuper$m(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$m() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$m() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$m = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Jihoon Lee - lee@magazino.eu */ -var Arrow2 = /*@__PURE__*/(function (superclass) { +var Arrow2 = /*#__PURE__*/function (_THREE$ArrowHelper) { + /** + * A Arrow is a THREE object that can be used to display an arrow model using ArrowHelper + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ function Arrow2(options) { + _classCallCheck(this, Arrow2); options = options || {}; - var origin = options.origin || new THREE.Vector3(0, 0, 0); - var direction = options.direction || new THREE.Vector3(1, 0, 0); + var origin = options.origin || new Vector3(0, 0, 0); + var direction = options.direction || new Vector3(1, 0, 0); var length = options.length || 1; options.headLength || 0.2; options.shaftDiameter || 0.05; options.headDiameter || 0.1; - options.material || new THREE.MeshBasicMaterial(); - - superclass.call(this, direction, origin, length, 0xff0000); - + options.material || new MeshBasicMaterial(); + return _callSuper$m(this, Arrow2, [direction, origin, length, 0xff0000]); } - - if ( superclass ) Arrow2.__proto__ = superclass; - Arrow2.prototype = Object.create( superclass && superclass.prototype ); - Arrow2.prototype.constructor = Arrow2; - - /* - * Free memory of elements in this object. - */ - Arrow2.prototype.dispose = function dispose () { - if (this.line !== undefined) { + _inherits(Arrow2, _THREE$ArrowHelper); + return _createClass(Arrow2, [{ + key: "dispose", + value: + /* + * Free memory of elements in this object. + */ + function dispose() { + if (this.line !== undefined) { this.line.material.dispose(); this.line.geometry.dispose(); - } - if (this.cone!== undefined) { + } + if (this.cone !== undefined) { this.cone.material.dispose(); this.cone.geometry.dispose(); + } } - }; + }]); +}(ArrowHelper); - return Arrow2; -}(THREE.ArrowHelper)); +function _callSuper$l(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$l() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$l() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$l = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ -var Axes = /*@__PURE__*/(function (superclass) { +var Axes = /*#__PURE__*/function (_THREE$Object3D) { + /** + * An Axes object can be used to display the axis of a particular coordinate frame. + * + * @constructor + * @param options - object with following keys: + * + * * shaftRadius (optional) - the radius of the shaft to render + * * headRadius (optional) - the radius of the head to render + * * headLength (optional) - the length of the head to render + * * scale (optional) - the scale of the frame (defaults to 1.0) + * * lineType (optional) - the line type for the axes. Supported line types: + * 'dashed' and 'full'. + * * lineDashLength (optional) - the length of the dashes, relative to the length of the axis. + * Maximum value is 1, which means the dash length is + * equal to the length of the axis. Parameter only applies when + * lineType is set to dashed. + */ function Axes(options) { - superclass.call(this); - var that = this; + var _this; + _classCallCheck(this, Axes); + _this = _callSuper$l(this, Axes); + var that = _this; options = options || {}; var shaftRadius = options.shaftRadius || 0.008; var headRadius = options.headRadius || 0.023; @@ -53908,13 +46086,11 @@ var Axes = /*@__PURE__*/(function (superclass) { var scaleArg = options.scale || 1.0; var lineType = options.lineType || 'full'; var lineDashLength = options.lineDashLength || 0.1; - - - this.scale.set(scaleArg, scaleArg, scaleArg); + _this.scale.set(scaleArg, scaleArg, scaleArg); // create the cylinders for the objects - this.lineGeom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); - this.headGeom = new THREE.CylinderGeometry(0, headRadius, headLength); + _this.lineGeom = new CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); + _this.headGeom = new CylinderGeometry(0, headRadius, headLength); /** * Adds an axis marker to this axes object. @@ -53923,20 +46099,20 @@ var Axes = /*@__PURE__*/(function (superclass) { */ function addAxis(axis) { // set the color of the axis - var color = new THREE.Color(); + var color = new Color(); color.setRGB(axis.x, axis.y, axis.z); - var material = new THREE.MeshBasicMaterial({ - color : color.getHex() + var material = new MeshBasicMaterial({ + color: color.getHex() }); // setup the rotation information - var rotAxis = new THREE.Vector3(); - rotAxis.crossVectors(axis, new THREE.Vector3(0, -1, 0)); - var rot = new THREE.Quaternion(); + var rotAxis = new Vector3(); + rotAxis.crossVectors(axis, new Vector3(0, -1, 0)); + var rot = new Quaternion(); rot.setFromAxisAngle(rotAxis, 0.5 * Math.PI); // create the arrow - var arrow = new THREE.Mesh(that.headGeom, material); + var arrow = new Mesh(that.headGeom, material); arrow.position.copy(axis); arrow.position.multiplyScalar(0.95); arrow.quaternion.copy(rot); @@ -53947,9 +46123,9 @@ var Axes = /*@__PURE__*/(function (superclass) { var line; if (lineType === 'dashed') { var l = lineDashLength; - for (var i = 0; (l / 2 + 3 * l * i + l / 2) <= 1; ++i) { - var geom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, l); - line = new THREE.Mesh(geom, material); + for (var i = 0; l / 2 + 3 * l * i + l / 2 <= 1; ++i) { + var geom = new CylinderGeometry(shaftRadius, shaftRadius, l); + line = new Mesh(geom, material); line.position.copy(axis); // Make spacing between dashes equal to 1.5 times the dash length. line.position.multiplyScalar(l / 2 + 3 * l * i); @@ -53958,7 +46134,7 @@ var Axes = /*@__PURE__*/(function (superclass) { that.add(line); } } else if (lineType === 'full') { - line = new THREE.Mesh(that.lineGeom, material); + line = new Mesh(that.lineGeom, material); line.position.copy(axis); line.position.multiplyScalar(0.45); line.quaternion.copy(rot); @@ -53970,315 +46146,413 @@ var Axes = /*@__PURE__*/(function (superclass) { } // add the three markers to the axes - addAxis(new THREE.Vector3(1, 0, 0)); - addAxis(new THREE.Vector3(0, 1, 0)); - addAxis(new THREE.Vector3(0, 0, 1)); + addAxis(new Vector3(1, 0, 0)); + addAxis(new Vector3(0, 1, 0)); + addAxis(new Vector3(0, 0, 1)); + return _this; } + _inherits(Axes, _THREE$Object3D); + return _createClass(Axes); +}(Object3D); - if ( superclass ) Axes.__proto__ = superclass; - Axes.prototype = Object.create( superclass && superclass.prototype ); - Axes.prototype.constructor = Axes; - - return Axes; -}(THREE.Object3D)); +function _callSuper$k(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$k() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$k() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$k = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var Grid = /*@__PURE__*/(function (superclass) { +var Grid = /*#__PURE__*/function (_THREE$Object3D) { + /** + * Create a grid object. + * + * @constructor + * @param options - object with following keys: + * + * * num_cells (optional) - The number of cells of the grid + * * color (optional) - the line color of the grid, like '#cccccc' + * * lineWidth (optional) - the width of the lines in the grid + * * cellSize (optional) - The length, in meters, of the side of each cell + */ + function Grid(options) { + var _this; + _classCallCheck(this, Grid); options = options || {}; var num_cells = options.num_cells || 10; var color = options.color || '#cccccc'; var lineWidth = options.lineWidth || 1; var cellSize = options.cellSize || 1; - - superclass.call(this); - - var material = new THREE.LineBasicMaterial({ + _this = _callSuper$k(this, Grid); + var material = new LineBasicMaterial({ color: color, linewidth: lineWidth }); - + var edges = []; for (var i = 0; i <= num_cells; ++i) { var edge = cellSize * num_cells / 2; - var position = edge - (i * cellSize); - var geometryH = new THREE.Geometry(); - geometryH.vertices.push( - new THREE.Vector3( -edge, position, 0 ), - new THREE.Vector3( edge, position, 0 ) - ); - var geometryV = new THREE.Geometry(); - geometryV.vertices.push( - new THREE.Vector3( position, -edge, 0 ), - new THREE.Vector3( position, edge, 0 ) - ); - this.add(new THREE.Line(geometryH, material)); - this.add(new THREE.Line(geometryV, material)); + var position = edge - i * cellSize; + + // Horizontal lines + edges.push(new Vector3(-edge, position, 0), new Vector3(edge, position, 0)); + + // Vertical lines + edges.push(new Vector3(position, -edge, 0), new Vector3(position, edge, 0)); } - } + var geometry = new BufferGeometry().setFromPoints(edges); - if ( superclass ) Grid.__proto__ = superclass; - Grid.prototype = Object.create( superclass && superclass.prototype ); - Grid.prototype.constructor = Grid; + // Define lines with the geometry + var lineSegments = new LineSegments(geometry, material); + _this.add(lineSegments); + return _this; + } + _inherits(Grid, _THREE$Object3D); + return _createClass(Grid); +}(Object3D); - return Grid; -}(THREE.Object3D)); +function _callSuper$j(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$j() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$j() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$j = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var OccupancyGrid = /*@__PURE__*/(function (superclass) { +var OccupancyGrid = /*#__PURE__*/function (_THREE$Mesh) { + /** + * An OccupancyGrid can convert a ROS occupancy grid message into a THREE object. + * + * @constructor + * @param options - object with following keys: + * + * * message - the occupancy grid message + * * color (optional) - color of the visualized grid + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + */ function OccupancyGrid(options) { + var _this; + _classCallCheck(this, OccupancyGrid); options = options || {}; var message = options.message; var opacity = options.opacity || 1.0; - var color = options.color || {r:255,g:255,b:255,a:255}; + var color = options.color || { + r: 255, + g: 255, + b: 255, + a: 255 + }; // create the geometry var info = message.info; var origin = info.origin; var width = info.width; var height = info.height; - var geom = new THREE.PlaneBufferGeometry(width, height); + var geom = new PlaneGeometry(width, height); // create the color material var imageData = new Uint8Array(width * height * 4); - var texture = new THREE.DataTexture(imageData, width, height, THREE.RGBAFormat); + var texture = new DataTexture(imageData, width, height, RGBAFormat); texture.flipY = true; - texture.minFilter = THREE.NearestFilter; - texture.magFilter = THREE.NearestFilter; + texture.minFilter = NearestFilter; + texture.magFilter = NearestFilter; texture.needsUpdate = true; - - var material = new THREE.MeshBasicMaterial({ - map : texture, - transparent : opacity < 1.0, - opacity : opacity + var material = new MeshBasicMaterial({ + map: texture, + transparent: opacity < 1.0, + opacity: opacity }); - material.side = THREE.DoubleSide; + material.side = DoubleSide; // create the mesh - superclass.call(this, geom, material); + _this = _callSuper$j(this, OccupancyGrid, [geom, material]); // move the map so the corner is at X, Y and correct orientation (informations from message.info) // assign options to this for subclasses - Object.assign(this, options); - - this.quaternion.copy(new THREE.Quaternion( - origin.orientation.x, - origin.orientation.y, - origin.orientation.z, - origin.orientation.w - )); - this.position.x = (width * info.resolution) / 2 + origin.position.x; - this.position.y = (height * info.resolution) / 2 + origin.position.y; - this.position.z = origin.position.z; - this.scale.x = info.resolution; - this.scale.y = info.resolution; - + Object.assign(_this, options); + _this.quaternion.copy(new Quaternion(origin.orientation.x, origin.orientation.y, origin.orientation.z, origin.orientation.w)); + _this.position.x = width * info.resolution / 2 + origin.position.x; + _this.position.y = height * info.resolution / 2 + origin.position.y; + _this.position.z = origin.position.z; + _this.scale.x = info.resolution; + _this.scale.y = info.resolution; var data = message.data; // update the texture (after the the super call and this are accessible) - this.color = color; - this.material = material; - this.texture = texture; - - for ( var row = 0; row < height; row++) { - for ( var col = 0; col < width; col++) { - + _this.color = color; + _this.material = material; + _this.texture = texture; + for (var row = 0; row < height; row++) { + for (var col = 0; col < width; col++) { // determine the index into the map data - var invRow = (height - row - 1); - var mapI = col + (invRow * width); + var invRow = height - row - 1; + var mapI = col + invRow * width; // determine the value - var val = this.getValue(mapI, invRow, col, data); + var val = _this.getValue(mapI, invRow, col, data); // determine the color - var color = this.getColor(mapI, invRow, col, val); + var color = _this.getColor(mapI, invRow, col, val); // determine the index into the image data array - var i = (col + (row * width)) * 4; + var i = (col + row * width) * 4; // copy the color imageData.set(color, i); } } - texture.needsUpdate = true; - + return _this; } + _inherits(OccupancyGrid, _THREE$Mesh); + return _createClass(OccupancyGrid, [{ + key: "dispose", + value: function dispose() { + this.material.dispose(); + this.texture.dispose(); + } + }, { + key: "getValue", + value: + /** + * Returns the value for a given grid cell + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {object} data the data buffer + */ + function getValue(index, row, col, data) { + return data[index]; + } + }, { + key: "getColor", + value: + /** + * Returns a color value given parameters of the position in the grid; the default implementation + * scales the default color value by the grid value. Subclasses can extend this functionality + * (e.g. lookup a color in a color map). + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {float} value the value of the cell + * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel + */ + function getColor(index, row, col, value) { + return [value * this.color.r / 255, value * this.color.g / 255, value * this.color.b / 255, 255]; + } + }]); +}(Mesh); - if ( superclass ) OccupancyGrid.__proto__ = superclass; - OccupancyGrid.prototype = Object.create( superclass && superclass.prototype ); - OccupancyGrid.prototype.constructor = OccupancyGrid; - OccupancyGrid.prototype.dispose = function dispose () { - this.material.dispose(); - this.texture.dispose(); - }; - /** - * Returns the value for a given grid cell - * @param {int} index the current index of the cell - * @param {int} row the row of the cell - * @param {int} col the column of the cell - * @param {object} data the data buffer - */ - OccupancyGrid.prototype.getValue = function getValue (index, row, col, data) { - return data[index]; - }; - /** - * Returns a color value given parameters of the position in the grid; the default implementation - * scales the default color value by the grid value. Subclasses can extend this functionality - * (e.g. lookup a color in a color map). - * @param {int} index the current index of the cell - * @param {int} row the row of the cell - * @param {int} col the column of the cell - * @param {float} value the value of the cell - * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel - */ - OccupancyGrid.prototype.getColor = function getColor (index, row, col, value) { - return [ - (value * this.color.r) / 255, - (value * this.color.g) / 255, - (value * this.color.b) / 255, - 255 - ]; - }; - - return OccupancyGrid; -}(THREE.Mesh)); +function _callSuper$i(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$i() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$i() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$i = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ -var OccupancyGridClient = /*@__PURE__*/(function (EventEmitter3) { +var OccupancyGridClient = /*#__PURE__*/function (_EventEmitter) { + /** + * An occupancy grid client that listens to a given map topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic (optional) - the map topic to listen to + * * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM) + * * tfClient (optional) - the TF client handle to use for a scene node + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to + * * offsetPose (optional) - offset pose of the grid visualization, e.g. for z-offset (ROSLIB.Pose type) + * * color (optional) - color of the visualized grid + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + */ function OccupancyGridClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, OccupancyGridClient); + _this = _callSuper$i(this, OccupancyGridClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/map'; - this.compression = options.compression || 'cbor'; - this.continuous = options.continuous; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.offsetPose = options.offsetPose || new ROSLIB.Pose(); - this.color = options.color || {r:255,g:255,b:255}; - this.opacity = options.opacity || 1.0; + _this.ros = options.ros; + _this.topicName = options.topic || '/map'; + _this.compression = options.compression || 'cbor'; + _this.continuous = options.continuous; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.offsetPose = options.offsetPose || new ROSLIB.Pose(); + _this.color = options.color || { + r: 255, + g: 255, + b: 255 + }; + _this.opacity = options.opacity || 1.0; // current grid that is displayed - this.currentGrid = null; + _this.currentGrid = null; // subscribe to the topic - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) OccupancyGridClient.__proto__ = EventEmitter3; - OccupancyGridClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - OccupancyGridClient.prototype.constructor = OccupancyGridClient; - OccupancyGridClient.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(OccupancyGridClient, _EventEmitter); + return _createClass(OccupancyGridClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } + } + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'nav_msgs/OccupancyGrid', + queue_length: 1, + compression: this.compression + }); + this.sceneNode = null; + this.rosTopic.subscribe(this.processMessageBound); } - }; - OccupancyGridClient.prototype.subscribe = function subscribe (){ - this.unsubscribe(); + }, { + key: "processMessage", + value: function processMessage(message) { + // check for an old map + if (this.currentGrid) { + // check if it there is a tf client + if (this.tfClient) { + // grid is of type ROS3D.SceneNode + this.sceneNode.unsubscribeTf(); + this.sceneNode.remove(this.currentGrid); + } else { + this.rootObject.remove(this.currentGrid); + } + this.currentGrid.dispose(); + } + var newGrid = new OccupancyGrid({ + message: message, + color: this.color, + opacity: this.opacity + }); - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'nav_msgs/OccupancyGrid', - queue_length : 1, - compression : this.compression - }); - this.sceneNode = null; - this.rosTopic.subscribe(this.processMessageBound); - }; - OccupancyGridClient.prototype.processMessage = function processMessage (message){ - // check for an old map - if (this.currentGrid) { - // check if it there is a tf client + // check if we care about the scene if (this.tfClient) { - // grid is of type ROS3D.SceneNode - this.sceneNode.unsubscribeTf(); - this.sceneNode.remove(this.currentGrid); + this.currentGrid = newGrid; + if (this.sceneNode === null) { + this.sceneNode = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newGrid, + pose: this.offsetPose + }); + this.rootObject.add(this.sceneNode); + } else { + this.sceneNode.add(this.currentGrid); + } } else { - this.rootObject.remove(this.currentGrid); + this.sceneNode = this.currentGrid = newGrid; + this.rootObject.add(this.currentGrid); } - this.currentGrid.dispose(); - } - - var newGrid = new OccupancyGrid({ - message : message, - color : this.color, - opacity : this.opacity - }); + this.emit('change'); - // check if we care about the scene - if (this.tfClient) { - this.currentGrid = newGrid; - if (this.sceneNode === null) { - this.sceneNode = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newGrid, - pose : this.offsetPose - }); - this.rootObject.add(this.sceneNode); - } else { - this.sceneNode.add(this.currentGrid); + // check if we should unsubscribe + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessageBound); } - } else { - this.sceneNode = this.currentGrid = newGrid; - this.rootObject.add(this.currentGrid); } + }]); +}(EventEmitter2); - this.emit('change'); +function _arrayLikeToArray(r, a) { + (null == a || a > r.length) && (a = r.length); + for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; + return n; +} - // check if we should unsubscribe - if (!this.continuous) { - this.rosTopic.unsubscribe(this.processMessageBound); - } - }; +function _arrayWithoutHoles(r) { + if (Array.isArray(r)) return _arrayLikeToArray(r); +} + +function _iterableToArray(r) { + if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); +} + +function _unsupportedIterableToArray(r, a) { + if (r) { + if ("string" == typeof r) return _arrayLikeToArray(r, a); + var t = {}.toString.call(r).slice(8, -1); + return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; + } +} - return OccupancyGridClient; -}(EventEmitter3)); +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +function _toConsumableArray(r) { + return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); +} /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ -var OcTreeBaseNode = function OcTreeBaseNode() { - this._children = [null, null, null, null, null, null, null, null]; - this.value = null; -}; -OcTreeBaseNode.prototype.createChildNodeAt = function createChildNodeAt (newNode, index) { - this._children[index % 8] = newNode; -}; -OcTreeBaseNode.prototype.hasChildAt = function hasChildAt (index) { - return this._children[index % 8] !== null; -}; -OcTreeBaseNode.prototype.getChildAt = function getChildAt (index) { - return this._children[index % 8]; -}; -OcTreeBaseNode.prototype.isLeafNode = function isLeafNode () { - for (var i = 0; i < 8; ++i) { - if (this._children[i] !== null) { return false; } - } - return true; -}; -OcTreeBaseNode.prototype.hasChildren = function hasChildren () { - for (var i = 0; i < 8; ++i) { - if (this._children[i] !== null) { return true; } +var OcTreeBaseNode = /*#__PURE__*/function () { + /** + * Base node type that represents one voxel as a node of the tree + */ + + function OcTreeBaseNode() { + _classCallCheck(this, OcTreeBaseNode); + this._children = [null, null, null, null, null, null, null, null]; + this.value = null; } - return false; -}; + return _createClass(OcTreeBaseNode, [{ + key: "createChildNodeAt", + value: function createChildNodeAt(newNode, index) { + this._children[index % 8] = newNode; + } + }, { + key: "hasChildAt", + value: function hasChildAt(index) { + return this._children[index % 8] !== null; + } + }, { + key: "getChildAt", + value: function getChildAt(index) { + return this._children[index % 8]; + } + }, { + key: "isLeafNode", + value: function isLeafNode() { + for (var i = 0; i < 8; ++i) { + if (this._children[i] !== null) { + return false; + } + } + return true; + } + }, { + key: "hasChildren", + value: function hasChildren() { + for (var i = 0; i < 8; ++i) { + if (this._children[i] !== null) { + return true; + } + } + return false; + } + }]); +}(); /** * @fileOverview @@ -54295,7 +46569,7 @@ OcTreeBaseNode.prototype.hasChildren = function hasChildren () { var OcTreeVoxelRenderMode = { OCCUPIED: 'occupied', FREE: 'free', - ALL: 'all', + ALL: 'all' }; /** @@ -54318,719 +46592,781 @@ var OcTreeColorMode = { to read ArrayBuffer in a streamed data-like fashion with mixed types in it */ function InStream(data, isLittleEndian) { - var this$1$1 = this; - + var _this = this; this.buffer = data.buffer; this.length = data.length; - this.isLittleEndian = (typeof isLittleEndian !== 'undefined') ? !!isLittleEndian : true; + this.isLittleEndian = typeof isLittleEndian !== 'undefined' ? !!isLittleEndian : true; this._dataView = new DataView(this.buffer); this._cursor = 0; // Creates a set of wrapper functions for DataView // also flattens all dependencies - [ - { kind: 'Int8', width: 1 }, - { kind: 'Uint8', width: 1 }, - { kind: 'Int16', width: 2 }, - { kind: 'Uint16', width: 2 }, - { kind: 'Int32', width: 4 }, - { kind: 'Uint32', width: 4 }, - { kind: 'BigInt64', width: 8 }, - { kind: 'BigUint64', width: 8 }, - { kind: 'Float32', width: 4 }, - { kind: 'Float64', width: 8 } ] - .forEach(function (wrap) { - var interfaceFunction = 'read' + wrap.kind; - var wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView - - this$1$1[interfaceFunction] = function () { - if (this$1$1._cursor + wrap.width > this$1$1.length) { throw new Error('Cannot read data stream. Overflow. Len=' + this$1$1.length + ' crsr=' + this$1$1._cursor); } - var returningValue = this$1$1._dataView[wrappedFunction](this$1$1._cursor, this$1$1.isLittleEndian); - this$1$1._cursor += wrap.width; - return returningValue; - }; - }); - - Object.defineProperty(this, 'isEnd', { get: function () { return this$1$1.cursor >= this$1$1.data.length; } }); + [{ + kind: 'Int8', + width: 1 + }, { + kind: 'Uint8', + width: 1 + }, { + kind: 'Int16', + width: 2 + }, { + kind: 'Uint16', + width: 2 + }, { + kind: 'Int32', + width: 4 + }, { + kind: 'Uint32', + width: 4 + }, { + kind: 'BigInt64', + width: 8 + }, { + kind: 'BigUint64', + width: 8 + }, { + kind: 'Float32', + width: 4 + }, { + kind: 'Float64', + width: 8 + }].forEach(function (wrap) { + var interfaceFunction = 'read' + wrap.kind; + var wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView + + _this[interfaceFunction] = function () { + if (_this._cursor + wrap.width > _this.length) { + throw new Error('Cannot read data stream. Overflow. Len=' + _this.length + ' crsr=' + _this._cursor); + } + var returningValue = _this._dataView[wrappedFunction](_this._cursor, _this.isLittleEndian); + _this._cursor += wrap.width; + return returningValue; + }; + }); + Object.defineProperty(this, 'isEnd', { + get: function get() { + return _this.cursor >= _this.data.length; + } + }); return this; } -// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - -var OcTreeBase = function OcTreeBase(options) { - - this.resolution = (typeof options.resolution !== 'undefined') ? options.resolution : 1.; - this.color = new THREE.Color((typeof options.color !== 'undefined') ? options.color : 'green'); - this.opacity = (typeof options.opacity !== 'undefined') ? options.opacity : 1.; - - this.voxelRenderMode = (typeof options.voxelRenderMode !== 'undefined') ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; - - this._rootNode = null; - this._treeDepth = 16; - this._treeMaxKeyVal = 32768; - - this._BINARY_UNALLOCATED = 0; - this._BINARY_LEAF_FREE = 1; - this._BINARY_LEAF_OCCUPIED = 2; - this._BINARY_HAS_CHILDREN = 3; - this._BINARY_CHILD_BUILD_TABLE = {}; - - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE] = function (child) { - child.value = this._defaultFreeValue; - }; - - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED] = function (child) { - child.value = this._defaultOccupiedValue; - }; - - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN] = function (child) { - child.value = null; - }; +// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- +var OcTreeBase = /*#__PURE__*/function () { /** - * Table which we are building the geometry data from. + * Represensta a BaseTree that can be build from ros message and create a THREE node from it. + * Due a tree can be represented different ways in a message, this class is also a base class to + * represent specialized versions fo the ree. + * + * @constructor + * @param options - object with following keys: + * + * * resolution - the size of leaf nodes in meter + * * color - color of the visualized map (if solid coloring option was set) + * * voxelRenderMode - toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode */ - this._FACES = [ - { // 0. left (x=0) - normal: [-1, 0, 0 ], - vertices: [ - [0, 1, 0], - [0, 0, 0], - [0, 1, 1], - [0, 0, 1] ], - childIndex: [ - 1, - 3, - 5, - 7 - ] - }, - { // 1. right (x=1) - normal: [1, 0, 0 ], - vertices: [ - [1, 1, 1], - [1, 0, 1], - [1, 1, 0], - [1, 0, 0] ], - - childIndex: [ - 0, - 2, - 4, - 6 - ] - }, - { // 2. bottom (y=0) - normal: [0, -1, 0 ], - vertices: [ - [1, 0, 1], - [0, 0, 1], - [1, 0, 0], - [0, 0, 0] ], - childIndex: [ - 2, - 3, - 6, - 7 - ] - }, - { // 3. top (y=1) - normal: [0, 1, 0 ], - vertices: [ - [0, 1, 1], - [1, 1, 1], - [0, 1, 0], - [1, 1, 0] ], - childIndex: [ - 0, - 1, - 4, - 5 - ] - }, - { // 4. back (z=0) - normal: [0, 0, -1 ], - vertices: [ - [1, 0, 0], - [0, 0, 0], - [1, 1, 0], - [0, 1, 0] ], - childIndex: [ - 4, - 5, - 6, - 7 - ] - }, - { // 5.front (z=1) - normal: [0, 0, 1 ], - vertices: [ - [0, 0, 1], - [1, 0, 1], - [0, 1, 1], - [1, 1, 1] ], - childIndex: [ - 0, - 1, - 2, - 3 - ] - } ]; - - // Table of voxel size for each level of the tree - this.nodeSizeTable = new Array(this._treeDepth); - var _val = this.resolution; - for (var i = this._treeDepth - 1; i >= 0; --i) { - this.nodeSizeTable[i] = _val; - _val = 2. * _val; - } - - this._defaultOccupiedValue = true; - this._defaultFreeValue = false; - - this.object = null; -}; - -/* - * Finds a key in a given depth. Search is performed on the lowest level by default. - * @return the node at given position, null if not found - */ -OcTreeBase.prototype.searchAtDepth = function searchAtDepth (key, depth) { - depth = (typeof depth !== 'undefined') ? (depth > 0 ? depth : this._treeDepth) : this._treeDepth; - - var keyAtDepth = this._adjustKeyAtDepth(key, depth); - var diff = this._treeDepth - depth; - var currentNode = this._rootNode; - - // follow nodes down to requested level (for diff = 0 it's the last level) - // Return the closest node, or null if not any + function OcTreeBase(options) { + _classCallCheck(this, OcTreeBase); + this.resolution = typeof options.resolution !== 'undefined' ? options.resolution : 1.; + this.color = new Color(typeof options.color !== 'undefined' ? options.color : 'green'); + this.opacity = typeof options.opacity !== 'undefined' ? options.opacity : 1.; + this.voxelRenderMode = typeof options.voxelRenderMode !== 'undefined' ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; + this._rootNode = null; + this._treeDepth = 16; + this._treeMaxKeyVal = 32768; + this._BINARY_UNALLOCATED = 0; + this._BINARY_LEAF_FREE = 1; + this._BINARY_LEAF_OCCUPIED = 2; + this._BINARY_HAS_CHILDREN = 3; + this._BINARY_CHILD_BUILD_TABLE = {}; + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE] = function (child) { + child.value = this._defaultFreeValue; + }; + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED] = function (child) { + child.value = this._defaultOccupiedValue; + }; + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN] = function (child) { + child.value = null; + }; - for (var i = (this._treeDepth - 1); i >= diff; --i) { - var pos = this._computeChildIdx(keyAtDepth, i); - if (currentNode.hasChildAt(pos)) { - currentNode = currentNode.getChildAt(pos); - } else { - // we expected a child but did not get it - // is the current node a leaf already? - if (!currentNode.hasChildren()) { return currentNode; } - // it is not, search failed - return null; + /** + * Table which we are building the geometry data from. + */ + this._FACES = [{ + // 0. left (x=0) + normal: [-1, 0, 0], + vertices: [[0, 1, 0], [0, 0, 0], [0, 1, 1], [0, 0, 1]], + childIndex: [1, 3, 5, 7] + }, { + // 1. right (x=1) + normal: [1, 0, 0], + vertices: [[1, 1, 1], [1, 0, 1], [1, 1, 0], [1, 0, 0]], + childIndex: [0, 2, 4, 6] + }, { + // 2. bottom (y=0) + normal: [0, -1, 0], + vertices: [[1, 0, 1], [0, 0, 1], [1, 0, 0], [0, 0, 0]], + childIndex: [2, 3, 6, 7] + }, { + // 3. top (y=1) + normal: [0, 1, 0], + vertices: [[0, 1, 1], [1, 1, 1], [0, 1, 0], [1, 1, 0]], + childIndex: [0, 1, 4, 5] + }, { + // 4. back (z=0) + normal: [0, 0, -1], + vertices: [[1, 0, 0], [0, 0, 0], [1, 1, 0], [0, 1, 0]], + childIndex: [4, 5, 6, 7] + }, { + // 5.front (z=1) + normal: [0, 0, 1], + vertices: [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]], + childIndex: [0, 1, 2, 3] + }]; + + // Table of voxel size for each level of the tree + this.nodeSizeTable = new Array(this._treeDepth); + var _val = this.resolution; + for (var i = this._treeDepth - 1; i >= 0; --i) { + this.nodeSizeTable[i] = _val; + _val = 2. * _val; } + this._defaultOccupiedValue = true; + this._defaultFreeValue = false; + this.object = null; } - - return currentNode; - -}; -/** - * - */ -OcTreeBase.prototype._computeCoordFromKey = function _computeCoordFromKey (key) { - var this$1$1 = this; - - return key.map(function (keyVal) { return this$1$1.resolution * (keyVal - this$1$1._treeMaxKeyVal); }); -}; -OcTreeBase.prototype._computeChildIdx = function _computeChildIdx (key, depth) { - var pos = 0; - if (key[0] & (1 << depth)) { pos += 1; } - if (key[1] & (1 << depth)) { pos += 2; } - if (key[2] & (1 << depth)) { pos += 4; } - - return pos; -}; -OcTreeBase.prototype._computeKeyFromChildIdx = function _computeKeyFromChildIdx (index, offset, depth) { - var diff = this._treeDepth - depth - 1; - - return [ - offset[0] + (!!(index & 1) << diff), - offset[1] + (!!(index & 2) << diff), - offset[2] + (!!(index & 4) << diff) ]; - -}; -OcTreeBase.prototype._adjustKeyAtDepth = function _adjustKeyAtDepth (key, depth) { - var this$1$1 = this; - - // generate appropriate key_at_depth for queried depth - var diff = this._treeDepth - depth; - if (diff === 0) { return key; } - - return key.map(function (keyVal) { return (((keyVal - this$1$1._treeMaxKeyVal) >> diff) << diff) + (1 << (diff - 1)) + this$1$1._treeMaxKeyVal; }); -}; -OcTreeBase.prototype._newNode = function _newNode () { return new OcTreeBaseNode(); }; -/* - * Reads and builds a tree which was represented in a binary form from a message - * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, - * occupation is represented as a binary value. - * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) - * starting with the root node. - */ - -OcTreeBase.prototype.readBinary = function readBinary (data) { - if (this._rootNode !== null) { - delete this._rootNode; - } - this._rootNode = this._newNode(); - - var dataStream = new InStream(data, true); - - var stack = new Array(); - stack.push(this._rootNode); - - while (stack.length > 0) { - var node = stack.pop(); - - // 2 bits per children, 16 bit total - var childAllocationMap = dataStream.readUint16(); - - // Insert all children and leaves - var index = 8; - while (index !== 0) { - --index; - var allocation = (childAllocationMap & (3 << (2 * index))) >> (2 * index); - - if (allocation !== this._BINARY_UNALLOCATED) { - var child = this._newNode(); - - var fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); - fn(child); - - node.createChildNodeAt(child, index); - if (allocation === this._BINARY_HAS_CHILDREN) { stack.push(child); } + return _createClass(OcTreeBase, [{ + key: "searchAtDepth", + value: + /* + * Finds a key in a given depth. Search is performed on the lowest level by default. + * @return the node at given position, null if not found + */ + function searchAtDepth(key, depth) { + depth = typeof depth !== 'undefined' ? depth > 0 ? depth : this._treeDepth : this._treeDepth; + var keyAtDepth = this._adjustKeyAtDepth(key, depth); + var diff = this._treeDepth - depth; + var currentNode = this._rootNode; + + // follow nodes down to requested level (for diff = 0 it's the last level) + // Return the closest node, or null if not any + + for (var i = this._treeDepth - 1; i >= diff; --i) { + var pos = this._computeChildIdx(keyAtDepth, i); + if (currentNode.hasChildAt(pos)) { + currentNode = currentNode.getChildAt(pos); + } else { + // we expected a child but did not get it + // is the current node a leaf already? + if (!currentNode.hasChildren()) { + return currentNode; + } + // it is not, search failed + return null; + } } + return currentNode; } - } - -}; -/** - * Reads a full tree (with node data) from a message. - * A pacjet starts with the node data, followed by the allocation map of their children. - * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData - */ -OcTreeBase.prototype.read = function read (data) { - if (this._rootNode !== null) { - delete this._rootNode; - } - - this._rootNode = this._newNode(); - - var dataStream = new InStream(data, true); - - var stack = new Array(); - stack.push(this._rootNode); - - while (stack.length > 0) { - var node = stack.pop(); - - // Data comes first - this._readNodeData(dataStream, node); - - var childAllocationMap = dataStream.readUint8(); - - // Insert all children and leaves - var index = 8; - while (index !== 0) { - --index; - var hasChild = childAllocationMap & (1 << index); - if (hasChild) { - var child = this._newNode(); - child.value = null; - node.createChildNodeAt(child, index); - stack.push(child); + }, { + key: "_computeCoordFromKey", + value: + /** + * + */ + function _computeCoordFromKey(key) { + var _this2 = this; + return key.map(function (keyVal) { + return _this2.resolution * (keyVal - _this2._treeMaxKeyVal); + }); + } + }, { + key: "_computeChildIdx", + value: function _computeChildIdx(key, depth) { + var pos = 0; + if (key[0] & 1 << depth) { + pos += 1; + } + if (key[1] & 1 << depth) { + pos += 2; } + if (key[2] & 1 << depth) { + pos += 4; + } + return pos; } - } - -}; -/** - * Abstract function; Reads and sets data of a node - */ -OcTreeBase.prototype._readNodeData = function _readNodeData (dataStream, node) { - // This needs to be implemented by specialized tree - console.error('Not implemented'); -}; -/** -* Builds up THREE.js geometry from tree data. -*/ -OcTreeBase.prototype.buildGeometry = function buildGeometry () { - console.assert(this._rootNode !== null, 'No tree data'); - var ref = this._buildFaces(); - var vertices = ref.vertices; - var normals = ref.normals; - var colors = ref.colors; - var indices = ref.indices; - - var geometry = new THREE.BufferGeometry(); - - var material = new THREE.MeshBasicMaterial({ - color: 'white', - flatShading: true, - vertexColors: THREE.VertexColors, - transparent: this.opacity < 1.0, - opacity: this.opacity - }); + }, { + key: "_computeKeyFromChildIdx", + value: function _computeKeyFromChildIdx(index, offset, depth) { + var diff = this._treeDepth - depth - 1; + return [offset[0] + (!!(index & 1) << diff), offset[1] + (!!(index & 2) << diff), offset[2] + (!!(index & 4) << diff)]; + } + }, { + key: "_adjustKeyAtDepth", + value: function _adjustKeyAtDepth(key, depth) { + var _this3 = this; + // generate appropriate key_at_depth for queried depth + var diff = this._treeDepth - depth; + if (diff === 0) { + return key; + } + return key.map(function (keyVal) { + return (keyVal - _this3._treeMaxKeyVal >> diff << diff) + (1 << diff - 1) + _this3._treeMaxKeyVal; + }); + } + }, { + key: "_newNode", + value: function _newNode() { + return new OcTreeBaseNode(); + } + }, { + key: "readBinary", + value: + /* + * Reads and builds a tree which was represented in a binary form from a message + * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, + * occupation is represented as a binary value. + * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) + * starting with the root node. + */ - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); + function readBinary(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + var dataStream = new InStream(data, true); + var stack = new Array(); + stack.push(this._rootNode); + while (stack.length > 0) { + var node = stack.pop(); - geometry.setIndex(indices); + // 2 bits per children, 16 bit total + var childAllocationMap = dataStream.readUint16(); + + // Insert all children and leaves + var index = 8; + while (index !== 0) { + --index; + var allocation = (childAllocationMap & 3 << 2 * index) >> 2 * index; + if (allocation !== this._BINARY_UNALLOCATED) { + var child = this._newNode(); + var fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); + fn(child); + node.createChildNodeAt(child, index); + if (allocation === this._BINARY_HAS_CHILDREN) { + stack.push(child); + } + } + } + } + } + }, { + key: "read", + value: + /** + * Reads a full tree (with node data) from a message. + * A pacjet starts with the node data, followed by the allocation map of their children. + * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData + */ + function read(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + var dataStream = new InStream(data, true); + var stack = new Array(); + stack.push(this._rootNode); + while (stack.length > 0) { + var node = stack.pop(); - var mesh = new THREE.Mesh(geometry, material); - this.object = new THREE.Object3D(); - this.object.add(mesh); -}; -OcTreeBase.prototype._traverseLeaves = function _traverseLeaves (callback) { - var stack = new Array(); - stack.push({ node: this._rootNode, depth: 0, key: [0, 0, 0] }); - - while (stack.length > 0) { - var current = stack.pop(); - if (current.node.isLeafNode()) { - callback(current.node, current.key, current.depth - 1); - } else { - for (var index = 0; index < 8; ++index) { - if (current.node.hasChildAt(index)) { - var key = this._computeKeyFromChildIdx(index, current.key, current.depth); - stack.push({ - node: current.node.getChildAt(index), - depth: current.depth + 1, - key: key - }); + // Data comes first + this._readNodeData(dataStream, node); + var childAllocationMap = dataStream.readUint8(); + + // Insert all children and leaves + var index = 8; + while (index !== 0) { + --index; + var hasChild = childAllocationMap & 1 << index; + if (hasChild) { + var child = this._newNode(); + child.value = null; + node.createChildNodeAt(child, index); + stack.push(child); + } } } } - } -}; -/** - * Abstract function; to implement different coloring schemes - */ -OcTreeBase.prototype._obtainColor = function _obtainColor (node) { - return this.color; -}; -OcTreeBase.prototype._checkOccupied = function _checkOccupied (node) { - return node.value !== false; -}; -OcTreeBase.prototype._buildFaces = function _buildFaces () { - var this$1$1 = this; - - var geometry = { - vertices: [], - indices: [], - normals: [], - colors: [], - - _insertFace: function (face, pos, size, color) { - var ref, ref$1; - - var indexCount = this.vertices.length / 3; - - face.vertices.forEach(function(vertex) { - this.vertices.push( - pos[0] + vertex[0] * size, - pos[1] + vertex[1] * size, - pos[2] + vertex[2] * size - ); + }, { + key: "_readNodeData", + value: + /** + * Abstract function; Reads and sets data of a node + */ + function _readNodeData(dataStream, node) { + // This needs to be implemented by specialized tree + console.error('Not implemented'); + } + }, { + key: "buildGeometry", + value: + /** + * Builds up THREE.js geometry from tree data. + */ + function buildGeometry() { + console.assert(this._rootNode !== null, 'No tree data'); + var _this$_buildFaces = this._buildFaces(), + vertices = _this$_buildFaces.vertices, + normals = _this$_buildFaces.normals, + colors = _this$_buildFaces.colors, + indices = _this$_buildFaces.indices; + var geometry = new BufferGeometry(); + var material = new MeshBasicMaterial({ + color: 'white', + flatShading: true, + vertexColors: true, + transparent: this.opacity < 1.0, + opacity: this.opacity }); - - var colorArr = [color.r, color.g, color.b]; - - (ref = this.colors).push.apply(ref, colorArr.concat( colorArr, colorArr, colorArr )); - (ref$1 = this.normals).push.apply(ref$1, ( face.normal ).concat( face.normal, face.normal, face.normal )); - - this.indices.push( - indexCount, indexCount + 1, indexCount + 2, - indexCount + 2, indexCount + 1, indexCount + 3 - ); - }, - - _checkNeighborsTouchingFace: function (face, neighborNode, voxelRenderMode) { - // Finds if there's not a node at a given position, aka a 'hole' + geometry.addAttribute('position', new BufferAttribute(new Float32Array(vertices), 3)); + geometry.addAttribute('normal', new BufferAttribute(new Float32Array(normals), 3)); + geometry.addAttribute('color', new BufferAttribute(new Float32Array(colors), 3)); + geometry.setIndex(indices); + var mesh = new Mesh(geometry, material); + this.object = new Object3D(); + this.object.add(mesh); + } + }, { + key: "_traverseLeaves", + value: function _traverseLeaves(callback) { var stack = new Array(); - stack.push(neighborNode); - var loop = function () { - var node = stack.pop(); - if (node.hasChildren()) { - face.childIndex.forEach(function(childIndex) { - if (node.hasChildAt(childIndex)) { - var child = node.getChildAt(childIndex); - - // filter occupancy - var isOccupied = this._checkOccupied(node); - var isNeedsToRender = (isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED) || (!isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE); - - if (isNeedsToRender) { stack.push(child); } - } - else { - return true; + stack.push({ + node: this._rootNode, + depth: 0, + key: [0, 0, 0] + }); + while (stack.length > 0) { + var current = stack.pop(); + if (current.node.isLeafNode()) { + callback(current.node, current.key, current.depth - 1); + } else { + for (var index = 0; index < 8; ++index) { + if (current.node.hasChildAt(index)) { + var key = this._computeKeyFromChildIdx(index, current.key, current.depth); + stack.push({ + node: current.node.getChildAt(index), + depth: current.depth + 1, + key: key + }); } + } + } + } + } + }, { + key: "_obtainColor", + value: + /** + * Abstract function; to implement different coloring schemes + */ + function _obtainColor(node) { + return this.color; + } + }, { + key: "_checkOccupied", + value: function _checkOccupied(node) { + return node.value !== false; + } + }, { + key: "_buildFaces", + value: function _buildFaces() { + var _this4 = this; + var geometry = { + vertices: [], + indices: [], + normals: [], + colors: [], + _insertFace: function _insertFace(face, pos, size, color) { + var _this$colors, _this$normals; + var indexCount = this.vertices.length / 3; + face.vertices.forEach(function (vertex) { + this.vertices.push(pos[0] + vertex[0] * size, pos[1] + vertex[1] * size, pos[2] + vertex[2] * size); }); + var colorArr = [color.r, color.g, color.b]; + (_this$colors = this.colors).push.apply(_this$colors, colorArr.concat(colorArr, colorArr, colorArr)); + (_this$normals = this.normals).push.apply(_this$normals, _toConsumableArray(face.normal).concat(_toConsumableArray(face.normal), _toConsumableArray(face.normal), _toConsumableArray(face.normal))); + this.indices.push(indexCount, indexCount + 1, indexCount + 2, indexCount + 2, indexCount + 1, indexCount + 3); + }, + _checkNeighborsTouchingFace: function _checkNeighborsTouchingFace(face, neighborNode, voxelRenderMode) { + // Finds if there's not a node at a given position, aka a 'hole' + var stack = new Array(); + stack.push(neighborNode); + var _loop = function _loop() { + var node = stack.pop(); + if (node.hasChildren()) { + face.childIndex.forEach(function (childIndex) { + if (node.hasChildAt(childIndex)) { + var child = node.getChildAt(childIndex); + + // filter occupancy + var isOccupied = this._checkOccupied(node); + var isNeedsToRender = isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED || !isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE; + if (isNeedsToRender) { + stack.push(child); + } + } else { + return true; + } + }); + } + }; + while (stack.length !== 0) { + _loop(); + } + return false; } }; + this._traverseLeaves(function (node, key, depth) { + var pos = _this4._computeCoordFromKey(key); + var size = _this4.nodeSizeTable[depth]; + var diff = _this4._treeDepth - depth; + var isOccupied = _this4._checkOccupied(node); + + // By default it will show ALL + // Hide free voxels if set + if (!isOccupied && _this4.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { + return; + } - while (stack.length !== 0) loop(); - return false; - } - - }; - - this._traverseLeaves(function (node, key, depth) { - var pos = this$1$1._computeCoordFromKey(key); - var size = this$1$1.nodeSizeTable[depth]; - var diff = this$1$1._treeDepth - depth; - - var isOccupied = this$1$1._checkOccupied(node); - - // By default it will show ALL - // Hide free voxels if set - if (!isOccupied && this$1$1.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { return; } - - // Hide occuped voxels if set. - if (isOccupied && this$1$1.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { return; } - - this$1$1._FACES.forEach(function(face) { - // Add geometry where there is no neighbor voxel - var neighborKey = [ - key[0] + face.normal[0] * diff * diff, - key[1] + face.normal[1] * diff * diff, - key[2] + face.normal[2] * diff * diff ]; - var neighborNode = this.searchAtDepth(neighborKey); - if (neighborNode === null) { - // 1. Simply add geometry where there is no neighbors - geometry._insertFace(face, pos, size, this._obtainColor(node)); - } else if (depth < this._treeDepth) { - // 2. Special case, when a node (voxel) is not on the lowest level - // of the tree, but also need to add a geometry, because might - // not be "fully covered" by neighboring voxels on the lowest level - - if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) ; - } - - }); - - }); + // Hide occuped voxels if set. + if (isOccupied && _this4.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { + return; + } + _this4._FACES.forEach(function (face) { + // Add geometry where there is no neighbor voxel + var neighborKey = [key[0] + face.normal[0] * diff * diff, key[1] + face.normal[1] * diff * diff, key[2] + face.normal[2] * diff * diff]; + var neighborNode = this.searchAtDepth(neighborKey); + if (neighborNode === null) { + // 1. Simply add geometry where there is no neighbors + geometry._insertFace(face, pos, size, this._obtainColor(node)); + } else if (depth < this._treeDepth) { + // 2. Special case, when a node (voxel) is not on the lowest level + // of the tree, but also need to add a geometry, because might + // not be "fully covered" by neighboring voxels on the lowest level + + if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) ; + } + }); + }); - // return geometry; - return { - vertices: geometry.vertices, - normals: geometry.normals, - colors: geometry.colors, - indices: geometry.indices - }; + // return geometry; + return { + vertices: geometry.vertices, + normals: geometry.normals, + colors: geometry.colors, + indices: geometry.indices + }; + } + }]); +}(); -}; +function _callSuper$h(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$h() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$h() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$h = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ -var OcTree = /*@__PURE__*/(function (OcTreeBase) { - function OcTree(options) { - OcTreeBase.call(this, options); - - this._defaultOccupiedValue = 1.; - this._defaultFreeValue = -1.; - - this.occupancyThreshold = (typeof options.occupancyThreshold !== 'undefined') ? options.occupancyThreshold : 0.0000001; - - this.useFlatColoring = (typeof options.colorMode !== 'undefined') && options.colorMode === OcTreeColorMode.SOLID; - - this.palette = (typeof options.palette !== 'undefined') ? options.palette.map(function (color) { return new THREE.Color(color); }) : - [ - { r: 0, g: 0, b: 128, }, // dark blue (low) - { r: 0, g: 255, b: 0, }, // green - { r: 255, g: 255, b: 0, }, // yellow (mid) - { r: 255, g: 128, b: 0, }, // orange - { r: 255, g: 0, b: 0, } // red (high) - ]; +var OcTree = /*#__PURE__*/function (_OcTreeBase) { + /** + * Specilaization of BaseOcTree + * + * @constructor + * @param options - object with following keys: + * * inherited from BaseOctree + * * occupancyThreshold (optional) - threshold value that separates occupied and free voxels from each other. (Default: 0) + * * colorMode (optional) - Coloring mode @see ROS3D.OcTreeColorMode. + * * palette (optional) - Palette used for false-coloring (default: predefined palette) + * * paletteSclae (optional) - Scale of palette to represent a wider range of values (default: 1.) + */ - this.paletteScale = (typeof options.paletteScale !== 'undefined') ? options.paletteScale : 1.; + function OcTree(options) { + var _this; + _classCallCheck(this, OcTree); + _this = _callSuper$h(this, OcTree, [options]); + _this._defaultOccupiedValue = 1.; + _this._defaultFreeValue = -1.; + _this.occupancyThreshold = typeof options.occupancyThreshold !== 'undefined' ? options.occupancyThreshold : 0.0000001; + _this.useFlatColoring = typeof options.colorMode !== 'undefined' && options.colorMode === OcTreeColorMode.SOLID; + _this.palette = typeof options.palette !== 'undefined' ? options.palette.map(function (color) { + return new Color(color); + }) : [{ + r: 0, + g: 0, + b: 128 + }, + // dark blue (low) + { + r: 0, + g: 255, + b: 0 + }, + // green + { + r: 255, + g: 255, + b: 0 + }, + // yellow (mid) + { + r: 255, + g: 128, + b: 0 + }, + // orange + { + r: 255, + g: 0, + b: 0 + } // red (high) + ]; + _this.paletteScale = typeof options.paletteScale !== 'undefined' ? options.paletteScale : 1.; + return _this; } - - if ( OcTreeBase ) OcTree.__proto__ = OcTreeBase; - OcTree.prototype = Object.create( OcTreeBase && OcTreeBase.prototype ); - OcTree.prototype.constructor = OcTree; - - OcTree.prototype._readNodeData = function _readNodeData (dataStream, node) { - node.value = dataStream.readFloat32(); - }; - OcTree.prototype._obtainColor = function _obtainColor (node) { - if (this.useFlatColoring) { - return this.color; + _inherits(OcTree, _OcTreeBase); + return _createClass(OcTree, [{ + key: "_readNodeData", + value: function _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); } + }, { + key: "_obtainColor", + value: function _obtainColor(node) { + if (this.useFlatColoring) { + return this.color; + } - // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range - var value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize - - var intVal = Math.trunc(value); - var fracVal = value - intVal; - - if (intVal < 0) { return this.palette[0]; } - if (intVal >= this.palette.length - 1) { return this.palette[this.palette.length - 1]; } + // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range + var value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize - // Simple lerp - return { - r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, - g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, - b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b, - }; + var intVal = Math.trunc(value); + var fracVal = value - intVal; + if (intVal < 0) { + return this.palette[0]; + } + if (intVal >= this.palette.length - 1) { + return this.palette[this.palette.length - 1]; + } - }; - OcTree.prototype._checkOccupied = function _checkOccupied (node) { - return node.value >= this.occupancyThreshold; - }; + // Simple lerp + return { + r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, + g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, + b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b + }; + } + }, { + key: "_checkOccupied", + value: function _checkOccupied(node) { + return node.value >= this.occupancyThreshold; + } + }]); +}(OcTreeBase); - return OcTree; -}(OcTreeBase)); +function _callSuper$g(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$g() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$g() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$g = function _isNativeReflectConstruct() { return !!t; })(); } +var ColorOcTree = /*#__PURE__*/function (_OcTree) { + /** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ -var ColorOcTree = /*@__PURE__*/(function (OcTree) { function ColorOcTree(options) { - OcTree.call(this, options); - this.useOwnColor = (typeof options.palette !== 'undefined') && options.colorMode === OcTreeColorMode.COLOR; + var _this; + _classCallCheck(this, ColorOcTree); + _this = _callSuper$g(this, ColorOcTree, [options]); + _this.useOwnColor = typeof options.palette !== 'undefined' && options.colorMode === OcTreeColorMode.COLOR; + return _this; } + _inherits(ColorOcTree, _OcTree); + return _createClass(ColorOcTree, [{ + key: "_readNodeData", + value: function _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); // occupancy + node.color = { + r: dataStream.readUint8(), + // red + g: dataStream.readUint8(), + // green + b: dataStream.readUint8() // blue + }; + } + }, { + key: "_obtainColor", + value: function _obtainColor(node) { + if (!this.useOwnColor) { + return OcTree.prototype._obtainColor.call(this, node); + } + return node.color; + } + }]); +}(OcTree); - if ( OcTree ) ColorOcTree.__proto__ = OcTree; - ColorOcTree.prototype = Object.create( OcTree && OcTree.prototype ); - ColorOcTree.prototype.constructor = ColorOcTree; - - ColorOcTree.prototype._readNodeData = function _readNodeData (dataStream, node) { - node.value = dataStream.readFloat32(); // occupancy - node.color = { - r: dataStream.readUint8(), // red - g: dataStream.readUint8(), // green - b: dataStream.readUint8(), // blue - }; - - }; - ColorOcTree.prototype._obtainColor = function _obtainColor (node) { - if (!this.useOwnColor) { return OcTree.prototype._obtainColor.call(this, node); } - return node.color; - }; - - return ColorOcTree; -}(OcTree)); +function _callSuper$f(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$f() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$f() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$f = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ -var OcTreeClient = /*@__PURE__*/(function (EventEmitter3) { +var OcTreeClient = /*#__PURE__*/function (_EventEmitter) { + /** + * An OcTree client that listens to a given OcTree topic. + * + * Emits the following events: + * + * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic (optional) - the map topic to listen to + * * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM) + * * tfClient (optional) - the TF client handle to use for a scene node + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to + * * offsetPose (optional) - offset pose of the mao visualization, e.g. for z-offset (ROSLIB.Pose type) + * * colorMode (optional)) - colorization mode for each voxels @see RORS3D.OcTreeColorMode (default 'color') + * * color (optional) - color of the visualized map (if solid coloring option was set). Can be any value accepted by THREE.Color + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + * * palette (optional) - list of RGB colors to be used as palette (THREE.Color) + * * paletteScale (optional) - scale favtor of palette to cover wider range of values. (default: 1) + * * voxelRenderMode (optional)- toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode. (default `occupid`) + * + */ + function OcTreeClient(options) { - EventEmitter3.call(this); + var _this; + _classCallCheck(this, OcTreeClient); + _this = _callSuper$f(this, OcTreeClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/octomap'; - this.compression = options.compression || 'cbor'; - this.continuous = options.continuous; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.offsetPose = options.offsetPose || new ROSLIB.Pose(); + _this.ros = options.ros; + _this.topicName = options.topic || '/octomap'; + _this.compression = options.compression || 'cbor'; + _this.continuous = options.continuous; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.offsetPose = options.offsetPose || new ROSLIB.Pose(); // Options passed to converter - this.options = {}; + _this.options = {}; // Append only when it was set, otherwise defaults are provided by the underlying layer - if (typeof options.color !== 'undefined') { this.options['color'] = options.color; } - if (typeof options.opacity !== 'undefined') { this.options['opacity'] = options.opacity; } - if (typeof options.colorMode !== 'undefined') { this.options['colorMode'] = options.colorMode; } - if (typeof options.palette !== 'undefined') { this.options['palette'] = options.palette; } - if (typeof options.paletteScale !== 'undefined') { this.options['paletteScale'] = options.palette; } - if (typeof options.voxelRenderMode !== 'undefined') { this.options['voxelRenderMode'] = options.voxelRenderMode; } + if (typeof options.color !== 'undefined') { + _this.options['color'] = options.color; + } + if (typeof options.opacity !== 'undefined') { + _this.options['opacity'] = options.opacity; + } + if (typeof options.colorMode !== 'undefined') { + _this.options['colorMode'] = options.colorMode; + } + if (typeof options.palette !== 'undefined') { + _this.options['palette'] = options.palette; + } + if (typeof options.paletteScale !== 'undefined') { + _this.options['paletteScale'] = options.palette; + } + if (typeof options.voxelRenderMode !== 'undefined') { + _this.options['voxelRenderMode'] = options.voxelRenderMode; + } // current grid that is displayed - this.currentMap = null; + _this.currentMap = null; // subscribe to the topic - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( EventEmitter3 ) OcTreeClient.__proto__ = EventEmitter3; - OcTreeClient.prototype = Object.create( EventEmitter3 && EventEmitter3.prototype ); - OcTreeClient.prototype.constructor = OcTreeClient; - - OcTreeClient.prototype.unsubscribe = function unsubscribe () { - if (this.rosTopic) { - this.rosTopic.unsubscribe(this.processMessageBound); - } - }; - OcTreeClient.prototype.subscribe = function subscribe () { - this.unsubscribe(); - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros: this.ros, - name: this.topicName, - messageType: 'octomap_msgs/Octomap', - queue_length: 1, - compression: this.compression - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - OcTreeClient.prototype.processMessage = function processMessage (message) { - // check for an old map - if (this.currentMap) { - if (this.currentMap.tfClient) { - this.currentMap.unsubscribeTf(); + _inherits(OcTreeClient, _EventEmitter); + return _createClass(OcTreeClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); } } - - this._processMessagePrivate(message); - - if (!this.continuous) { - this.rosTopic.unsubscribe(this.processMessageBound); + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'octomap_msgs/Octomap', + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessageBound); } - }; - - OcTreeClient.prototype._loadOcTree = function _loadOcTree (message) { - - return new Promise( - function (resolve, reject) { - + }, { + key: "processMessage", + value: function processMessage(message) { + // check for an old map + if (this.currentMap) { + if (this.currentMap.tfClient) { + this.currentMap.unsubscribeTf(); + } + } + this._processMessagePrivate(message); + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessageBound); + } + } + }, { + key: "_loadOcTree", + value: function _loadOcTree(message) { + return new Promise(function (resolve, reject) { // 1. Create the corresponding octree object from message var options = Object.assign({ - resolution: message.resolution, + resolution: message.resolution }, this.options); - var newOcTree = null; { if (message.binary) { - newOcTree = new OcTreeBase( - options - ); + newOcTree = new OcTreeBase(options); newOcTree.readBinary(message.data); } else { - var ctorTable = { 'OcTree': OcTree, - 'ColorOcTree': ColorOcTree, + 'ColorOcTree': ColorOcTree }; - if (message.id in ctorTable) { console.log(message.id, ctorTable); - - newOcTree = new ctorTable[message.id]( - options - ); - + newOcTree = new ctorTable[message.id](options); newOcTree.read(message.data); } - } } - { newOcTree.buildGeometry(); } - resolve(newOcTree); }.bind(this)); - - }; - OcTreeClient.prototype._processMessagePrivate = function _processMessagePrivate (message) { - var promise = this._loadOcTree(message); - - promise.then( + } + }, { + key: "_processMessagePrivate", + value: function _processMessagePrivate(message) { + var promise = this._loadOcTree(message); + promise.then( // 3. Replace geometry function (newOcTree) { // check if we care about the scene @@ -55047,543 +47383,643 @@ var OcTreeClient = /*@__PURE__*/(function (EventEmitter3) { this.sceneNode = newOcTree.object; this.currentMap = newOcTree; } - this.rootObject.remove(oldNode); this.rootObject.add(this.sceneNode); - this.emit('change'); - }.bind(this) - ); - }; + }.bind(this)); + } + }]); +}(EventEmitter2); - return OcTreeClient; -}(EventEmitter3)); +function _callSuper$e(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$e() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$e() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$e = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David V. Lu!! - davidvlu@gmail.com */ -var Odometry = /*@__PURE__*/(function (superclass) { +var Odometry = /*#__PURE__*/function (_THREE$Object3D) { + /** + * An Odometry client + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * keep (optional) - number of markers to keep around (default: 1) + * * color (optional) - color for line (default: 0xcc00ff) + * * length (optional) - the length of the arrow (default: 1.0) + * * headLength (optional) - the head length of the arrow (default: 0.2) + * * shaftDiameter (optional) - the shaft diameter of the arrow (default: 0.05) + * * headDiameter (optional) - the head diameter of the arrow (default: 0.1) + */ function Odometry(options) { - superclass.call(this); - this.options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/particlecloud'; - this.tfClient = options.tfClient; - this.color = options.color || 0xcc00ff; - this.length = options.length || 1.0; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.keep = options.keep || 1; - - this.sns = []; - - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + var _this; + _classCallCheck(this, Odometry); + _this = _callSuper$e(this, Odometry); + _this.options = options || {}; + _this.ros = options.ros; + _this.topicName = options.topic || '/particlecloud'; + _this.tfClient = options.tfClient; + _this.color = options.color || 0xcc00ff; + _this.length = options.length || 1.0; + _this.rootObject = options.rootObject || new Object3D(); + _this.keep = options.keep || 1; + _this.sns = []; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) Odometry.__proto__ = superclass; - Odometry.prototype = Object.create( superclass && superclass.prototype ); - Odometry.prototype.constructor = Odometry; - - Odometry.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(Odometry, _THREE$Object3D); + return _createClass(Odometry, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - Odometry.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'nav_msgs/Odometry' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - Odometry.prototype.processMessage = function processMessage (message){ - if(this.sns.length >= this.keep) { + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'nav_msgs/Odometry' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + if (this.sns.length >= this.keep) { this.sns[0].unsubscribeTf(); this.rootObject.remove(this.sns[0]); this.sns.shift(); + } + this.options.origin = new Vector3(message.pose.pose.position.x, message.pose.pose.position.y, message.pose.pose.position.z); + var rot = new Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, message.pose.pose.orientation.z, message.pose.pose.orientation.w); + this.options.direction = new Vector3(1, 0, 0); + this.options.direction.applyQuaternion(rot); + this.options.material = new MeshBasicMaterial({ + color: this.color + }); + var arrow = new Arrow(this.options); + this.sns.push(new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: arrow + })); + this.rootObject.add(this.sns[this.sns.length - 1]); } + }]); +}(Object3D); - this.options.origin = new THREE.Vector3( message.pose.pose.position.x, message.pose.pose.position.y, - message.pose.pose.position.z); - - var rot = new THREE.Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, - message.pose.pose.orientation.z, message.pose.pose.orientation.w); - this.options.direction = new THREE.Vector3(1,0,0); - this.options.direction.applyQuaternion(rot); - this.options.material = new THREE.MeshBasicMaterial({color: this.color}); - var arrow = new Arrow(this.options); - - this.sns.push(new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : arrow - })); - - this.rootObject.add(this.sns[ this.sns.length - 1]); - }; - - return Odometry; -}(THREE.Object3D)); +function _callSuper$d(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$d() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$d() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$d = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David V. Lu!! - davidvlu@gmail.com */ -var Path = /*@__PURE__*/(function (superclass) { +var Path = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A Path client that listens to a given topic and displays a line connecting the poses. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * color (optional) - color for line (default: 0xcc00ff) + */ function Path(options) { - superclass.call(this); + var _this; + _classCallCheck(this, Path); + _this = _callSuper$d(this, Path); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/path'; - this.tfClient = options.tfClient; - this.color = options.color || 0xcc00ff; - this.rootObject = options.rootObject || new THREE.Object3D(); - - this.sn = null; - this.line = null; - - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.ros = options.ros; + _this.topicName = options.topic || '/path'; + _this.tfClient = options.tfClient; + _this.color = options.color || 0xcc00ff; + _this.rootObject = options.rootObject || new Object3D(); + _this.sn = null; + _this.line = null; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) Path.__proto__ = superclass; - Path.prototype = Object.create( superclass && superclass.prototype ); - Path.prototype.constructor = Path; - - Path.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(Path, _THREE$Object3D); + return _createClass(Path, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - Path.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'nav_msgs/Path' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - Path.prototype.processMessage = function processMessage (message){ - if(this.sn!==null){ + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'nav_msgs/Path' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + if (this.sn !== null) { this.sn.unsubscribeTf(); this.rootObject.remove(this.sn); - } - - var lineGeometry = new THREE.Geometry(); - for(var i=0; i= message.range_min && range <= message.range_max){ + }, { + key: "processMessage", + value: function processMessage(message) { + if (!this.points.setup(message.header.frame_id)) { + return; + } + var n = message.ranges.length; + var j = 0; + for (var i = 0; i < n; i += this.points.pointRatio) { + var range = message.ranges[i]; + if (range >= message.range_min && range <= message.range_max) { var angle = message.angle_min + i * message.angle_increment; this.points.positions.array[j++] = range * Math.cos(angle); this.points.positions.array[j++] = range * Math.sin(angle); this.points.positions.array[j++] = 0.0; + } } + this.points.update(j / 3); } - this.points.update(j/3); - }; + }]); +}(Object3D); - return LaserScan; -}(THREE.Object3D)); +function _callSuper$5(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$5() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$5() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$5 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Mathieu Bredif - mathieu.bredif@ign.fr */ -var NavSatFix = /*@__PURE__*/(function (superclass) { +var NavSatFix = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A NavSatFix client that listens to a given topic and displays a line connecting the gps fixes. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the NavSatFix topic to listen to + * * rootObject (optional) - the root object to add the trajectory line and the gps marker to + * * object3d (optional) - the object3d to be translated by the gps position + * * material (optional) - THREE.js material or options passed to a THREE.LineBasicMaterial, such as : + * * material.color (optional) - color for line + * * material.linewidth (optional) - line width + * * altitudeNaN (optional) - default altitude when the message altitude is NaN (default: 0) + * * keep (optional) - number of gps fix points to keep (default: 100) + * * convert (optional) - conversion function from lon/lat/alt to THREE.Vector3 (default: passthrough) + */ + function NavSatFix(options) { - - superclass.call(this); + var _this; + _classCallCheck(this, NavSatFix); + _this = _callSuper$5(this, NavSatFix); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/gps/fix'; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.object3d = options.object3d || new THREE.Object3D(); + _this.ros = options.ros; + _this.topicName = options.topic || '/gps/fix'; + _this.rootObject = options.rootObject || new Object3D(); + _this.object3d = options.object3d || new Object3D(); var material = options.material || {}; - this.altitudeNaN = options.altitudeNaN || 0; - this.keep = options.keep || 100; - this.convert = options.convert || function(lon,lat,alt) { return new THREE.Vector3(lon,lat,alt); }; - this.count = 0; - this.next1 = 0; - this.next2 = this.keep; - - this.geom = new THREE.BufferGeometry(); - this.vertices = new THREE.BufferAttribute(new Float32Array( 6 * this.keep ), 3 ); - this.geom.addAttribute( 'position', this.vertices); - this.material = material.isMaterial ? material : new THREE.LineBasicMaterial( material ); - this.line = new THREE.Line( this.geom, this.material ); - this.rootObject.add(this.object3d); - this.rootObject.add(this.line); - - this.rosTopic = undefined; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.altitudeNaN = options.altitudeNaN || 0; + _this.keep = options.keep || 100; + _this.convert = options.convert || function (lon, lat, alt) { + return new Vector3(lon, lat, alt); + }; + _this.count = 0; + _this.next1 = 0; + _this.next2 = _this.keep; + _this.geom = new BufferGeometry(); + _this.vertices = new BufferAttribute(new Float32Array(6 * _this.keep), 3); + _this.geom.addAttribute('position', _this.vertices); + _this.material = material.isMaterial ? material : new LineBasicMaterial(material); + _this.line = new Line(_this.geom, _this.material); + _this.rootObject.add(_this.object3d); + _this.rootObject.add(_this.line); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) NavSatFix.__proto__ = superclass; - NavSatFix.prototype = Object.create( superclass && superclass.prototype ); - NavSatFix.prototype.constructor = NavSatFix; - - NavSatFix.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(NavSatFix, _THREE$Object3D); + return _createClass(NavSatFix, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - NavSatFix.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'sensor_msgs/NavSatFix' - }); + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'sensor_msgs/NavSatFix' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; + var p = this.convert(message.longitude, message.latitude, altitude); + + // move the object3d to the gps position + this.object3d.position.copy(p); + this.object3d.updateMatrixWorld(true); + + // copy the position twice in the circular buffer + // the second half replicates the first to allow a single drawRange + this.vertices.array[3 * this.next1] = p.x; + this.vertices.array[3 * this.next1 + 1] = p.y; + this.vertices.array[3 * this.next1 + 2] = p.z; + this.vertices.array[3 * this.next2] = p.x; + this.vertices.array[3 * this.next2 + 1] = p.y; + this.vertices.array[3 * this.next2 + 2] = p.z; + this.vertices.needsUpdate = true; + this.next1 = (this.next1 + 1) % this.keep; + this.next2 = this.next1 + this.keep; + this.count = Math.min(this.count + 1, this.keep); + this.geom.setDrawRange(this.next2 - this.count, this.count); + } + }]); +}(Object3D); - this.rosTopic.subscribe(this.processMessageBound); - }; - NavSatFix.prototype.processMessage = function processMessage (message){ - var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; - var p = this.convert(message.longitude, message.latitude, altitude); - - // move the object3d to the gps position - this.object3d.position.copy(p); - this.object3d.updateMatrixWorld(true); - - // copy the position twice in the circular buffer - // the second half replicates the first to allow a single drawRange - this.vertices.array[3*this.next1 ] = p.x; - this.vertices.array[3*this.next1+1] = p.y; - this.vertices.array[3*this.next1+2] = p.z; - this.vertices.array[3*this.next2 ] = p.x; - this.vertices.array[3*this.next2+1] = p.y; - this.vertices.array[3*this.next2+2] = p.z; - this.vertices.needsUpdate = true; - - this.next1 = (this.next1+1) % this.keep; - this.next2 = this.next1 + this.keep; - this.count = Math.min(this.count+1, this.keep); - this.geom.setDrawRange(this.next2-this.count, this.count ); - }; - - return NavSatFix; -}(THREE.Object3D)); +function _callSuper$4(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$4() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$4() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$4 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -55854,156 +48350,200 @@ var NavSatFix = /*@__PURE__*/(function (superclass) { * returns the number of decoded records */ function decode64(inbytes, outbytes, record_size, pointRatio) { - var x,b=0,l=0,j=0,L=inbytes.length,A=outbytes.length; - record_size = record_size || A; // default copies everything (no skipping) - pointRatio = pointRatio || 1; // default copies everything (no skipping) - var bitskip = (pointRatio-1) * record_size * 8; - for(x=0;x=8){ - l-=8; - outbytes[j++]=(b>>>l)&0xff; - if((j % record_size) === 0) { // skip records - // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} - // first optimization: for(;l0){b=decode64.e[inbytes.charAt(x)];} - } + var x, + b = 0, + l = 0, + j = 0, + L = inbytes.length, + A = outbytes.length; + record_size = record_size || A; // default copies everything (no skipping) + pointRatio = pointRatio || 1; // default copies everything (no skipping) + var bitskip = (pointRatio - 1) * record_size * 8; + for (x = 0; x < L && j < A; x++) { + b = (b << 6) + decode64.e[inbytes.charAt(x)]; + l += 6; + if (l >= 8) { + l -= 8; + outbytes[j++] = b >>> l & 0xff; + if (j % record_size === 0) { + // skip records + // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} + // first optimization: for(;l 0) { + b = decode64.e[inbytes.charAt(x)]; } + } } - return Math.floor(j/record_size); + } + return Math.floor(j / record_size); } // initialize decoder with static lookup table 'e' -decode64.S='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; -decode64.e={}; -for(var i=0;i<64;i++){decode64.e[decode64.S.charAt(i)]=i;} - - -var PointCloud2 = /*@__PURE__*/(function (superclass) { +decode64.S = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +decode64.e = {}; +for (var i = 0; i < 64; i++) { + decode64.e[decode64.S.charAt(i)] = i; +} +var PointCloud2 = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A PointCloud2 client that listens to a given topic and displays the points. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to (default: '/points') + * * tfClient - the TF client handle to use + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to use for the points. + * * max_pts (optional) - number of points to draw (default: 10000) + * * pointRatio (optional) - point subsampling ratio (default: 1, no subsampling) + * * messageRatio (optional) - message subsampling ratio (default: 1, no subsampling) + * * material (optional) - a material object or an option to construct a PointsMaterial. + * * colorsrc (optional) - the field to be used for coloring (default: 'rgb') + * * colormap (optional) - function that turns the colorsrc field value to a color + */ function PointCloud2(options) { - superclass.call(this); + var _this; + _classCallCheck(this, PointCloud2); + _this = _callSuper$4(this, PointCloud2); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/points'; - this.throttle_rate = options.throttle_rate || null; - this.compression = options.compression || 'cbor'; - this.max_pts = options.max_pts || 10000; - this.points = new Points(options); - this.rosTopic = undefined; - this.buffer = null; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); + _this.ros = options.ros; + _this.topicName = options.topic || '/points'; + _this.throttle_rate = options.throttle_rate || null; + _this.compression = options.compression || 'cbor'; + _this.max_pts = options.max_pts || 10000; + _this.points = new Points(options); + _this.rosTopic = undefined; + _this.buffer = null; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; } - - if ( superclass ) PointCloud2.__proto__ = superclass; - PointCloud2.prototype = Object.create( superclass && superclass.prototype ); - PointCloud2.prototype.constructor = PointCloud2; - - PointCloud2.prototype.unsubscribe = function unsubscribe (){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _inherits(PointCloud2, _THREE$Object3D); + return _createClass(PointCloud2, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - PointCloud2.prototype.subscribe = function subscribe (){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'sensor_msgs/PointCloud2', - throttle_rate : this.throttle_rate, - queue_length : 1, - compression: this.compression - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - PointCloud2.prototype.processMessage = function processMessage (msg){ - if(!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { - return; + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'sensor_msgs/PointCloud2', + throttle_rate: this.throttle_rate, + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessageBound); } - - var n, pointRatio = this.points.pointRatio; - var bufSz = this.max_pts * msg.point_step; - - if (msg.data.buffer) { - this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); - n = Math.min(msg.height*msg.width / pointRatio, this.points.positions.array.length / 3); - } else { - if (!this.buffer || this.buffer.byteLength < bufSz) { - this.buffer = new Uint8Array(bufSz); + }, { + key: "processMessage", + value: function processMessage(msg) { + if (!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { + return; } - n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); - pointRatio = 1; - } - - var dv = new DataView(this.buffer.buffer); - var littleEndian = !msg.is_bigendian; - var x = this.points.fields.x.offset; - var y = this.points.fields.y.offset; - var z = this.points.fields.z.offset; - var base, color; - for(var i = 0; i < n; i++){ - base = i * pointRatio * msg.point_step; - this.points.positions.array[3*i ] = dv.getFloat32(base+x, littleEndian); - this.points.positions.array[3*i + 1] = dv.getFloat32(base+y, littleEndian); - this.points.positions.array[3*i + 2] = dv.getFloat32(base+z, littleEndian); - - if(this.points.colors){ - color = this.points.colormap(this.points.getColor(dv,base,littleEndian)); - this.points.colors.array[3*i ] = color.r; - this.points.colors.array[3*i + 1] = color.g; - this.points.colors.array[3*i + 2] = color.b; + var n, + pointRatio = this.points.pointRatio; + var bufSz = this.max_pts * msg.point_step; + if (msg.data.buffer) { + this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); + n = Math.min(msg.height * msg.width / pointRatio, this.points.positions.array.length / 3); + } else { + if (!this.buffer || this.buffer.byteLength < bufSz) { + this.buffer = new Uint8Array(bufSz); + } + n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); + pointRatio = 1; + } + var dv = new DataView(this.buffer.buffer); + var littleEndian = !msg.is_bigendian; + var x = this.points.fields.x.offset; + var y = this.points.fields.y.offset; + var z = this.points.fields.z.offset; + var base, color; + for (var i = 0; i < n; i++) { + base = i * pointRatio * msg.point_step; + this.points.positions.array[3 * i] = dv.getFloat32(base + x, littleEndian); + this.points.positions.array[3 * i + 1] = dv.getFloat32(base + y, littleEndian); + this.points.positions.array[3 * i + 2] = dv.getFloat32(base + z, littleEndian); + if (this.points.colors) { + color = this.points.colormap(this.points.getColor(dv, base, littleEndian)); + this.points.colors.array[3 * i] = color.r; + this.points.colors.array[3 * i + 1] = color.g; + this.points.colors.array[3 * i + 2] = color.b; + } } + this.points.update(n); } - this.points.update(n); - }; + }]); +}(Object3D); - return PointCloud2; -}(THREE.Object3D)); +function _callSuper$3(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$3() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$3() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$3 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Jihoon Lee - jihoon.lee@kakaobrain.com */ -var TFAxes = /*@__PURE__*/(function (superclass) { +var TFAxes = /*#__PURE__*/function (_THREE$Object3D) { + /** + * An Axes node can be used to display the axis of a particular coordinate frame. + * + * @constructor + * @param options - object with following keys: + * + * * frame_id - the frame id to visualize axes + * * tfClient - the TF client handle to use + * * shaftRadius (optional) - the radius of the shaft to render + * * headRadius (optional) - the radius of the head to render + * * headLength (optional) - the length of the head to render + * * scale (optional) - the scale of the frame (defaults to 1.0) + * * lineType (optional) - the line type for the axes. Supported line types: + * 'dashed' and 'full'. + * * lineDashLength (optional) - the length of the dashes, relative to the length of the axis. + * Maximum value is 1, which means the dash length is + * equal to the length of the axis. Parameter only applies when + * lineType is set to dashed. + */ function TFAxes(options) { - superclass.call(this); + var _this; + _classCallCheck(this, TFAxes); + _this = _callSuper$3(this, TFAxes); options = options || {}; - - this.frame_id = options.frame_id; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.axes = new Axes( - { - shaftRadius: options.shaftRadius || 0.025, - headRadius: options.headRaidus || 0.07, - headLength: options.headLength || 0.2, - scale: options.scale || 1.0, - lineType: options.lineType || 'full', - lineDashLength: options.lineDashLength || 0.1 - }); - - this.sn = new SceneNode({ - frameID: this.frame_id, - tfClient : this.tfClient, - object : this.axes + _this.frame_id = options.frame_id; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.axes = new Axes({ + shaftRadius: options.shaftRadius || 0.025, + headRadius: options.headRaidus || 0.07, + headLength: options.headLength || 0.2, + scale: options.scale || 1.0, + lineType: options.lineType || 'full', + lineDashLength: options.lineDashLength || 0.1 }); - - this.rootObject.add(this.sn); - + _this.sn = new SceneNode({ + frameID: _this.frame_id, + tfClient: _this.tfClient, + object: _this.axes + }); + _this.rootObject.add(_this.sn); + return _this; } + _inherits(TFAxes, _THREE$Object3D); + return _createClass(TFAxes); +}(Object3D); - if ( superclass ) TFAxes.__proto__ = superclass; - TFAxes.prototype = Object.create( superclass && superclass.prototype ); - TFAxes.prototype.constructor = TFAxes; - - return TFAxes; -}(THREE.Object3D)); +function _callSuper$2(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$2() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct$2() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$2 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -56011,22 +48551,36 @@ var TFAxes = /*@__PURE__*/(function (superclass) { * @author Russell Toris - rctoris@wpi.edu */ -var Urdf = /*@__PURE__*/(function (superclass) { +var Urdf = /*#__PURE__*/function (_THREE$Object3D) { + /** + * A URDF can be used to load a ROSLIB.UrdfModel and its associated models into a 3D object. + * + * @constructor + * @param options - object with following keys: + * + * * urdfModel - the ROSLIB.UrdfModel to load + * * tfClient - the TF client handle to use + * * path (optional) - the base path to the associated Collada models that will be loaded + * * tfPrefix (optional) - the TF prefix to used for multi-robots + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ function Urdf(options) { + var _this; + _classCallCheck(this, Urdf); options = options || {}; var urdfModel = options.urdfModel; var path = options.path || '/'; var tfClient = options.tfClient; var tfPrefix = options.tfPrefix || ''; var loader = options.loader; - - superclass.call(this); + console.log('Path ' + path); + _this = _callSuper$2(this, Urdf); // load all models var links = urdfModel.links; - for ( var l in links) { + for (var l in links) { var link = links[l]; - for( var i=0; i 0) { - target = intersections[0].object; - event3D.intersection = this.lastIntersection = intersections[0]; - } else { - target = this.fallbackTarget; - } - - // if the mouse moves from one object to another (or from/to the 'null' object), notify both - if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { - - // Event Status. TODO: Make it as enum - // 0: Accepted - // 1: Failed - // 2: Continued - var eventStatus = this.notify(target, 'mouseover', event3D); - if (eventStatus === 0) { - this.notify(this.lastTarget, 'mouseout', event3D); - } else if(eventStatus === 1) { - // if target was null or no target has caught our event, fall back + // in the normal case, we need to check what is under the mouse + target = this.lastTarget; + var intersections = []; + intersections = mouseRaycaster.intersectObject(this.rootObject, true); + if (intersections.length > 0) { + target = intersections[0].object; + event3D.intersection = this.lastIntersection = intersections[0]; + } else { target = this.fallbackTarget; - if (target !== this.lastTarget) { - this.notify(target, 'mouseover', event3D); + } + + // if the mouse moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { + // Event Status. TODO: Make it as enum + // 0: Accepted + // 1: Failed + // 2: Continued + var eventStatus = this.notify(target, 'mouseover', event3D); + if (eventStatus === 0) { this.notify(this.lastTarget, 'mouseout', event3D); + } else if (eventStatus === 1) { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(target, 'mouseover', event3D); + this.notify(this.lastTarget, 'mouseout', event3D); + } } } - } - // if the finger moves from one object to another (or from/to the 'null' object), notify both - if (target !== this.lastTarget && domEvent.type.match(/touch/)) { - var toucheventAccepted = this.notify(target, domEvent.type, event3D); - if (toucheventAccepted) { - this.notify(this.lastTarget, 'touchleave', event3D); - this.notify(this.lastTarget, 'touchend', event3D); - } else { - // if target was null or no target has caught our event, fall back - target = this.fallbackTarget; - if (target !== this.lastTarget) { - this.notify(this.lastTarget, 'touchmove', event3D); + // if the finger moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/touch/)) { + var toucheventAccepted = this.notify(target, domEvent.type, event3D); + if (toucheventAccepted) { + this.notify(this.lastTarget, 'touchleave', event3D); this.notify(this.lastTarget, 'touchend', event3D); + } else { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(this.lastTarget, 'touchmove', event3D); + this.notify(this.lastTarget, 'touchend', event3D); + } } } - } - // pass through event - this.notify(target, domEvent.type, event3D); - if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { - this.dragging = true; + // pass through event + this.notify(target, domEvent.type, event3D); + if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { + this.dragging = true; + } + this.lastTarget = target; } - this.lastTarget = target; - }; - /** - * Notify the listener of the type of event that occurred. - * - * @param target - the target of the event - * @param type - the type of event that occurred - * @param event3D - the 3D mouse even information - * @returns if an event was canceled - */ - MouseHandler.prototype.notify = function notify (target, type, event3D) { - // ensure the type is set - // - event3D.type = type; - - // make the event cancelable - event3D.cancelBubble = false; - event3D.continueBubble = false; - event3D.stopPropagation = function() { - event3D.cancelBubble = true; - }; + }, { + key: "notify", + value: + /** + * Notify the listener of the type of event that occurred. + * + * @param target - the target of the event + * @param type - the type of event that occurred + * @param event3D - the 3D mouse even information + * @returns if an event was canceled + */ + function notify(target, type, event3D) { + // ensure the type is set + // + event3D.type = type; + + // make the event cancelable + event3D.cancelBubble = false; + event3D.continueBubble = false; + event3D.stopPropagation = function () { + event3D.cancelBubble = true; + }; - // it hit the selectable object but don't highlight - event3D.continuePropagation = function () { - event3D.continueBubble = true; - }; + // it hit the selectable object but don't highlight + event3D.continuePropagation = function () { + event3D.continueBubble = true; + }; - // walk up graph until event is canceled or root node has been reached - event3D.currentTarget = target; - - while (event3D.currentTarget) { - // try to fire event on object - if (event3D.currentTarget.dispatchEvent - && event3D.currentTarget.dispatchEvent instanceof Function) { - event3D.currentTarget.dispatchEvent(event3D); - if (event3D.cancelBubble) { - this.dispatchEvent(event3D); - return 0; // Event Accepted - } - else if(event3D.continueBubble) { - return 2; // Event Continued + // walk up graph until event is canceled or root node has been reached + event3D.currentTarget = target; + while (event3D.currentTarget) { + // try to fire event on object + if (event3D.currentTarget.dispatchEvent && event3D.currentTarget.dispatchEvent instanceof Function) { + event3D.currentTarget.dispatchEvent(event3D); + if (event3D.cancelBubble) { + this.dispatchEvent(event3D); + return 0; // Event Accepted + } else if (event3D.continueBubble) { + return 2; // Event Continued + } } + // walk up + event3D.currentTarget = event3D.currentTarget.parent; } - // walk up - event3D.currentTarget = event3D.currentTarget.parent; + return 1; // Event Failed } + }]); +}(EventDispatcher); - return 1; // Event Failed - }; - - return MouseHandler; -}(THREE.EventDispatcher)); +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -56520,65 +49131,80 @@ var MouseHandler = /*@__PURE__*/(function (superclass) { * @author AlteredQualia - http://alteredqualia.com */ -var OrbitControls = /*@__PURE__*/(function (superclass) { +var OrbitControls = /*#__PURE__*/function (_THREE$EventDispatche) { + /** + * Behaves like THREE.OrbitControls, but uses right-handed coordinates and z as up vector. + * + * @constructor + * @param scene - the global scene to use + * @param camera - the camera to use + * @param userZoomSpeed (optional) - the speed for zooming + * @param userRotateSpeed (optional) - the speed for rotating + * @param autoRotate (optional) - if the orbit should auto rotate + * @param autoRotateSpeed (optional) - the speed for auto rotating + * @param displayPanAndZoomFrame - whether to display a frame when panning/zooming + * (defaults to true) + * @param lineTypePanAndZoomFrame - line type for the frame that is displayed when + * panning/zooming. Only has effect when + * displayPanAndZoomFrame is set to true. + */ function OrbitControls(options) { - superclass.call(this); - var that = this; + var _this; + _classCallCheck(this, OrbitControls); + _this = _callSuper(this, OrbitControls); + var that = _this; options = options || {}; var scene = options.scene; - this.camera = options.camera; - this.center = new THREE.Vector3(); - this.userZoom = true; - this.userZoomSpeed = options.userZoomSpeed || 1.0; - this.userRotate = true; - this.userRotateSpeed = options.userRotateSpeed || 1.0; - this.autoRotate = options.autoRotate; - this.autoRotateSpeed = options.autoRotateSpeed || 2.0; - this.displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? - true : - !!options.displayPanAndZoomFrame; - this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; + _this.camera = options.camera; + _this.center = new Vector3(); + _this.userZoom = true; + _this.userZoomSpeed = options.userZoomSpeed || 1.0; + _this.userRotate = true; + _this.userRotateSpeed = options.userRotateSpeed || 1.0; + _this.autoRotate = options.autoRotate; + _this.autoRotateSpeed = options.autoRotateSpeed || 2.0; + _this.displayPanAndZoomFrame = options.displayPanAndZoomFrame === undefined ? true : !!options.displayPanAndZoomFrame; + _this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; // In ROS, z is pointing upwards - this.camera.up = new THREE.Vector3(0, 0, 1); + _this.camera.up = new Vector3(0, 0, 1); // internals var pixelsPerRound = 1800; var touchMoveThreshold = 10; - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); - var zoomStart = new THREE.Vector2(); - var zoomEnd = new THREE.Vector2(); - var zoomDelta = new THREE.Vector2(); - var moveStartCenter = new THREE.Vector3(); - var moveStartNormal = new THREE.Vector3(); - var moveStartPosition = new THREE.Vector3(); - var moveStartIntersection = new THREE.Vector3(); + var rotateStart = new Vector2(); + var rotateEnd = new Vector2(); + var rotateDelta = new Vector2(); + var zoomStart = new Vector2(); + var zoomEnd = new Vector2(); + var zoomDelta = new Vector2(); + var moveStartCenter = new Vector3(); + var moveStartNormal = new Vector3(); + var moveStartPosition = new Vector3(); + var moveStartIntersection = new Vector3(); var touchStartPosition = new Array(2); var touchMoveVector = new Array(2); - this.phiDelta = 0; - this.thetaDelta = 0; - this.scale = 1; - this.lastPosition = new THREE.Vector3(); + _this.phiDelta = 0; + _this.thetaDelta = 0; + _this.scale = 1; + _this.lastPosition = new Vector3(); // internal states var STATE = { - NONE : -1, - ROTATE : 0, - ZOOM : 1, - MOVE : 2 + NONE: -1, + ROTATE: 0, + ZOOM: 1, + MOVE: 2 }; var state = STATE.NONE; - - this.axes = new Axes({ - shaftRadius : 0.025, - headRadius : 0.07, - headLength : 0.2, - lineType: this.lineTypePanAndZoomFrame + _this.axes = new Axes({ + shaftRadius: 0.025, + headRadius: 0.07, + headLength: 0.2, + lineType: _this.lineTypePanAndZoomFrame }); - if (this.displayPanAndZoomFrame) { + if (_this.displayPanAndZoomFrame) { // initially not visible - scene.add(this.axes); - this.axes.traverse(function(obj) { + scene.add(_this.axes); + _this.axes.traverse(function (obj) { obj.visible = false; }); } @@ -56591,7 +49217,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { function onMouseDown(event3D) { var event = event3D.domEvent; event.preventDefault(); - switch (event.button) { case 0: state = STATE.ROTATE; @@ -56599,23 +49224,18 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { break; case 1: state = STATE.MOVE; - - moveStartNormal = new THREE.Vector3(0, 0, 1); - var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal = new Vector3(0, 0, 1); + var rMat = new Matrix4().extractRotation(this.camera.matrix); moveStartNormal.applyMatrix4(rMat); - moveStartCenter = that.center.clone(); moveStartPosition = that.camera.position.clone(); - moveStartIntersection = intersectViewPlane(event3D.mouseRay, - moveStartCenter, - moveStartNormal); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, moveStartCenter, moveStartNormal); break; case 2: state = STATE.ZOOM; zoomStart.set(event.clientX, event.clientY); break; } - this.showAxes(); } @@ -56627,38 +49247,28 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { function onMouseMove(event3D) { var event = event3D.domEvent; if (state === STATE.ROTATE) { - rotateEnd.set(event.clientX, event.clientY); rotateDelta.subVectors(rotateEnd, rotateStart); - that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); - rotateStart.copy(rotateEnd); this.showAxes(); } else if (state === STATE.ZOOM) { zoomEnd.set(event.clientX, event.clientY); zoomDelta.subVectors(zoomEnd, zoomStart); - if (zoomDelta.y > 0) { that.zoomIn(); } else { that.zoomOut(); } - zoomStart.copy(zoomEnd); this.showAxes(); - } else if (state === STATE.MOVE) { var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); - if (!intersection) { return; } - - var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), intersection - .clone()); - + var delta = new Vector3().subVectors(moveStartIntersection.clone(), intersection.clone()); that.center.addVectors(moveStartCenter.clone(), delta.clone()); that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); that.update(); @@ -56676,10 +49286,8 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { * @returns the intersection */ function intersectViewPlane(mouseRay, planeOrigin, planeNormal) { - - var vector = new THREE.Vector3(); - var intersection = new THREE.Vector3(); - + var vector = new Vector3(); + var intersection = new Vector3(); vector.subVectors(planeOrigin, mouseRay.origin); var dot = mouseRay.direction.dot(planeNormal); @@ -56690,7 +49298,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { // calc distance to plane var scalar = planeNormal.dot(vector) / dot; - intersection = mouseRay.direction.clone().multiplyScalar(scalar); return intersection; } @@ -56704,7 +49311,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { if (!that.userRotate) { return; } - state = STATE.NONE; } @@ -56717,11 +49323,10 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { if (!that.userZoom) { return; } - var event = event3D.domEvent; // wheelDelta --> Chrome, detail --> Firefox var delta; - if (typeof (event.wheelDelta) !== 'undefined') { + if (typeof event.wheelDelta !== 'undefined') { delta = event.wheelDelta; } else { delta = -event.detail; @@ -56731,7 +49336,6 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { } else { that.zoomOut(); } - this.showAxes(); } @@ -56745,31 +49349,24 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { switch (event.touches.length) { case 1: state = STATE.ROTATE; - rotateStart.set(event.touches[0].pageX - window.scrollX, - event.touches[0].pageY - window.scrollY); + rotateStart.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); break; case 2: state = STATE.NONE; /* ready for move */ - moveStartNormal = new THREE.Vector3(0, 0, 1); - var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal = new Vector3(0, 0, 1); + var rMat = new Matrix4().extractRotation(this.camera.matrix); moveStartNormal.applyMatrix4(rMat); moveStartCenter = that.center.clone(); moveStartPosition = that.camera.position.clone(); - moveStartIntersection = intersectViewPlane(event3D.mouseRay, - moveStartCenter, - moveStartNormal); - touchStartPosition[0] = new THREE.Vector2(event.touches[0].pageX, - event.touches[0].pageY); - touchStartPosition[1] = new THREE.Vector2(event.touches[1].pageX, - event.touches[1].pageY); - touchMoveVector[0] = new THREE.Vector2(0, 0); - touchMoveVector[1] = new THREE.Vector2(0, 0); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, moveStartCenter, moveStartNormal); + touchStartPosition[0] = new Vector2(event.touches[0].pageX, event.touches[0].pageY); + touchStartPosition[1] = new Vector2(event.touches[1].pageX, event.touches[1].pageY); + touchMoveVector[0] = new Vector2(0, 0); + touchMoveVector[1] = new Vector2(0, 0); break; } - this.showAxes(); - event.preventDefault(); } @@ -56781,236 +49378,222 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { function onTouchMove(event3D) { var event = event3D.domEvent; if (state === STATE.ROTATE) { - rotateEnd.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); rotateDelta.subVectors(rotateEnd, rotateStart); - that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); - rotateStart.copy(rotateEnd); this.showAxes(); } else { - touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, - touchStartPosition[0].y - event.touches[0].pageY); - touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, - touchStartPosition[1].y - event.touches[1].pageY); - if (touchMoveVector[0].lengthSq() > touchMoveThreshold && - touchMoveVector[1].lengthSq() > touchMoveThreshold) { - touchStartPosition[0].set(event.touches[0].pageX, - event.touches[0].pageY); - touchStartPosition[1].set(event.touches[1].pageX, - event.touches[1].pageY); - if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && - state !== STATE.ZOOM) { + touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, touchStartPosition[0].y - event.touches[0].pageY); + touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, touchStartPosition[1].y - event.touches[1].pageY); + if (touchMoveVector[0].lengthSq() > touchMoveThreshold && touchMoveVector[1].lengthSq() > touchMoveThreshold) { + touchStartPosition[0].set(event.touches[0].pageX, event.touches[0].pageY); + touchStartPosition[1].set(event.touches[1].pageX, event.touches[1].pageY); + if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && state !== STATE.ZOOM) { state = STATE.MOVE; - } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && - state !== STATE.MOVE) { + } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && state !== STATE.MOVE) { state = STATE.ZOOM; } if (state === STATE.ZOOM) { - var tmpVector = new THREE.Vector2(); - tmpVector.subVectors(touchStartPosition[0], - touchStartPosition[1]); - if (touchMoveVector[0].dot(tmpVector) < 0 && - touchMoveVector[1].dot(tmpVector) > 0) { + var tmpVector = new Vector2(); + tmpVector.subVectors(touchStartPosition[0], touchStartPosition[1]); + if (touchMoveVector[0].dot(tmpVector) < 0 && touchMoveVector[1].dot(tmpVector) > 0) { that.zoomOut(); - } else if (touchMoveVector[0].dot(tmpVector) > 0 && - touchMoveVector[1].dot(tmpVector) < 0) { + } else if (touchMoveVector[0].dot(tmpVector) > 0 && touchMoveVector[1].dot(tmpVector) < 0) { that.zoomIn(); } } } if (state === STATE.MOVE) { - var intersection = intersectViewPlane(event3D.mouseRay, - that.center, - moveStartNormal); + var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); if (!intersection) { return; } - var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), - intersection.clone()); + var delta = new Vector3().subVectors(moveStartIntersection.clone(), intersection.clone()); that.center.addVectors(moveStartCenter.clone(), delta.clone()); that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); that.update(); that.camera.updateMatrixWorld(); } - this.showAxes(); - event.preventDefault(); } } - function onTouchEnd(event3D) { var event = event3D.domEvent; - if (event.touches.length === 1 && - state !== STATE.ROTATE) { + if (event.touches.length === 1 && state !== STATE.ROTATE) { state = STATE.ROTATE; - rotateStart.set(event.touches[0].pageX - window.scrollX, - event.touches[0].pageY - window.scrollY); - } - else { - state = STATE.NONE; + rotateStart.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); + } else { + state = STATE.NONE; } } // add event listeners - this.addEventListener('mousedown', onMouseDown); - this.addEventListener('mouseup', onMouseUp); - this.addEventListener('mousemove', onMouseMove); - this.addEventListener('touchstart', onTouchDown); - this.addEventListener('touchmove', onTouchMove); - this.addEventListener('touchend', onTouchEnd); + _this.addEventListener('mousedown', onMouseDown); + _this.addEventListener('mouseup', onMouseUp); + _this.addEventListener('mousemove', onMouseMove); + _this.addEventListener('touchstart', onTouchDown); + _this.addEventListener('touchmove', onTouchMove); + _this.addEventListener('touchend', onTouchEnd); // Chrome/Firefox have different events here - this.addEventListener('mousewheel', onMouseWheel); - this.addEventListener('DOMMouseScroll', onMouseWheel); + _this.addEventListener('mousewheel', onMouseWheel); + _this.addEventListener('DOMMouseScroll', onMouseWheel); + return _this; } - - if ( superclass ) OrbitControls.__proto__ = superclass; - OrbitControls.prototype = Object.create( superclass && superclass.prototype ); - OrbitControls.prototype.constructor = OrbitControls; - /** - * Display the main axes for 1 second. - */ - OrbitControls.prototype.showAxes = function showAxes () { - var that = this; - - this.axes.traverse(function(obj) { - obj.visible = true; - }); - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - } - this.hideTimeout = setTimeout(function() { - that.axes.traverse(function(obj) { - obj.visible = false; + _inherits(OrbitControls, _THREE$EventDispatche); + return _createClass(OrbitControls, [{ + key: "showAxes", + value: + /** + * Display the main axes for 1 second. + */ + function showAxes() { + var that = this; + this.axes.traverse(function (obj) { + obj.visible = true; }); - that.hideTimeout = false; - }, 1000); - }; - /** - * Rotate the camera to the left by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateLeft = function rotateLeft (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + if (this.hideTimeout) { + clearTimeout(this.hideTimeout); + } + this.hideTimeout = setTimeout(function () { + that.axes.traverse(function (obj) { + obj.visible = false; + }); + that.hideTimeout = false; + }, 1000); } - this.thetaDelta -= angle; - }; - /** - * Rotate the camera to the right by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateRight = function rotateRight (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateLeft", + value: + /** + * Rotate the camera to the left by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateLeft(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta -= angle; } - this.thetaDelta += angle; - }; - /** - * Rotate the camera up by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateUp = function rotateUp (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateRight", + value: + /** + * Rotate the camera to the right by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateRight(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta += angle; } - this.phiDelta -= angle; - }; - /** - * Rotate the camera down by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - OrbitControls.prototype.rotateDown = function rotateDown (angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateUp", + value: + /** + * Rotate the camera up by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateUp(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta -= angle; } - this.phiDelta += angle; - }; - /** - * Zoom in by the given scale. - * - * @param zoomScale (optional) - the scale to zoom in by - */ - OrbitControls.prototype.zoomIn = function zoomIn (zoomScale) { - if (zoomScale === undefined) { - zoomScale = Math.pow(0.95, this.userZoomSpeed); + }, { + key: "rotateDown", + value: + /** + * Rotate the camera down by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateDown(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta += angle; } - this.scale /= zoomScale; - }; - /** - * Zoom out by the given scale. - * - * @param zoomScale (optional) - the scale to zoom in by - */ - OrbitControls.prototype.zoomOut = function zoomOut (zoomScale) { - if (zoomScale === undefined) { - zoomScale = Math.pow(0.95, this.userZoomSpeed); + }, { + key: "zoomIn", + value: + /** + * Zoom in by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + function zoomIn(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale /= zoomScale; } - this.scale *= zoomScale; - }; - /** - * Update the camera to the current settings. - */ - OrbitControls.prototype.update = function update () { - // x->y, y->z, z->x - var position = this.camera.position; - var offset = position.clone().sub(this.center); - - // angle from z-axis around y-axis - var theta = Math.atan2(offset.y, offset.x); - - // angle from y-axis - var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); - - if (this.autoRotate) { - this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + }, { + key: "zoomOut", + value: + /** + * Zoom out by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + function zoomOut(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale *= zoomScale; } - - theta += this.thetaDelta; - phi += this.phiDelta; - - // restrict phi to be between EPS and PI-EPS - var eps = 0.000001; - phi = Math.max(eps, Math.min(Math.PI - eps, phi)); - - var radius = offset.length(); - offset.set( - radius * Math.sin(phi) * Math.cos(theta), - radius * Math.sin(phi) * Math.sin(theta), - radius * Math.cos(phi) - ); - offset.multiplyScalar(this.scale); - - position.copy(this.center).add(offset); - - this.camera.lookAt(this.center); - - radius = offset.length(); - this.axes.position.copy(this.center); - this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); - this.axes.updateMatrixWorld(true); - - this.thetaDelta = 0; - this.phiDelta = 0; - this.scale = 1; - - if (this.lastPosition.distanceTo(this.camera.position) > 0) { - this.dispatchEvent({ - type : 'change' - }); - this.lastPosition.copy(this.camera.position); + }, { + key: "update", + value: + /** + * Update the camera to the current settings. + */ + function update() { + // x->y, y->z, z->x + var position = this.camera.position; + var offset = position.clone().sub(this.center); + + // angle from z-axis around y-axis + var theta = Math.atan2(offset.y, offset.x); + + // angle from y-axis + var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); + if (this.autoRotate) { + this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + } + theta += this.thetaDelta; + phi += this.phiDelta; + + // restrict phi to be between EPS and PI-EPS + var eps = 0.000001; + phi = Math.max(eps, Math.min(Math.PI - eps, phi)); + var radius = offset.length(); + offset.set(radius * Math.sin(phi) * Math.cos(theta), radius * Math.sin(phi) * Math.sin(theta), radius * Math.cos(phi)); + offset.multiplyScalar(this.scale); + position.copy(this.center).add(offset); + this.camera.lookAt(this.center); + radius = offset.length(); + this.axes.position.copy(this.center); + this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); + this.axes.updateMatrixWorld(true); + this.thetaDelta = 0; + this.phiDelta = 0; + this.scale = 1; + if (this.lastPosition.distanceTo(this.camera.position) > 0) { + this.dispatchEvent({ + type: 'change' + }); + this.lastPosition.copy(this.camera.position); + } } - }; - - return OrbitControls; -}(THREE.EventDispatcher)); + }]); +}(EventDispatcher); /** * @fileOverview @@ -57019,151 +49602,195 @@ var OrbitControls = /*@__PURE__*/(function (superclass) { * @author Jihoon Lee - jihoonlee.in@gmail.com */ -var Viewer = function Viewer(options) { - options = options || {}; - var divID = options.divID; - var elem = options.elem; - var width = options.width; - var height = options.height; - var background = options.background || '#111111'; - var antialias = options.antialias; - var intensity = options.intensity || 0.66; - var near = options.near || 0.01; - var far = options.far || 1000; - var alpha = options.alpha || 1.0; - var cameraPosition = options.cameraPose || { - x : 3, - y : 3, - z : 3 - }; - var cameraZoomSpeed = options.cameraZoomSpeed || 0.5; - var displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? true : !!options.displayPanAndZoomFrame; - var lineTypePanAndZoomFrame = options.lineTypePanAndZoomFrame || 'full'; - - // create the canvas to render to - this.renderer = new THREE.WebGLRenderer({ - antialias : antialias, - alpha: true - }); - this.renderer.setClearColor(parseInt(background.replace('#', '0x'), 16), alpha); - this.renderer.sortObjects = false; - this.renderer.setSize(width, height); - this.renderer.shadowMap.enabled = false; - this.renderer.autoClear = false; - - // create the global scene - this.scene = new THREE.Scene(); - - // create the global camera - this.camera = new THREE.PerspectiveCamera(40, width / height, near, far); - this.camera.position.x = cameraPosition.x; - this.camera.position.y = cameraPosition.y; - this.camera.position.z = cameraPosition.z; - // add controls to the camera - this.cameraControls = new OrbitControls({ - scene : this.scene, - camera : this.camera, - displayPanAndZoomFrame : displayPanAndZoomFrame, - lineTypePanAndZoomFrame: lineTypePanAndZoomFrame - }); - this.cameraControls.userZoomSpeed = cameraZoomSpeed; - - // lights - this.scene.add(new THREE.AmbientLight(0x555555)); - this.directionalLight = new THREE.DirectionalLight(0xffffff, intensity); - this.scene.add(this.directionalLight); - - // propagates mouse events to three.js objects - this.selectableObjects = new THREE.Group(); - this.scene.add(this.selectableObjects); - var mouseHandler = new MouseHandler({ - renderer : this.renderer, - camera : this.camera, - rootObject : this.selectableObjects, - fallbackTarget : this.cameraControls - }); +var Viewer = /*#__PURE__*/function () { + /** + * A Viewer can be used to render an interactive 3D scene to a HTML5 canvas. + * + * @constructor + * @param options - object with following keys: + * + * * divID - the ID of the div to place the viewer in + * * elem - the elem to place the viewer in (overrides divID if provided) + * * width - the initial width, in pixels, of the canvas + * * height - the initial height, in pixels, of the canvas + * * background (optional) - the color to render the background, like '#efefef' + * * alpha (optional) - the alpha of the background + * * antialias (optional) - if antialiasing should be used + * * intensity (optional) - the lighting intensity setting to use + * * cameraPosition (optional) - the starting position of the camera + * * displayPanAndZoomFrame (optional) - whether to display a frame when + * * panning/zooming. Defaults to true. + * * lineTypePanAndZoomFrame - line type for the frame that is displayed when + * * panning/zooming. Only has effect when + * * displayPanAndZoomFrame is set to true. + */ - // highlights the receiver of mouse events - this.highlighter = new Highlighter({ - mouseHandler : mouseHandler - }); + function Viewer(options) { + _classCallCheck(this, Viewer); + console.log('Here 1'); + options = options || {}; + var divID = options.divID; + var elem = options.elem; + var width = options.width; + var height = options.height; + var background = options.background || '#111111'; + var antialias = options.antialias; + var intensity = options.intensity || 0.66; + var near = options.near || 0.01; + var far = options.far || 1000; + var alpha = options.alpha || 1.0; + var cameraPosition = options.cameraPose || { + x: 3, + y: 3, + z: 3 + }; + var cameraZoomSpeed = options.cameraZoomSpeed || 0.5; + var displayPanAndZoomFrame = options.displayPanAndZoomFrame === undefined ? true : !!options.displayPanAndZoomFrame; + var lineTypePanAndZoomFrame = options.lineTypePanAndZoomFrame || 'full'; + + // create the canvas to render to + this.renderer = new WebGLRenderer({ + antialias: antialias, + alpha: true + }); + this.renderer.setClearColor(parseInt(background.replace('#', '0x'), 16), alpha); + this.renderer.sortObjects = false; + this.renderer.setSize(width, height); + this.renderer.shadowMap.enabled = false; + this.renderer.autoClear = false; + + // create the global scene + this.scene = new Scene(); + + // create the global camera + this.camera = new PerspectiveCamera(40, width / height, near, far); + this.camera.position.x = cameraPosition.x; + this.camera.position.y = cameraPosition.y; + this.camera.position.z = cameraPosition.z; + // add controls to the camera + this.cameraControls = new OrbitControls({ + scene: this.scene, + camera: this.camera, + displayPanAndZoomFrame: displayPanAndZoomFrame, + lineTypePanAndZoomFrame: lineTypePanAndZoomFrame + }); + this.cameraControls.userZoomSpeed = cameraZoomSpeed; + + // lights + this.scene.add(new AmbientLight(0x555555)); + this.directionalLight = new DirectionalLight(0xffffff, intensity); + this.scene.add(this.directionalLight); + console.log('Here 2'); + + // propagates mouse events to three.js objects + this.selectableObjects = new Group(); + this.scene.add(this.selectableObjects); + var mouseHandler = new MouseHandler({ + renderer: this.renderer, + camera: this.camera, + rootObject: this.selectableObjects, + fallbackTarget: this.cameraControls + }); - this.stopped = true; - this.animationRequestId = undefined; + // highlights the receiver of mouse events + this.highlighter = new Highlighter({ + mouseHandler: mouseHandler + }); + this.stopped = true; + this.animationRequestId = undefined; - // add the renderer to the page - var node = elem || document.getElementById(divID); - node.appendChild(this.renderer.domElement); + // add the renderer to the page + var node = elem || document.getElementById(divID); + node.appendChild(this.renderer.domElement); - // begin the render loop - this.start(); -}; -/** - *Start the render loop - */ -Viewer.prototype.start = function start (){ - this.stopped = false; - this.draw(); -}; -/** - * Renders the associated scene to the viewer. - */ -Viewer.prototype.draw = function draw (){ - if(this.stopped){ - // Do nothing if stopped - return; + // begin the render loop + this.start(); + console.log('Here 3'); } + return _createClass(Viewer, [{ + key: "start", + value: + /** + * Start the render loop + */ + function start() { + this.stopped = false; + this.draw(); + } + }, { + key: "draw", + value: + /** + * Renders the associated scene to the viewer. + */ + function draw() { + if (this.stopped) { + // Do nothing if stopped + return; + } - // update the controls - this.cameraControls.update(); + // update the controls + this.cameraControls.update(); + console.log('Here 5'); - // put light to the top-left of the camera - // BUG: position is a read-only property of DirectionalLight, - // attempting to assign to it either does nothing or throws an error. - //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); - this.directionalLight.position.normalize(); + // put light to the top-left of the camera + // BUG: position is a read-only property of DirectionalLight, + // attempting to assign to it either does nothing or throws an error. + //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); + this.directionalLight.position.normalize(); - // set the scene - this.renderer.clear(true, true, true); - this.renderer.render(this.scene, this.camera); - this.highlighter.renderHighlights(this.scene, this.renderer, this.camera); + // set the scene + this.renderer.clear(true, true, true); + this.renderer.render(this.scene, this.camera); + this.highlighter.renderHighlights(this.scene, this.renderer, this.camera); - // draw the frame - this.animationRequestId = requestAnimationFrame(this.draw.bind(this)); -}; -/** - *Stop the render loop - */ -Viewer.prototype.stop = function stop (){ - if(!this.stopped){ - // Stop animation render loop - cancelAnimationFrame(this.animationRequestId); - } - this.stopped = true; -}; -/** - * Add the given THREE Object3D to the global scene in the viewer. - * - * @param object - the THREE Object3D to add - * @param selectable (optional) - if the object should be added to the selectable list - */ -Viewer.prototype.addObject = function addObject (object, selectable) { - if (selectable) { - this.selectableObjects.add(object); - } else { - this.scene.add(object); - } -}; -/** - * Resize 3D viewer - * - * @param width - new width value - * @param height - new height value - */ -Viewer.prototype.resize = function resize (width, height) { - this.camera.aspect = width / height; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(width, height); -}; + // draw the frame + this.animationRequestId = requestAnimationFrame(this.draw.bind(this)); + } + }, { + key: "stop", + value: + /** + * Stop the render loop + */ + function stop() { + if (!this.stopped) { + // Stop animation render loop + cancelAnimationFrame(this.animationRequestId); + } + this.stopped = true; + } + }, { + key: "addObject", + value: + /** + * Add the given THREE Object3D to the global scene in the viewer. + * + * @param object - the THREE Object3D to add + * @param selectable (optional) - if the object should be added to the selectable list + */ + function addObject(object, selectable) { + if (selectable) { + this.selectableObjects.add(object); + } else { + this.scene.add(object); + } + } + }, { + key: "resize", + value: + /** + * Resize 3D viewer + * + * @param width - new width value + * @param height - new height value + */ + function resize(width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + }]); +}(); export { Arrow, Arrow2, Axes, ColorOcTree, DepthCloud, Grid, Highlighter, INTERACTIVE_MARKER_BUTTON, INTERACTIVE_MARKER_BUTTON_CLICK, INTERACTIVE_MARKER_FIXED, INTERACTIVE_MARKER_INHERIT, INTERACTIVE_MARKER_KEEP_ALIVE, INTERACTIVE_MARKER_MENU, INTERACTIVE_MARKER_MENU_SELECT, INTERACTIVE_MARKER_MOUSE_DOWN, INTERACTIVE_MARKER_MOUSE_UP, INTERACTIVE_MARKER_MOVE_3D, INTERACTIVE_MARKER_MOVE_AXIS, INTERACTIVE_MARKER_MOVE_PLANE, INTERACTIVE_MARKER_MOVE_ROTATE, INTERACTIVE_MARKER_MOVE_ROTATE_3D, INTERACTIVE_MARKER_NONE, INTERACTIVE_MARKER_POSE_UPDATE, INTERACTIVE_MARKER_ROTATE_3D, INTERACTIVE_MARKER_ROTATE_AXIS, INTERACTIVE_MARKER_VIEW_FACING, InteractiveMarker, InteractiveMarkerClient, InteractiveMarkerControl, InteractiveMarkerHandle, InteractiveMarkerMenu, LaserScan, MARKER_ARROW, MARKER_CUBE, MARKER_CUBE_LIST, MARKER_CYLINDER, MARKER_LINE_LIST, MARKER_LINE_STRIP, MARKER_MESH_RESOURCE, MARKER_POINTS, MARKER_SPHERE, MARKER_SPHERE_LIST, MARKER_TEXT_VIEW_FACING, MARKER_TRIANGLE_LIST, Marker, MarkerArrayClient, MarkerClient, MeshLoader, MeshResource, MouseHandler, NavSatFix, OcTree, OcTreeClient, OccupancyGrid, OccupancyGridClient, Odometry, OrbitControls, Path, Point, PointCloud2, Points, Polygon, Pose, PoseArray, PoseWithCovariance, SceneNode, TFAxes, TriangleList, Urdf, UrdfClient, Viewer, closestAxisPoint, findClosestPoint, intersectPlane, makeColorMaterial }; diff --git a/build/ros3d.js b/build/ros3d.js index 5f80b819..9f4d9e0c 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -21,550 +21,675 @@ var ROS3D = (function (exports, ROSLIB) { var ROSLIB__namespace = /*#__PURE__*/_interopNamespace(ROSLIB); - // Polyfills + /** + * @license + * Copyright 2010-2024 Three.js Authors + * SPDX-License-Identifier: MIT + */ + const REVISION = '167'; + const CullFaceNone = 0; + const CullFaceBack = 1; + const CullFaceFront = 2; + const PCFShadowMap = 1; + const PCFSoftShadowMap = 2; + const VSMShadowMap = 3; + const FrontSide = 0; + const BackSide = 1; + const DoubleSide = 2; + const NoBlending = 0; + const NormalBlending = 1; + const AdditiveBlending = 2; + const SubtractiveBlending = 3; + const MultiplyBlending = 4; + const CustomBlending = 5; + const AddEquation = 100; + const SubtractEquation = 101; + const ReverseSubtractEquation = 102; + const MinEquation = 103; + const MaxEquation = 104; + const ZeroFactor = 200; + const OneFactor = 201; + const SrcColorFactor = 202; + const OneMinusSrcColorFactor = 203; + const SrcAlphaFactor = 204; + const OneMinusSrcAlphaFactor = 205; + const DstAlphaFactor = 206; + const OneMinusDstAlphaFactor = 207; + const DstColorFactor = 208; + const OneMinusDstColorFactor = 209; + const SrcAlphaSaturateFactor = 210; + const ConstantColorFactor = 211; + const OneMinusConstantColorFactor = 212; + const ConstantAlphaFactor = 213; + const OneMinusConstantAlphaFactor = 214; + const NeverDepth = 0; + const AlwaysDepth = 1; + const LessDepth = 2; + const LessEqualDepth = 3; + const EqualDepth = 4; + const GreaterEqualDepth = 5; + const GreaterDepth = 6; + const NotEqualDepth = 7; + const MultiplyOperation = 0; + const MixOperation = 1; + const AddOperation = 2; + const NoToneMapping = 0; + const LinearToneMapping = 1; + const ReinhardToneMapping = 2; + const CineonToneMapping = 3; + const ACESFilmicToneMapping = 4; + const CustomToneMapping = 5; + const AgXToneMapping = 6; + const NeutralToneMapping = 7; + const AttachedBindMode = 'attached'; + const DetachedBindMode = 'detached'; + + const UVMapping = 300; + const CubeReflectionMapping = 301; + const CubeRefractionMapping = 302; + const EquirectangularReflectionMapping = 303; + const EquirectangularRefractionMapping = 304; + const CubeUVReflectionMapping = 306; + const RepeatWrapping = 1000; + const ClampToEdgeWrapping = 1001; + const MirroredRepeatWrapping = 1002; + const NearestFilter = 1003; + const NearestMipmapNearestFilter = 1004; + const NearestMipmapLinearFilter = 1005; + const LinearFilter = 1006; + const LinearMipmapNearestFilter = 1007; + const LinearMipmapLinearFilter = 1008; + const UnsignedByteType = 1009; + const ByteType = 1010; + const ShortType = 1011; + const UnsignedShortType = 1012; + const IntType = 1013; + const UnsignedIntType = 1014; + const FloatType = 1015; + const HalfFloatType = 1016; + const UnsignedShort4444Type = 1017; + const UnsignedShort5551Type = 1018; + const UnsignedInt248Type = 1020; + const UnsignedInt5999Type = 35902; + const AlphaFormat = 1021; + const RGBFormat = 1022; + const RGBAFormat = 1023; + const LuminanceFormat = 1024; + const LuminanceAlphaFormat = 1025; + const DepthFormat = 1026; + const DepthStencilFormat = 1027; + const RedFormat = 1028; + const RedIntegerFormat = 1029; + const RGFormat = 1030; + const RGIntegerFormat = 1031; + const RGBAIntegerFormat = 1033; + + const RGB_S3TC_DXT1_Format = 33776; + const RGBA_S3TC_DXT1_Format = 33777; + const RGBA_S3TC_DXT3_Format = 33778; + const RGBA_S3TC_DXT5_Format = 33779; + const RGB_PVRTC_4BPPV1_Format = 35840; + const RGB_PVRTC_2BPPV1_Format = 35841; + const RGBA_PVRTC_4BPPV1_Format = 35842; + const RGBA_PVRTC_2BPPV1_Format = 35843; + const RGB_ETC1_Format = 36196; + const RGB_ETC2_Format = 37492; + const RGBA_ETC2_EAC_Format = 37496; + const RGBA_ASTC_4x4_Format = 37808; + const RGBA_ASTC_5x4_Format = 37809; + const RGBA_ASTC_5x5_Format = 37810; + const RGBA_ASTC_6x5_Format = 37811; + const RGBA_ASTC_6x6_Format = 37812; + const RGBA_ASTC_8x5_Format = 37813; + const RGBA_ASTC_8x6_Format = 37814; + const RGBA_ASTC_8x8_Format = 37815; + const RGBA_ASTC_10x5_Format = 37816; + const RGBA_ASTC_10x6_Format = 37817; + const RGBA_ASTC_10x8_Format = 37818; + const RGBA_ASTC_10x10_Format = 37819; + const RGBA_ASTC_12x10_Format = 37820; + const RGBA_ASTC_12x12_Format = 37821; + const RGBA_BPTC_Format = 36492; + const RGB_BPTC_SIGNED_Format = 36494; + const RGB_BPTC_UNSIGNED_Format = 36495; + const RED_RGTC1_Format = 36283; + const SIGNED_RED_RGTC1_Format = 36284; + const RED_GREEN_RGTC2_Format = 36285; + const SIGNED_RED_GREEN_RGTC2_Format = 36286; + const InterpolateDiscrete = 2300; + const InterpolateLinear = 2301; + const InterpolateSmooth = 2302; + const ZeroCurvatureEnding = 2400; + const ZeroSlopeEnding = 2401; + const WrapAroundEnding = 2402; + const NormalAnimationBlendMode = 2500; + const BasicDepthPacking = 3200; + const RGBADepthPacking = 3201; + const TangentSpaceNormalMap = 0; + const ObjectSpaceNormalMap = 1; + + // Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. + const NoColorSpace = ''; + const SRGBColorSpace = 'srgb'; + const LinearSRGBColorSpace = 'srgb-linear'; + const DisplayP3ColorSpace = 'display-p3'; + const LinearDisplayP3ColorSpace = 'display-p3-linear'; + + const LinearTransfer = 'linear'; + const SRGBTransfer = 'srgb'; + + const Rec709Primaries = 'rec709'; + const P3Primaries = 'p3'; + const KeepStencilOp = 7680; + const AlwaysStencilFunc = 519; + + const NeverCompare = 512; + const LessCompare = 513; + const EqualCompare = 514; + const LessEqualCompare = 515; + const GreaterCompare = 516; + const NotEqualCompare = 517; + const GreaterEqualCompare = 518; + const AlwaysCompare = 519; + + const StaticDrawUsage = 35044; + const DynamicDrawUsage = 35048; + const GLSL3 = '300 es'; + + const WebGLCoordinateSystem = 2000; + const WebGPUCoordinateSystem = 2001; + + /** + * https://github.com/mrdoob/eventdispatcher.js/ + */ - if ( Number.EPSILON === undefined ) { + class EventDispatcher { - Number.EPSILON = Math.pow( 2, - 52 ); + addEventListener( type, listener ) { - } + if ( this._listeners === undefined ) this._listeners = {}; - if ( Number.isInteger === undefined ) { + const listeners = this._listeners; - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger + if ( listeners[ type ] === undefined ) { - Number.isInteger = function ( value ) { + listeners[ type ] = []; - return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value; + } - }; + if ( listeners[ type ].indexOf( listener ) === - 1 ) { - } + listeners[ type ].push( listener ); - // + } - if ( Math.sign === undefined ) { + } - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign + hasEventListener( type, listener ) { - Math.sign = function ( x ) { + if ( this._listeners === undefined ) return false; - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x; + const listeners = this._listeners; - }; + return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; - } + } + + removeEventListener( type, listener ) { + + if ( this._listeners === undefined ) return; + + const listeners = this._listeners; + const listenerArray = listeners[ type ]; - if ( 'name' in Function.prototype === false ) { + if ( listenerArray !== undefined ) { - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name + const index = listenerArray.indexOf( listener ); - Object.defineProperty( Function.prototype, 'name', { + if ( index !== - 1 ) { - get: function () { + listenerArray.splice( index, 1 ); - return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ]; + } } - } ); + } - } + dispatchEvent( event ) { + + if ( this._listeners === undefined ) return; - if ( Object.assign === undefined ) { + const listeners = this._listeners; + const listenerArray = listeners[ event.type ]; - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign + if ( listenerArray !== undefined ) { - ( function () { + event.target = this; - Object.assign = function ( target ) { + // Make a copy, in case listeners are removed while iterating. + const array = listenerArray.slice( 0 ); - if ( target === undefined || target === null ) { + for ( let i = 0, l = array.length; i < l; i ++ ) { - throw new TypeError( 'Cannot convert undefined or null to object' ); + array[ i ].call( this, event ); } - var output = Object( target ); + event.target = null; - for ( var index = 1; index < arguments.length; index ++ ) { + } - var source = arguments[ index ]; + } - if ( source !== undefined && source !== null ) { + } - for ( var nextKey in source ) { + const _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' ]; - if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) { + let _seed = 1234567; - output[ nextKey ] = source[ nextKey ]; - } + const DEG2RAD = Math.PI / 180; + const RAD2DEG = 180 / Math.PI; - } + // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 + function generateUUID() { - } + const d0 = Math.random() * 0xffffffff | 0; + const d1 = Math.random() * 0xffffffff | 0; + const d2 = Math.random() * 0xffffffff | 0; + const d3 = Math.random() * 0xffffffff | 0; + const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + + _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + + _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + + _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; - } + // .toLowerCase() here flattens concatenated strings to save heap memory space. + return uuid.toLowerCase(); - return output; + } - }; + function clamp( value, min, max ) { - } )(); + return Math.max( min, Math.min( max, value ) ); } - /** - * https://github.com/mrdoob/eventdispatcher.js/ - */ + // compute euclidean modulo of m % n + // https://en.wikipedia.org/wiki/Modulo_operation + function euclideanModulo( n, m ) { - function EventDispatcher() {} + return ( ( n % m ) + m ) % m; - Object.assign( EventDispatcher.prototype, { + } - addEventListener: function ( type, listener ) { + // Linear mapping from range to range + function mapLinear( x, a1, a2, b1, b2 ) { - if ( this._listeners === undefined ) this._listeners = {}; + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); - var listeners = this._listeners; + } - if ( listeners[ type ] === undefined ) { + // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ + function inverseLerp( x, y, value ) { - listeners[ type ] = []; + if ( x !== y ) { - } + return ( value - x ) / ( y - x ); - if ( listeners[ type ].indexOf( listener ) === - 1 ) { + } else { - listeners[ type ].push( listener ); + return 0; - } + } - }, + } - hasEventListener: function ( type, listener ) { + // https://en.wikipedia.org/wiki/Linear_interpolation + function lerp( x, y, t ) { - if ( this._listeners === undefined ) return false; + return ( 1 - t ) * x + t * y; - var listeners = this._listeners; + } - return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; + // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ + function damp( x, y, lambda, dt ) { - }, + return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); - removeEventListener: function ( type, listener ) { + } - if ( this._listeners === undefined ) return; + // https://www.desmos.com/calculator/vcsjnyz7x4 + function pingpong( x, length = 1 ) { - var listeners = this._listeners; - var listenerArray = listeners[ type ]; + return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); - if ( listenerArray !== undefined ) { + } - var index = listenerArray.indexOf( listener ); + // http://en.wikipedia.org/wiki/Smoothstep + function smoothstep( x, min, max ) { - if ( index !== - 1 ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - listenerArray.splice( index, 1 ); + x = ( x - min ) / ( max - min ); - } + return x * x * ( 3 - 2 * x ); - } + } - }, + function smootherstep( x, min, max ) { - dispatchEvent: function ( event ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - if ( this._listeners === undefined ) return; + x = ( x - min ) / ( max - min ); - var listeners = this._listeners; - var listenerArray = listeners[ event.type ]; + return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); - if ( listenerArray !== undefined ) { + } - event.target = this; + // Random integer from interval + function randInt( low, high ) { - var array = listenerArray.slice( 0 ); + return low + Math.floor( Math.random() * ( high - low + 1 ) ); - for ( var i = 0, l = array.length; i < l; i ++ ) { + } - array[ i ].call( this, event ); + // Random float from interval + function randFloat( low, high ) { - } + return low + Math.random() * ( high - low ); - } + } - } + // Random float from <-range/2, range/2> interval + function randFloatSpread( range ) { - } ); - - var REVISION = '89'; - var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; - var CullFaceNone = 0; - var CullFaceBack = 1; - var CullFaceFront = 2; - var CullFaceFrontBack = 3; - var FrontFaceDirectionCW = 0; - var FrontFaceDirectionCCW = 1; - var BasicShadowMap = 0; - var PCFShadowMap = 1; - var PCFSoftShadowMap = 2; - var FrontSide = 0; - var BackSide = 1; - var DoubleSide = 2; - var FlatShading = 1; - var SmoothShading = 2; - var NoColors = 0; - var FaceColors = 1; - var VertexColors = 2; - 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 Uncharted2ToneMapping = 3; - var CineonToneMapping = 4; - var UVMapping = 300; - var CubeReflectionMapping = 301; - var CubeRefractionMapping = 302; - var EquirectangularReflectionMapping = 303; - var EquirectangularRefractionMapping = 304; - var SphericalReflectionMapping = 305; - var CubeUVReflectionMapping = 306; - var CubeUVRefractionMapping = 307; - var RepeatWrapping = 1000; - 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 UnsignedShort565Type = 1019; - var UnsignedInt248Type = 1020; - var AlphaFormat = 1021; - var RGBFormat = 1022; - var RGBAFormat = 1023; - var LuminanceFormat = 1024; - var LuminanceAlphaFormat = 1025; - var RGBEFormat = RGBAFormat; - var DepthFormat = 1026; - var DepthStencilFormat = 1027; - var RGB_S3TC_DXT1_Format = 2001; - var RGBA_S3TC_DXT1_Format = 2002; - var RGBA_S3TC_DXT3_Format = 2003; - var RGBA_S3TC_DXT5_Format = 2004; - var RGB_PVRTC_4BPPV1_Format = 2100; - var RGB_PVRTC_2BPPV1_Format = 2101; - var RGBA_PVRTC_4BPPV1_Format = 2102; - var RGBA_PVRTC_2BPPV1_Format = 2103; - var RGB_ETC1_Format = 2151; - var LoopOnce = 2200; - var LoopRepeat = 2201; - var LoopPingPong = 2202; - var InterpolateDiscrete = 2300; - var InterpolateLinear = 2301; - var InterpolateSmooth = 2302; - var ZeroCurvatureEnding = 2400; - var ZeroSlopeEnding = 2401; - var WrapAroundEnding = 2402; - var TrianglesDrawMode = 0; - var TriangleStripDrawMode = 1; - var TriangleFanDrawMode = 2; - var LinearEncoding = 3000; - var sRGBEncoding = 3001; - var GammaEncoding = 3007; - var RGBEEncoding = 3002; - var LogLuvEncoding = 3003; - var RGBM7Encoding = 3004; - var RGBM16Encoding = 3005; - var RGBDEncoding = 3006; - var BasicDepthPacking = 3200; - var RGBADepthPacking = 3201; + return range * ( 0.5 - Math.random() ); - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + } - var _Math = { + // Deterministic pseudo-random float in the interval [ 0, 1 ] + function seededRandom( s ) { - DEG2RAD: Math.PI / 180, - RAD2DEG: 180 / Math.PI, + if ( s !== undefined ) _seed = s; - generateUUID: ( function () { + // Mulberry32 generator - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 + let t = _seed += 0x6D2B79F5; - var lut = []; + t = Math.imul( t ^ t >>> 15, t | 1 ); - for ( var i = 0; i < 256; i ++ ) { + t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); - lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 ).toUpperCase(); + return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; - } + } - return function () { + function degToRad( degrees ) { - var d0 = Math.random() * 0xffffffff | 0; - var d1 = Math.random() * 0xffffffff | 0; - var d2 = Math.random() * 0xffffffff | 0; - var d3 = Math.random() * 0xffffffff | 0; - return lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' + - lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' + - lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] + - lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ]; + return degrees * DEG2RAD; - }; + } - } )(), + function radToDeg( radians ) { - clamp: function ( value, min, max ) { + return radians * RAD2DEG; - return Math.max( min, Math.min( max, value ) ); + } - }, + function isPowerOfTwo( value ) { - // compute euclidian modulo of m % n - // https://en.wikipedia.org/wiki/Modulo_operation + return ( value & ( value - 1 ) ) === 0 && value !== 0; - euclideanModulo: function ( n, m ) { + } - return ( ( n % m ) + m ) % m; + function ceilPowerOfTwo( value ) { - }, + return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); - // Linear mapping from range to range + } - mapLinear: function ( x, a1, a2, b1, b2 ) { + function floorPowerOfTwo( value ) { - return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); + return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); - }, + } - // https://en.wikipedia.org/wiki/Linear_interpolation + function setQuaternionFromProperEuler( q, a, b, c, order ) { - lerp: function ( x, y, t ) { + // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles - return ( 1 - t ) * x + t * y; + // rotations are applied to the axes in the order specified by 'order' + // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' + // angles are in radians - }, + const cos = Math.cos; + const sin = Math.sin; - // http://en.wikipedia.org/wiki/Smoothstep + const c2 = cos( b / 2 ); + const s2 = sin( b / 2 ); - smoothstep: function ( x, min, max ) { + const c13 = cos( ( a + c ) / 2 ); + const s13 = sin( ( a + c ) / 2 ); - if ( x <= min ) return 0; - if ( x >= max ) return 1; + const c1_3 = cos( ( a - c ) / 2 ); + const s1_3 = sin( ( a - c ) / 2 ); - x = ( x - min ) / ( max - min ); + const c3_1 = cos( ( c - a ) / 2 ); + const s3_1 = sin( ( c - a ) / 2 ); - return x * x * ( 3 - 2 * x ); + switch ( order ) { - }, + case 'XYX': + q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); + break; - smootherstep: function ( x, min, max ) { + case 'YZY': + q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); + break; - if ( x <= min ) return 0; - if ( x >= max ) return 1; + case 'ZXZ': + q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); + break; - x = ( x - min ) / ( max - min ); + case 'XZX': + q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); + break; - return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); + case 'YXY': + q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); + break; - }, + case 'ZYZ': + q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); + break; - // Random integer from interval + default: + console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); - randInt: function ( low, high ) { + } - return low + Math.floor( Math.random() * ( high - low + 1 ) ); + } - }, + function denormalize( value, array ) { - // Random float from interval + switch ( array.constructor ) { - randFloat: function ( low, high ) { + case Float32Array: - return low + Math.random() * ( high - low ); + return value; - }, + case Uint32Array: - // Random float from <-range/2, range/2> interval + return value / 4294967295.0; - randFloatSpread: function ( range ) { + case Uint16Array: - return range * ( 0.5 - Math.random() ); + return value / 65535.0; - }, + case Uint8Array: - degToRad: function ( degrees ) { + return value / 255.0; - return degrees * _Math.DEG2RAD; + case Int32Array: - }, + return Math.max( value / 2147483647.0, - 1.0 ); - radToDeg: function ( radians ) { + case Int16Array: - return radians * _Math.RAD2DEG; + return Math.max( value / 32767.0, - 1.0 ); - }, + case Int8Array: - isPowerOfTwo: function ( value ) { + return Math.max( value / 127.0, - 1.0 ); - return ( value & ( value - 1 ) ) === 0 && value !== 0; + default: - }, + throw new Error( 'Invalid component type.' ); - ceilPowerOfTwo: function ( value ) { + } - return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); + } - }, + function normalize( value, array ) { - floorPowerOfTwo: function ( value ) { + switch ( array.constructor ) { - return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); + case Float32Array: - } + return value; - }; + case Uint32Array: - /** - * @author mrdoob / http://mrdoob.com/ - * @author philogb / http://blog.thejit.org/ - * @author egraether / http://egraether.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - */ + return Math.round( value * 4294967295.0 ); - function Vector2( x, y ) { + case Uint16Array: - this.x = x || 0; - this.y = y || 0; + return Math.round( value * 65535.0 ); - } + case Uint8Array: - Object.defineProperties( Vector2.prototype, { + return Math.round( value * 255.0 ); - "width": { + case Int32Array: - get: function () { + return Math.round( value * 2147483647.0 ); - return this.x; + case Int16Array: - }, + return Math.round( value * 32767.0 ); - set: function ( value ) { + case Int8Array: - this.x = value; + return Math.round( value * 127.0 ); - } + default: - }, + throw new Error( 'Invalid component type.' ); + + } + + } + + const MathUtils = { + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler, + normalize: normalize, + denormalize: denormalize + }; - "height": { + class Vector2 { - get: function () { + constructor( x = 0, y = 0 ) { - return this.y; + Vector2.prototype.isVector2 = true; - }, + this.x = x; + this.y = y; + + } - set: function ( value ) { + get width() { - this.y = value; + return this.x; - } + } + + set width( value ) { + + this.x = value; + + } + + get height() { + + return this.y; } - } ); + set height( value ) { - Object.assign( Vector2.prototype, { + this.y = value; - isVector2: true, + } - set: function ( x, y ) { + set( x, y ) { this.x = x; this.y = y; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { @@ -576,9 +701,9 @@ var ROS3D = (function (exports, ROSLIB) { return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { @@ -588,164 +713,150 @@ var ROS3D = (function (exports, ROSLIB) { } - }, + } - clone: function () { + clone() { return new this.constructor( this.x, this.y ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; return this; - }, + } - addScaledVector: function ( v, s ) { + addScaledVector( v, s ) { this.x += v.x * s; this.y += v.y * s; return this; - }, - - sub: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; return this; - }, + } - multiply: function ( v ) { + multiply( v ) { this.x *= v.x; this.y *= v.y; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; return this; - }, + } - divide: function ( v ) { + divide( v ) { this.x /= v.x; this.y /= v.y; return this; - }, + } - divideScalar: function ( scalar ) { + divideScalar( scalar ) { return this.multiplyScalar( 1 / scalar ); - }, + } - applyMatrix3: function ( m ) { + applyMatrix3( m ) { - var x = this.x, y = this.y; - var e = m.elements; + const x = this.x, y = this.y; + const e = m.elements; this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; return this; - }, + } - min: function ( v ) { + min( v ) { this.x = Math.min( this.x, v.x ); this.y = Math.min( this.y, v.y ); return this; - }, + } - max: function ( v ) { + max( v ) { this.x = Math.max( this.x, v.x ); this.y = Math.max( this.y, v.y ); return this; - }, + } - clamp: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise @@ -754,209 +865,212 @@ var ROS3D = (function (exports, ROSLIB) { return this; - }, - - clampScalar: function () { - - var min = new Vector2(); - var max = new Vector2(); - - return function clampScalar( minVal, maxVal ) { + } - min.set( minVal, minVal ); - max.set( maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - }; + return this; - }(), + } - clampLength: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + floor() { this.x = Math.floor( this.x ); this.y = Math.floor( this.y ); return this; - }, + } - ceil: function () { + ceil() { this.x = Math.ceil( this.x ); this.y = Math.ceil( this.y ); return this; - }, + } - round: function () { + round() { this.x = Math.round( this.x ); this.y = Math.round( this.y ); return this; - }, + } - roundToZero: function () { + 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.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; return this; - }, + } - dot: function ( v ) { + dot( v ) { return this.x * v.x + this.y * v.y; - }, + } + + cross( v ) { + + return this.x * v.y - this.y * v.x; - lengthSq: function () { + } + + lengthSq() { return this.x * this.x + this.y * this.y; - }, + } - length: function () { + length() { return Math.sqrt( this.x * this.x + this.y * this.y ); - }, + } - manhattanLength: function () { + manhattanLength() { return Math.abs( this.x ) + Math.abs( this.y ); - }, + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - angle: function () { + angle() { // computes the angle in radians with respect to the positive x-axis - var angle = Math.atan2( this.y, this.x ); - - if ( angle < 0 ) angle += 2 * Math.PI; + const angle = Math.atan2( - this.y, - this.x ) + Math.PI; return angle; - }, + } + + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; - distanceTo: function ( v ) { + const theta = this.dot( v ) / denominator; + + // clamp, to handle numerical problems + + return Math.acos( clamp( theta, - 1, 1 ) ); + + } + + distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); - }, + } - distanceToSquared: function ( v ) { + distanceToSquared( v ) { - var dx = this.x - v.x, dy = this.y - v.y; + const dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; - }, + } - manhattanDistanceTo: function ( v ) { + manhattanDistanceTo( v ) { return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + lerp( v, alpha ) { this.x += ( v.x - this.x ) * alpha; this.y += ( v.y - this.y ) * alpha; return this; - }, + } - lerpVectors: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; - }, + return this; - equals: function ( v ) { + } - return ( ( v.x === this.x ) && ( v.y === this.y ) ); + equals( v ) { - }, + return ( ( v.x === this.x ) && ( v.y === this.y ) ); - fromArray: function ( array, offset ) { + } - if ( offset === undefined ) offset = 0; + fromArray( array, offset = 0 ) { this.x = array[ offset ]; this.y = array[ offset + 1 ]; return this; - }, - - toArray: function ( array, offset ) { + } - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + toArray( array = [], offset = 0 ) { array[ offset ] = this.x; array[ offset + 1 ] = this.y; return array; - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' ); + } - } + fromBufferAttribute( attribute, index ) { this.x = attribute.getX( index ); this.y = attribute.getY( index ); return this; - }, + } - rotateAround: function ( center, angle ) { + rotateAround( center, angle ) { - var c = Math.cos( angle ), s = Math.sin( angle ); + const c = Math.cos( angle ), s = Math.sin( angle ); - var x = this.x - center.x; - var y = this.y - center.y; + const x = this.x - center.x; + const y = this.y - center.y; this.x = x * c - y * s + center.x; this.y = x * s + y * c + center.y; @@ -965,10886 +1079,10343 @@ var ROS3D = (function (exports, ROSLIB) { } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author jordi_ros / http://plattsoft.com - * @author D1plo1d / http://github.com/D1plo1d - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author timknip / http://www.floorplanner.com/ - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - */ - - function Matrix4() { + random() { - this.elements = [ + this.x = Math.random(); + this.y = Math.random(); - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + return this; - ]; + } - if ( arguments.length > 0 ) { + *[ Symbol.iterator ]() { - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + yield this.x; + yield this.y; } } - Object.assign( Matrix4.prototype, { + class Matrix3 { - isMatrix4: true, + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + Matrix3.prototype.isMatrix3 = true; - var te = this.elements; + 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; + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 - return this; + ]; - }, + if ( n11 !== undefined ) { - identity: function () { + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); - this.set( + } - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + } - ); + set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - return this; + 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; - clone: function () { + return this; - return new Matrix4().fromArray( this.elements ); + } - }, + identity() { - copy: function ( m ) { + this.set( - var te = this.elements; - var me = m.elements; + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 - 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: function ( m ) { + copy( m ) { - var te = this.elements, me = m.elements; + const te = this.elements; + const me = m.elements; - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; + 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: function ( xAxis, yAxis, zAxis ) { + extractBasis( xAxis, yAxis, zAxis ) { - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); + xAxis.setFromMatrix3Column( this, 0 ); + yAxis.setFromMatrix3Column( this, 1 ); + zAxis.setFromMatrix3Column( this, 2 ); return this; - }, + } - makeBasis: function ( xAxis, yAxis, zAxis ) { + setFromMatrix4( m ) { + + const me = m.elements; 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; + me[ 0 ], me[ 4 ], me[ 8 ], + me[ 1 ], me[ 5 ], me[ 9 ], + me[ 2 ], me[ 6 ], me[ 10 ] - }, + ); - extractRotation: function () { + return this; - var v1 = new Vector3(); + } - return function extractRotation( m ) { + multiply( m ) { - var te = this.elements; - var me = m.elements; + return this.multiplyMatrices( this, m ); - var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); - var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); - var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); + } - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; + premultiply( m ) { - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; + return this.multiplyMatrices( m, this ); - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; + } - return this; + multiplyMatrices( a, b ) { - }; + const ae = a.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 ]; - makeRotationFromEuler: function ( euler ) { + 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 ]; - if ( ! ( euler && euler.isEuler ) ) { + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; + te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; + te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + 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; - var te = this.elements; + return this; - var x = euler.x, y = euler.y, z = euler.z; - var a = Math.cos( x ), b = Math.sin( x ); - var c = Math.cos( y ), d = Math.sin( y ); - var e = Math.cos( z ), f = Math.sin( z ); + } - if ( euler.order === 'XYZ' ) { + multiplyScalar( s ) { - var ae = a * e, af = a * f, be = b * e, bf = b * f; + const te = this.elements; - te[ 0 ] = c * e; - te[ 4 ] = - c * f; - te[ 8 ] = d; + 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; - te[ 1 ] = af + be * d; - te[ 5 ] = ae - bf * d; - te[ 9 ] = - b * c; + return this; - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'YXZ' ) { + determinant() { - var ce = c * e, cf = c * f, de = d * e, df = d * f; + const te = this.elements; - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; + const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], + d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], + g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'ZXY' ) { + invert() { - var ce = c * e, cf = c * f, de = d * e, df = d * f; + const te = this.elements, - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; + 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 ], - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; + t11 = n33 * n22 - n32 * n23, + t12 = n32 * n13 - n33 * n12, + t13 = n23 * n12 - n22 * n13, - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; + det = n11 * t11 + n21 * t12 + n31 * t13; - } else if ( euler.order === 'ZYX' ) { + if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var ae = a * e, af = a * f, be = b * e, bf = b * f; + const detInv = 1 / det; - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; + te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; + te[ 3 ] = t12 * detInv; + te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; + te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; + te[ 6 ] = t13 * detInv; + te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; + te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; - } else if ( euler.order === 'YZX' ) { + return this; - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + } - te[ 0 ] = c * e; - te[ 4 ] = bd - ac * f; - te[ 8 ] = bc * f + ad; + transpose() { - te[ 1 ] = f; - te[ 5 ] = a * e; - te[ 9 ] = - b * e; + let tmp; + const m = this.elements; - te[ 2 ] = - d * e; - te[ 6 ] = ad * f + bc; - te[ 10 ] = ac - bd * f; + tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; + tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; + tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; - } else if ( euler.order === 'XZY' ) { + return this; - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + } - te[ 0 ] = c * e; - te[ 4 ] = - f; - te[ 8 ] = d * e; + getNormalMatrix( matrix4 ) { - te[ 1 ] = ac * f + bd; - te[ 5 ] = a * e; - te[ 9 ] = ad * f - bc; + return this.setFromMatrix4( matrix4 ).invert().transpose(); - te[ 2 ] = bc * f - ad; - te[ 6 ] = b * e; - te[ 10 ] = bd * f + ac; + } - } + transposeIntoArray( r ) { - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + const m = this.elements; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + r[ 0 ] = m[ 0 ]; + r[ 1 ] = m[ 3 ]; + r[ 2 ] = m[ 6 ]; + r[ 3 ] = m[ 1 ]; + r[ 4 ] = m[ 4 ]; + r[ 5 ] = m[ 7 ]; + r[ 6 ] = m[ 2 ]; + r[ 7 ] = m[ 5 ]; + r[ 8 ] = m[ 8 ]; return this; - }, + } - makeRotationFromQuaternion: function ( q ) { + setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { - var te = this.elements; + const c = Math.cos( rotation ); + const s = Math.sin( rotation ); - var x = q._x, y = q._y, z = q._z, w = q._w; - var x2 = x + x, y2 = y + y, z2 = z + z; - var xx = x * x2, xy = x * y2, xz = x * z2; - var yy = y * y2, yz = y * z2, zz = z * z2; - var wx = w * x2, wy = w * y2, wz = w * z2; + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 1 + ); - te[ 0 ] = 1 - ( yy + zz ); - te[ 4 ] = xy - wz; - te[ 8 ] = xz + wy; + return this; - te[ 1 ] = xy + wz; - te[ 5 ] = 1 - ( xx + zz ); - te[ 9 ] = yz - wx; + } - te[ 2 ] = xz - wy; - te[ 6 ] = yz + wx; - te[ 10 ] = 1 - ( xx + yy ); + // - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + scale( sx, sy ) { - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + this.premultiply( _m3.makeScale( sx, sy ) ); return this; - }, + } - lookAt: function () { + rotate( theta ) { - var x = new Vector3(); - var y = new Vector3(); - var z = new Vector3(); + this.premultiply( _m3.makeRotation( - theta ) ); - return function lookAt( eye, target, up ) { + return this; - var te = this.elements; + } - z.subVectors( eye, target ); + translate( tx, ty ) { - if ( z.lengthSq() === 0 ) { + this.premultiply( _m3.makeTranslation( tx, ty ) ); - // eye and target are in the same position + return this; - z.z = 1; + } - } + // for 2D Transforms - z.normalize(); - x.crossVectors( up, z ); + makeTranslation( x, y ) { - if ( x.lengthSq() === 0 ) { + if ( x.isVector2 ) { - // up and z are parallel + this.set( - if ( Math.abs( up.z ) === 1 ) { + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 - z.x += 0.0001; + ); - } else { + } else { - z.z += 0.0001; + this.set( - } + 1, 0, x, + 0, 1, y, + 0, 0, 1 - z.normalize(); - x.crossVectors( up, z ); + ); - } + } - x.normalize(); - y.crossVectors( z, x ); + return this; - 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; + makeRotation( theta ) { - }; + // counterclockwise - }(), + const c = Math.cos( theta ); + const s = Math.sin( theta ); - multiply: function ( m, n ) { + this.set( - if ( n !== undefined ) { + c, - s, 0, + s, c, 0, + 0, 0, 1 - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); - return this.multiplyMatrices( m, n ); + ); - } - - return this.multiplyMatrices( this, m ); + return this; - }, + } - premultiply: function ( m ) { + makeScale( x, y ) { - return this.multiplyMatrices( m, this ); + this.set( - }, + x, 0, 0, + 0, y, 0, + 0, 0, 1 - multiplyMatrices: function ( a, b ) { + ); - var ae = a.elements; - var be = b.elements; - var te = this.elements; + return this; - var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; - var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; - var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; - var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; + } - var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; - var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; - var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; - var 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; + equals( matrix ) { - 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; + const te = this.elements; + const me = matrix.elements; - 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; + for ( let i = 0; i < 9; i ++ ) { - 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; + if ( te[ i ] !== me[ i ] ) return false; - return this; + } - }, + return true; - multiplyScalar: function ( s ) { + } - var te = this.elements; + fromArray( array, offset = 0 ) { - 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; + for ( let i = 0; i < 9; i ++ ) { - return this; + this.elements[ i ] = array[ i + offset ]; - }, + } - applyToBufferAttribute: function () { + return this; - var v1 = new Vector3(); + } - return function applyToBufferAttribute( attribute ) { + toArray( array = [], offset = 0 ) { - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + const te = this.elements; - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; - v1.applyMatrix4( this ); + array[ offset + 3 ] = te[ 3 ]; + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; + array[ offset + 8 ] = te[ 8 ]; - } + return array; - return attribute; + } - }; + clone() { - }(), + return new this.constructor().fromArray( this.elements ); - determinant: function () { + } - var te = this.elements; + } - var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; - var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; - var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; - var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; + const _m3 = /*@__PURE__*/ new Matrix3(); - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + function arrayNeedsUint32( array ) { - 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 - ) + // assumes larger values usually on last - ); + for ( let i = array.length - 1; i >= 0; -- i ) { - }, + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 - transpose: function () { + } - var te = this.elements; - var tmp; + return false; - 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; + function createElementNS( name ) { - return this; + return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); - }, + } - setPosition: function ( v ) { + function createCanvasElement() { - var te = this.elements; + const canvas = createElementNS( 'canvas' ); + canvas.style.display = 'block'; + return canvas; - te[ 12 ] = v.x; - te[ 13 ] = v.y; - te[ 14 ] = v.z; + } - return this; + const _cache = {}; - }, + function warnOnce( message ) { - getInverse: function ( m, throwOnDegenerate ) { + if ( message in _cache ) return; - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - var te = this.elements, - me = m.elements, + _cache[ message ] = true; - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ], - n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ], - n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ], - n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ], + console.warn( message ); - 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; + } - var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + function probeAsync( gl, sync, interval ) { - if ( det === 0 ) { + return new Promise( function ( resolve, reject ) { - var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; + function probe() { - if ( throwOnDegenerate === true ) { + switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) { - throw new Error( msg ); + case gl.WAIT_FAILED: + reject(); + break; - } else { + case gl.TIMEOUT_EXPIRED: + setTimeout( probe, interval ); + break; - console.warn( msg ); + default: + resolve(); } - return this.identity(); - } - var 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; + setTimeout( probe, interval ); - 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; + /** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + + const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( + 0.8224621, 0.177538, 0.0, + 0.0331941, 0.9668058, 0.0, + 0.0170827, 0.0723974, 0.9105199, + ); + + const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( + 1.2249401, - 0.2249404, 0.0, + - 0.0420569, 1.0420571, 0.0, + - 0.0196376, - 0.0786361, 1.0982735 + ); + + /** + * Defines supported color spaces by transfer function and primaries, + * and provides conversions to/from the Linear-sRGB reference space. + */ + const COLOR_SPACES = { + [ LinearSRGBColorSpace ]: { + transfer: LinearTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color, + fromReference: ( color ) => color, + }, + [ SRGBColorSpace ]: { + transfer: SRGBTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color.convertSRGBToLinear(), + fromReference: ( color ) => color.convertLinearToSRGB(), + }, + [ LinearDisplayP3ColorSpace ]: { + transfer: LinearTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), + }, + [ DisplayP3ColorSpace ]: { + transfer: SRGBTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), + }, + }; - return this; + const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); - }, + const ColorManagement = { - scale: function ( v ) { + enabled: true, - var te = this.elements; - var x = v.x, y = v.y, z = v.z; + _workingColorSpace: LinearSRGBColorSpace, - te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; - te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; - te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; - te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; + get workingColorSpace() { - return this; + return this._workingColorSpace; }, - getMaxScaleOnAxis: function () { + set workingColorSpace( colorSpace ) { - var te = this.elements; + if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { - var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; - var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; - var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; + throw new Error( `Unsupported working color space, "${ colorSpace }".` ); - return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); + } + + this._workingColorSpace = colorSpace; }, - makeTranslation: function ( x, y, z ) { + convert: function ( color, sourceColorSpace, targetColorSpace ) { - this.set( + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + return color; - ); + } - return this; + const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; + const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; + + return targetFromReference( sourceToReference( color ) ); }, - makeRotationX: function ( theta ) { + fromWorkingColorSpace: function ( color, targetColorSpace ) { - var c = Math.cos( theta ), s = Math.sin( theta ); + return this.convert( color, this._workingColorSpace, targetColorSpace ); - this.set( + }, - 1, 0, 0, 0, - 0, c, - s, 0, - 0, s, c, 0, - 0, 0, 0, 1 + toWorkingColorSpace: function ( color, sourceColorSpace ) { - ); + return this.convert( color, sourceColorSpace, this._workingColorSpace ); - return this; + }, + + getPrimaries: function ( colorSpace ) { + + return COLOR_SPACES[ colorSpace ].primaries; }, - makeRotationY: function ( theta ) { + getTransfer: function ( colorSpace ) { - var c = Math.cos( theta ), s = Math.sin( theta ); + if ( colorSpace === NoColorSpace ) return LinearTransfer; - this.set( + return COLOR_SPACES[ colorSpace ].transfer; - c, 0, s, 0, - 0, 1, 0, 0, - - s, 0, c, 0, - 0, 0, 0, 1 + }, - ); + getLuminanceCoefficients: function ( target, colorSpace = this._workingColorSpace ) { - return this; + return target.fromArray( COLOR_SPACES[ colorSpace ].luminanceCoefficients ); }, - makeRotationZ: function ( theta ) { + }; - var c = Math.cos( theta ), s = Math.sin( theta ); - this.set( + function SRGBToLinear( c ) { - c, - s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); - ); + } - return this; + function LinearToSRGB( c ) { - }, + return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; - makeRotationAxis: function ( axis, angle ) { + } - // Based on http://www.gamedev.net/reference/articles/article1199.asp + let _canvas; - var c = Math.cos( angle ); - var s = Math.sin( angle ); - var t = 1 - c; - var x = axis.x, y = axis.y, z = axis.z; - var tx = t * x, ty = t * y; + class ImageUtils { - this.set( + static getDataURL( image ) { - tx * x + c, tx * y - s * z, tx * z + s * y, 0, - tx * y + s * z, ty * y + c, ty * z - s * x, 0, - tx * z - s * y, ty * z + s * x, t * z * z + c, 0, - 0, 0, 0, 1 + if ( /^data:/i.test( image.src ) ) { - ); + return image.src; - return this; + } - }, + if ( typeof HTMLCanvasElement === 'undefined' ) { - makeScale: function ( x, y, z ) { + return image.src; - this.set( + } - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 + let canvas; - ); + if ( image instanceof HTMLCanvasElement ) { - return this; + canvas = image; - }, + } else { - makeShear: function ( x, y, z ) { + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - this.set( + _canvas.width = image.width; + _canvas.height = image.height; - 1, y, z, 0, - x, 1, z, 0, - x, y, 1, 0, - 0, 0, 0, 1 + const context = _canvas.getContext( '2d' ); - ); + if ( image instanceof ImageData ) { - return this; + context.putImageData( image, 0, 0 ); - }, + } else { - compose: function ( position, quaternion, scale ) { + context.drawImage( image, 0, 0, image.width, image.height ); - this.makeRotationFromQuaternion( quaternion ); - this.scale( scale ); - this.setPosition( position ); + } - return this; + canvas = _canvas; - }, + } - decompose: function () { + if ( canvas.width > 2048 || canvas.height > 2048 ) { - var vector = new Vector3(); - var matrix = new Matrix4(); + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - return function decompose( position, quaternion, scale ) { + return canvas.toDataURL( 'image/jpeg', 0.6 ); - var te = this.elements; + } else { - var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); - var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); - var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); + return canvas.toDataURL( 'image/png' ); - // if determine is negative, we need to invert one scale - var det = this.determinant(); - if ( det < 0 ) sx = - sx; + } - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; + } - // scale the rotation part - matrix.copy( this ); + static sRGBToLinear( image ) { - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - matrix.elements[ 0 ] *= invSX; - matrix.elements[ 1 ] *= invSX; - matrix.elements[ 2 ] *= invSX; + const canvas = createElementNS( 'canvas' ); - matrix.elements[ 4 ] *= invSY; - matrix.elements[ 5 ] *= invSY; - matrix.elements[ 6 ] *= invSY; + canvas.width = image.width; + canvas.height = image.height; - matrix.elements[ 8 ] *= invSZ; - matrix.elements[ 9 ] *= invSZ; - matrix.elements[ 10 ] *= invSZ; + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - quaternion.setFromRotationMatrix( matrix ); + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - scale.x = sx; - scale.y = sy; - scale.z = sz; + for ( let i = 0; i < data.length; i ++ ) { - return this; + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - }; + } - }(), + context.putImageData( imageData, 0, 0 ); - makePerspective: function ( left, right, top, bottom, near, far ) { + return canvas; - if ( far === undefined ) { + } else if ( image.data ) { - console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); + const data = image.data.slice( 0 ); - } + for ( let i = 0; i < data.length; i ++ ) { - var te = this.elements; - var x = 2 * near / ( right - left ); - var y = 2 * near / ( top - bottom ); + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - var a = ( right + left ) / ( right - left ); - var b = ( top + bottom ) / ( top - bottom ); - var c = - ( far + near ) / ( far - near ); - var d = - 2 * far * near / ( far - near ); + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; - te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; - te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; - te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; + } else { - return this; + // assuming float - }, + data[ i ] = SRGBToLinear( data[ i ] ); - makeOrthographic: function ( left, right, top, bottom, near, far ) { + } - var te = this.elements; - var w = 1.0 / ( right - left ); - var h = 1.0 / ( top - bottom ); - var p = 1.0 / ( far - near ); + } - var x = ( right + left ) * w; - var y = ( top + bottom ) * h; - var z = ( far + near ) * p; + return { + data: data, + width: image.width, + height: image.height + }; - te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; - te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; - 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; + } else { - return this; + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; - }, + } - equals: function ( matrix ) { + } - var te = this.elements; - var me = matrix.elements; + } - for ( var i = 0; i < 16; i ++ ) { + let _sourceId = 0; - if ( te[ i ] !== me[ i ] ) return false; + class Source { - } + constructor( data = null ) { - return true; + this.isSource = true; - }, + Object.defineProperty( this, 'id', { value: _sourceId ++ } ); - fromArray: function ( array, offset ) { + this.uuid = generateUUID(); - if ( offset === undefined ) offset = 0; + this.data = data; + this.dataReady = true; - for ( var i = 0; i < 16; i ++ ) { + this.version = 0; - this.elements[ i ] = array[ i + offset ]; + } - } + set needsUpdate( value ) { - return this; + if ( value === true ) this.version ++; - }, + } - toArray: function ( array, offset ) { + toJSON( meta ) { - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - var te = this.elements; + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - array[ offset + 3 ] = te[ 3 ]; + return meta.images[ this.uuid ]; - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; + } - array[ offset + 8 ] = te[ 8 ]; - array[ offset + 9 ] = te[ 9 ]; - array[ offset + 10 ] = te[ 10 ]; - array[ offset + 11 ] = te[ 11 ]; + const output = { + uuid: this.uuid, + url: '' + }; - array[ offset + 12 ] = te[ 12 ]; - array[ offset + 13 ] = te[ 13 ]; - array[ offset + 14 ] = te[ 14 ]; - array[ offset + 15 ] = te[ 15 ]; + const data = this.data; - return array; + if ( data !== null ) { - } + let url; - } ); + if ( Array.isArray( data ) ) { - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - */ + // cube texture - function Quaternion( x, y, z, w ) { + url = []; - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._w = ( w !== undefined ) ? w : 1; + for ( let i = 0, l = data.length; i < l; i ++ ) { - } + if ( data[ i ].isDataTexture ) { - Object.assign( Quaternion, { + url.push( serializeImage( data[ i ].image ) ); - slerp: function ( qa, qb, qm, t ) { + } else { - return qm.copy( qa ).slerp( qb, t ); + url.push( serializeImage( data[ i ] ) ); - }, + } - slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + } - // fuzz-free, array-based Quaternion SLERP operation + } else { - var x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ], + // texture - x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + url = serializeImage( data ); - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + } - var s = 1 - t, + output.url = url; - cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + } - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; + if ( ! isRootObject ) { - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { + meta.images[ this.uuid ] = output; - var sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + } - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + return output; - } + } - var tDir = t * dir; + } - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + function serializeImage( image ) { - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + // default images - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + return ImageUtils.getDataURL( image ); - } + } else { - } + if ( image.data ) { - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; + // images of DataTexture + + 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 {}; + + } } - } ); + } - Object.defineProperties( Quaternion.prototype, { + let _textureId = 0; - x: { + class Texture extends EventDispatcher { - get: function () { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { - return this._x; + super(); - }, + this.isTexture = true; - set: function ( value ) { + Object.defineProperty( this, 'id', { value: _textureId ++ } ); - this._x = value; - this.onChangeCallback(); + this.uuid = generateUUID(); - } + this.name = ''; - }, + this.source = new Source( image ); + this.mipmaps = []; - y: { + this.mapping = mapping; + this.channel = 0; - get: function () { + this.wrapS = wrapS; + this.wrapT = wrapT; - return this._y; + this.magFilter = magFilter; + this.minFilter = minFilter; - }, + this.anisotropy = anisotropy; - set: function ( value ) { + this.format = format; + this.internalFormat = null; + this.type = type; - this._y = value; - this.onChangeCallback(); + 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; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - z: { + this.colorSpace = colorSpace; - get: function () { + this.userData = {}; - return this._z; + this.version = 0; + this.onUpdate = null; - }, + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) - set: function ( value ) { + } - this._z = value; - this.onChangeCallback(); + get image() { - } + return this.source.data; - }, + } - w: { + set image( value = null ) { - get: function () { + this.source.data = value; - return this._w; + } - }, + updateMatrix() { - set: function ( value ) { + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); - this._w = value; - this.onChangeCallback(); + } - } + clone() { + + return new this.constructor().copy( this ); } - } ); + copy( source ) { - Object.assign( Quaternion.prototype, { + this.name = source.name; - set: function ( x, y, z, w ) { + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); - this._x = x; - this._y = y; - this._z = z; - this._w = w; + this.mapping = source.mapping; + this.channel = source.channel; - this.onChangeCallback(); + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - return this; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - }, + this.anisotropy = source.anisotropy; - clone: function () { + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return new this.constructor( this._x, this._y, this._z, this._w ); + 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 ); - copy: function ( quaternion ) { + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - this.onChangeCallback(); + this.needsUpdate = true; return this; - }, + } - setFromEuler: function ( euler, update ) { + toJSON( meta ) { - if ( ! ( euler && euler.isEuler ) ) { + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + return meta.textures[ this.uuid ]; } - var x = euler._x, y = euler._y, z = euler._z, order = euler.order; + const output = { - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, - var cos = Math.cos; - var sin = Math.sin; + uuid: this.uuid, + name: this.name, - var c1 = cos( x / 2 ); - var c2 = cos( y / 2 ); - var c3 = cos( z / 2 ); + image: this.source.toJSON( meta ).uuid, - var s1 = sin( x / 2 ); - var s2 = sin( y / 2 ); - var s3 = sin( z / 2 ); + mapping: this.mapping, + channel: this.channel, - if ( order === 'XYZ' ) { + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - 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; + wrap: [ this.wrapS, this.wrapT ], - } else if ( order === 'YXZ' ) { + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, - 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; + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - } else if ( order === 'ZXY' ) { + flipY: this.flipY, - 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; + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - } else if ( order === '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; + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; - } else if ( order === 'YZX' ) { + if ( ! isRootObject ) { - 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; + meta.textures[ this.uuid ] = output; - } else if ( order === '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; + return output; - } + } - if ( update !== false ) this.onChangeCallback(); + dispose() { - return this; + this.dispatchEvent( { type: 'dispose' } ); - }, + } - setFromAxisAngle: function ( axis, angle ) { + transformUv( uv ) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + if ( this.mapping !== UVMapping ) return uv; - // assumes axis is normalized + uv.applyMatrix3( this.matrix ); - var halfAngle = angle / 2, s = Math.sin( halfAngle ); + if ( uv.x < 0 || uv.x > 1 ) { - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + switch ( this.wrapS ) { - this.onChangeCallback(); + case RepeatWrapping: - return this; + uv.x = uv.x - Math.floor( uv.x ); + break; - }, + case ClampToEdgeWrapping: - setFromRotationMatrix: function ( m ) { + uv.x = uv.x < 0 ? 0 : 1; + break; - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + case MirroredRepeatWrapping: - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { - var te = m.elements, + uv.x = Math.ceil( uv.x ) - uv.x; - 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 ], + } else { - trace = m11 + m22 + m33, - s; + uv.x = uv.x - Math.floor( uv.x ); - if ( trace > 0 ) { + } - s = 0.5 / Math.sqrt( trace + 1.0 ); + break; - 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 ) { + } - s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); + if ( uv.y < 0 || uv.y > 1 ) { - this._w = ( m32 - m23 ) / s; - this._x = 0.25 * s; - this._y = ( m12 + m21 ) / s; - this._z = ( m13 + m31 ) / s; + switch ( this.wrapT ) { - } else if ( m22 > m33 ) { + case RepeatWrapping: - s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + uv.y = uv.y - Math.floor( uv.y ); + break; - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + case ClampToEdgeWrapping: - } else { + uv.y = uv.y < 0 ? 0 : 1; + break; - s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + case MirroredRepeatWrapping: - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - } + uv.y = Math.ceil( uv.y ) - uv.y; - this.onChangeCallback(); + } else { - return this; + uv.y = uv.y - Math.floor( uv.y ); - }, + } - setFromUnitVectors: function () { + break; - // assumes direction vectors vFrom and vTo are normalized + } - var v1 = new Vector3(); - var r; + } - var EPS = 0.000001; + if ( this.flipY ) { - return function setFromUnitVectors( vFrom, vTo ) { + uv.y = 1 - uv.y; - if ( v1 === undefined ) v1 = new Vector3(); + } - r = vFrom.dot( vTo ) + 1; + return uv; - if ( r < EPS ) { + } - r = 0; + set needsUpdate( value ) { - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + if ( value === true ) { - v1.set( - vFrom.y, vFrom.x, 0 ); + this.version ++; + this.source.needsUpdate = true; - } else { + } - v1.set( 0, - vFrom.z, vFrom.y ); + } - } + set needsPMREMUpdate( value ) { - } else { + if ( value === true ) { - v1.crossVectors( vFrom, vTo ); + this.pmremVersion ++; - } + } - this._x = v1.x; - this._y = v1.y; - this._z = v1.z; - this._w = r; + } - return this.normalize(); + } - }; + Texture.DEFAULT_IMAGE = null; + Texture.DEFAULT_MAPPING = UVMapping; + Texture.DEFAULT_ANISOTROPY = 1; - }(), + class Vector4 { - inverse: function () { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - return this.conjugate().normalize(); + Vector4.prototype.isVector4 = true; - }, + this.x = x; + this.y = y; + this.z = z; + this.w = w; - conjugate: function () { + } - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; - - this.onChangeCallback(); - - return this; - - }, - - dot: function ( v ) { - - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - - }, - - lengthSq: function () { - - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - - }, - - length: function () { - - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); - - }, - - normalize: function () { - - var 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: function ( q, p ) { - - if ( p !== undefined ) { - - console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); - return this.multiplyQuaternions( q, p ); - - } - - return this.multiplyQuaternions( this, q ); - - }, - - premultiply: function ( q ) { - - return this.multiplyQuaternions( q, this ); - - }, - - multiplyQuaternions: function ( a, b ) { - - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - - var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - var 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: function ( qb, t ) { - - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - var x = this._x, y = this._y, z = this._z, w = this._w; - - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - - var cosHalfTheta = w * qb._w + x * qb._x + y * 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.0 ) { - - this._w = w; - this._x = x; - this._y = y; - this._z = z; - - return this; - - } - - var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - - this._w = 0.5 * ( w + this._w ); - this._x = 0.5 * ( x + this._x ); - this._y = 0.5 * ( y + this._y ); - this._z = 0.5 * ( z + this._z ); - - return this; - - } - - var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); - - this.onChangeCallback(); - - return this; - - }, - - equals: function ( quaternion ) { - - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this.onChangeCallback(); - - return this; + get width() { - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; + return this.z; - return array; - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; + } - }, + set width( value ) { - onChangeCallback: function () {} + this.z = value; - } ); + } - /** - * @author mrdoob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ + get height() { - function Vector3( x, y, z ) { + return this.w; - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; + } - } + set height( value ) { - Object.assign( Vector3.prototype, { + this.w = value; - isVector3: true, + } - set: function ( x, y, z ) { + set( x, y, z, w ) { this.x = x; this.y = y; this.z = z; + this.w = w; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; this.z = scalar; + this.w = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setZ: function ( z ) { + setZ( z ) { this.z = z; return this; - }, + } + + setW( w ) { + + this.w = w; + + return this; - setComponent: function ( index, value ) { + } + + setComponent( index, value ) { switch ( index ) { 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: ' + index ); } return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { 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: ' + index ); } - }, + } - clone: function () { + clone() { - return new this.constructor( this.x, this.y, this.z ); + return new this.constructor( this.x, this.y, this.z, this.w ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; this.z += v.z; + this.w += v.w; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; this.z += s; + this.w += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; + this.w = a.w + b.w; return this; - }, + } - addScaledVector: function ( v, s ) { + 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: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; + this.w -= v.w; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; this.z -= s; + this.w -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; + this.w = a.w - b.w; return this; - }, - - multiply: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); - return this.multiplyVectors( v, w ); + } - } + multiply( v ) { this.x *= v.x; this.y *= v.y; this.z *= v.z; + this.w *= v.w; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiplyScalar( scalar ) { this.x *= scalar; this.y *= scalar; this.z *= scalar; + this.w *= scalar; return this; - }, + } - multiplyVectors: function ( a, b ) { + applyMatrix4( m ) { - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; - return this; + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; - }, + return this; - applyEuler: function () { + } - var quaternion = new Quaternion(); + divideScalar( scalar ) { - return function applyEuler( euler ) { + return this.multiplyScalar( 1 / scalar ); - if ( ! ( euler && euler.isEuler ) ) { + } - console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + setAxisAngleFromQuaternion( q ) { - } + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - return this.applyQuaternion( quaternion.setFromEuler( euler ) ); + // q is assumed to be normalized - }; + this.w = 2 * Math.acos( q.w ); - }(), + const s = Math.sqrt( 1 - q.w * q.w ); - applyAxisAngle: function () { + if ( s < 0.0001 ) { - var quaternion = new Quaternion(); + this.x = 1; + this.y = 0; + this.z = 0; - return function applyAxisAngle( axis, angle ) { + } else { - return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) ); + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; - }; + } - }(), + return this; - applyMatrix3: function ( m ) { + } - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + setAxisAngleFromRotationMatrix( m ) { - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - return this; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - }, + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - applyMatrix4: function ( m ) { + te = m.elements, - var x = this.x, y = this.y, z = this.z; - var e = m.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 ]; - var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms - return this; + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - }, + // this singularity is identity matrix so angle = 0 - applyQuaternion: function ( q ) { + this.set( 1, 0, 0, 0 ); - var x = this.x, y = this.y, z = this.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; + return this; // zero angle, arbitrary axis - // calculate quat * vector + } - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = - qx * x - qy * y - qz * z; + // otherwise this singularity is angle = 180 - // calculate result * inverse quat + angle = Math.PI; - 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; + 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; - return this; + if ( ( xx > yy ) && ( xx > zz ) ) { - }, + // m11 is the largest diagonal term - project: function () { + if ( xx < epsilon ) { + + x = 0; + y = 0.707106781; + z = 0.707106781; + + } else { + + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - var matrix = new Matrix4(); + } - return function project( camera ) { + } else if ( yy > zz ) { - matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) ); - return this.applyMatrix4( matrix ); + // m22 is the largest diagonal term - }; + if ( yy < epsilon ) { - }(), + x = 0.707106781; + y = 0; + z = 0.707106781; - unproject: function () { + } else { - var matrix = new Matrix4(); + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - return function unproject( camera ) { + } - matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) ); - return this.applyMatrix4( matrix ); + } else { - }; + // m33 is the largest diagonal term so base result on this - }(), + if ( zz < epsilon ) { - transformDirection: function ( m ) { + x = 0.707106781; + y = 0.707106781; + z = 0; - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction + } else { - var x = this.x, y = this.y, z = this.z; - var e = m.elements; + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; + } - return this.normalize(); + } - }, + this.set( x, y, z, angle ); - divide: function ( v ) { + return this; // return 180 deg rotation - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; + } + + // as we have reached here there are no singularities so we can handle normally + + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + + if ( Math.abs( s ) < 0.001 ) s = 1; + + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case + + 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; - }, + } - divideScalar: function ( scalar ) { + setFromMatrixPosition( m ) { - return this.multiplyScalar( 1 / scalar ); + const e = m.elements; - }, + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + this.w = e[ 15 ]; + + return this; - min: function ( v ) { + } + + 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: function ( v ) { + 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: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); return this; - }, - - clampScalar: function () { - - var min = new Vector3(); - var max = new Vector3(); - - return function clampScalar( minVal, maxVal ) { + } - min.set( minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + 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: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + 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: function () { + 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: function () { + 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: function () { + 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.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); + this.w = Math.trunc( this.w ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; this.z = - this.z; + this.w = - this.w; return this; - }, - - dot: function ( v ) { + } - return this.x * v.x + this.y * v.y + this.z * v.z; + dot( v ) { - }, + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - // TODO lengthSquared? + } - lengthSq: function () { + lengthSq() { - return this.x * this.x + this.y * this.y + this.z * this.z; + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - }, + } - length: function () { + length() { - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - }, + } - manhattanLength: function () { + manhattanLength() { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - }, + } - normalize: function () { + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + 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: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + 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; - cross: function ( v, w ) { + } - if ( w !== undefined ) { + equals( v ) { - console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); - return this.crossVectors( v, w ); + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - } + } - return this.crossVectors( this, v ); + fromArray( array, offset = 0 ) { - }, + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - crossVectors: function ( a, b ) { + return this; - var ax = a.x, ay = a.y, az = a.z; - var 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; + toArray( array = [], offset = 0 ) { - return this; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; - }, + return array; - projectOnVector: function ( vector ) { + } - var scalar = vector.dot( this ) / vector.lengthSq(); + fromBufferAttribute( attribute, index ) { - return this.copy( vector ).multiplyScalar( scalar ); + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); - }, + return this; - projectOnPlane: function () { + } - var v1 = new Vector3(); + random() { - return function projectOnPlane( planeNormal ) { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); - v1.copy( this ).projectOnVector( planeNormal ); + return this; - return this.sub( v1 ); + } - }; + *[ Symbol.iterator ]() { - }(), + yield this.x; + yield this.y; + yield this.z; + yield this.w; - reflect: function () { + } - // reflect incident vector off plane orthogonal to normal - // normal is assumed to have unit length + } - var v1 = new Vector3(); + /* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers + */ + class RenderTarget extends EventDispatcher { - return function reflect( normal ) { + constructor( width = 1, height = 1, options = {} ) { - return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + super(); - }; + this.isRenderTarget = true; - }(), + this.width = width; + this.height = height; + this.depth = 1; - angleTo: function ( v ) { + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); + this.viewport = new Vector4( 0, 0, width, height ); - // clamp, to handle numerical problems + const image = { width: width, height: height, depth: 1 }; - return Math.acos( _Math.clamp( theta, - 1, 1 ) ); + options = Object.assign( { + generateMipmaps: false, + internalFormat: null, + minFilter: LinearFilter, + depthBuffer: true, + stencilBuffer: false, + resolveDepthBuffer: true, + resolveStencilBuffer: true, + depthTexture: null, + samples: 0, + count: 1 + }, options ); - }, + const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); - distanceTo: function ( v ) { + texture.flipY = false; + texture.generateMipmaps = options.generateMipmaps; + texture.internalFormat = options.internalFormat; - return Math.sqrt( this.distanceToSquared( v ) ); + this.textures = []; - }, + const count = options.count; + for ( let i = 0; i < count; i ++ ) { - distanceToSquared: function ( v ) { + this.textures[ i ] = texture.clone(); + this.textures[ i ].isRenderTargetTexture = true; - var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + } - return dx * dx + dy * dy + dz * dz; + this.depthBuffer = options.depthBuffer; + this.stencilBuffer = options.stencilBuffer; - }, + this.resolveDepthBuffer = options.resolveDepthBuffer; + this.resolveStencilBuffer = options.resolveStencilBuffer; - manhattanDistanceTo: function ( v ) { + this.depthTexture = options.depthTexture; - return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); + this.samples = options.samples; - }, + } - setFromSpherical: function ( s ) { + get texture() { - var sinPhiRadius = Math.sin( s.phi ) * s.radius; + return this.textures[ 0 ]; - this.x = sinPhiRadius * Math.sin( s.theta ); - this.y = Math.cos( s.phi ) * s.radius; - this.z = sinPhiRadius * Math.cos( s.theta ); + } - return this; + set texture( value ) { - }, + this.textures[ 0 ] = value; - setFromCylindrical: function ( c ) { + } - this.x = c.radius * Math.sin( c.theta ); - this.y = c.y; - this.z = c.radius * Math.cos( c.theta ); + setSize( width, height, depth = 1 ) { - return this; + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - }, + this.width = width; + this.height = height; + this.depth = depth; - setFromMatrixPosition: function ( m ) { + for ( let i = 0, il = this.textures.length; i < il; i ++ ) { - var e = m.elements; + this.textures[ i ].image.width = width; + this.textures[ i ].image.height = height; + this.textures[ i ].image.depth = depth; - this.x = e[ 12 ]; - this.y = e[ 13 ]; - this.z = e[ 14 ]; + } - return this; + this.dispose(); - }, + } - setFromMatrixScale: function ( m ) { + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - var sx = this.setFromMatrixColumn( m, 0 ).length(); - var sy = this.setFromMatrixColumn( m, 1 ).length(); - var sz = this.setFromMatrixColumn( m, 2 ).length(); + } - this.x = sx; - this.y = sy; - this.z = sz; + clone() { - return this; - - }, - - setFromMatrixColumn: function ( m, index ) { - - return this.fromArray( m.elements, index * 4 ); - - }, - - equals: function ( v ) { - - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); - - }, + return new this.constructor().copy( this ); - fromArray: function ( array, offset ) { + } - if ( offset === undefined ) offset = 0; + copy( source ) { - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - return this; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - }, + this.viewport.copy( source.viewport ); - toArray: function ( array, offset ) { + this.textures.length = 0; - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + for ( let i = 0, il = source.textures.length; i < il; i ++ ) { - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; + this.textures[ i ] = source.textures[ i ].clone(); + this.textures[ i ].isRenderTargetTexture = true; - return array; + } - }, + // ensure image object is not shared, see #20328 - fromBufferAttribute: function ( attribute, index, offset ) { + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); - if ( offset !== undefined ) { + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); + this.resolveDepthBuffer = source.resolveDepthBuffer; + this.resolveStencilBuffer = source.resolveStencilBuffer; - } + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); + this.samples = source.samples; return this; } - } ); + dispose() { - /** - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - * @author tschw - */ + this.dispatchEvent( { type: 'dispose' } ); - function Matrix3() { + } - this.elements = [ + } - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 + class WebGLRenderTarget extends RenderTarget { - ]; + constructor( width = 1, height = 1, options = {} ) { - if ( arguments.length > 0 ) { + super( width, height, options ); - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); + this.isWebGLRenderTarget = true; } } - Object.assign( Matrix3.prototype, { + class DataArrayTexture extends Texture { - isMatrix3: true, + constructor( data = null, width = 1, height = 1, depth = 1 ) { - set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { + super( null ); - var te = this.elements; + this.isDataArrayTexture = true; - 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; + this.image = { data, width, height, depth }; - return this; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - }, + this.wrapR = ClampToEdgeWrapping; - identity: function () { + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - this.set( + this.layerUpdates = new Set(); - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 + } - ); + addLayerUpdate( layerIndex ) { - return this; + this.layerUpdates.add( layerIndex ); - }, + } - clone: function () { + clearLayerUpdates() { - return new this.constructor().fromArray( this.elements ); + this.layerUpdates.clear(); - }, + } - copy: function ( m ) { + } - var te = this.elements; - var me = m.elements; + class Data3DTexture extends Texture { - 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 ]; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - return this; + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 - }, + super( null ); - setFromMatrix4: function ( m ) { + this.isData3DTexture = true; - var me = m.elements; + this.image = { data, width, height, depth }; - this.set( + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - me[ 0 ], me[ 4 ], me[ 8 ], - me[ 1 ], me[ 5 ], me[ 9 ], - me[ 2 ], me[ 6 ], me[ 10 ] + this.wrapR = ClampToEdgeWrapping; - ); + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - return this; + } - }, + } - applyToBufferAttribute: function () { + class Quaternion { - var v1 = new Vector3(); + constructor( x = 0, y = 0, z = 0, w = 1 ) { - return function applyToBufferAttribute( attribute ) { + this.isQuaternion = true; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + this._x = x; + this._y = y; + this._z = z; + this._w = w; - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + } - v1.applyMatrix3( this ); + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + // fuzz-free, array-based Quaternion SLERP operation - } + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; - return attribute; + 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; - multiply: function ( m ) { + } - return this.multiplyMatrices( this, m ); + if ( t === 1 ) { - }, + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; - premultiply: function ( m ) { + } - return this.multiplyMatrices( m, this ); + 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; - multiplyMatrices: function ( a, b ) { + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - var ae = a.elements; - var be = b.elements; - var te = this.elements; + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; - var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; - var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; - var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; - var 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; + const tDir = t * dir; - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; - te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; - te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; - te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; - te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - return this; + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - }, + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - multiplyScalar: function ( s ) { + } - var 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; + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; - return this; + } - }, + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - determinant: function () { + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - var te = this.elements; + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; - var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], - d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], - g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; + 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 a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; + return dst; - }, + } - getInverse: function ( matrix, throwOnDegenerate ) { + get x() { - if ( matrix && matrix.isMatrix4 ) { + return this._x; - console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); + } - } + set x( value ) { - var me = matrix.elements, - te = this.elements, + this._x = value; + this._onChangeCallback(); - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], - n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ], - n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ], + } - t11 = n33 * n22 - n32 * n23, - t12 = n32 * n13 - n33 * n12, - t13 = n23 * n12 - n22 * n13, + get y() { - det = n11 * t11 + n21 * t12 + n31 * t13; + return this._y; - if ( det === 0 ) { + } - var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; + set y( value ) { - if ( throwOnDegenerate === true ) { + this._y = value; + this._onChangeCallback(); - throw new Error( msg ); + } - } else { + get z() { - console.warn( msg ); + return this._z; - } + } - return this.identity(); + set z( value ) { - } + this._z = value; + this._onChangeCallback(); - var detInv = 1 / det; + } - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; - te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; + get w() { - te[ 3 ] = t12 * detInv; - te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; - te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; + return this._w; - te[ 6 ] = t13 * detInv; - te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; - te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; + } - return this; + set w( value ) { - }, + this._w = value; + this._onChangeCallback(); - transpose: function () { + } - var tmp, m = this.elements; + set( x, y, z, w ) { - tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; - tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; - tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; + this._x = x; + this._y = y; + this._z = z; + this._w = w; + + this._onChangeCallback(); return this; - }, + } - getNormalMatrix: function ( matrix4 ) { + clone() { - return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); + return new this.constructor( this._x, this._y, this._z, this._w ); - }, + } - transposeIntoArray: function ( r ) { + copy( quaternion ) { - var m = this.elements; + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; - r[ 0 ] = m[ 0 ]; - r[ 1 ] = m[ 3 ]; - r[ 2 ] = m[ 6 ]; - r[ 3 ] = m[ 1 ]; - r[ 4 ] = m[ 4 ]; - r[ 5 ] = m[ 7 ]; - r[ 6 ] = m[ 2 ]; - r[ 7 ] = m[ 5 ]; - r[ 8 ] = m[ 8 ]; + this._onChangeCallback(); return this; - }, + } - setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { + setFromEuler( euler, update = true ) { - var c = Math.cos( rotation ); - var s = Math.sin( rotation ); + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - this.set( - sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, - - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, - 0, 0, 1 - ); + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - }, + const cos = Math.cos; + const sin = Math.sin; - scale: function ( sx, sy ) { + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - var te = this.elements; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; - te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; + switch ( order ) { - return this; + 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; - rotate: function ( theta ) { + 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; - var c = Math.cos( theta ); - var s = Math.sin( theta ); + 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; - var te = this.elements; + 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; - var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ]; - var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ]; + 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; - te[ 0 ] = c * a11 + s * a21; - te[ 3 ] = c * a12 + s * a22; - te[ 6 ] = c * a13 + s * a23; + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); - te[ 1 ] = - s * a11 + c * a21; - te[ 4 ] = - s * a12 + c * a22; - te[ 7 ] = - s * a13 + c * a23; + } - return this; + if ( update === true ) this._onChangeCallback(); - }, + return this; - translate: function ( tx, ty ) { + } - var te = this.elements; + setFromAxisAngle( axis, angle ) { - 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 ]; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - return this; + // assumes axis is normalized - }, + const halfAngle = angle / 2, s = Math.sin( halfAngle ); - equals: function ( matrix ) { + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos( halfAngle ); - var te = this.elements; - var me = matrix.elements; + this._onChangeCallback(); - for ( var i = 0; i < 9; i ++ ) { + return this; - if ( te[ i ] !== me[ i ] ) return false; + } - } + setFromRotationMatrix( m ) { - return true; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - }, + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - fromArray: function ( array, offset ) { + const te = m.elements, - if ( offset === undefined ) offset = 0; + 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 ], - for ( var i = 0; i < 9; i ++ ) { + trace = m11 + m22 + m33; - this.elements[ i ] = array[ i + offset ]; + if ( trace > 0 ) { - } + const s = 0.5 / Math.sqrt( trace + 1.0 ); - return this; + 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 ) { - toArray: function ( array, offset ) { + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - var te = this.elements; + } else if ( m22 > m33 ) { - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - array[ offset + 3 ] = te[ 3 ]; - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; - array[ offset + 8 ] = te[ 8 ]; + } else { - return array; + const s = 2.0 * Math.sqrt( 1.0 + 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 ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - */ + // assumes direction vectors vFrom and vTo are normalized - var textureId = 0; + let r = vFrom.dot( vTo ) + 1; - function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + if ( r < Number.EPSILON ) { - Object.defineProperty( this, 'id', { value: textureId ++ } ); + // vFrom and vTo point in opposite directions - this.uuid = _Math.generateUUID(); + r = 0; - this.name = ''; + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; - this.mipmaps = []; + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + } else { - this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; + } - this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + } else { - this.format = format !== undefined ? format : RGBAFormat; - this.type = type !== undefined ? type : UnsignedByteType; + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); - this.center = new Vector2( 0, 0 ); - this.rotation = 0; + 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; - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); + } - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + return this.normalize(); - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding !== undefined ? encoding : LinearEncoding; + } - this.version = 0; - this.onUpdate = null; + angleTo( q ) { - } + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); - Texture.DEFAULT_IMAGE = undefined; - Texture.DEFAULT_MAPPING = UVMapping; + } - Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + rotateTowards( q, step ) { - constructor: Texture, + const angle = this.angleTo( q ); - isTexture: true, + if ( angle === 0 ) return this; - clone: function () { + const t = Math.min( 1, step / angle ); - return new this.constructor().copy( this ); + this.slerp( q, t ); - }, + return this; - copy: function ( source ) { + } - this.name = source.name; + identity() { - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); + return this.set( 0, 0, 0, 1 ); - this.mapping = source.mapping; + } - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + invert() { - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + // quaternion is assumed to have unit length - this.anisotropy = source.anisotropy; + return this.conjugate(); - this.format = source.format; - this.type = source.type; + } - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + conjugate() { - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + this._onChangeCallback(); return this; - }, + } - toJSON: function ( meta ) { + dot( v ) { - var isRootObject = ( meta === undefined || typeof meta === 'string' ); + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { + } - return meta.textures[ this.uuid ]; + lengthSq() { - } + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + + } - function getDataURL( image ) { + length() { - var canvas; + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); - if ( image instanceof HTMLCanvasElement ) { + } - canvas = image; + normalize() { - } else { + let l = this.length(); - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; + if ( l === 0 ) { - var context = canvas.getContext( '2d' ); + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - if ( image instanceof ImageData ) { + } else { - context.putImageData( image, 0, 0 ); + l = 1 / l; - } else { + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - context.drawImage( image, 0, 0, image.width, image.height ); + } - } + this._onChangeCallback(); - } + return this; - if ( canvas.width > 2048 || canvas.height > 2048 ) { + } - return canvas.toDataURL( 'image/jpeg', 0.6 ); + multiply( q ) { - } else { + return this.multiplyQuaternions( this, q ); - return canvas.toDataURL( 'image/png' ); + } - } + premultiply( q ) { - } + return this.multiplyQuaternions( q, this ); - var output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + } - uuid: this.uuid, - name: this.name, + multiplyQuaternions( a, b ) { - mapping: this.mapping, + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - wrap: [ this.wrapS, this.wrapT ], + 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; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + this._onChangeCallback(); - flipY: this.flipY - }; + return this; + + } - if ( this.image !== undefined ) { + slerp( qb, t ) { - // TODO: Move to THREE.Image + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - var image = this.image; + const x = this._x, y = this._y, z = this._z, w = this._w; - if ( image.uuid === undefined ) { + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - image.uuid = _Math.generateUUID(); // UGH + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - } + if ( cosHalfTheta < 0 ) { - if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: getDataURL( image ) - }; + cosHalfTheta = - cosHalfTheta; - } + } else { - output.image = image.uuid; + this.copy( qb ); } - if ( ! isRootObject ) { + if ( cosHalfTheta >= 1.0 ) { - meta.textures[ this.uuid ] = output; + this._w = w; + this._x = x; + this._y = y; + this._z = z; + + return this; } - return output; + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - }, + if ( sqrSinHalfTheta <= Number.EPSILON ) { - dispose: function () { + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - this.dispatchEvent( { type: 'dispose' } ); + this.normalize(); // normalize calls _onChangeCallback() - }, + return this; - transformUv: function ( uv ) { + } - if ( this.mapping !== UVMapping ) return; + 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; - uv.applyMatrix3( this.matrix ); + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - if ( uv.x < 0 || uv.x > 1 ) { + this._onChangeCallback(); - switch ( this.wrapS ) { + return this; - case RepeatWrapping: + } - uv.x = uv.x - Math.floor( uv.x ); - break; + slerpQuaternions( qa, qb, t ) { - case ClampToEdgeWrapping: + return this.copy( qa ).slerp( qb, t ); - uv.x = uv.x < 0 ? 0 : 1; - break; + } - case MirroredRepeatWrapping: + random() { - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + // sets this quaternion to a uniform random unit quaternnion - uv.x = Math.ceil( uv.x ) - uv.x; + // Ken Shoemake + // Uniform random rotations + // D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992. - } else { + const theta1 = 2 * Math.PI * Math.random(); + const theta2 = 2 * Math.PI * Math.random(); - uv.x = uv.x - Math.floor( uv.x ); + const x0 = Math.random(); + const r1 = Math.sqrt( 1 - x0 ); + const r2 = Math.sqrt( x0 ); - } - break; + return this.set( + r1 * Math.sin( theta1 ), + r1 * Math.cos( theta1 ), + r2 * Math.sin( theta2 ), + r2 * Math.cos( theta2 ), + ); - } + } - } + equals( quaternion ) { - if ( uv.y < 0 || uv.y > 1 ) { + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - switch ( this.wrapT ) { + } - case RepeatWrapping: + fromArray( array, offset = 0 ) { - uv.y = uv.y - Math.floor( uv.y ); - break; + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - case ClampToEdgeWrapping: + this._onChangeCallback(); - uv.y = uv.y < 0 ? 0 : 1; - break; + return this; - case MirroredRepeatWrapping: + } - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + toArray( array = [], offset = 0 ) { - uv.y = Math.ceil( uv.y ) - uv.y; + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; - } else { + return array; - uv.y = uv.y - Math.floor( uv.y ); + } - } - break; + fromBufferAttribute( attribute, index ) { - } + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); - } + this._onChangeCallback(); - if ( this.flipY ) { + return this; - uv.y = 1 - uv.y; + } - } + toJSON() { - } + return this.toArray(); - } ); + } - Object.defineProperty( Texture.prototype, "needsUpdate", { + _onChange( callback ) { - set: function ( value ) { + this._onChangeCallback = callback; - if ( value === true ) this.version ++; + return this; } - } ); + _onChangeCallback() {} - /** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ + *[ Symbol.iterator ]() { - function Vector4( x, y, z, w ) { + yield this._x; + yield this._y; + yield this._z; + yield this._w; - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; + } } - Object.assign( Vector4.prototype, { + class Vector3 { - isVector4: true, + constructor( x = 0, y = 0, z = 0 ) { - set: function ( x, y, z, w ) { + Vector3.prototype.isVector3 = true; + + this.x = x; + this.y = y; + this.z = z; + + } + + set( x, y, z ) { + + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) this.x = x; this.y = y; this.z = z; - this.w = w; return this; - }, + } - setScalar: function ( scalar ) { + setScalar( scalar ) { this.x = scalar; this.y = scalar; this.z = scalar; - this.w = scalar; return this; - }, + } - setX: function ( x ) { + setX( x ) { this.x = x; return this; - }, + } - setY: function ( y ) { + setY( y ) { this.y = y; return this; - }, + } - setZ: function ( z ) { + setZ( z ) { this.z = z; return this; - }, - - setW: function ( w ) { - - this.w = w; - - return this; - - }, + } - setComponent: function ( index, value ) { + setComponent( index, value ) { switch ( index ) { 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: ' + index ); } return this; - }, + } - getComponent: function ( index ) { + getComponent( index ) { switch ( index ) { 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: ' + index ); } - }, + } - clone: function () { + clone() { - return new this.constructor( this.x, this.y, this.z, this.w ); + return new this.constructor( this.x, this.y, this.z ); - }, + } - copy: function ( v ) { + copy( v ) { this.x = v.x; this.y = v.y; this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; return this; - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + } - } + add( v ) { this.x += v.x; this.y += v.y; this.z += v.z; - this.w += v.w; return this; - }, + } - addScalar: function ( s ) { + addScalar( s ) { this.x += s; this.y += s; this.z += s; - this.w += s; return this; - }, + } - addVectors: function ( a, b ) { + addVectors( a, b ) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; - this.w = a.w + b.w; return this; - }, + } - addScaledVector: function ( v, s ) { + 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: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + } - } + sub( v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; - this.w -= v.w; return this; - }, + } - subScalar: function ( s ) { + subScalar( s ) { this.x -= s; this.y -= s; this.z -= s; - this.w -= s; return this; - }, + } - subVectors: function ( a, b ) { + subVectors( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; - this.w = a.w - b.w; return this; - }, + } - multiplyScalar: function ( scalar ) { + multiply( v ) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; return this; - }, - - applyMatrix4: function ( m ) { + } - var x = this.x, y = this.y, z = this.z, w = this.w; - var e = m.elements; + multiplyScalar( scalar ) { - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; return this; - }, - - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - setAxisAngleFromQuaternion: function ( q ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - - // q is assumed to be normalized - - this.w = 2 * Math.acos( q.w ); - - var s = Math.sqrt( 1 - q.w * q.w ); - - if ( s < 0.0001 ) { - - 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; + multiplyVectors( a, b ) { - } + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; return this; - }, - - setAxisAngleFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + } - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + applyEuler( euler ) { - var angle, x, y, z, // variables for result - epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - te = m.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 ]; + applyAxisAngle( axis, angle ) { - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + } - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + applyMatrix3( m ) { - // this singularity is identity matrix so angle = 0 + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - this.set( 1, 0, 0, 0 ); + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - return this; // zero angle, arbitrary axis + return this; - } + } - // otherwise this singularity is angle = 180 + applyNormalMatrix( m ) { - angle = Math.PI; + return this.applyMatrix3( m ).normalize(); - var xx = ( m11 + 1 ) / 2; - var yy = ( m22 + 1 ) / 2; - var zz = ( m33 + 1 ) / 2; - var xy = ( m12 + m21 ) / 4; - var xz = ( m13 + m31 ) / 4; - var yz = ( m23 + m32 ) / 4; + } - if ( ( xx > yy ) && ( xx > zz ) ) { + applyMatrix4( m ) { - // m11 is the largest diagonal term + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - if ( xx < epsilon ) { + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - x = 0; - y = 0.707106781; - z = 0.707106781; + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - } else { + return this; - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + } - } + applyQuaternion( q ) { - } else if ( yy > zz ) { + // quaternion q is assumed to have unit length - // m22 is the largest diagonal term + const vx = this.x, vy = this.y, vz = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - if ( yy < epsilon ) { + // t = 2 * cross( q.xyz, v ); + const tx = 2 * ( qy * vz - qz * vy ); + const ty = 2 * ( qz * vx - qx * vz ); + const tz = 2 * ( qx * vy - qy * vx ); - x = 0.707106781; - y = 0; - z = 0.707106781; + // v + q.w * t + cross( q.xyz, t ); + this.x = vx + qw * tx + qy * tz - qz * ty; + this.y = vy + qw * ty + qz * tx - qx * tz; + this.z = vz + qw * tz + qx * ty - qy * tx; - } else { + return this; - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + } - } + project( camera ) { - } else { + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - // m33 is the largest diagonal term so base result on this + } - if ( zz < epsilon ) { + unproject( camera ) { - x = 0.707106781; - y = 0.707106781; - z = 0; + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); - } else { + } - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + transformDirection( m ) { - } + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - this.set( x, y, z, angle ); + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - return this; // return 180 deg rotation + return this.normalize(); - } + } - // as we have reached here there are no singularities so we can handle normally + divide( v ) { - var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; - if ( Math.abs( s ) < 0.001 ) s = 1; + return this; - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + } - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + divideScalar( scalar ) { - return this; + return this.multiplyScalar( 1 / scalar ); - }, + } - min: function ( v ) { + 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: function ( v ) { + 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: function ( min, max ) { + clamp( min, max ) { // assumes min < max, componentwise this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); return this; - }, - - clampScalar: function () { - - var min, max; - - return function clampScalar( minVal, maxVal ) { - - if ( min === undefined ) { - - min = new Vector4(); - max = new Vector4(); - - } + } - min.set( minVal, minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal, maxVal ); + clampScalar( minVal, maxVal ) { - return this.clamp( min, max ); + 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: function ( min, max ) { + clampLength( min, max ) { - var length = this.length(); + const length = this.length(); return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - }, + } - floor: function () { + 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: function () { + 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: function () { + 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: function () { + 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 ); + this.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); return this; - }, + } - negate: function () { + negate() { this.x = - this.x; this.y = - this.y; this.z = - this.z; - this.w = - this.w; return this; - }, + } - dot: function ( v ) { + dot( v ) { - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + return this.x * v.x + this.y * v.y + this.z * v.z; - }, + } - lengthSq: function () { + // TODO lengthSquared? - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + lengthSq() { - }, + return this.x * this.x + this.y * this.y + this.z * this.z; - length: function () { + } - return Math.sqrt( 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 ); - manhattanLength: function () { + } - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + manhattanLength() { - }, + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - normalize: function () { + } + + normalize() { return this.divideScalar( this.length() || 1 ); - }, + } - setLength: function ( length ) { + setLength( length ) { return this.normalize().multiplyScalar( length ); - }, + } - lerp: function ( v, alpha ) { + 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: function ( v1, v2, alpha ) { + lerpVectors( v1, v2, alpha ) { - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + 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; - equals: function ( v ) { + } - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - - }, + cross( v ) { - fromArray: function ( array, offset ) { + return this.crossVectors( this, v ); - if ( offset === undefined ) offset = 0; + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + crossVectors( a, b ) { - return this; + const ax = a.x, ay = a.y, az = a.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; - toArray: function ( array, offset ) { + return this; - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + } - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + projectOnVector( v ) { - return array; + const denominator = v.lengthSq(); - }, + if ( denominator === 0 ) return this.set( 0, 0, 0 ); - fromBufferAttribute: function ( attribute, index, offset ) { + const scalar = v.dot( this ) / denominator; - if ( offset !== undefined ) { + return this.copy( v ).multiplyScalar( scalar ); - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); + } - } + projectOnPlane( planeNormal ) { - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); + _vector$c.copy( this ).projectOnVector( planeNormal ); - return this; + return this.sub( _vector$c ); } - } ); - - /** - * @author szimek / https://github.com/szimek/ - * @author alteredq / http://alteredqualia.com/ - * @author Marius Kintel / https://github.com/kintel - */ - - /* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers - */ - function WebGLRenderTarget( width, height, options ) { - - this.uuid = _Math.generateUUID(); + reflect( normal ) { - this.width = width; - this.height = height; + // reflect incident vector off plane orthogonal to normal + // normal is assumed to have unit length - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); - this.viewport = new Vector4( 0, 0, width, height ); + } - options = options || {}; + angleTo( v ) { - if ( options.minFilter === undefined ) options.minFilter = LinearFilter; + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); - this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( denominator === 0 ) return Math.PI / 2; - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + const theta = this.dot( v ) / denominator; - } + // clamp, to handle numerical problems - WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + return Math.acos( clamp( theta, - 1, 1 ) ); - constructor: WebGLRenderTarget, + } - isWebGLRenderTarget: true, + distanceTo( v ) { - setSize: function ( width, height ) { + return Math.sqrt( this.distanceToSquared( v ) ); - if ( this.width !== width || this.height !== height ) { + } - this.width = width; - this.height = height; + distanceToSquared( v ) { - this.dispose(); + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; - } + return dx * dx + dy * dy + dz * dz; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + } - }, + manhattanDistanceTo( v ) { - clone: function () { + return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); - return new this.constructor().copy( this ); + } - }, + setFromSpherical( s ) { - copy: function ( source ) { + return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); - this.width = source.width; - this.height = source.height; + } - this.viewport.copy( source.viewport ); + setFromSphericalCoords( radius, phi, theta ) { - this.texture = source.texture.clone(); + const sinPhiRadius = Math.sin( phi ) * radius; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + this.x = sinPhiRadius * Math.sin( theta ); + this.y = Math.cos( phi ) * radius; + this.z = sinPhiRadius * Math.cos( theta ); return this; - }, + } - dispose: function () { + setFromCylindrical( c ) { - this.dispatchEvent( { type: 'dispose' } ); + return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); } - } ); - - /** - * @author alteredq / http://alteredqualia.com - */ + setFromCylindricalCoords( radius, theta, y ) { - function WebGLRenderTargetCube( width, height, options ) { + this.x = radius * Math.sin( theta ); + this.y = y; + this.z = radius * Math.cos( theta ); - WebGLRenderTarget.call( this, width, height, options ); + return this; - this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 - this.activeMipMapLevel = 0; + } - } + setFromMatrixPosition( m ) { - WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); - WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; + const e = m.elements; - WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; - /** - * @author alteredq / http://alteredqualia.com/ - */ + return this; - function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + } - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + setFromMatrixScale( m ) { - this.image = { data: data, width: width, height: height }; + const sx = this.setFromMatrixColumn( m, 0 ).length(); + const sy = this.setFromMatrixColumn( m, 1 ).length(); + const sz = this.setFromMatrixColumn( m, 2 ).length(); - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + this.x = sx; + this.y = sy; + this.z = sz; - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; - } + } - DataTexture.prototype = Object.create( Texture.prototype ); - DataTexture.prototype.constructor = DataTexture; + setFromMatrixColumn( m, index ) { - DataTexture.prototype.isDataTexture = true; + return this.fromArray( m.elements, index * 4 ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + } - function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + setFromMatrix3Column( m, index ) { - images = images !== undefined ? images : []; - mapping = mapping !== undefined ? mapping : CubeReflectionMapping; + return this.fromArray( m.elements, index * 3 ); - Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + } - this.flipY = false; + setFromEuler( e ) { - } + this.x = e._x; + this.y = e._y; + this.z = e._z; - CubeTexture.prototype = Object.create( Texture.prototype ); - CubeTexture.prototype.constructor = CubeTexture; + return this; - CubeTexture.prototype.isCubeTexture = true; + } - Object.defineProperty( CubeTexture.prototype, 'images', { + setFromColor( c ) { - get: function () { + this.x = c.r; + this.y = c.g; + this.z = c.b; - return this.image; + return this; - }, + } - set: function ( value ) { + equals( v ) { - this.image = value; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); } - } ); - - /** - * @author tschw - * - * Uniforms of a program. - * Those form a tree structure with a special top-level container for the root, - * which you get by calling 'new WebGLUniforms( gl, program, renderer )'. - * - * - * Properties of inner nodes including the top-level container: - * - * .seq - array of nested uniforms - * .map - nested uniforms by name - * - * - * Methods of all nodes except the top-level container: - * - * .setValue( gl, value, [renderer] ) - * - * uploads a uniform value(s) - * the 'renderer' parameter is needed for sampler uniforms - * - * - * Static methods of the top-level container (renderer factorizations): - * - * .upload( gl, seq, values, renderer ) - * - * sets uniforms in 'seq' to 'values[id].value' - * - * .seqWithValue( seq, values ) : filteredSeq - * - * filters 'seq' entries with corresponding entry in values - * - * - * Methods of the top-level container (renderer factorizations): - * - * .setValue( gl, name, value ) - * - * sets uniform with name 'name' to 'value' - * - * .set( gl, obj, prop ) - * - * sets uniform from object and property with same name than uniform - * - * .setOptional( gl, obj, prop ) - * - * like .set for an optional property of the object - * - */ + fromArray( array, offset = 0 ) { - var emptyTexture = new Texture(); - var emptyCubeTexture = new CubeTexture(); + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; - // --- Base for inner nodes (including the root) --- + return this; - function UniformContainer() { + } - this.seq = []; - this.map = {}; + toArray( array = [], offset = 0 ) { - } + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; - // --- Utilities --- + return array; - // Array Caches (provide typed arrays for temporary by size) + } - var arrayCacheF32 = []; - var arrayCacheI32 = []; + fromBufferAttribute( attribute, index ) { - // Float32Array caches used for uploading Matrix uniforms + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); - var mat4array = new Float32Array( 16 ); - var mat3array = new Float32Array( 9 ); + return this; - // Flattening for arrays of vectors and matrices + } - function flatten( array, nBlocks, blockSize ) { + random() { - var firstElem = array[ 0 ]; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); - if ( firstElem <= 0 || firstElem > 0 ) return array; - // unoptimized: ! isNaN( firstElem ) - // see http://jacksondunstan.com/articles/983 + return this; - var n = nBlocks * blockSize, - r = arrayCacheF32[ n ]; + } - if ( r === undefined ) { + randomDirection() { - r = new Float32Array( n ); - arrayCacheF32[ n ] = r; + // https://mathworld.wolfram.com/SpherePointPicking.html - } + const theta = Math.random() * Math.PI * 2; + const u = Math.random() * 2 - 1; + const c = Math.sqrt( 1 - u * u ); - if ( nBlocks !== 0 ) { + this.x = c * Math.cos( theta ); + this.y = u; + this.z = c * Math.sin( theta ); - firstElem.toArray( r, 0 ); + return this; - for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) { + } - offset += blockSize; - array[ i ].toArray( r, offset ); + *[ Symbol.iterator ]() { - } + yield this.x; + yield this.y; + yield this.z; } - return r; - } - // Texture unit allocation + const _vector$c = /*@__PURE__*/ new Vector3(); + const _quaternion$4 = /*@__PURE__*/ new Quaternion(); - function allocTexUnits( renderer, n ) { + class Box3 { - var r = arrayCacheI32[ n ]; + constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { - if ( r === undefined ) { + this.isBox3 = true; - r = new Int32Array( n ); - arrayCacheI32[ n ] = r; + this.min = min; + this.max = max; } - for ( var i = 0; i !== n; ++ i ) - r[ i ] = renderer.allocTextureUnit(); - - return r; + set( min, max ) { - } + this.min.copy( min ); + this.max.copy( max ); - // --- Setters --- + return this; - // Note: Defining these methods externally, because they come in a bunch - // and this way their names minify. + } - // Single scalar + setFromArray( array ) { - function setValue1f( gl, v ) { + this.makeEmpty(); - gl.uniform1f( this.addr, v ); + for ( let i = 0, il = array.length; i < il; i += 3 ) { - } + this.expandByPoint( _vector$b.fromArray( array, i ) ); - function setValue1i( gl, v ) { + } - gl.uniform1i( this.addr, v ); + return this; - } + } - // Single float vector (from flat array or THREE.VectorN) + setFromBufferAttribute( attribute ) { - function setValue2fv( gl, v ) { + this.makeEmpty(); - if ( v.x === undefined ) { + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - gl.uniform2fv( this.addr, v ); + this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); - } else { + } - gl.uniform2f( this.addr, v.x, v.y ); + return this; } - } + setFromPoints( points ) { - function setValue3fv( gl, v ) { + this.makeEmpty(); - if ( v.x !== undefined ) { + for ( let i = 0, il = points.length; i < il; i ++ ) { - gl.uniform3f( this.addr, v.x, v.y, v.z ); + this.expandByPoint( points[ i ] ); - } else if ( v.r !== undefined ) { + } - gl.uniform3f( this.addr, v.r, v.g, v.b ); + return this; - } else { + } - gl.uniform3fv( this.addr, v ); + setFromCenterAndSize( center, size ) { - } + const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); - } + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); - function setValue4fv( gl, v ) { + return this; - if ( v.x === undefined ) { + } - gl.uniform4fv( this.addr, v ); + setFromObject( object, precise = false ) { - } else { + this.makeEmpty(); - gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); + return this.expandByObject( object, precise ); } - } + clone() { - // Single matrix (from flat array or MatrixN) + return new this.constructor().copy( this ); - function setValue2fm( gl, v ) { + } - gl.uniformMatrix2fv( this.addr, false, v.elements || v ); + copy( box ) { - } + this.min.copy( box.min ); + this.max.copy( box.max ); - function setValue3fm( gl, v ) { + return this; - if ( v.elements === undefined ) { + } - gl.uniformMatrix3fv( this.addr, false, v ); + makeEmpty() { - } else { + this.min.x = this.min.y = this.min.z = + Infinity; + this.max.x = this.max.y = this.max.z = - Infinity; - mat3array.set( v.elements ); - gl.uniformMatrix3fv( this.addr, false, mat3array ); + return this; } - } + isEmpty() { - function setValue4fm( gl, v ) { + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - if ( v.elements === undefined ) { + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); - gl.uniformMatrix4fv( this.addr, false, v ); + } - } else { + getCenter( target ) { - mat4array.set( v.elements ); - gl.uniformMatrix4fv( this.addr, false, mat4array ); + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); } - } + getSize( target ) { - // Single texture (2D / Cube) + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); - function setValueT1( gl, v, renderer ) { + } - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTexture2D( v || emptyTexture, unit ); + expandByPoint( point ) { - } + this.min.min( point ); + this.max.max( point ); - function setValueT6( gl, v, renderer ) { + return this; - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTextureCube( v || emptyCubeTexture, unit ); + } - } - - // Integer / Boolean vectors or arrays thereof (always flat arrays) + expandByVector( vector ) { - function setValue2iv( gl, v ) { + this.min.sub( vector ); + this.max.add( vector ); - gl.uniform2iv( this.addr, v ); + return this; - } + } - function setValue3iv( gl, v ) { + expandByScalar( scalar ) { - gl.uniform3iv( this.addr, v ); + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); - } + return this; - function setValue4iv( gl, v ) { + } - gl.uniform4iv( this.addr, v ); + expandByObject( object, precise = false ) { - } + // Computes the world-axis-aligned bounding box of an object (including its children), + // accounting for both the object's, and children's, world transforms - // Helper to pick the right setter for the singular case + object.updateWorldMatrix( false, false ); - function getSingularSetter( type ) { + const geometry = object.geometry; - switch ( type ) { + if ( geometry !== undefined ) { - case 0x1406: return setValue1f; // FLOAT - case 0x8b50: return setValue2fv; // _VEC2 - case 0x8b51: return setValue3fv; // _VEC3 - case 0x8b52: return setValue4fv; // _VEC4 + const positionAttribute = geometry.getAttribute( 'position' ); - case 0x8b5a: return setValue2fm; // _MAT2 - case 0x8b5b: return setValue3fm; // _MAT3 - case 0x8b5c: return setValue4fm; // _MAT4 + // precise AABB computation based on vertex data requires at least a position attribute. + // instancing isn't supported so far and uses the normal (conservative) code path. - case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES - case 0x8b60: return setValueT6; // SAMPLER_CUBE + if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { - case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 + for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { - } + if ( object.isMesh === true ) { - } + object.getVertexPosition( i, _vector$b ); - // Array of scalars + } else { - function setValue1fv( gl, v ) { + _vector$b.fromBufferAttribute( positionAttribute, i ); - gl.uniform1fv( this.addr, v ); + } - } - function setValue1iv( gl, v ) { + _vector$b.applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$b ); - gl.uniform1iv( this.addr, v ); + } - } + } else { - // Array of vectors (flat or from THREE classes) + if ( object.boundingBox !== undefined ) { - function setValueV2a( gl, v ) { + // object-level bounding box - gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) ); + if ( object.boundingBox === null ) { - } + object.computeBoundingBox(); - function setValueV3a( gl, v ) { + } - gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) ); + _box$4.copy( object.boundingBox ); - } - function setValueV4a( gl, v ) { + } else { - gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) ); + // geometry-level bounding box - } + if ( geometry.boundingBox === null ) { - // Array of matrices (flat or from THREE clases) + geometry.computeBoundingBox(); - function setValueM2a( gl, v ) { + } - gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) ); + _box$4.copy( geometry.boundingBox ); - } + } - function setValueM3a( gl, v ) { + _box$4.applyMatrix4( object.matrixWorld ); - gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) ); + this.union( _box$4 ); - } + } - function setValueM4a( gl, v ) { + } - gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) ); + const children = object.children; - } + for ( let i = 0, l = children.length; i < l; i ++ ) { - // Array of textures (2D / Cube) + this.expandByObject( children[ i ], precise ); - function setValueT1a( gl, v, renderer ) { + } - var n = v.length, - units = allocTexUnits( renderer, n ); + return this; - gl.uniform1iv( this.addr, units ); + } - for ( var i = 0; i !== n; ++ i ) { + containsPoint( point ) { - renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); + 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; } - } + containsBox( box ) { - function setValueT6a( gl, v, renderer ) { + 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; - var n = v.length, - units = allocTexUnits( renderer, n ); + } - gl.uniform1iv( this.addr, units ); + getParameter( point, target ) { - for ( var i = 0; i !== n; ++ i ) { + // This can potentially have a divide by zero if the box + // has a size dimension of 0. - renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); + 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 ) + ); } - } - - // Helper to pick the right setter for a pure (bottom-level) array - - function getPureArraySetter( type ) { + intersectsBox( box ) { - switch ( type ) { + // using 6 splitting planes to rule out intersections. + 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; - case 0x1406: return setValue1fv; // FLOAT - case 0x8b50: return setValueV2a; // _VEC2 - case 0x8b51: return setValueV3a; // _VEC3 - case 0x8b52: return setValueV4a; // _VEC4 + } - case 0x8b5a: return setValueM2a; // _MAT2 - case 0x8b5b: return setValueM3a; // _MAT3 - case 0x8b5c: return setValueM4a; // _MAT4 + intersectsSphere( sphere ) { - case 0x8b5e: return setValueT1a; // SAMPLER_2D - case 0x8b60: return setValueT6a; // SAMPLER_CUBE + // Find the point on the AABB closest to the sphere center. + this.clampPoint( sphere.center, _vector$b ); - case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 + // If that point is inside the sphere, the AABB and sphere intersect. + return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); } - } + intersectsPlane( plane ) { - // --- Uniform Classes --- + // We compute the minimum and maximum dot product values. If those values + // are on the same side (back or front) of the plane, then there is no intersection. - function SingleUniform( id, activeInfo, addr ) { + let min, max; - this.id = id; - this.addr = addr; - this.setValue = getSingularSetter( activeInfo.type ); + if ( plane.normal.x > 0 ) { - // this.path = activeInfo.name; // DEBUG + min = plane.normal.x * this.min.x; + max = plane.normal.x * this.max.x; - } + } else { - function PureArrayUniform( id, activeInfo, addr ) { + min = plane.normal.x * this.max.x; + max = plane.normal.x * this.min.x; - this.id = id; - this.addr = addr; - this.size = activeInfo.size; - this.setValue = getPureArraySetter( activeInfo.type ); + } - // this.path = activeInfo.name; // DEBUG + if ( plane.normal.y > 0 ) { - } + min += plane.normal.y * this.min.y; + max += plane.normal.y * this.max.y; - function StructuredUniform( id ) { + } else { - this.id = id; + min += plane.normal.y * this.max.y; + max += plane.normal.y * this.min.y; - UniformContainer.call( this ); // mix-in + } - } + if ( plane.normal.z > 0 ) { - StructuredUniform.prototype.setValue = function ( gl, value ) { + min += plane.normal.z * this.min.z; + max += plane.normal.z * this.max.z; - // Note: Don't need an extra 'renderer' parameter, since samplers - // are not allowed in structured uniforms. + } else { - var seq = this.seq; + min += plane.normal.z * this.max.z; + max += plane.normal.z * this.min.z; - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + } - var u = seq[ i ]; - u.setValue( gl, value[ u.id ] ); + return ( min <= - plane.constant && max >= - plane.constant ); } - }; + intersectsTriangle( triangle ) { - // --- Top-level --- + if ( this.isEmpty() ) { - // Parser - builds up the property tree from the path strings + return false; - var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g; + } - // extracts - // - the identifier (member name or array index) - // - followed by an optional right bracket (found when array index) - // - followed by an optional left bracket or dot (type of subscript) - // - // Note: These portions can be read in a non-overlapping fashion and - // allow straightforward parsing of the hierarchy that WebGL encodes - // in the uniform names. + // compute box center and extents + this.getCenter( _center ); + _extents.subVectors( this.max, _center ); - function addUniform( container, uniformObject ) { + // translate triangle to aabb origin + _v0$3.subVectors( triangle.a, _center ); + _v1$7.subVectors( triangle.b, _center ); + _v2$4.subVectors( triangle.c, _center ); - container.seq.push( uniformObject ); - container.map[ uniformObject.id ] = uniformObject; + // compute edge vectors for triangle + _f0.subVectors( _v1$7, _v0$3 ); + _f1.subVectors( _v2$4, _v1$7 ); + _f2.subVectors( _v0$3, _v2$4 ); - } + // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb + // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation + // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) + 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$3, _v1$7, _v2$4, _extents ) ) { - function parseUniform( activeInfo, addr, container ) { + return false; - var path = activeInfo.name, - pathLength = path.length; + } - // reset RegExp object, because of the early exit of a previous run - RePathPart.lastIndex = 0; + // test 3 face normals from the aabb + axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; + if ( ! satForAxes( axes, _v0$3, _v1$7, _v2$4, _extents ) ) { - for ( ; ; ) { + return false; - var match = RePathPart.exec( path ), - matchEnd = RePathPart.lastIndex, + } - id = match[ 1 ], - idIsIndex = match[ 2 ] === ']', - subscript = match[ 3 ]; + // finally testing the face normal of the triangle + // use already existing triangle edge vectors here + _triangleNormal.crossVectors( _f0, _f1 ); + axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; - if ( idIsIndex ) id = id | 0; // convert to integer + return satForAxes( axes, _v0$3, _v1$7, _v2$4, _extents ); - if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { + } - // bare name or "pure" bottom-level array "[0]" suffix + clampPoint( point, target ) { - addUniform( container, subscript === undefined ? - new SingleUniform( id, activeInfo, addr ) : - new PureArrayUniform( id, activeInfo, addr ) ); + return target.copy( point ).clamp( this.min, this.max ); - break; + } - } else { + distanceToPoint( point ) { - // step into inner node / create it in case it doesn't exist + return this.clampPoint( point, _vector$b ).distanceTo( point ); - var map = container.map, next = map[ id ]; + } - if ( next === undefined ) { + getBoundingSphere( target ) { - next = new StructuredUniform( id ); - addUniform( container, next ); + if ( this.isEmpty() ) { - } + target.makeEmpty(); - container = next; + } else { + + this.getCenter( target.center ); + + target.radius = this.getSize( _vector$b ).length() * 0.5; } - } + return target; - } + } - // Root Container + intersect( box ) { - function WebGLUniforms( gl, program, renderer ) { + this.min.max( box.min ); + this.max.min( box.max ); - UniformContainer.call( this ); + // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. + if ( this.isEmpty() ) this.makeEmpty(); - this.renderer = renderer; + return this; - var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); + } - for ( var i = 0; i < n; ++ i ) { + union( box ) { - var info = gl.getActiveUniform( program, i ), - path = info.name, - addr = gl.getUniformLocation( program, path ); + this.min.min( box.min ); + this.max.max( box.max ); - parseUniform( info, addr, this ); + return this; } - } + applyMatrix4( matrix ) { - WebGLUniforms.prototype.setValue = function ( gl, name, value ) { + // transform of empty box is an empty box. + if ( this.isEmpty() ) return this; - var u = this.map[ name ]; + // NOTE: I am using a binary pattern to specify all 2^3 combinations below + _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 + _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 + _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 + _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 + _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 + _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 + _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 + _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 - if ( u !== undefined ) u.setValue( gl, value, this.renderer ); + this.setFromPoints( _points ); - }; + return this; + + } + + translate( offset ) { - WebGLUniforms.prototype.setOptional = function ( gl, object, name ) { + this.min.add( offset ); + this.max.add( offset ); + + return this; - var v = object[ name ]; + } - if ( v !== undefined ) this.setValue( gl, name, v ); + equals( box ) { - }; + return box.min.equals( this.min ) && box.max.equals( this.max ); + + } + } - // Static interface + const _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() + ]; - WebGLUniforms.upload = function ( gl, seq, values, renderer ) { + const _vector$b = /*@__PURE__*/ new Vector3(); - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + const _box$4 = /*@__PURE__*/ new Box3(); - var u = seq[ i ], - v = values[ u.id ]; + // triangle centered vertices - if ( v.needsUpdate !== false ) { + const _v0$3 = /*@__PURE__*/ new Vector3(); + const _v1$7 = /*@__PURE__*/ new Vector3(); + const _v2$4 = /*@__PURE__*/ new Vector3(); - // note: always updating when .needsUpdate is undefined - u.setValue( gl, v.value, renderer ); + // triangle edge vectors - } + const _f0 = /*@__PURE__*/ new Vector3(); + const _f1 = /*@__PURE__*/ new Vector3(); + const _f2 = /*@__PURE__*/ new Vector3(); - } + const _center = /*@__PURE__*/ new Vector3(); + const _extents = /*@__PURE__*/ new Vector3(); + const _triangleNormal = /*@__PURE__*/ new Vector3(); + const _testAxis = /*@__PURE__*/ new Vector3(); - }; + function satForAxes( axes, v0, v1, v2, extents ) { - WebGLUniforms.seqWithValue = function ( seq, values ) { + for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { - var r = []; + _testAxis.fromArray( axes, i ); + // project the aabb onto the separating axis + const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); + // project all 3 vertices of the triangle onto the separating axis + const p0 = v0.dot( _testAxis ); + const p1 = v1.dot( _testAxis ); + const p2 = v2.dot( _testAxis ); + // actual test, basically see if either of the most extreme of the triangle points intersects r + if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { - for ( var i = 0, n = seq.length; i !== n; ++ i ) { + // points of the projected triangle are outside the projected half-length of the aabb + // the axis is separating and we can exit + return false; - var u = seq[ i ]; - if ( u.id in values ) r.push( u ); + } } - return r; + return true; - }; + } - /** - * @author mrdoob / http://mrdoob.com/ - */ + const _box$3 = /*@__PURE__*/ new Box3(); + const _v1$6 = /*@__PURE__*/ new Vector3(); + const _v2$3 = /*@__PURE__*/ new Vector3(); - var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; + class Sphere { - function Color( r, g, b ) { + constructor( center = new Vector3(), radius = - 1 ) { - if ( g === undefined && b === undefined ) { + this.isSphere = true; - // r is THREE.Color, hex or string - return this.set( r ); + this.center = center; + this.radius = radius; } - return this.setRGB( r, g, b ); + set( center, radius ) { - } + this.center.copy( center ); + this.radius = radius; - Object.assign( Color.prototype, { + return this; + + } + + setFromPoints( points, optionalCenter ) { - isColor: true, + const center = this.center; - r: 1, g: 1, b: 1, + if ( optionalCenter !== undefined ) { - set: function ( value ) { + center.copy( optionalCenter ); - if ( value && value.isColor ) { + } else { - this.copy( value ); + _box$3.setFromPoints( points ).getCenter( center ); - } else if ( typeof value === 'number' ) { + } - this.setHex( value ); + let maxRadiusSq = 0; - } else if ( typeof value === 'string' ) { + for ( let i = 0, il = points.length; i < il; i ++ ) { - this.setStyle( value ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); } + this.radius = Math.sqrt( maxRadiusSq ); + return this; - }, + } - setScalar: function ( scalar ) { + copy( sphere ) { - this.r = scalar; - this.g = scalar; - this.b = scalar; + this.center.copy( sphere.center ); + this.radius = sphere.radius; return this; - }, - - setHex: function ( hex ) { - - hex = Math.floor( hex ); + } - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + isEmpty() { - return this; + return ( this.radius < 0 ); - }, + } - setRGB: function ( r, g, b ) { + makeEmpty() { - this.r = r; - this.g = g; - this.b = b; + this.center.set( 0, 0, 0 ); + this.radius = - 1; return this; - }, + } - setHSL: function () { + containsPoint( point ) { - function hue2rgb( p, q, t ) { + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - 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; + } - } + distanceToPoint( point ) { - return function setHSL( h, s, l ) { + return ( point.distanceTo( this.center ) - this.radius ); - // h,s,l ranges are in 0.0 - 1.0 - h = _Math.euclideanModulo( h, 1 ); - s = _Math.clamp( s, 0, 1 ); - l = _Math.clamp( l, 0, 1 ); + } - if ( s === 0 ) { + intersectsSphere( sphere ) { - this.r = this.g = this.b = l; + const radiusSum = this.radius + sphere.radius; - } else { + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - var 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 ); + intersectsBox( box ) { - } + return box.intersectsSphere( this ); - return this; + } - }; + intersectsPlane( plane ) { - }(), + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - setStyle: function ( style ) { + } - function handleAlpha( string ) { + clampPoint( point, target ) { - if ( string === undefined ) return; + const deltaLengthSq = this.center.distanceToSquared( point ); - if ( parseFloat( string ) < 1 ) { + target.copy( point ); - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + if ( deltaLengthSq > ( this.radius * this.radius ) ) { - } + target.sub( this.center ).normalize(); + target.multiplyScalar( this.radius ).add( this.center ); } + return target; - var m; + } - if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) { + getBoundingBox( target ) { - // rgb / hsl + if ( this.isEmpty() ) { - var color; - var name = m[ 1 ]; - var components = m[ 2 ]; + // Empty sphere produces empty bounding box + target.makeEmpty(); + return target; - switch ( name ) { + } - case 'rgb': - case 'rgba': + target.set( this.center, this.center ); + target.expandByScalar( this.radius ); - if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + return target; - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; + } - handleAlpha( color[ 5 ] ); + applyMatrix4( matrix ) { - return this; + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); - } + return this; - if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + } - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; + translate( offset ) { - handleAlpha( color[ 5 ] ); + this.center.add( offset ); - return this; + return this; - } + } - break; + expandByPoint( point ) { - case 'hsl': - case 'hsla': + if ( this.isEmpty() ) { - if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { + this.center.copy( point ); - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - var h = parseFloat( color[ 1 ] ) / 360; - var s = parseInt( color[ 2 ], 10 ) / 100; - var l = parseInt( color[ 3 ], 10 ) / 100; + this.radius = 0; - handleAlpha( color[ 5 ] ); + return this; - return this.setHSL( h, s, l ); + } - } + _v1$6.subVectors( point, this.center ); - break; + const lengthSq = _v1$6.lengthSq(); - } + if ( lengthSq > ( this.radius * this.radius ) ) { - } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) { + // calculate the minimal sphere - // hex color + const length = Math.sqrt( lengthSq ); - var hex = m[ 1 ]; - var size = hex.length; + const delta = ( length - this.radius ) * 0.5; - if ( size === 3 ) { + this.center.addScaledVector( _v1$6, delta / length ); - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; + this.radius += delta; - return this; + } - } else if ( size === 6 ) { + return this; - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + } - return this; + union( sphere ) { - } + if ( sphere.isEmpty() ) { + + return this; } - if ( style && style.length > 0 ) { + if ( this.isEmpty() ) { - // color keywords - var hex = ColorKeywords[ style ]; + this.copy( sphere ); - if ( hex !== undefined ) { + return this; - // red - this.setHex( hex ); + } - } else { + if ( this.center.equals( sphere.center ) === true ) { - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + this.radius = Math.max( this.radius, sphere.radius ); - } + } else { + + _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); + + this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); + + this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); } return this; - }, - - clone: function () { + } - return new this.constructor( this.r, this.g, this.b ); + equals( sphere ) { - }, + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - copy: function ( color ) { + } - this.r = color.r; - this.g = color.g; - this.b = color.b; + clone() { - return this; + return new this.constructor().copy( this ); - }, + } - copyGammaToLinear: function ( color, gammaFactor ) { + } - if ( gammaFactor === undefined ) gammaFactor = 2.0; + const _vector$a = /*@__PURE__*/ new Vector3(); + const _segCenter = /*@__PURE__*/ new Vector3(); + const _segDir = /*@__PURE__*/ new Vector3(); + const _diff = /*@__PURE__*/ new Vector3(); - this.r = Math.pow( color.r, gammaFactor ); - this.g = Math.pow( color.g, gammaFactor ); - this.b = Math.pow( color.b, gammaFactor ); + const _edge1 = /*@__PURE__*/ new Vector3(); + const _edge2 = /*@__PURE__*/ new Vector3(); + const _normal$1 = /*@__PURE__*/ new Vector3(); - return this; + class Ray { - }, + constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 1 ) ) { - copyLinearToGamma: function ( color, gammaFactor ) { + this.origin = origin; + this.direction = direction; - if ( gammaFactor === undefined ) gammaFactor = 2.0; + } - var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; + set( origin, direction ) { - this.r = Math.pow( color.r, safeInverse ); - this.g = Math.pow( color.g, safeInverse ); - this.b = Math.pow( color.b, safeInverse ); + this.origin.copy( origin ); + this.direction.copy( direction ); return this; - }, - - convertGammaToLinear: function () { + } - var r = this.r, g = this.g, b = this.b; + copy( ray ) { - this.r = r * r; - this.g = g * g; - this.b = b * b; + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); return this; - }, + } - convertLinearToGamma: function () { + at( t, target ) { - this.r = Math.sqrt( this.r ); - this.g = Math.sqrt( this.g ); - this.b = Math.sqrt( this.b ); + return target.copy( this.origin ).addScaledVector( this.direction, t ); - return this; + } - }, + lookAt( v ) { - getHex: function () { + this.direction.copy( v ).sub( this.origin ).normalize(); - return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; + return this; - }, + } - getHexString: function () { + recast( t ) { - return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); + this.origin.copy( this.at( t, _vector$a ) ); - }, + return this; - getHSL: function ( optionalTarget ) { + } - // h,s,l ranges are in 0.0 - 1.0 + closestPointToPoint( point, target ) { - var hsl = optionalTarget || { h: 0, s: 0, l: 0 }; + target.subVectors( point, this.origin ); - var r = this.r, g = this.g, b = this.b; + const directionDistance = target.dot( this.direction ); - var max = Math.max( r, g, b ); - var min = Math.min( r, g, b ); + if ( directionDistance < 0 ) { - var hue, saturation; - var lightness = ( min + max ) / 2.0; + return target.copy( this.origin ); - if ( min === max ) { + } - hue = 0; - saturation = 0; + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - } else { + } - var delta = max - min; + distanceToPoint( point ) { - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + return Math.sqrt( this.distanceSqToPoint( point ) ); - switch ( max ) { + } - 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; + distanceSqToPoint( point ) { - } + const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); - hue /= 6; + // point behind the ray + + if ( directionDistance < 0 ) { + + return this.origin.distanceToSquared( point ); } - hsl.h = hue; - hsl.s = saturation; - hsl.l = lightness; + _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - return hsl; + return _vector$a.distanceToSquared( point ); - }, + } - getStyle: function () { + distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h + // It returns the min distance between the ray and the segment + // defined by v0 and v1 + // It can also set two optional targets : + // - The closest point on the ray + // - The closest point on the segment - }, + _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); + _segDir.copy( v1 ).sub( v0 ).normalize(); + _diff.copy( this.origin ).sub( _segCenter ); - offsetHSL: function ( h, s, l ) { + 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 c = _diff.lengthSq(); + const det = Math.abs( 1 - a01 * a01 ); + let s0, s1, sqrDist, extDet; - var hsl = this.getHSL(); + if ( det > 0 ) { - hsl.h += h; hsl.s += s; hsl.l += l; + // The ray and segment are not parallel. - this.setHSL( hsl.h, hsl.s, hsl.l ); + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; - return this; + if ( s0 >= 0 ) { - }, + if ( s1 >= - extDet ) { - add: function ( color ) { + if ( s1 <= extDet ) { - this.r += color.r; - this.g += color.g; - this.b += color.b; + // region 0 + // Minimum at interior points of ray and segment. - return this; + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - }, + } else { - addColors: function ( color1, color2 ) { + // region 1 - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + } else { - addScalar: function ( s ) { + // region 5 - this.r += s; - this.g += s; - this.b += s; + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + } else { - sub: function ( color ) { + if ( s1 <= - extDet ) { - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + // region 4 - return this; + 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 ) + c; - }, + } else if ( s1 <= extDet ) { - multiply: function ( color ) { + // region 3 - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; - return this; + } else { - }, + // region 2 - multiplyScalar: function ( s ) { + 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 ) + c; - this.r *= s; - this.g *= s; - this.b *= s; + } - return this; + } - }, + } else { - lerp: function ( color, alpha ) { + // Ray and segment are parallel. - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return this; + } - }, + if ( optionalPointOnRay ) { - equals: function ( c ) { + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + } - }, + if ( optionalPointOnSegment ) { - fromArray: function ( array, offset ) { + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); - if ( offset === undefined ) offset = 0; + } - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + return sqrDist; - return this; + } - }, + intersectSphere( sphere, target ) { - toArray: function ( array, offset ) { + _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 ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + if ( d2 > radius2 ) return null; - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + const thc = Math.sqrt( radius2 - d2 ); - return array; + // t0 = first intersect point - entrance on front of sphere + const t0 = tca - thc; - }, + // t1 = second intersect point - exit point on back of sphere + const t1 = tca + thc; - toJSON: function () { + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; - return this.getHex(); + // test to see if t0 is behind the ray: + // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, + // in order to always return an intersect point that is in front of the ray. + if ( t0 < 0 ) return this.at( t1, target ); + + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, target ); } - } ); + intersectsSphere( sphere ) { - /** - * Uniforms library for shared webgl shaders - */ + return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); - var UniformsLib = { + } - common: { + distanceToPlane( plane ) { - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, + const denominator = plane.normal.dot( this.direction ); - map: { value: null }, - uvTransform: { value: new Matrix3() }, + if ( denominator === 0 ) { - alphaMap: { value: null }, + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { - }, + return 0; - specularmap: { + } - specularMap: { value: null }, + // Null is preferable to undefined since undefined means.... it is undefined - }, + return null; - envmap: { + } - envMap: { value: null }, - flipEnvMap: { value: - 1 }, - reflectivity: { value: 1.0 }, - refractionRatio: { value: 0.98 } + const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - }, + // Return if the ray never intersects the plane - aomap: { + return t >= 0 ? t : null; - aoMap: { value: null }, - aoMapIntensity: { value: 1 } + } - }, + intersectPlane( plane, target ) { - lightmap: { + const t = this.distanceToPlane( plane ); - lightMap: { value: null }, - lightMapIntensity: { value: 1 } + if ( t === null ) { - }, + return null; - emissivemap: { + } - emissiveMap: { value: null } + return this.at( t, target ); - }, + } - bumpmap: { + intersectsPlane( plane ) { - bumpMap: { value: null }, - bumpScale: { value: 1 } + // check if the ray lies on the plane first - }, + const distToPoint = plane.distanceToPoint( this.origin ); - normalmap: { + if ( distToPoint === 0 ) { - normalMap: { value: null }, - normalScale: { value: new Vector2( 1, 1 ) } + return true; - }, + } - displacementmap: { + const denominator = plane.normal.dot( this.direction ); - displacementMap: { value: null }, - displacementScale: { value: 1 }, - displacementBias: { value: 0 } + if ( denominator * distToPoint < 0 ) { - }, + return true; - roughnessmap: { + } - roughnessMap: { value: null } + // ray origin is behind the plane (and is pointing behind it) - }, + return false; - metalnessmap: { + } - metalnessMap: { value: null } + intersectBox( box, target ) { - }, + let tmin, tmax, tymin, tymax, tzmin, tzmax; - gradientmap: { + const invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; - gradientMap: { value: null } + const origin = this.origin; - }, + if ( invdirx >= 0 ) { - fog: { + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; - fogDensity: { value: 0.00025 }, - fogNear: { value: 1 }, - fogFar: { value: 2000 }, - fogColor: { value: new Color( 0xffffff ) } + } else { - }, + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; - lights: { + } - ambientLightColor: { value: [] }, + if ( invdiry >= 0 ) { - directionalLights: { value: [], properties: { - direction: {}, - color: {}, + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, + } else { - directionalShadowMap: { value: [] }, - directionalShadowMatrix: { value: [] }, + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; - spotLights: { value: [], properties: { - color: {}, - position: {}, - direction: {}, - distance: {}, - coneCos: {}, - penumbraCos: {}, - decay: {}, + } - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; - spotShadowMap: { value: [] }, - spotShadowMatrix: { value: [] }, + if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; - pointLights: { value: [], properties: { - color: {}, - position: {}, - decay: {}, - distance: {}, + if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {}, - shadowCameraNear: {}, - shadowCameraFar: {} - } }, + if ( invdirz >= 0 ) { - pointShadowMap: { value: [] }, - pointShadowMatrix: { value: [] }, + tzmin = ( box.min.z - origin.z ) * invdirz; + tzmax = ( box.max.z - origin.z ) * invdirz; - hemisphereLights: { value: [], properties: { - direction: {}, - skyColor: {}, - groundColor: {} - } }, + } else { - // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src - rectAreaLights: { value: [], properties: { - color: {}, - position: {}, - width: {}, - height: {} - } } + tzmin = ( box.max.z - origin.z ) * invdirz; + tzmax = ( box.min.z - origin.z ) * invdirz; - }, + } - points: { + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, - size: { value: 1.0 }, - scale: { value: 1.0 }, - map: { value: null }, - uvTransform: { value: new Matrix3() } + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + + //return point closest to the ray (positive side) + + if ( tmax < 0 ) return null; + + return this.at( tmin >= 0 ? tmin : tmax, target ); } - }; + intersectsBox( box ) { - /** - * Uniform Utilities - */ + return this.intersectBox( box, _vector$a ) !== null; - var UniformsUtils = { + } - merge: function ( uniforms ) { + intersectTriangle( a, b, c, backfaceCulling, target ) { - var merged = {}; + // Compute the offset origin, edges, and normal. - for ( var u = 0; u < uniforms.length; u ++ ) { + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - var tmp = this.clone( uniforms[ u ] ); + _edge1.subVectors( b, a ); + _edge2.subVectors( c, a ); + _normal$1.crossVectors( _edge1, _edge2 ); - for ( var p in tmp ) { + // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, + // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by + // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) + // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) + // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) + let DdN = this.direction.dot( _normal$1 ); + let sign; - merged[ p ] = tmp[ p ]; + if ( DdN > 0 ) { - } + if ( backfaceCulling ) return null; + sign = 1; - } + } else if ( DdN < 0 ) { - return merged; + sign = - 1; + DdN = - DdN; - }, + } else { - clone: function ( uniforms_src ) { + return null; - var uniforms_dst = {}; + } - for ( var u in uniforms_src ) { + _diff.subVectors( this.origin, a ); + const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); - uniforms_dst[ u ] = {}; + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { - for ( var p in uniforms_src[ u ] ) { + return null; - var parameter_src = uniforms_src[ u ][ p ]; + } - if ( parameter_src && ( parameter_src.isColor || - parameter_src.isMatrix3 || parameter_src.isMatrix4 || - parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 || - parameter_src.isTexture ) ) { + const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); - uniforms_dst[ u ][ p ] = parameter_src.clone(); + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { - } else if ( Array.isArray( parameter_src ) ) { + return null; - uniforms_dst[ u ][ p ] = parameter_src.slice(); + } - } else { + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { - uniforms_dst[ u ][ p ] = parameter_src; + return null; - } + } - } + // Line intersects triangle, check if ray does. + const QdN = - sign * _diff.dot( _normal$1 ); + + // t < 0, no intersection + if ( QdN < 0 ) { + + return null; } - return uniforms_dst; + // Ray intersects triangle. + return this.at( QdN / DdN, target ); } - }; + applyMatrix4( matrix4 ) { - var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n"; + this.origin.applyMatrix4( matrix4 ); + this.direction.transformDirection( matrix4 ); - var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n"; + return this; - var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n"; + } - var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n"; + equals( ray ) { - var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; + return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); - var begin_vertex = "\nvec3 transformed = vec3( position );\n"; + } - var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n"; + clone() { - var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; + return new this.constructor().copy( this ); - var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n"; + } - var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n"; + } - var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n"; + class Matrix4 { - var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n"; + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n"; + Matrix4.prototype.isMatrix4 = true; - var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif"; + this.elements = [ - var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n"; + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif"; + ]; - var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif"; + if ( n11 !== undefined ) { - var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n"; + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); - var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n"; + } - var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n"; + } - var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n"; + set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; + const te = this.elements; - var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n"; + 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; - var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n"; + return this; - var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n"; + } - var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n"; + identity() { - var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n"; + this.set( - var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n"; + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n"; + ); - var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n"; + return this; - var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif"; + } - var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n"; + clone() { - var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n"; + return new Matrix4().fromArray( this.elements ); - var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n"; + } - var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n"; + copy( m ) { - var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n"; + const te = this.elements; + const me = m.elements; - var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; + 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 ]; - var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n"; + return this; - var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; + } - var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n"; + copyPosition( m ) { - var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n"; + const te = this.elements, me = m.elements; - var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n"; + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; - var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n"; + return this; - var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; + } - var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; + setFromMatrix3( m ) { - var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n"; + const me = m.elements; - var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif"; + this.set( - var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n"; + 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 - var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n"; + ); - var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n"; + return this; - var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; + } - var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n"; + extractBasis( xAxis, yAxis, zAxis ) { - var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n"; + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); - var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; + return this; - var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n"; + } - var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif"; + makeBasis( xAxis, yAxis, zAxis ) { - var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n"; + 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 + ); - var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; + return this; - var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; + } - var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 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\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; + extractRotation( m ) { - var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n"; + // this method does not support reflection matrices - var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n"; + const te = this.elements; + const me = m.elements; - var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n"; + const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); + const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); + const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); - var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n"; + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; + te[ 3 ] = 0; - var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n"; + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; + te[ 7 ] = 0; - var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; + te[ 11 ] = 0; - var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n"; + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; - var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n"; + return this; - var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n"; + } - var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n"; + makeRotationFromEuler( euler ) { - var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; + const te = this.elements; - var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n"; + const x = euler.x, y = euler.y, z = euler.z; + const a = Math.cos( x ), b = Math.sin( x ); + const c = Math.cos( y ), d = Math.sin( y ); + const e = Math.cos( z ), f = Math.sin( z ); - var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n"; + if ( euler.order === 'XYZ' ) { - var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n"; + const ae = a * e, af = a * f, be = b * e, bf = b * f; - var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; - var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; - var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n"; + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; - var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n"; + } else if ( euler.order === 'YXZ' ) { - var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif"; + const ce = c * e, cf = c * f, de = d * e, df = d * f; - var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n"; + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; - var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; - var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; - var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif"; + } else if ( euler.order === 'ZXY' ) { - var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif"; + const ce = c * e, cf = c * f, de = d * e, df = d * f; - var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n"; + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; - var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; - var cube_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n"; + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; - var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n"; + } else if ( euler.order === 'ZYX' ) { - var depth_vert = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + const ae = a * e, af = a * f, be = b * e, bf = b * f; - var distanceRGBA_frag = "#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n"; + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; - var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n"; + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; - var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; - var equirect_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; + } else if ( euler.order === 'YZX' ) { - var linedashed_frag = "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\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; - var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n"; + te[ 0 ] = c * e; + te[ 4 ] = bd - ac * f; + te[ 8 ] = bc * f + ad; - var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + te[ 1 ] = f; + te[ 5 ] = a * e; + te[ 9 ] = - b * e; - var meshbasic_vert = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + te[ 2 ] = - d * e; + te[ 6 ] = ad * f + bc; + te[ 10 ] = ac - bd * f; - var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } else if ( euler.order === 'XZY' ) { - var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; - var meshphong_frag = "#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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + te[ 0 ] = c * e; + te[ 4 ] = - f; + te[ 8 ] = d * e; - var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + te[ 1 ] = ac * f + bd; + te[ 5 ] = a * e; + te[ 9 ] = ad * f - bc; - var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + te[ 2 ] = bc * f - ad; + te[ 6 ] = b * e; + te[ 10 ] = bd * f + ac; - var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n"; + } - var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; + // bottom row + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; - var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; + // last column + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; - var points_frag = "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\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + return this; - var points_vert = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + } - var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n"; + makeRotationFromQuaternion( q ) { - var shadow_vert = "#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + return this.compose( _zero, q, _one ); - var ShaderChunk = { - alphamap_fragment: alphamap_fragment, - alphamap_pars_fragment: alphamap_pars_fragment, - alphatest_fragment: alphatest_fragment, - aomap_fragment: aomap_fragment, - aomap_pars_fragment: aomap_pars_fragment, - begin_vertex: begin_vertex, - beginnormal_vertex: beginnormal_vertex, - bsdfs: bsdfs, - bumpmap_pars_fragment: bumpmap_pars_fragment, - clipping_planes_fragment: clipping_planes_fragment, - clipping_planes_pars_fragment: clipping_planes_pars_fragment, - clipping_planes_pars_vertex: clipping_planes_pars_vertex, - clipping_planes_vertex: clipping_planes_vertex, - color_fragment: color_fragment, - color_pars_fragment: color_pars_fragment, - color_pars_vertex: color_pars_vertex, - color_vertex: color_vertex, - common: common, - cube_uv_reflection_fragment: cube_uv_reflection_fragment, - defaultnormal_vertex: defaultnormal_vertex, - displacementmap_pars_vertex: displacementmap_pars_vertex, - displacementmap_vertex: displacementmap_vertex, - emissivemap_fragment: emissivemap_fragment, - emissivemap_pars_fragment: emissivemap_pars_fragment, - encodings_fragment: encodings_fragment, - encodings_pars_fragment: encodings_pars_fragment, - envmap_fragment: envmap_fragment, - envmap_pars_fragment: envmap_pars_fragment, - envmap_pars_vertex: envmap_pars_vertex, - envmap_vertex: envmap_vertex, - fog_vertex: fog_vertex, - fog_pars_vertex: fog_pars_vertex, - fog_fragment: fog_fragment, - fog_pars_fragment: fog_pars_fragment, - gradientmap_pars_fragment: gradientmap_pars_fragment, - lightmap_fragment: lightmap_fragment, - lightmap_pars_fragment: lightmap_pars_fragment, - lights_lambert_vertex: lights_lambert_vertex, - lights_pars: lights_pars, - lights_phong_fragment: lights_phong_fragment, - lights_phong_pars_fragment: lights_phong_pars_fragment, - lights_physical_fragment: lights_physical_fragment, - lights_physical_pars_fragment: lights_physical_pars_fragment, - lights_template: lights_template, - logdepthbuf_fragment: logdepthbuf_fragment, - logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, - logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, - logdepthbuf_vertex: logdepthbuf_vertex, - map_fragment: map_fragment, - map_pars_fragment: map_pars_fragment, - map_particle_fragment: map_particle_fragment, - map_particle_pars_fragment: map_particle_pars_fragment, - metalnessmap_fragment: metalnessmap_fragment, - metalnessmap_pars_fragment: metalnessmap_pars_fragment, - morphnormal_vertex: morphnormal_vertex, - morphtarget_pars_vertex: morphtarget_pars_vertex, - morphtarget_vertex: morphtarget_vertex, - normal_fragment: normal_fragment, - normalmap_pars_fragment: normalmap_pars_fragment, - packing: packing, - premultiplied_alpha_fragment: premultiplied_alpha_fragment, - project_vertex: project_vertex, - dithering_fragment: dithering_fragment, - dithering_pars_fragment: dithering_pars_fragment, - roughnessmap_fragment: roughnessmap_fragment, - roughnessmap_pars_fragment: roughnessmap_pars_fragment, - shadowmap_pars_fragment: shadowmap_pars_fragment, - shadowmap_pars_vertex: shadowmap_pars_vertex, - shadowmap_vertex: shadowmap_vertex, - shadowmask_pars_fragment: shadowmask_pars_fragment, - skinbase_vertex: skinbase_vertex, - skinning_pars_vertex: skinning_pars_vertex, - skinning_vertex: skinning_vertex, - skinnormal_vertex: skinnormal_vertex, - specularmap_fragment: specularmap_fragment, - specularmap_pars_fragment: specularmap_pars_fragment, - tonemapping_fragment: tonemapping_fragment, - tonemapping_pars_fragment: tonemapping_pars_fragment, - uv_pars_fragment: uv_pars_fragment, - uv_pars_vertex: uv_pars_vertex, - uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, - worldpos_vertex: worldpos_vertex, - - cube_frag: cube_frag, - cube_vert: cube_vert, - depth_frag: depth_frag, - depth_vert: depth_vert, - distanceRGBA_frag: distanceRGBA_frag, - distanceRGBA_vert: distanceRGBA_vert, - equirect_frag: equirect_frag, - equirect_vert: equirect_vert, - linedashed_frag: linedashed_frag, - linedashed_vert: linedashed_vert, - meshbasic_frag: meshbasic_frag, - meshbasic_vert: meshbasic_vert, - meshlambert_frag: meshlambert_frag, - meshlambert_vert: meshlambert_vert, - meshphong_frag: meshphong_frag, - meshphong_vert: meshphong_vert, - meshphysical_frag: meshphysical_frag, - meshphysical_vert: meshphysical_vert, - normal_frag: normal_frag, - normal_vert: normal_vert, - points_frag: points_frag, - points_vert: points_vert, - shadow_frag: shadow_frag, - shadow_vert: shadow_vert - }; - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - */ + } - var ShaderLib = { + lookAt( eye, target, up ) { - basic: { + const te = this.elements; - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.fog - ] ), + _z.subVectors( eye, target ); - vertexShader: ShaderChunk.meshbasic_vert, - fragmentShader: ShaderChunk.meshbasic_frag + if ( _z.lengthSq() === 0 ) { - }, + // eye and target are in the same position - lambert: { + _z.z = 1; - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) } - } - ] ), + } - vertexShader: ShaderChunk.meshlambert_vert, - fragmentShader: ShaderChunk.meshlambert_frag + _z.normalize(); + _x.crossVectors( up, _z ); - }, + if ( _x.lengthSq() === 0 ) { - phong: { + // up and z are parallel - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - UniformsLib.gradientmap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) }, - specular: { value: new Color( 0x111111 ) }, - shininess: { value: 30 } - } - ] ), + if ( Math.abs( up.z ) === 1 ) { - vertexShader: ShaderChunk.meshphong_vert, - fragmentShader: ShaderChunk.meshphong_frag + _z.x += 0.0001; - }, + } else { - standard: { + _z.z += 0.0001; - uniforms: UniformsUtils.merge( [ - 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: new Color( 0x000000 ) }, - roughness: { value: 0.5 }, - metalness: { value: 0.5 }, - envMapIntensity: { value: 1 } // temporary } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - - }, - - points: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.points, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.points_vert, - fragmentShader: ShaderChunk.points_frag - }, + _z.normalize(); + _x.crossVectors( up, _z ); - dashed: { + } - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.fog, - { - scale: { value: 1 }, - dashSize: { value: 1 }, - totalSize: { value: 2 } - } - ] ), + _x.normalize(); + _y.crossVectors( _z, _x ); - vertexShader: ShaderChunk.linedashed_vert, - fragmentShader: ShaderChunk.linedashed_frag + 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; - depth: { + } - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap - ] ), + multiply( m ) { - vertexShader: ShaderChunk.depth_vert, - fragmentShader: ShaderChunk.depth_frag + return this.multiplyMatrices( this, m ); - }, + } - normal: { + premultiply( m ) { - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - { - opacity: { value: 1.0 } - } - ] ), + return this.multiplyMatrices( m, this ); - vertexShader: ShaderChunk.normal_vert, - fragmentShader: ShaderChunk.normal_frag + } - }, + multiplyMatrices( a, b ) { - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ + const ae = a.elements; + const be = b.elements; + const te = this.elements; - cube: { + 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 ]; - uniforms: { - tCube: { value: null }, - tFlip: { value: - 1 }, - opacity: { value: 1.0 } - }, + 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 ]; - vertexShader: ShaderChunk.cube_vert, - fragmentShader: ShaderChunk.cube_frag + 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; - equirect: { + 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; - uniforms: { - tEquirect: { value: null }, - }, + 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; - vertexShader: ShaderChunk.equirect_vert, - fragmentShader: ShaderChunk.equirect_frag + return this; - }, + } - distanceRGBA: { + multiplyScalar( s ) { - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap, - { - referencePosition: { value: new Vector3() }, - nearDistance: { value: 1 }, - farDistance: { value: 1000 } - } - ] ), + const te = this.elements; - vertexShader: ShaderChunk.distanceRGBA_vert, - fragmentShader: ShaderChunk.distanceRGBA_frag + 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; - shadow: { + } - uniforms: UniformsUtils.merge( [ - UniformsLib.lights, - UniformsLib.fog, - { - color: { value: new Color( 0x00000 ) }, - opacity: { value: 1.0 } - }, - ] ), + determinant() { - vertexShader: ShaderChunk.shadow_vert, - fragmentShader: ShaderChunk.shadow_frag + 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 ]; - }; + //TODO: make this more efficient + //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) - ShaderLib.physical = { - - uniforms: UniformsUtils.merge( [ - ShaderLib.standard.uniforms, - { - clearCoat: { value: 0 }, - clearCoatRoughness: { value: 0 } - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag + 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 + ) - }; + ); - /** - * @author bhouston / http://clara.io - */ + } - function Box2( min, max ) { + transpose() { - this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity ); + 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; - Object.assign( Box2.prototype, { + 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; - set: function ( min, max ) { + return this; - this.min.copy( min ); - this.max.copy( max ); + } - return this; + setPosition( x, y, z ) { - }, + const te = this.elements; - setFromPoints: function ( points ) { + if ( x.isVector3 ) { - this.makeEmpty(); + te[ 12 ] = x.x; + te[ 13 ] = x.y; + te[ 14 ] = x.z; - for ( var i = 0, il = points.length; i < il; i ++ ) { + } else { - this.expandByPoint( points[ i ] ); + te[ 12 ] = x; + te[ 13 ] = y; + te[ 14 ] = z; } return this; - }, - - setFromCenterAndSize: function () { + } - var v1 = new Vector2(); + invert() { - return function setFromCenterAndSize( center, size ) { + // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + const te = this.elements, - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); + 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 ], - return this; + 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 ); - clone: function () { + const detInv = 1 / det; - return new this.constructor().copy( this ); + 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; - copy: function ( box ) { + 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; - this.min.copy( box.min ); - this.max.copy( box.max ); + 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; - }, + } - makeEmpty: function () { + scale( v ) { - this.min.x = this.min.y = + Infinity; - this.max.x = this.max.y = - Infinity; + const te = this.elements; + const x = v.x, y = v.y, z = v.z; - return this; + te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; + te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; + te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; + te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; - }, + return this; - isEmpty: function () { + } - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes + getMaxScaleOnAxis() { - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); + 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 ]; - getCenter: function ( optionalTarget ) { + return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); + } - }, + makeTranslation( x, y, z ) { - getSize: function ( optionalTarget ) { + if ( x.isVector3 ) { - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.subVectors( this.max, this.min ); + this.set( - }, + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 - expandByPoint: function ( point ) { + ); - this.min.min( point ); - this.max.max( point ); + } else { - return this; + this.set( - }, + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 - expandByVector: function ( vector ) { + ); - this.min.sub( vector ); - this.max.add( vector ); + } return this; - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); + } - return this; + makeRotationX( theta ) { - }, + const c = Math.cos( theta ), s = Math.sin( theta ); - containsPoint: function ( point ) { + this.set( - return point.x < this.min.x || point.x > this.max.x || - point.y < this.min.y || point.y > this.max.y ? false : true; + 1, 0, 0, 0, + 0, c, - s, 0, + 0, s, c, 0, + 0, 0, 0, 1 - }, + ); - containsBox: function ( box ) { + return this; - 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; + } - }, + makeRotationY( theta ) { - getParameter: function ( point, optionalTarget ) { + const c = Math.cos( theta ), s = Math.sin( theta ); - // This can potentially have a divide by zero if the box - // has a size dimension of 0. + this.set( - var result = optionalTarget || new Vector2(); + c, 0, s, 0, + 0, 1, 0, 0, + - s, 0, c, 0, + 0, 0, 0, 1 - return result.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ) ); - }, - - intersectsBox: function ( box ) { + return this; - // using 4 splitting planes to rule out intersections + } - 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; + makeRotationZ( theta ) { - }, + const c = Math.cos( theta ), s = Math.sin( theta ); - clampPoint: function ( point, optionalTarget ) { + this.set( - var result = optionalTarget || new Vector2(); - return result.copy( point ).clamp( this.min, this.max ); + c, - s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - }, + ); - distanceToPoint: function () { + return this; - var v1 = new Vector2(); + } - return function distanceToPoint( point ) { + makeRotationAxis( axis, angle ) { - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); + // Based on http://www.gamedev.net/reference/articles/article1199.asp - }; + const c = Math.cos( angle ); + const s = Math.sin( angle ); + const t = 1 - c; + const x = axis.x, y = axis.y, z = axis.z; + const tx = t * x, ty = t * y; - }(), + this.set( - intersect: function ( box ) { + tx * x + c, tx * y - s * z, tx * z + s * y, 0, + tx * y + s * z, ty * y + c, ty * z - s * x, 0, + tx * z - s * y, ty * z + s * x, t * z * z + c, 0, + 0, 0, 0, 1 - this.min.max( box.min ); - this.max.min( box.max ); + ); return this; - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); + } - return this; + makeScale( x, y, z ) { - }, + this.set( - translate: function ( offset ) { + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 - this.min.add( offset ); - this.max.add( offset ); + ); return this; - }, - - equals: function ( box ) { + } - return box.min.equals( this.min ) && box.max.equals( this.max ); + 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 - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + ); - function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) { + return this; - var vertexBuffer, elementBuffer; - var shader, program, attributes, uniforms; + } - var tempTexture, occlusionTexture; + compose( position, quaternion, scale ) { - function init() { + const te = this.elements; - var vertices = new Float32Array( [ - - 1, - 1, 0, 0, - 1, - 1, 1, 0, - 1, 1, 1, 1, - - 1, 1, 0, 1 - ] ); + const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; + const x2 = x + x, y2 = y + y, z2 = z + z; + const xx = x * x2, xy = x * y2, xz = x * z2; + const yy = y * y2, yz = y * z2, zz = z * z2; + const wx = w * x2, wy = w * y2, wz = w * z2; - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); + const sx = scale.x, sy = scale.y, sz = scale.z; - // buffers + te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; + te[ 1 ] = ( xy + wz ) * sx; + te[ 2 ] = ( xz - wy ) * sx; + te[ 3 ] = 0; - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); + te[ 4 ] = ( xy - wz ) * sy; + te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; + te[ 6 ] = ( yz + wx ) * sy; + te[ 7 ] = 0; - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); + te[ 8 ] = ( xz + wy ) * sz; + te[ 9 ] = ( yz - wx ) * sz; + te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; + te[ 11 ] = 0; - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); + te[ 12 ] = position.x; + te[ 13 ] = position.y; + te[ 14 ] = position.z; + te[ 15 ] = 1; - // textures + return this; - tempTexture = gl.createTexture(); - occlusionTexture = gl.createTexture(); + } - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + decompose( position, quaternion, scale ) { - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + const te = this.elements; - shader = { + 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(); - vertexShader: [ + // if determine is negative, we need to invert one scale + const det = this.determinant(); + if ( det < 0 ) sx = - sx; - 'uniform lowp int renderType;', + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', - 'uniform float rotation;', + // scale the rotation part + _m1$4.copy( this ); - 'uniform sampler2D occlusionMap;', + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; - 'attribute vec2 position;', - 'attribute vec2 uv;', + _m1$4.elements[ 0 ] *= invSX; + _m1$4.elements[ 1 ] *= invSX; + _m1$4.elements[ 2 ] *= invSX; - 'varying vec2 vUV;', - 'varying float vVisibility;', + _m1$4.elements[ 4 ] *= invSY; + _m1$4.elements[ 5 ] *= invSY; + _m1$4.elements[ 6 ] *= invSY; - 'void main() {', + _m1$4.elements[ 8 ] *= invSZ; + _m1$4.elements[ 9 ] *= invSZ; + _m1$4.elements[ 10 ] *= invSZ; - ' vUV = uv;', + quaternion.setFromRotationMatrix( _m1$4 ); - ' vec2 pos = position;', + scale.x = sx; + scale.y = sy; + scale.z = sz; - ' if ( renderType == 2 ) {', + return this; - ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', + } - ' vVisibility = visibility.r / 9.0;', - ' vVisibility *= 1.0 - visibility.g / 9.0;', - ' vVisibility *= visibility.b / 9.0;', - ' vVisibility *= 1.0 - visibility.a / 9.0;', + makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { - ' pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;', - ' pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;', + const te = this.elements; + const x = 2 * near / ( right - left ); + const y = 2 * near / ( top - bottom ); - ' }', + const a = ( right + left ) / ( right - left ); + const b = ( top + bottom ) / ( top - bottom ); - ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', + let c, d; - '}' + if ( coordinateSystem === WebGLCoordinateSystem ) { - ].join( '\n' ), + c = - ( far + near ) / ( far - near ); + d = ( - 2 * far * near ) / ( far - near ); - fragmentShader: [ + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - 'uniform lowp int renderType;', + c = - far / ( far - near ); + d = ( - far * near ) / ( far - near ); - 'uniform sampler2D map;', - 'uniform float opacity;', - 'uniform vec3 color;', + } else { - 'varying vec2 vUV;', - 'varying float vVisibility;', + throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); - 'void main() {', + } - // pink square + te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; + te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; - ' if ( renderType == 0 ) {', + return this; - ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );', + } - // restore + makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { - ' } else if ( renderType == 1 ) {', + const te = this.elements; + const w = 1.0 / ( right - left ); + const h = 1.0 / ( top - bottom ); + const p = 1.0 / ( far - near ); - ' gl_FragColor = texture2D( map, vUV );', + const x = ( right + left ) * w; + const y = ( top + bottom ) * h; - // flare + let z, zInv; - ' } else {', + if ( coordinateSystem === WebGLCoordinateSystem ) { - ' vec4 texture = texture2D( map, vUV );', - ' texture.a *= opacity * vVisibility;', - ' gl_FragColor = texture;', - ' gl_FragColor.rgb *= color;', + z = ( far + near ) * p; + zInv = - 2 * p; - ' }', + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - '}' + z = near * p; + zInv = - 1 * p; - ].join( '\n' ) + } else { - }; + throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); - program = createProgram( shader ); + } - attributes = { - vertex: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; + te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; + te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; - uniforms = { - renderType: gl.getUniformLocation( program, 'renderType' ), - map: gl.getUniformLocation( program, 'map' ), - occlusionMap: gl.getUniformLocation( program, 'occlusionMap' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - color: gl.getUniformLocation( program, 'color' ), - scale: gl.getUniformLocation( program, 'scale' ), - rotation: gl.getUniformLocation( program, 'rotation' ), - screenPosition: gl.getUniformLocation( program, 'screenPosition' ) - }; + return this; } - /* - * Render lens flares - * Method: renders 16x16 0xff00ff-colored points scattered over the light source area, - * reads these back and calculates occlusion. - */ - - this.render = function ( flares, scene, camera, viewport ) { + equals( matrix ) { - if ( flares.length === 0 ) return; + const te = this.elements; + const me = matrix.elements; - var tempPosition = new Vector3(); + for ( let i = 0; i < 16; i ++ ) { - var invAspect = viewport.w / viewport.z, - halfViewportWidth = viewport.z * 0.5, - halfViewportHeight = viewport.w * 0.5; + if ( te[ i ] !== me[ i ] ) return false; - var size = 16 / viewport.w, - scale = new Vector2( size * invAspect, size ); + } - var screenPosition = new Vector3( 1, 1, 0 ), - screenPositionPixels = new Vector2( 1, 1 ); + return true; - var validArea = new Box2(); + } - validArea.min.set( viewport.x, viewport.y ); - validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); + fromArray( array, offset = 0 ) { - if ( program === undefined ) { + for ( let i = 0; i < 16; i ++ ) { - init(); + this.elements[ i ] = array[ i + offset ]; } - state.useProgram( program ); + return this; - state.initAttributes(); - state.enableAttribute( attributes.vertex ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); + } - // loop through all lens flares to update their occlusion and positions - // setup gl and common used attribs/uniforms + toArray( array = [], offset = 0 ) { - gl.uniform1i( uniforms.occlusionMap, 0 ); - gl.uniform1i( uniforms.map, 1 ); + const te = this.elements; - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + array[ offset + 3 ] = te[ 3 ]; - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; - state.disable( gl.CULL_FACE ); - state.buffers.depth.setMask( false ); + array[ offset + 8 ] = te[ 8 ]; + array[ offset + 9 ] = te[ 9 ]; + array[ offset + 10 ] = te[ 10 ]; + array[ offset + 11 ] = te[ 11 ]; - for ( var i = 0, l = flares.length; i < l; i ++ ) { + array[ offset + 12 ] = te[ 12 ]; + array[ offset + 13 ] = te[ 13 ]; + array[ offset + 14 ] = te[ 14 ]; + array[ offset + 15 ] = te[ 15 ]; - size = 16 / viewport.w; - scale.set( size * invAspect, size ); + return array; - // calc object screen position + } - var flare = flares[ i ]; + } - tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] ); + const _v1$5 = /*@__PURE__*/ new Vector3(); + const _m1$4 = /*@__PURE__*/ new Matrix4(); + const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); + const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); + const _x = /*@__PURE__*/ new Vector3(); + const _y = /*@__PURE__*/ new Vector3(); + const _z = /*@__PURE__*/ new Vector3(); - tempPosition.applyMatrix4( camera.matrixWorldInverse ); - tempPosition.applyMatrix4( camera.projectionMatrix ); + const _matrix$2 = /*@__PURE__*/ new Matrix4(); + const _quaternion$3 = /*@__PURE__*/ new Quaternion(); - // setup arrays for gl programs + class Euler { - screenPosition.copy( tempPosition ); + constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { - // horizontal and vertical coordinate of the lower left corner of the pixels to copy + this.isEuler = true; - screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8; - screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8; + this._x = x; + this._y = y; + this._z = z; + this._order = order; - // screen cull + } - if ( validArea.containsPoint( screenPositionPixels ) === true ) { + get x() { - // save current RGB to temp texture + return this._x; - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, null ); - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); + } + set x( value ) { - // render pink quad + this._x = value; + this._onChangeCallback(); - gl.uniform1i( uniforms.renderType, 0 ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); + } - state.disable( gl.BLEND ); - state.enable( gl.DEPTH_TEST ); + get y() { - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + return this._y; + } - // copy result to occlusionMap + set y( value ) { - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); + this._y = value; + this._onChangeCallback(); + } - // restore graphics + get z() { - gl.uniform1i( uniforms.renderType, 1 ); - state.disable( gl.DEPTH_TEST ); + return this._z; - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + } + set z( value ) { - // update object positions + this._z = value; + this._onChangeCallback(); - flare.positionScreen.copy( screenPosition ); + } - if ( flare.customUpdateCallback ) { + get order() { - flare.customUpdateCallback( flare ); + return this._order; - } else { + } - flare.updateLensFlares(); + set order( value ) { - } + this._order = value; + this._onChangeCallback(); - // render flares + } - gl.uniform1i( uniforms.renderType, 2 ); - state.enable( gl.BLEND ); + set( x, y, z, order = this._order ) { - for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) { + this._x = x; + this._y = y; + this._z = z; + this._order = order; - var sprite = flare.lensFlares[ j ]; + this._onChangeCallback(); - if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) { + return this; - screenPosition.x = sprite.x; - screenPosition.y = sprite.y; - screenPosition.z = sprite.z; + } - size = sprite.size * sprite.scale / viewport.w; + clone() { - scale.x = size * invAspect; - scale.y = size; + return new this.constructor( this._x, this._y, this._z, this._order ); - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform1f( uniforms.rotation, sprite.rotation ); + } - gl.uniform1f( uniforms.opacity, sprite.opacity ); - gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); + copy( euler ) { - state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); + this._x = euler._x; + this._y = euler._y; + this._z = euler._z; + this._order = euler._order; - textures.setTexture2D( sprite.texture, 1 ); + this._onChangeCallback(); - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + return this; - } + } - } + setFromRotationMatrix( m, order = this._order, update = true ) { - } + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - } + const te = m.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 ]; - // restore gl + switch ( order ) { - state.enable( gl.CULL_FACE ); - state.enable( gl.DEPTH_TEST ); - state.buffers.depth.setMask( true ); + case 'XYZ': - state.reset(); + this._y = Math.asin( clamp( m13, - 1, 1 ) ); - }; + if ( Math.abs( m13 ) < 0.9999999 ) { - function createProgram( shader ) { + this._x = Math.atan2( - m23, m33 ); + this._z = Math.atan2( - m12, m11 ); - var program = gl.createProgram(); + } else { - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); + this._x = Math.atan2( m32, m22 ); + this._z = 0; - var prefix = 'precision ' + capabilities.precision + ' float;\n'; + } - gl.shaderSource( fragmentShader, prefix + shader.fragmentShader ); - gl.shaderSource( vertexShader, prefix + shader.vertexShader ); + break; - gl.compileShader( fragmentShader ); - gl.compileShader( vertexShader ); + case 'YXZ': - gl.attachShader( program, fragmentShader ); - gl.attachShader( program, vertexShader ); + this._x = Math.asin( - clamp( m23, - 1, 1 ) ); - gl.linkProgram( program ); + if ( Math.abs( m23 ) < 0.9999999 ) { - return program; + this._y = Math.atan2( m13, m33 ); + this._z = Math.atan2( m21, m22 ); - } + } else { - } + this._y = Math.atan2( - m31, m11 ); + this._z = 0; - /** - * @author mrdoob / http://mrdoob.com/ - */ + } - function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + break; - Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + case 'ZXY': - this.needsUpdate = true; + this._x = Math.asin( clamp( m32, - 1, 1 ) ); - } + if ( Math.abs( m32 ) < 0.9999999 ) { - CanvasTexture.prototype = Object.create( Texture.prototype ); - CanvasTexture.prototype.constructor = CanvasTexture; + this._y = Math.atan2( - m31, m33 ); + this._z = Math.atan2( - m12, m22 ); - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + } else { + + this._y = 0; + this._z = Math.atan2( m21, m11 ); - function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { + } - var vertexBuffer, elementBuffer; - var program, attributes, uniforms; + break; - var texture; + case 'ZYX': - // decompose matrixWorld + this._y = Math.asin( - clamp( m31, - 1, 1 ) ); - var spritePosition = new Vector3(); - var spriteRotation = new Quaternion(); - var spriteScale = new Vector3(); + if ( Math.abs( m31 ) < 0.9999999 ) { - function init() { + this._x = Math.atan2( m32, m33 ); + this._z = Math.atan2( m21, m11 ); - var vertices = new Float32Array( [ - - 0.5, - 0.5, 0, 0, - 0.5, - 0.5, 1, 0, - 0.5, 0.5, 1, 1, - - 0.5, 0.5, 0, 1 - ] ); + } else { - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); + this._x = 0; + this._z = Math.atan2( - m12, m22 ); - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); + } - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); + break; - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); + case 'YZX': - program = createProgram(); + this._z = Math.asin( clamp( m21, - 1, 1 ) ); - attributes = { - position: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; + if ( Math.abs( m21 ) < 0.9999999 ) { - uniforms = { - uvOffset: gl.getUniformLocation( program, 'uvOffset' ), - uvScale: gl.getUniformLocation( program, 'uvScale' ), + this._x = Math.atan2( - m23, m22 ); + this._y = Math.atan2( - m31, m11 ); - rotation: gl.getUniformLocation( program, 'rotation' ), - scale: gl.getUniformLocation( program, 'scale' ), + } else { - color: gl.getUniformLocation( program, 'color' ), - map: gl.getUniformLocation( program, 'map' ), - opacity: gl.getUniformLocation( program, 'opacity' ), + this._x = 0; + this._y = Math.atan2( m13, m33 ); - modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ), - projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ), + } - fogType: gl.getUniformLocation( program, 'fogType' ), - fogDensity: gl.getUniformLocation( program, 'fogDensity' ), - fogNear: gl.getUniformLocation( program, 'fogNear' ), - fogFar: gl.getUniformLocation( program, 'fogFar' ), - fogColor: gl.getUniformLocation( program, 'fogColor' ), - fogDepth: gl.getUniformLocation( program, 'fogDepth' ), + break; - alphaTest: gl.getUniformLocation( program, 'alphaTest' ) - }; + case 'XZY': - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = 8; - canvas.height = 8; + this._z = Math.asin( - clamp( m12, - 1, 1 ) ); - var context = canvas.getContext( '2d' ); - context.fillStyle = 'white'; - context.fillRect( 0, 0, 8, 8 ); + if ( Math.abs( m12 ) < 0.9999999 ) { - texture = new CanvasTexture( canvas ); + this._x = Math.atan2( m32, m22 ); + this._y = Math.atan2( m13, m11 ); - } + } else { - this.render = function ( sprites, scene, camera ) { + this._x = Math.atan2( - m23, m33 ); + this._y = 0; - if ( sprites.length === 0 ) return; + } - // setup gl + break; - if ( program === undefined ) { + default: - init(); + console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); } - state.useProgram( program ); + this._order = order; - state.initAttributes(); - state.enableAttribute( attributes.position ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); + if ( update === true ) this._onChangeCallback(); - state.disable( gl.CULL_FACE ); - state.enable( gl.BLEND ); + return this; - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); + } - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); + setFromQuaternion( q, order, update ) { - gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements ); + _matrix$2.makeRotationFromQuaternion( q ); - state.activeTexture( gl.TEXTURE0 ); - gl.uniform1i( uniforms.map, 0 ); + return this.setFromRotationMatrix( _matrix$2, order, update ); - var oldFogType = 0; - var sceneFogType = 0; - var fog = scene.fog; + } - if ( fog ) { + setFromVector3( v, order = this._order ) { - gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b ); + return this.set( v.x, v.y, v.z, order ); - if ( fog.isFog ) { + } - gl.uniform1f( uniforms.fogNear, fog.near ); - gl.uniform1f( uniforms.fogFar, fog.far ); + reorder( newOrder ) { - gl.uniform1i( uniforms.fogType, 1 ); - oldFogType = 1; - sceneFogType = 1; + // WARNING: this discards revolution information -bhouston - } else if ( fog.isFogExp2 ) { + _quaternion$3.setFromEuler( this ); - gl.uniform1f( uniforms.fogDensity, fog.density ); + return this.setFromQuaternion( _quaternion$3, newOrder ); - gl.uniform1i( uniforms.fogType, 2 ); - oldFogType = 2; - sceneFogType = 2; + } - } + equals( euler ) { - } else { + return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); - gl.uniform1i( uniforms.fogType, 0 ); - oldFogType = 0; - sceneFogType = 0; + } - } + fromArray( array ) { + this._x = array[ 0 ]; + this._y = array[ 1 ]; + this._z = array[ 2 ]; + if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; - // update positions and sort + this._onChangeCallback(); - for ( var i = 0, l = sprites.length; i < l; i ++ ) { + return this; - var sprite = sprites[ i ]; + } - sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); - sprite.z = - sprite.modelViewMatrix.elements[ 14 ]; + toArray( array = [], offset = 0 ) { - } + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._order; - sprites.sort( painterSortStable ); + return array; - // render all sprites + } - var scale = []; + _onChange( callback ) { - for ( var i = 0, l = sprites.length; i < l; i ++ ) { + this._onChangeCallback = callback; - var sprite = sprites[ i ]; - var material = sprite.material; + return this; - if ( material.visible === false ) continue; + } - sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); + _onChangeCallback() {} - gl.uniform1f( uniforms.alphaTest, material.alphaTest ); - gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); + *[ Symbol.iterator ]() { - sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale ); + yield this._x; + yield this._y; + yield this._z; + yield this._order; - scale[ 0 ] = spriteScale.x; - scale[ 1 ] = spriteScale.y; + } - var fogType = 0; + } - if ( scene.fog && material.fog ) { + Euler.DEFAULT_ORDER = 'XYZ'; - fogType = sceneFogType; + class Layers { - } + constructor() { - if ( oldFogType !== fogType ) { + this.mask = 1 | 0; - gl.uniform1i( uniforms.fogType, fogType ); - oldFogType = fogType; + } - } + set( channel ) { - if ( material.map !== null ) { + this.mask = ( 1 << channel | 0 ) >>> 0; - gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y ); - gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y ); + } - } else { + enable( channel ) { - gl.uniform2f( uniforms.uvOffset, 0, 0 ); - gl.uniform2f( uniforms.uvScale, 1, 1 ); + this.mask |= 1 << channel | 0; - } + } - gl.uniform1f( uniforms.opacity, material.opacity ); - gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b ); + enableAll() { - gl.uniform1f( uniforms.rotation, material.rotation ); - gl.uniform2fv( uniforms.scale, scale ); + this.mask = 0xffffffff | 0; - state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); - state.buffers.depth.setTest( material.depthTest ); - state.buffers.depth.setMask( material.depthWrite ); - state.buffers.color.setMask( material.colorWrite ); + } - textures.setTexture2D( material.map || texture, 0 ); + toggle( channel ) { - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + this.mask ^= 1 << channel | 0; - sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); + } - } + disable( channel ) { - // restore gl + this.mask &= ~ ( 1 << channel | 0 ); - state.enable( gl.CULL_FACE ); + } - state.reset(); + disableAll() { - }; + this.mask = 0; - function createProgram() { + } - var program = gl.createProgram(); + test( layers ) { - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); + return ( this.mask & layers.mask ) !== 0; - gl.shaderSource( vertexShader, [ + } - 'precision ' + capabilities.precision + ' float;', + isEnabled( channel ) { - '#define SHADER_NAME ' + 'SpriteMaterial', + return ( this.mask & ( 1 << channel | 0 ) ) !== 0; - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform float rotation;', - 'uniform vec2 scale;', - 'uniform vec2 uvOffset;', - 'uniform vec2 uvScale;', + } - 'attribute vec2 position;', - 'attribute vec2 uv;', + } - 'varying vec2 vUV;', - 'varying float fogDepth;', + let _object3DId = 0; - 'void main() {', + const _v1$4 = /*@__PURE__*/ new Vector3(); + const _q1 = /*@__PURE__*/ new Quaternion(); + const _m1$3 = /*@__PURE__*/ new Matrix4(); + const _target = /*@__PURE__*/ new Vector3(); - ' vUV = uvOffset + uv * uvScale;', + const _position$3 = /*@__PURE__*/ new Vector3(); + const _scale$2 = /*@__PURE__*/ new Vector3(); + const _quaternion$2 = /*@__PURE__*/ new Quaternion(); - ' vec2 alignedPosition = position * scale;', + const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); + const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); + const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); - ' vec2 rotatedPosition;', - ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', - ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', + const _addedEvent = { type: 'added' }; + const _removedEvent = { type: 'removed' }; - ' vec4 mvPosition;', + const _childaddedEvent = { type: 'childadded', child: null }; + const _childremovedEvent = { type: 'childremoved', child: null }; - ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', - ' mvPosition.xy += rotatedPosition;', + class Object3D extends EventDispatcher { - ' gl_Position = projectionMatrix * mvPosition;', + constructor() { - ' fogDepth = - mvPosition.z;', + super(); - '}' + this.isObject3D = true; - ].join( '\n' ) ); + Object.defineProperty( this, 'id', { value: _object3DId ++ } ); - gl.shaderSource( fragmentShader, [ + this.uuid = generateUUID(); - 'precision ' + capabilities.precision + ' float;', + this.name = ''; + this.type = 'Object3D'; - '#define SHADER_NAME ' + 'SpriteMaterial', + this.parent = null; + this.children = []; - 'uniform vec3 color;', - 'uniform sampler2D map;', - 'uniform float opacity;', + this.up = Object3D.DEFAULT_UP.clone(); - 'uniform int fogType;', - 'uniform vec3 fogColor;', - 'uniform float fogDensity;', - 'uniform float fogNear;', - 'uniform float fogFar;', - 'uniform float alphaTest;', + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3( 1, 1, 1 ); - 'varying vec2 vUV;', - 'varying float fogDepth;', + function onRotationChange() { - 'void main() {', + quaternion.setFromEuler( rotation, false ); - ' vec4 texture = texture2D( map, vUV );', + } - ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', + function onQuaternionChange() { - ' if ( gl_FragColor.a < alphaTest ) discard;', + rotation.setFromQuaternion( quaternion, undefined, false ); - ' if ( fogType > 0 ) {', + } - ' float fogFactor = 0.0;', + rotation._onChange( onRotationChange ); + quaternion._onChange( onQuaternionChange ); - ' if ( fogType == 1 ) {', + 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() + } + } ); - ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );', + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); - ' } else {', + this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; - ' const float LOG2 = 1.442695;', - ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', - ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', + this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer + this.matrixWorldNeedsUpdate = false; - ' }', + this.layers = new Layers(); + this.visible = true; - ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', + this.castShadow = false; + this.receiveShadow = false; - ' }', + this.frustumCulled = true; + this.renderOrder = 0; - '}' + this.animations = []; - ].join( '\n' ) ); + this.userData = {}; - gl.compileShader( vertexShader ); - gl.compileShader( fragmentShader ); + } - gl.attachShader( program, vertexShader ); - gl.attachShader( program, fragmentShader ); + onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} - gl.linkProgram( program ); + onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} - return program; + onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} - } + onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} - function painterSortStable( a, b ) { + applyMatrix4( matrix ) { - if ( a.renderOrder !== b.renderOrder ) { + if ( this.matrixAutoUpdate ) this.updateMatrix(); - return a.renderOrder - b.renderOrder; + this.matrix.premultiply( matrix ); - } else if ( a.z !== b.z ) { + this.matrix.decompose( this.position, this.quaternion, this.scale ); - return b.z - a.z; + } - } else { + applyQuaternion( q ) { - return b.id - a.id; + this.quaternion.premultiply( q ); - } + return this; } - } - - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + setRotationFromAxisAngle( axis, angle ) { - var materialId = 0; + // assumes axis is normalized - function Material() { + this.quaternion.setFromAxisAngle( axis, angle ); - Object.defineProperty( this, 'id', { value: materialId ++ } ); + } - this.uuid = _Math.generateUUID(); + setRotationFromEuler( euler ) { - this.name = ''; - this.type = 'Material'; + this.quaternion.setFromEuler( euler, true ); - this.fog = true; - this.lights = true; + } - this.blending = NormalBlending; - this.side = FrontSide; - this.flatShading = false; - this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors + setRotationFromMatrix( m ) { - this.opacity = 1; - this.transparent = false; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - this.blendSrc = SrcAlphaFactor; - this.blendDst = OneMinusSrcAlphaFactor; - this.blendEquation = AddEquation; - this.blendSrcAlpha = null; - this.blendDstAlpha = null; - this.blendEquationAlpha = null; + this.quaternion.setFromRotationMatrix( m ); - this.depthFunc = LessEqualDepth; - this.depthTest = true; - this.depthWrite = true; + } - this.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; + setRotationFromQuaternion( q ) { - this.colorWrite = true; + // assumes q is normalized - this.precision = null; // override the renderer's default precision for this material + this.quaternion.copy( q ); - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; + } - this.dithering = false; + rotateOnAxis( axis, angle ) { - this.alphaTest = 0; - this.premultipliedAlpha = false; + // rotate object on axis in object space + // axis is assumed to be normalized - this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer + _q1.setFromAxisAngle( axis, angle ); - this.visible = true; + this.quaternion.multiply( _q1 ); - this.userData = {}; + return this; - this.needsUpdate = true; + } - } + rotateOnWorldAxis( axis, angle ) { - Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + // rotate object on axis in world space + // axis is assumed to be normalized + // method assumes no rotated parent - constructor: Material, + _q1.setFromAxisAngle( axis, angle ); - isMaterial: true, + this.quaternion.premultiply( _q1 ); - onBeforeCompile: function () {}, + return this; - setValues: function ( values ) { + } - if ( values === undefined ) return; + rotateX( angle ) { - for ( var key in values ) { + return this.rotateOnAxis( _xAxis, angle ); - var newValue = values[ key ]; + } - if ( newValue === undefined ) { + rotateY( angle ) { - console.warn( "THREE.Material: '" + key + "' parameter is undefined." ); - continue; + return this.rotateOnAxis( _yAxis, angle ); - } + } - // for backward compatability if shading is set in the constructor - if ( key === 'shading' ) { + rotateZ( angle ) { - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( newValue === FlatShading ) ? true : false; - continue; + return this.rotateOnAxis( _zAxis, angle ); - } + } - var currentValue = this[ key ]; + translateOnAxis( axis, distance ) { - if ( currentValue === undefined ) { + // translate object by distance along axis in object space + // axis is assumed to be normalized - console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." ); - continue; + _v1$4.copy( axis ).applyQuaternion( this.quaternion ); - } + this.position.add( _v1$4.multiplyScalar( distance ) ); - if ( currentValue && currentValue.isColor ) { + return this; - currentValue.set( newValue ); + } - } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + translateX( distance ) { - currentValue.copy( newValue ); + return this.translateOnAxis( _xAxis, distance ); - } else if ( key === 'overdraw' ) { + } - // ensure overdraw is backwards-compatible with legacy boolean type - this[ key ] = Number( newValue ); + translateY( distance ) { - } else { + return this.translateOnAxis( _yAxis, distance ); - this[ key ] = newValue; + } - } + translateZ( distance ) { - } + return this.translateOnAxis( _zAxis, distance ); - }, + } - toJSON: function ( meta ) { + localToWorld( vector ) { - var isRoot = ( meta === undefined || typeof meta === 'string' ); + this.updateWorldMatrix( true, false ); - if ( isRoot ) { + return vector.applyMatrix4( this.matrixWorld ); - meta = { - textures: {}, - images: {} - }; + } - } + worldToLocal( vector ) { - var data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; + this.updateWorldMatrix( true, false ); - // standard Material serialization - data.uuid = this.uuid; - data.type = this.type; + return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() ); - if ( this.name !== '' ) data.name = this.name; + } - if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + lookAt( x, y, z ) { - if ( this.roughness !== undefined ) data.roughness = this.roughness; - if ( this.metalness !== undefined ) data.metalness = this.metalness; + // This method does not support objects having non-uniformly-scaled parent(s) - if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); - if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + if ( x.isVector3 ) { - if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); - if ( this.shininess !== undefined ) data.shininess = this.shininess; - if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat; - if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness; + _target.copy( x ); - if ( this.map && this.map.isTexture ) data.map = this.map.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; - if ( this.bumpMap && this.bumpMap.isTexture ) { + } else { - data.bumpMap = this.bumpMap.toJSON( meta ).uuid; - data.bumpScale = this.bumpScale; + _target.set( x, y, z ); } - if ( this.normalMap && this.normalMap.isTexture ) { - data.normalMap = this.normalMap.toJSON( meta ).uuid; - data.normalScale = this.normalScale.toArray(); + const parent = this.parent; - } - if ( this.displacementMap && this.displacementMap.isTexture ) { + this.updateWorldMatrix( true, false ); - data.displacementMap = this.displacementMap.toJSON( meta ).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; + _position$3.setFromMatrixPosition( this.matrixWorld ); - } - 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.isCamera || this.isLight ) { - 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; + _m1$3.lookAt( _position$3, _target, this.up ); - if ( this.envMap && this.envMap.isTexture ) { + } else { - data.envMap = this.envMap.toJSON( meta ).uuid; - data.reflectivity = this.reflectivity; // Scale behind envMap + _m1$3.lookAt( _target, _position$3, this.up ); } - if ( this.gradientMap && this.gradientMap.isTexture ) { + this.quaternion.setFromRotationMatrix( _m1$3 ); - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + if ( parent ) { + + _m1$3.extractRotation( parent.matrixWorld ); + _q1.setFromRotationMatrix( _m1$3 ); + this.quaternion.premultiply( _q1.invert() ); } - if ( this.size !== undefined ) data.size = this.size; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + } - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.flatShading === true ) data.flatShading = this.flatShading; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; + add( object ) { - if ( this.opacity < 1 ) data.opacity = this.opacity; - if ( this.transparent === true ) data.transparent = this.transparent; + if ( arguments.length > 1 ) { - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; + for ( let i = 0; i < arguments.length; i ++ ) { - // rotation (SpriteMaterial) - if ( this.rotation !== 0 ) data.rotation = this.rotation; + this.add( arguments[ i ] ); - if ( this.linewidth !== 1 ) data.linewidth = this.linewidth; - if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; - if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; - if ( this.scale !== undefined ) data.scale = this.scale; + } - if ( this.dithering === true ) data.dithering = true; + return this; - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - 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 ( object === this ) { - if ( this.morphTargets === true ) data.morphTargets = true; - if ( this.skinning === true ) data.skinning = true; + console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); + return this; - if ( this.visible === false ) data.visible = false; - if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; + } - // TODO: Copied from Object3D.toJSON + if ( object && object.isObject3D ) { - function extractFromCache( cache ) { + object.removeFromParent(); + object.parent = this; + this.children.push( object ); - var values = []; + object.dispatchEvent( _addedEvent ); - for ( var key in cache ) { + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; - var data = cache[ key ]; - delete data.metadata; - values.push( data ); + } 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 values; + return this; } - if ( isRoot ) { + const index = this.children.indexOf( object ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); + if ( index !== - 1 ) { - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; + object.parent = null; + this.children.splice( index, 1 ); + + object.dispatchEvent( _removedEvent ); + + _childremovedEvent.child = object; + this.dispatchEvent( _childremovedEvent ); + _childremovedEvent.child = null; } - return data; + return this; - }, + } - clone: function () { + removeFromParent() { - return new this.constructor().copy( this ); + const parent = this.parent; - }, + if ( parent !== null ) { - copy: function ( source ) { + parent.remove( this ); - this.name = source.name; + } - this.fog = source.fog; - this.lights = source.lights; + return this; - this.blending = source.blending; - this.side = source.side; - this.flatShading = source.flatShading; - this.vertexColors = source.vertexColors; + } - this.opacity = source.opacity; - this.transparent = source.transparent; + clear() { - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; + return this.remove( ... this.children ); - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; + } - this.colorWrite = source.colorWrite; + attach( object ) { - this.precision = source.precision; + // adds object as a child of this, while maintaining the object's world transform - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; + // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) - this.dithering = source.dithering; + this.updateWorldMatrix( true, false ); - this.alphaTest = source.alphaTest; - this.premultipliedAlpha = source.premultipliedAlpha; + _m1$3.copy( this.matrixWorld ).invert(); - this.overdraw = source.overdraw; + if ( object.parent !== null ) { - this.visible = source.visible; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + object.parent.updateWorldMatrix( true, false ); - this.clipShadows = source.clipShadows; - this.clipIntersection = source.clipIntersection; + _m1$3.multiply( object.parent.matrixWorld ); - var srcPlanes = source.clippingPlanes, - dstPlanes = null; + } - if ( srcPlanes !== null ) { + object.applyMatrix4( _m1$3 ); - var n = srcPlanes.length; - dstPlanes = new Array( n ); + object.removeFromParent(); + object.parent = this; + this.children.push( object ); - for ( var i = 0; i !== n; ++ i ) - dstPlanes[ i ] = srcPlanes[ i ].clone(); + object.updateWorldMatrix( false, true ); - } + object.dispatchEvent( _addedEvent ); - this.clippingPlanes = dstPlanes; + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; return this; - }, + } - dispose: function () { + getObjectById( id ) { - this.dispatchEvent( { type: 'dispose' } ); + return this.getObjectByProperty( 'id', id ); } - } ); + getObjectByName( name ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author bhouston / https://clara.io - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * - * opacity: , - * - * map: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * wireframe: , - * wireframeLinewidth: - * } - */ + return this.getObjectByProperty( 'name', name ); - function MeshDepthMaterial( parameters ) { + } - Material.call( this ); + getObjectByProperty( name, value ) { - this.type = 'MeshDepthMaterial'; + if ( this[ name ] === value ) return this; - this.depthPacking = BasicDepthPacking; + for ( let i = 0, l = this.children.length; i < l; i ++ ) { - this.skinning = false; - this.morphTargets = false; + const child = this.children[ i ]; + const object = child.getObjectByProperty( name, value ); - this.map = null; + if ( object !== undefined ) { - this.alphaMap = null; + return object; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + } - this.wireframe = false; - this.wireframeLinewidth = 1; + } - this.fog = false; - this.lights = false; + return undefined; - this.setValues( parameters ); + } - } + getObjectsByProperty( name, value, result = [] ) { - MeshDepthMaterial.prototype = Object.create( Material.prototype ); - MeshDepthMaterial.prototype.constructor = MeshDepthMaterial; + if ( this[ name ] === value ) result.push( this ); - MeshDepthMaterial.prototype.isMeshDepthMaterial = true; + const children = this.children; - MeshDepthMaterial.prototype.copy = function ( source ) { + for ( let i = 0, l = children.length; i < l; i ++ ) { - Material.prototype.copy.call( this, source ); + children[ i ].getObjectsByProperty( name, value, result ); - this.depthPacking = source.depthPacking; + } - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; + return result; - this.map = source.map; + } - this.alphaMap = source.alphaMap; + getWorldPosition( target ) { - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + this.updateWorldMatrix( true, false ); - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; + return target.setFromMatrixPosition( this.matrixWorld ); - return this; + } - }; + getWorldQuaternion( target ) { - /** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * - * referencePosition: , - * nearDistance: , - * farDistance: , - * - * skinning: , - * morphTargets: , - * - * map: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: - * - * } - */ + this.updateWorldMatrix( true, false ); - function MeshDistanceMaterial( parameters ) { + this.matrixWorld.decompose( _position$3, target, _scale$2 ); - Material.call( this ); + return target; - this.type = 'MeshDistanceMaterial'; + } - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; + getWorldScale( target ) { - this.skinning = false; - this.morphTargets = false; + this.updateWorldMatrix( true, false ); - this.map = null; + this.matrixWorld.decompose( _position$3, _quaternion$2, target ); - this.alphaMap = null; + return target; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + } - this.fog = false; - this.lights = false; + getWorldDirection( target ) { - this.setValues( parameters ); + this.updateWorldMatrix( true, false ); - } + const e = this.matrixWorld.elements; - MeshDistanceMaterial.prototype = Object.create( Material.prototype ); - MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; + return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); - MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; + } - MeshDistanceMaterial.prototype.copy = function ( source ) { + raycast( /* raycaster, intersects */ ) {} - Material.prototype.copy.call( this, source ); + traverse( callback ) { - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; + callback( this ); - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; + const children = this.children; - this.map = source.map; + for ( let i = 0, l = children.length; i < l; i ++ ) { - this.alphaMap = source.alphaMap; + children[ i ].traverse( callback ); - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + } - return this; + } - }; + traverseVisible( callback ) { - /** - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - */ + if ( this.visible === false ) return; - function Box3( min, max ) { + callback( this ); - this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity ); + const children = this.children; - } + for ( let i = 0, l = children.length; i < l; i ++ ) { - Object.assign( Box3.prototype, { + children[ i ].traverseVisible( callback ); - isBox3: true, + } - set: function ( min, max ) { + } - this.min.copy( min ); - this.max.copy( max ); + traverseAncestors( callback ) { - return this; + const parent = this.parent; - }, + if ( parent !== null ) { - setFromArray: function ( array ) { + callback( parent ); - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; + parent.traverseAncestors( callback ); - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; + } - for ( var i = 0, l = array.length; i < l; i += 3 ) { + } - var x = array[ i ]; - var y = array[ i + 1 ]; - var z = array[ i + 2 ]; + updateMatrix() { - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + this.matrix.compose( this.position, this.quaternion, this.scale ); - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.matrixWorldNeedsUpdate = true; - } + } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); + updateMatrixWorld( force ) { - return this; + if ( this.matrixAutoUpdate ) this.updateMatrix(); - }, + if ( this.matrixWorldNeedsUpdate || force ) { - setFromBufferAttribute: function ( attribute ) { + if ( this.matrixWorldAutoUpdate === true ) { - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; + if ( this.parent === null ) { - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; + this.matrixWorld.copy( this.matrix ); - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + } else { - var x = attribute.getX( i ); - var y = attribute.getY( i ); - var z = attribute.getZ( i ); + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + } - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + } - } + this.matrixWorldNeedsUpdate = false; - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); + force = true; - return this; + } - }, + // make sure descendants are updated if required - setFromPoints: function ( points ) { + const children = this.children; - this.makeEmpty(); + for ( let i = 0, l = children.length; i < l; i ++ ) { - for ( var i = 0, il = points.length; i < il; i ++ ) { + const child = children[ i ]; - this.expandByPoint( points[ i ] ); + child.updateMatrixWorld( force ); } - return this; + } - }, + updateWorldMatrix( updateParents, updateChildren ) { - setFromCenterAndSize: function () { + const parent = this.parent; - var v1 = new Vector3(); + if ( updateParents === true && parent !== null ) { - return function setFromCenterAndSize( center, size ) { + parent.updateWorldMatrix( true, false ); - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); + } - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); + if ( this.matrixAutoUpdate ) this.updateMatrix(); - return this; + if ( this.matrixWorldAutoUpdate === true ) { - }; + if ( this.parent === null ) { - }(), + this.matrixWorld.copy( this.matrix ); - setFromObject: function ( object ) { + } else { - this.makeEmpty(); + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - return this.expandByObject( object ); + } - }, + } - clone: function () { + // make sure descendants are updated - return new this.constructor().copy( this ); + if ( updateChildren === true ) { - }, + const children = this.children; - copy: function ( box ) { + for ( let i = 0, l = children.length; i < l; i ++ ) { - this.min.copy( box.min ); - this.max.copy( box.max ); + const child = children[ i ]; - return this; + child.updateWorldMatrix( false, true ); - }, + } - makeEmpty: function () { + } - this.min.x = this.min.y = this.min.z = + Infinity; - this.max.x = this.max.y = this.max.z = - Infinity; + } - return this; + toJSON( meta ) { - }, + // meta is a string when called from JSON.stringify + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - isEmpty: function () { + const output = {}; - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {}, + nodes: {} + }; - }, + output.metadata = { + version: 4.6, + type: 'Object', + generator: 'Object3D.toJSON' + }; - getCenter: function ( optionalTarget ) { + } - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); + // standard Object3D serialization - }, + const object = {}; - getSize: function ( optionalTarget ) { + object.uuid = this.uuid; + object.type = this.type; - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.subVectors( this.max, this.min ); + 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 ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; - }, + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); - expandByPoint: function ( point ) { + if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; - this.min.min( point ); - this.max.max( point ); + // object specific properties - return this; + if ( this.isInstancedMesh ) { - }, + object.type = 'InstancedMesh'; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); - expandByVector: function ( vector ) { + } - this.min.sub( vector ); - this.max.add( vector ); + if ( this.isBatchedMesh ) { - return this; + object.type = 'BatchedMesh'; + object.perObjectFrustumCulled = this.perObjectFrustumCulled; + object.sortObjects = this.sortObjects; - }, + object.drawRanges = this._drawRanges; + object.reservedRanges = this._reservedRanges; - expandByScalar: function ( scalar ) { + object.visibility = this._visibility; + object.active = this._active; + object.bounds = this._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + boxMin: bound.box.min.toArray(), + boxMax: bound.box.max.toArray(), - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); + sphereInitialized: bound.sphereInitialized, + sphereRadius: bound.sphere.radius, + sphereCenter: bound.sphere.center.toArray() + } ) ); - return this; + object.maxInstanceCount = this._maxInstanceCount; + object.maxVertexCount = this._maxVertexCount; + object.maxIndexCount = this._maxIndexCount; - }, + object.geometryInitialized = this._geometryInitialized; + object.geometryCount = this._geometryCount; - expandByObject: function () { + object.matricesTexture = this._matricesTexture.toJSON( meta ); - // Computes the world-axis-aligned bounding box of an object (including its children), - // accounting for both the object's, and children's, world transforms + if ( this._colorsTexture !== null ) object.colorsTexture = this._colorsTexture.toJSON( meta ); - var scope, i, l; + if ( this.boundingSphere !== null ) { - var v1 = new Vector3(); + object.boundingSphere = { + center: object.boundingSphere.center.toArray(), + radius: object.boundingSphere.radius + }; + + } - function traverse( node ) { + if ( this.boundingBox !== null ) { - var geometry = node.geometry; + object.boundingBox = { + min: object.boundingBox.min.toArray(), + max: object.boundingBox.max.toArray() + }; - if ( geometry !== undefined ) { + } - if ( geometry.isGeometry ) { + } - var vertices = geometry.vertices; + // - for ( i = 0, l = vertices.length; i < l; i ++ ) { + function serialize( library, element ) { - v1.copy( vertices[ i ] ); - v1.applyMatrix4( node.matrixWorld ); + if ( library[ element.uuid ] === undefined ) { - scope.expandByPoint( v1 ); + library[ element.uuid ] = element.toJSON( meta ); - } + } - } else if ( geometry.isBufferGeometry ) { + return element.uuid; - var attribute = geometry.attributes.position; + } - if ( attribute !== undefined ) { + if ( this.isScene ) { - for ( i = 0, l = attribute.count; i < l; i ++ ) { + if ( this.background ) { - v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); + if ( this.background.isColor ) { - scope.expandByPoint( v1 ); + 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 ) { - return function expandByObject( object ) { + object.environment = this.environment.toJSON( meta ).uuid; - scope = this; + } - object.updateMatrixWorld( true ); + } else if ( this.isMesh || this.isLine || this.isPoints ) { - object.traverse( traverse ); + object.geometry = serialize( meta.geometries, this.geometry ); - return this; + const parameters = this.geometry.parameters; - }; + if ( parameters !== undefined && parameters.shapes !== undefined ) { - }(), + const shapes = parameters.shapes; - containsPoint: function ( point ) { + if ( Array.isArray( shapes ) ) { - 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; + for ( let i = 0, l = shapes.length; i < l; i ++ ) { - }, + const shape = shapes[ i ]; - containsBox: function ( box ) { + serialize( meta.shapes, shape ); - 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: function ( point, optionalTarget ) { + } else { - // This can potentially have a divide by zero if the box - // has a size dimension of 0. + serialize( meta.shapes, shapes ); - var result = optionalTarget || new Vector3(); + } - return result.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: function ( box ) { + if ( this.isSkinnedMesh ) { - // using 6 splitting planes to rule out intersections. - 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; + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); - }, + if ( this.skeleton !== undefined ) { - intersectsSphere: ( function () { + serialize( meta.skeletons, this.skeleton ); - var closestPoint = new Vector3(); + object.skeleton = this.skeleton.uuid; - return function intersectsSphere( sphere ) { + } - // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, closestPoint ); + } - // If that point is inside the sphere, the AABB and sphere intersect. - return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); + if ( this.material !== undefined ) { - }; + if ( Array.isArray( this.material ) ) { - } )(), + const uuids = []; - intersectsPlane: function ( plane ) { + for ( let i = 0, l = this.material.length; i < l; i ++ ) { - // We compute the minimum and maximum dot product values. If those values - // are on the same side (back or front) of the plane, then there is no intersection. + uuids.push( serialize( meta.materials, this.material[ i ] ) ); - var min, max; + } - if ( plane.normal.x > 0 ) { + object.material = uuids; - min = plane.normal.x * this.min.x; - max = plane.normal.x * this.max.x; + } else { - } else { + object.material = serialize( meta.materials, this.material ); - min = plane.normal.x * this.max.x; - max = plane.normal.x * this.min.x; + } } - if ( plane.normal.y > 0 ) { - - min += plane.normal.y * this.min.y; - max += plane.normal.y * this.max.y; - - } else { - - min += plane.normal.y * this.max.y; - max += plane.normal.y * this.min.y; + // - } + if ( this.children.length > 0 ) { - if ( plane.normal.z > 0 ) { + object.children = []; - min += plane.normal.z * this.min.z; - max += plane.normal.z * this.max.z; + for ( let i = 0; i < this.children.length; i ++ ) { - } else { + object.children.push( this.children[ i ].toJSON( meta ).object ); - min += plane.normal.z * this.max.z; - max += plane.normal.z * this.min.z; + } } - return ( min <= plane.constant && max >= plane.constant ); - - }, + // - clampPoint: function ( point, optionalTarget ) { + if ( this.animations.length > 0 ) { - var result = optionalTarget || new Vector3(); - return result.copy( point ).clamp( this.min, this.max ); + object.animations = []; - }, + for ( let i = 0; i < this.animations.length; i ++ ) { - distanceToPoint: function () { + const animation = this.animations[ i ]; - var v1 = new Vector3(); + object.animations.push( serialize( meta.animations, animation ) ); - return function distanceToPoint( point ) { + } - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); + } - }; + 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 ); - getBoundingSphere: function () { + 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; - var v1 = new Vector3(); + } - return function getBoundingSphere( optionalTarget ) { + output.object = object; - var result = optionalTarget || new Sphere(); + return output; - this.getCenter( result.center ); + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { - result.radius = this.getSize( v1 ).length() * 0.5; + const values = []; + for ( const key in cache ) { - return result; + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - }; + } - }(), + return values; - intersect: function ( box ) { + } - this.min.max( box.min ); - this.max.min( box.max ); + } - // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. - if ( this.isEmpty() ) this.makeEmpty(); + clone( recursive ) { - return this; + return new this.constructor().copy( this, recursive ); - }, + } - union: function ( box ) { + copy( source, recursive = true ) { - this.min.min( box.min ); - this.max.max( box.max ); + this.name = source.name; - return this; + 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 ); - applyMatrix4: function () { - - var points = [ - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3() - ]; + this.matrix.copy( source.matrix ); + this.matrixWorld.copy( source.matrixWorld ); - return function applyMatrix4( matrix ) { + this.matrixAutoUpdate = source.matrixAutoUpdate; - // transform of empty box is an empty box. - if ( this.isEmpty() ) return this; + this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; - // NOTE: I am using a binary pattern to specify all 2^3 combinations below - points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 - points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 - points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 - points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 - points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 - points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 - points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 - points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 + this.layers.mask = source.layers.mask; + this.visible = source.visible; - this.setFromPoints( points ); + this.castShadow = source.castShadow; + this.receiveShadow = source.receiveShadow; - return this; + this.frustumCulled = source.frustumCulled; + this.renderOrder = source.renderOrder; - }; + this.animations = source.animations.slice(); - }(), + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - translate: function ( offset ) { + if ( recursive === true ) { - this.min.add( offset ); - this.max.add( offset ); + for ( let i = 0; i < source.children.length; i ++ ) { - return this; + const child = source.children[ i ]; + this.add( child.clone() ); - }, + } - equals: function ( box ) { + } - return box.min.equals( this.min ) && box.max.equals( this.max ); + return this; } - } ); - - /** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ - - function Sphere( center, radius ) { - - this.center = ( center !== undefined ) ? center : new Vector3(); - this.radius = ( radius !== undefined ) ? radius : 0; - } - Object.assign( Sphere.prototype, { + Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); + Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; + Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; - set: function ( center, radius ) { + const _v0$2 = /*@__PURE__*/ new Vector3(); + const _v1$3 = /*@__PURE__*/ new Vector3(); + const _v2$2 = /*@__PURE__*/ new Vector3(); + const _v3$2 = /*@__PURE__*/ new Vector3(); - this.center.copy( center ); - this.radius = radius; + const _vab = /*@__PURE__*/ new Vector3(); + const _vac = /*@__PURE__*/ new Vector3(); + const _vbc = /*@__PURE__*/ new Vector3(); + const _vap = /*@__PURE__*/ new Vector3(); + const _vbp = /*@__PURE__*/ new Vector3(); + const _vcp = /*@__PURE__*/ new Vector3(); - return this; + class Triangle { - }, + constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { - setFromPoints: function () { + this.a = a; + this.b = b; + this.c = c; - var box = new Box3(); + } - return function setFromPoints( points, optionalCenter ) { + static getNormal( a, b, c, target ) { - var center = this.center; + target.subVectors( c, b ); + _v0$2.subVectors( a, b ); + target.cross( _v0$2 ); - if ( optionalCenter !== undefined ) { + const targetLengthSq = target.lengthSq(); + if ( targetLengthSq > 0 ) { - center.copy( optionalCenter ); + return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); - } else { + } - box.setFromPoints( points ).getCenter( center ); + return target.set( 0, 0, 0 ); - } + } - var maxRadiusSq = 0; + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + static getBarycoord( point, a, b, c, target ) { - for ( var i = 0, il = points.length; i < il; i ++ ) { + _v0$2.subVectors( c, a ); + _v1$3.subVectors( b, a ); + _v2$2.subVectors( point, a ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); + const dot00 = _v0$2.dot( _v0$2 ); + const dot01 = _v0$2.dot( _v1$3 ); + const dot02 = _v0$2.dot( _v2$2 ); + const dot11 = _v1$3.dot( _v1$3 ); + const dot12 = _v1$3.dot( _v2$2 ); - } + const denom = ( dot00 * dot11 - dot01 * dot01 ); - this.radius = Math.sqrt( maxRadiusSq ); + // collinear or singular triangle + if ( denom === 0 ) { - return this; + target.set( 0, 0, 0 ); + return null; - }; + } - }(), + const invDenom = 1 / denom; + const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - clone: function () { + // barycentric coordinates must always sum to 1 + return target.set( 1 - u - v, v, u ); - return new this.constructor().copy( this ); + } - }, + static containsPoint( point, a, b, c ) { - copy: function ( sphere ) { + // if the triangle is degenerate then we can't contain a point + if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) { - this.center.copy( sphere.center ); - this.radius = sphere.radius; + return false; - return this; + } - }, + return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 ); - empty: function () { + } - return ( this.radius <= 0 ); + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { - }, + if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) { - containsPoint: function ( point ) { + target.x = 0; + target.y = 0; + if ( 'z' in target ) target.z = 0; + if ( 'w' in target ) target.w = 0; + return null; - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); + } - }, + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$2.x ); + target.addScaledVector( v2, _v3$2.y ); + target.addScaledVector( v3, _v3$2.z ); - distanceToPoint: function ( point ) { + return target; - return ( point.distanceTo( this.center ) - this.radius ); + } - }, + static isFrontFacing( a, b, c, direction ) { - intersectsSphere: function ( sphere ) { + _v0$2.subVectors( c, b ); + _v1$3.subVectors( a, b ); - var radiusSum = this.radius + sphere.radius; + // strictly front facing + return ( _v0$2.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); + } - }, + set( a, b, c ) { - intersectsBox: function ( box ) { + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); - return box.intersectsSphere( this ); + return this; - }, + } - intersectsPlane: function ( plane ) { + setFromPointsAndIndices( points, i0, i1, i2 ) { - return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); - }, + return this; - clampPoint: function ( point, optionalTarget ) { + } - var deltaLengthSq = this.center.distanceToSquared( point ); + setFromAttributeAndIndices( attribute, i0, i1, i2 ) { - var result = optionalTarget || new Vector3(); + this.a.fromBufferAttribute( attribute, i0 ); + this.b.fromBufferAttribute( attribute, i1 ); + this.c.fromBufferAttribute( attribute, i2 ); - result.copy( point ); + return this; - if ( deltaLengthSq > ( this.radius * this.radius ) ) { + } - result.sub( this.center ).normalize(); - result.multiplyScalar( this.radius ).add( this.center ); + clone() { - } + return new this.constructor().copy( this ); - return result; + } - }, + copy( triangle ) { - getBoundingBox: function ( optionalTarget ) { + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); - var box = optionalTarget || new Box3(); + return this; - box.set( this.center, this.center ); - box.expandByScalar( this.radius ); + } - return box; + getArea() { - }, + _v0$2.subVectors( this.c, this.b ); + _v1$3.subVectors( this.a, this.b ); - applyMatrix4: function ( matrix ) { + return _v0$2.cross( _v1$3 ).length() * 0.5; - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); + } - return this; + getMidpoint( target ) { - }, + return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - translate: function ( offset ) { + } - this.center.add( offset ); + getNormal( target ) { - return this; + return Triangle.getNormal( this.a, this.b, this.c, target ); - }, + } - equals: function ( sphere ) { + getPlane( target ) { - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); + return target.setFromCoplanarPoints( this.a, this.b, this.c ); } - } ); + getBarycoord( point, target ) { - /** - * @author bhouston / http://clara.io - */ + return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); - function Plane( normal, constant ) { + } - // normal is assumed to be normalized + getInterpolation( point, v1, v2, v3, target ) { - this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); - this.constant = ( constant !== undefined ) ? constant : 0; + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); - } + } - Object.assign( Plane.prototype, { + containsPoint( point ) { - set: function ( normal, constant ) { + return Triangle.containsPoint( point, this.a, this.b, this.c ); - this.normal.copy( normal ); - this.constant = constant; + } - return this; + isFrontFacing( direction ) { - }, + return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); - setComponents: function ( x, y, z, w ) { + } - this.normal.set( x, y, z ); - this.constant = w; + intersectsBox( box ) { - return this; + return box.intersectsTriangle( this ); - }, + } - setFromNormalAndCoplanarPoint: function ( normal, point ) { + closestPointToPoint( p, target ) { - this.normal.copy( normal ); - this.constant = - point.dot( this.normal ); + const a = this.a, b = this.b, c = this.c; + let v, w; - return this; + // algorithm thanks to Real-Time Collision Detection by Christer Ericson, + // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., + // under the accompanying license; see chapter 5.1.5 for detailed explanation. + // basically, we're distinguishing which of the voronoi regions of the triangle + // the point lies in with the minimum amount of redundant computation. - }, + _vab.subVectors( b, a ); + _vac.subVectors( c, a ); + _vap.subVectors( p, a ); + const d1 = _vab.dot( _vap ); + const d2 = _vac.dot( _vap ); + if ( d1 <= 0 && d2 <= 0 ) { - setFromCoplanarPoints: function () { + // vertex region of A; barycentric coords (1, 0, 0) + return target.copy( a ); - var v1 = new Vector3(); - var v2 = new Vector3(); + } - return function setFromCoplanarPoints( a, b, c ) { + _vbp.subVectors( p, b ); + const d3 = _vab.dot( _vbp ); + const d4 = _vac.dot( _vbp ); + if ( d3 >= 0 && d4 <= d3 ) { - var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize(); + // vertex region of B; barycentric coords (0, 1, 0) + return target.copy( b ); - // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? + } - this.setFromNormalAndCoplanarPoint( normal, a ); + const vc = d1 * d4 - d3 * d2; + if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { - return this; + v = d1 / ( d1 - d3 ); + // edge region of AB; barycentric coords (1-v, v, 0) + return target.copy( a ).addScaledVector( _vab, v ); - }; + } - }(), + _vcp.subVectors( p, c ); + const d5 = _vab.dot( _vcp ); + const d6 = _vac.dot( _vcp ); + if ( d6 >= 0 && d5 <= d6 ) { - clone: function () { + // vertex region of C; barycentric coords (0, 0, 1) + return target.copy( c ); - return new this.constructor().copy( this ); + } - }, + const vb = d5 * d2 - d1 * d6; + if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { - copy: function ( plane ) { + w = d2 / ( d2 - d6 ); + // edge region of AC; barycentric coords (1-w, 0, w) + return target.copy( a ).addScaledVector( _vac, w ); - this.normal.copy( plane.normal ); - this.constant = plane.constant; + } - return this; + const va = d3 * d6 - d5 * d4; + if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { - }, + _vbc.subVectors( c, b ); + w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + // edge region of BC; barycentric coords (0, 1-w, w) + return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC - normalize: function () { + } - // Note: will lead to a divide by zero if the plane is invalid. + // face region + const denom = 1 / ( va + vb + vc ); + // u = va * denom + v = vb * denom; + w = vc * denom; - var inverseNormalLength = 1.0 / this.normal.length(); - this.normal.multiplyScalar( inverseNormalLength ); - this.constant *= inverseNormalLength; + return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); - return this; + } - }, + equals( triangle ) { - negate: function () { + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - this.constant *= - 1; - this.normal.negate(); + } - return this; + } - }, - - distanceToPoint: function ( point ) { + const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - return this.normal.dot( point ) + this.constant; + const _hslA = { h: 0, s: 0, l: 0 }; + const _hslB = { h: 0, s: 0, l: 0 }; - }, + function hue2rgb( p, q, t ) { - distanceToSphere: function ( sphere ) { + 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; - return this.distanceToPoint( sphere.center ) - sphere.radius; + } - }, + class Color { - projectPoint: function ( point, optionalTarget ) { + constructor( r, g, b ) { - var result = optionalTarget || new Vector3(); + this.isColor = true; - return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); + this.r = 1; + this.g = 1; + this.b = 1; - }, + return this.set( r, g, b ); - intersectLine: function () { + } - var v1 = new Vector3(); + set( r, g, b ) { - return function intersectLine( line, optionalTarget ) { + if ( g === undefined && b === undefined ) { - var result = optionalTarget || new Vector3(); + // r is THREE.Color, hex or string - var direction = line.delta( v1 ); + const value = r; - var denominator = this.normal.dot( direction ); + if ( value && value.isColor ) { - if ( denominator === 0 ) { + this.copy( value ); - // line is coplanar, return origin - if ( this.distanceToPoint( line.start ) === 0 ) { + } else if ( typeof value === 'number' ) { - return result.copy( line.start ); + this.setHex( value ); - } + } else if ( typeof value === 'string' ) { - // Unsure if this is the correct method to handle this case. - return undefined; + this.setStyle( value ); } - var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - - if ( t < 0 || t > 1 ) { + } else { - return undefined; + this.setRGB( r, g, b ); - } + } - return result.copy( direction ).multiplyScalar( t ).add( line.start ); + return this; - }; + } - }(), + setScalar( scalar ) { - intersectsLine: function ( line ) { + this.r = scalar; + this.g = scalar; + this.b = scalar; - // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. + return this; - var startSign = this.distanceToPoint( line.start ); - var endSign = this.distanceToPoint( line.end ); + } - return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); + setHex( hex, colorSpace = SRGBColorSpace ) { - }, + hex = Math.floor( hex ); - intersectsBox: function ( box ) { + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; - return box.intersectsPlane( this ); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - }, + return this; - intersectsSphere: function ( sphere ) { + } - return sphere.intersectsPlane( this ); + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - }, + this.r = r; + this.g = g; + this.b = b; - coplanarPoint: function ( optionalTarget ) { + ColorManagement.toWorkingColorSpace( this, colorSpace ); - var result = optionalTarget || new Vector3(); + return this; - return result.copy( this.normal ).multiplyScalar( - this.constant ); + } - }, + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { - applyMatrix4: function () { + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); - var v1 = new Vector3(); - var m1 = new Matrix3(); + if ( s === 0 ) { - return function applyMatrix4( matrix, optionalNormalMatrix ) { + this.r = this.g = this.b = l; - var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); + } else { - var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); + const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + const q = ( 2 * l ) - p; - var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); - this.constant = - referencePoint.dot( normal ); + } - return this; + ColorManagement.toWorkingColorSpace( this, colorSpace ); - }; + return this; - }(), + } - translate: function ( offset ) { + setStyle( style, colorSpace = SRGBColorSpace ) { - this.constant -= offset.dot( this.normal ); + function handleAlpha( string ) { - return this; + if ( string === undefined ) return; - }, + if ( parseFloat( string ) < 1 ) { - equals: function ( plane ) { + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); - return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); + } - } + } - } ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author bhouston / http://clara.io - */ + let m; - function Frustum( p0, p1, p2, p3, p4, p5 ) { + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { - this.planes = [ + // rgb / hsl - ( p0 !== undefined ) ? p0 : new Plane(), - ( p1 !== undefined ) ? p1 : new Plane(), - ( p2 !== undefined ) ? p2 : new Plane(), - ( p3 !== undefined ) ? p3 : new Plane(), - ( p4 !== undefined ) ? p4 : new Plane(), - ( p5 !== undefined ) ? p5 : new Plane() + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - ]; + switch ( name ) { - } + case 'rgb': + case 'rgba': - Object.assign( Frustum.prototype, { + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - set: function ( p0, p1, p2, p3, p4, p5 ) { + // rgb(255,0,0) rgba(255,0,0,0.5) - var planes = this.planes; + handleAlpha( color[ 4 ] ); - 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.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); - return this; + } - }, + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - clone: function () { + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - return new this.constructor().copy( this ); + handleAlpha( color[ 4 ] ); - }, + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); - copy: function ( frustum ) { + } - var planes = this.planes; + break; - for ( var i = 0; i < 6; i ++ ) { + case 'hsl': + case 'hsla': - planes[ i ].copy( frustum.planes[ i ] ); + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - } + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - return this; + handleAlpha( color[ 4 ] ); - }, + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); - setFromMatrix: function ( m ) { + } - var planes = this.planes; - var me = m.elements; - var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; - var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; - var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; - var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; + break; - 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(); + default: - return this; + console.warn( 'THREE.Color: Unknown color model ' + style ); - }, + } - intersectsObject: function () { + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - var sphere = new Sphere(); + // hex color - return function intersectsObject( object ) { + const hex = m[ 1 ]; + const size = hex.length; - var geometry = object.geometry; + if ( size === 3 ) { - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); - sphere.copy( geometry.boundingSphere ) - .applyMatrix4( object.matrixWorld ); + } else if ( size === 6 ) { - return this.intersectsSphere( sphere ); + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); - }; + } else { - }(), + console.warn( 'THREE.Color: Invalid hex color ' + style ); - intersectsSprite: function () { + } - var sphere = new Sphere(); + } else if ( style && style.length > 0 ) { - return function intersectsSprite( sprite ) { + return this.setColorName( style, colorSpace ); - sphere.center.set( 0, 0, 0 ); - sphere.radius = 0.7071067811865476; - sphere.applyMatrix4( sprite.matrixWorld ); + } - return this.intersectsSphere( sphere ); + return this; - }; + } - }(), + setColorName( style, colorSpace = SRGBColorSpace ) { - intersectsSphere: function ( sphere ) { + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - var planes = this.planes; - var center = sphere.center; - var negRadius = - sphere.radius; + if ( hex !== undefined ) { - for ( var i = 0; i < 6; i ++ ) { + // red + this.setHex( hex, colorSpace ); - var distance = planes[ i ].distanceToPoint( center ); + } else { - if ( distance < negRadius ) { + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - return false; + } - } + return this; - } + } - return true; + clone() { - }, + return new this.constructor( this.r, this.g, this.b ); - intersectsBox: function () { + } - var p1 = new Vector3(), - p2 = new Vector3(); + copy( color ) { - return function intersectsBox( box ) { + this.r = color.r; + this.g = color.g; + this.b = color.b; - var planes = this.planes; + return this; - for ( var i = 0; i < 6; i ++ ) { + } - var plane = planes[ i ]; + copySRGBToLinear( color ) { - p1.x = plane.normal.x > 0 ? box.min.x : box.max.x; - p2.x = plane.normal.x > 0 ? box.max.x : box.min.x; - p1.y = plane.normal.y > 0 ? box.min.y : box.max.y; - p2.y = plane.normal.y > 0 ? box.max.y : box.min.y; - p1.z = plane.normal.z > 0 ? box.min.z : box.max.z; - p2.z = plane.normal.z > 0 ? box.max.z : box.min.z; + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - var d1 = plane.distanceToPoint( p1 ); - var d2 = plane.distanceToPoint( p2 ); + return this; - // if both outside plane, no intersection + } - if ( d1 < 0 && d2 < 0 ) { + copyLinearToSRGB( color ) { - return false; + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - } + return this; - } + } - return true; + convertSRGBToLinear() { - }; + this.copySRGBToLinear( this ); - }(), + return this; - containsPoint: function ( point ) { + } - var planes = this.planes; + convertLinearToSRGB() { - for ( var i = 0; i < 6; i ++ ) { + this.copyLinearToSRGB( this ); - if ( planes[ i ].distanceToPoint( point ) < 0 ) { + return this; - return false; + } - } + getHex( colorSpace = SRGBColorSpace ) { - } + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - return true; + return Math.round( clamp( _color$1.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color$1.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color$1.b * 255, 0, 255 ) ); } - } ); + getHexString( colorSpace = SRGBColorSpace ) { - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); - function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { + } - var _frustum = new Frustum(), - _projScreenMatrix = new Matrix4(), + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { - _shadowMapSize = new Vector2(), - _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), + // h,s,l ranges are in 0.0 - 1.0 - _lookTarget = new Vector3(), - _lightPositionWorld = new Vector3(), + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - _MorphingFlag = 1, - _SkinningFlag = 2, + const r = _color$1.r, g = _color$1.g, b = _color$1.b; - _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1, + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - _depthMaterials = new Array( _NumberOfMaterialVariants ), - _distanceMaterials = new Array( _NumberOfMaterialVariants ), + let hue, saturation; + const lightness = ( min + max ) / 2.0; - _materialCache = {}; + if ( min === max ) { - var cubeDirections = [ - new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), - new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) - ]; + hue = 0; + saturation = 0; - var cubeUps = [ - new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), - new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) - ]; + } else { - var cube2DViewPorts = [ - new Vector4(), new Vector4(), new Vector4(), - new Vector4(), new Vector4(), new Vector4() - ]; + const delta = max - min; - // init + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { + switch ( max ) { - var useMorphing = ( i & _MorphingFlag ) !== 0; - var useSkinning = ( i & _SkinningFlag ) !== 0; + 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; - var depthMaterial = new MeshDepthMaterial( { + } - depthPacking: RGBADepthPacking, + hue /= 6; - morphTargets: useMorphing, - skinning: useSkinning + } - } ); + target.h = hue; + target.s = saturation; + target.l = lightness; - _depthMaterials[ i ] = depthMaterial; + return target; - // + } - var distanceMaterial = new MeshDistanceMaterial( { + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - morphTargets: useMorphing, - skinning: useSkinning + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - } ); + target.r = _color$1.r; + target.g = _color$1.g; + target.b = _color$1.b; - _distanceMaterials[ i ] = distanceMaterial; + return target; } - // + getStyle( colorSpace = SRGBColorSpace ) { - var scope = this; + ColorManagement.fromWorkingColorSpace( _color$1.copy( this ), colorSpace ); - this.enabled = false; + const r = _color$1.r, g = _color$1.g, b = _color$1.b; - this.autoUpdate = true; - this.needsUpdate = false; + if ( colorSpace !== SRGBColorSpace ) { - this.type = PCFShadowMap; + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; - this.renderReverseSided = true; - this.renderSingleSided = true; + } - this.render = function ( lights, scene, camera ) { + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; - if ( scope.enabled === false ) return; - if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; + } - if ( lights.length === 0 ) return; + offsetHSL( h, s, l ) { - // TODO Clean up (needed in case of contextlost) - var _gl = _renderer.context; - var _state = _renderer.state; + this.getHSL( _hslA ); - // Set GL state for depth map. - _state.disable( _gl.BLEND ); - _state.buffers.color.setClear( 1, 1, 1, 1 ); - _state.buffers.depth.setTest( true ); - _state.setScissorTest( false ); + return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); - // render depth map + } - var faceCount; + add( color ) { - for ( var i = 0, il = lights.length; i < il; i ++ ) { + this.r += color.r; + this.g += color.g; + this.b += color.b; - var light = lights[ i ]; - var shadow = light.shadow; - var isPointLight = light && light.isPointLight; + return this; - if ( shadow === undefined ) { + } - console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); - continue; + addColors( color1, color2 ) { - } + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - var shadowCamera = shadow.camera; + return this; - _shadowMapSize.copy( shadow.mapSize ); - _shadowMapSize.min( _maxShadowMapSize ); + } - if ( isPointLight ) { + addScalar( s ) { - var vpWidth = _shadowMapSize.x; - var vpHeight = _shadowMapSize.y; + this.r += s; + this.g += s; + this.b += s; - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction + return this; - // positive X - cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); - // negative X - cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); - // positive Z - cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); - // negative Z - cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); - // positive Y - cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); - // negative Y - cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); + } - _shadowMapSize.x *= 4.0; - _shadowMapSize.y *= 2.0; + sub( color ) { - } + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - if ( shadow.map === null ) { + return this; - var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; + } - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + ".shadowMap"; + multiply( color ) { - shadowCamera.updateProjectionMatrix(); + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - } + return this; - if ( shadow.isSpotLightShadow ) { + } - shadow.update( light ); + multiplyScalar( s ) { - } + this.r *= s; + this.g *= s; + this.b *= s; - var shadowMap = shadow.map; - var shadowMatrix = shadow.matrix; + return this; - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld ); + } - if ( isPointLight ) { + lerp( color, alpha ) { - faceCount = 6; + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; - // for point lights we set the shadow matrix to be a translation-only matrix - // equal to inverse of the light's position + return this; - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); + } - } else { + lerpColors( color1, color2, alpha ) { - faceCount = 1; + 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; - _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); + return this; - // compute shadow matrix + } - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); + lerpHSL( color, alpha ) { - shadowMatrix.multiply( shadowCamera.projectionMatrix ); - shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); + this.getHSL( _hslA ); + color.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 ); - _renderer.setRenderTarget( shadowMap ); - _renderer.clear(); + this.setHSL( h, s, l ); - // render shadow map for each cube face (if omni-directional) or - // run a single pass if not + return this; - for ( var face = 0; face < faceCount; face ++ ) { + } - if ( isPointLight ) { + setFromVector3( v ) { - _lookTarget.copy( shadowCamera.position ); - _lookTarget.add( cubeDirections[ face ] ); - shadowCamera.up.copy( cubeUps[ face ] ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); + this.r = v.x; + this.g = v.y; + this.b = v.z; - var vpDimensions = cube2DViewPorts[ face ]; - _state.viewport( vpDimensions ); + return this; - } + } - // update camera matrices and frustum + applyMatrix3( m ) { - _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); + const r = this.r, g = this.g, b = this.b; + const e = m.elements; - // set object matrices & frustum culling + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; - renderObject( scene, camera, shadowCamera, isPointLight ); + return this; - } + } - } + equals( c ) { - scope.needsUpdate = false; + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - }; + } - function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { + fromArray( array, offset = 0 ) { - var geometry = object.geometry; + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; + + return this; - var result = null; + } - var materialVariants = _depthMaterials; - var customMaterial = object.customDepthMaterial; + toArray( array = [], offset = 0 ) { - if ( isPointLight ) { + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; - materialVariants = _distanceMaterials; - customMaterial = object.customDistanceMaterial; + return array; - } + } - if ( ! customMaterial ) { + fromBufferAttribute( attribute, index ) { - var useMorphing = false; + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); - if ( material.morphTargets ) { + return this; - if ( geometry && geometry.isBufferGeometry ) { + } - useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; + toJSON() { - } else if ( geometry && geometry.isGeometry ) { + return this.getHex(); - useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; + } - } + *[ Symbol.iterator ]() { - } + yield this.r; + yield this.g; + yield this.b; - if ( object.isSkinnedMesh && material.skinning === false ) { + } - console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); + } - } + const _color$1 = /*@__PURE__*/ new Color(); - var useSkinning = object.isSkinnedMesh && material.skinning; + Color.NAMES = _colorKeywords; - var variantIndex = 0; + let _materialId = 0; - if ( useMorphing ) variantIndex |= _MorphingFlag; - if ( useSkinning ) variantIndex |= _SkinningFlag; + class Material extends EventDispatcher { - result = materialVariants[ variantIndex ]; + constructor() { - } else { + super(); - result = customMaterial; + this.isMaterial = true; - } + Object.defineProperty( this, 'id', { value: _materialId ++ } ); - if ( _renderer.localClippingEnabled && - material.clipShadows === true && - material.clippingPlanes.length !== 0 ) { + this.uuid = generateUUID(); - // in this case we need a unique material instance reflecting the - // appropriate state + this.name = ''; + this.type = 'Material'; - var keyA = result.uuid, keyB = material.uuid; + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; - var materialsForVariant = _materialCache[ keyA ]; + this.opacity = 1; + this.transparent = false; + this.alphaHash = false; - if ( materialsForVariant === undefined ) { + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + this.blendColor = new Color( 0, 0, 0 ); + this.blendAlpha = 0; - materialsForVariant = {}; - _materialCache[ keyA ] = materialsForVariant; + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; - } + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; - var cachedMaterial = materialsForVariant[ keyB ]; + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; - if ( cachedMaterial === undefined ) { + this.shadowSide = null; - cachedMaterial = result.clone(); - materialsForVariant[ keyB ] = cachedMaterial; + this.colorWrite = true; - } + this.precision = null; // override the renderer's default precision for this material - result = cachedMaterial; + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; - } + this.dithering = false; - result.visible = material.visible; - result.wireframe = material.wireframe; + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; - var side = material.side; + this.visible = true; - if ( scope.renderSingleSided && side == DoubleSide ) { + this.toneMapped = true; - side = FrontSide; + this.userData = {}; - } + this.version = 0; - if ( scope.renderReverseSided ) { + this._alphaTest = 0; - if ( side === FrontSide ) side = BackSide; - else if ( side === BackSide ) side = FrontSide; + } - } + get alphaTest() { - result.side = side; + return this._alphaTest; - result.clipShadows = material.clipShadows; - result.clippingPlanes = material.clippingPlanes; - result.clipIntersection = material.clipIntersection; + } - result.wireframeLinewidth = material.wireframeLinewidth; - result.linewidth = material.linewidth; + set alphaTest( value ) { - if ( isPointLight && result.isMeshDistanceMaterial ) { + if ( this._alphaTest > 0 !== value > 0 ) { - result.referencePosition.copy( lightPositionWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; + this.version ++; } - return result; + this._alphaTest = value; } - function renderObject( object, camera, shadowCamera, isPointLight ) { - - if ( object.visible === false ) return; + onBeforeCompile( /* shaderobject, renderer */ ) {} - var visible = object.layers.test( camera.layers ); + customProgramCacheKey() { - if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { + return this.onBeforeCompile.toString(); - if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { + } - object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); + setValues( values ) { - var geometry = _objects.update( object ); - var material = object.material; + if ( values === undefined ) return; - if ( Array.isArray( material ) ) { + for ( const key in values ) { - var groups = geometry.groups; + const newValue = values[ key ]; - for ( var k = 0, kl = groups.length; k < kl; k ++ ) { + if ( newValue === undefined ) { - var group = groups[ k ]; - var groupMaterial = material[ group.materialIndex ]; + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; - if ( groupMaterial && groupMaterial.visible ) { + } - var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); + const currentValue = this[ key ]; - } + if ( currentValue === undefined ) { - } + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; - } else if ( material.visible ) { + } - var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); + if ( currentValue && currentValue.isColor ) { - } + currentValue.set( newValue ); - } + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { - } + currentValue.copy( newValue ); - var children = object.children; + } else { - for ( var i = 0, l = children.length; i < l; i ++ ) { + this[ key ] = newValue; - renderObject( children[ i ], camera, shadowCamera, isPointLight ); + } } } - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLAttributes( gl ) { - - var buffers = {}; - - function createBuffer( attribute, bufferType ) { - - var array = attribute.array; - var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; + toJSON( meta ) { - var buffer = gl.createBuffer(); + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - gl.bindBuffer( bufferType, buffer ); - gl.bufferData( bufferType, array, usage ); - - attribute.onUploadCallback(); + if ( isRootObject ) { - var type = gl.FLOAT; + meta = { + textures: {}, + images: {} + }; - if ( array instanceof Float32Array ) { + } - type = gl.FLOAT; + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; - } else if ( array instanceof Float64Array ) { + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; - console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); + if ( this.name !== '' ) data.name = this.name; - } else if ( array instanceof Uint16Array ) { + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); - type = gl.UNSIGNED_SHORT; + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; - } else if ( array instanceof Int16Array ) { + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; - type = gl.SHORT; + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; - } else if ( array instanceof Uint32Array ) { + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { - type = gl.UNSIGNED_INT; + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; - } else if ( array instanceof Int32Array ) { + } - type = gl.INT; + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { - } else if ( array instanceof Int8Array ) { + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; - type = gl.BYTE; + } - } else if ( array instanceof Uint8Array ) { + if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { - type = gl.UNSIGNED_BYTE; + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); } - return { - buffer: buffer, - type: type, - bytesPerElement: array.BYTES_PER_ELEMENT, - version: attribute.version - }; + if ( this.dispersion !== undefined ) data.dispersion = this.dispersion; - } + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; - function updateBuffer( buffer, attribute, bufferType ) { + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { - var array = attribute.array; - var updateRange = attribute.updateRange; + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; - gl.bindBuffer( bufferType, buffer ); + } - if ( attribute.dynamic === false ) { + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { - gl.bufferData( bufferType, array, gl.STATIC_DRAW ); + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; - } else if ( updateRange.count === - 1 ) { + } - // Not using update ranges + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; - gl.bufferSubData( bufferType, 0, array ); + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { - } else if ( updateRange.count === 0 ) { + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; - console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); + } - } else { + 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; - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); + if ( this.lightMap && this.lightMap.isTexture ) { - updateRange.count = - 1; // reset range + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; } - } - - // + if ( this.aoMap && this.aoMap.isTexture ) { - function get( attribute ) { + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + } - return buffers[ attribute.uuid ]; + if ( this.bumpMap && this.bumpMap.isTexture ) { - } + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; - function remove( attribute ) { + } - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + if ( this.normalMap && this.normalMap.isTexture ) { - var data = buffers[ attribute.uuid ]; + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); - if ( data ) { + } - gl.deleteBuffer( data.buffer ); + if ( this.displacementMap && this.displacementMap.isTexture ) { - delete buffers[ attribute.uuid ]; + 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; - function update( attribute, bufferType ) { + 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 ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + if ( this.envMap && this.envMap.isTexture ) { - var data = buffers[ attribute.uuid ]; + data.envMap = this.envMap.toJSON( meta ).uuid; - if ( data === undefined ) { + if ( this.combine !== undefined ) data.combine = this.combine; - buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); + } - } else if ( data.version < attribute.version ) { + if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray(); + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; - updateBuffer( data.buffer, attribute, bufferType ); + if ( this.gradientMap && this.gradientMap.isTexture ) { - data.version = attribute.version; + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; } - } + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); - return { + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; - get: get, - remove: remove, - update: update + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors === true ) data.vertexColors = true; - }; + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = true; + + if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; + if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; + if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; + if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; + if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; + if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; + if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); + if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; + + if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; + if ( this.depthTest === false ) data.depthTest = this.depthTest; + if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; + if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; + + if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; + if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; + if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; + if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask; + if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; + if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; + if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; + if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; - } + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; - /** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - */ + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; - function Euler( x, y, z, order ) { + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._order = order || Euler.DefaultOrder; + if ( this.dithering === true ) data.dithering = true; - } + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaHash === true ) data.alphaHash = true; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; + if ( this.forceSinglePass === true ) data.forceSinglePass = true; - Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]; + if ( this.wireframe === true ) data.wireframe = true; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; - Euler.DefaultOrder = 'XYZ'; + if ( this.flatShading === true ) data.flatShading = true; - Object.defineProperties( Euler.prototype, { + if ( this.visible === false ) data.visible = false; - x: { + if ( this.toneMapped === false ) data.toneMapped = false; - get: function () { + if ( this.fog === false ) data.fog = false; - return this._x; + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; - }, + // TODO: Copied from Object3D.toJSON - set: function ( value ) { + function extractFromCache( cache ) { - this._x = value; - this.onChangeCallback(); + const values = []; - } + for ( const key in cache ) { - }, + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - y: { + } - get: function () { + return values; - return this._y; + } - }, + if ( isRootObject ) { - set: function ( value ) { + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); - this._y = value; - this.onChangeCallback(); + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; } - }, + return data; - z: { + } - get: function () { + clone() { - return this._z; + return new this.constructor().copy( this ); - }, + } - set: function ( value ) { + copy( source ) { - this._z = value; - this.onChangeCallback(); + this.name = source.name; - } + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; - }, + this.opacity = source.opacity; + this.transparent = source.transparent; - order: { + 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.blendColor.copy( source.blendColor ); + this.blendAlpha = source.blendAlpha; - get: function () { - - return this._order; - - }, + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; - set: function ( value ) { + 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; - this._order = value; - this.onChangeCallback(); + 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 ) { - Object.assign( Euler.prototype, { + dstPlanes[ i ] = srcPlanes[ i ].clone(); - isEuler: true, + } - set: function ( x, y, z, order ) { + } - this._x = x; - this._y = y; - this._z = z; - this._order = order || this._order; + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; - this.onChangeCallback(); + this.shadowSide = source.shadowSide; - return this; + this.colorWrite = source.colorWrite; - }, + this.precision = source.precision; - clone: function () { + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; - return new this.constructor( this._x, this._y, this._z, this._order ); + this.dithering = source.dithering; - }, + this.alphaTest = source.alphaTest; + this.alphaHash = source.alphaHash; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; - copy: function ( euler ) { + this.visible = source.visible; - this._x = euler._x; - this._y = euler._y; - this._z = euler._z; - this._order = euler._order; + this.toneMapped = source.toneMapped; - this.onChangeCallback(); + this.userData = JSON.parse( JSON.stringify( source.userData ) ); return this; - }, + } - setFromRotationMatrix: function ( m, order, update ) { + dispose() { - var clamp = _Math.clamp; + this.dispatchEvent( { type: 'dispose' } ); - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + } - var te = m.elements; - var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; - var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; - var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; + set needsUpdate( value ) { - order = order || this._order; + if ( value === true ) this.version ++; - if ( order === 'XYZ' ) { + } - this._y = Math.asin( clamp( m13, - 1, 1 ) ); + onBuild( /* shaderobject, renderer */ ) { - if ( Math.abs( m13 ) < 0.99999 ) { + console.warn( 'Material: onBuild() has been removed.' ); // @deprecated, r166 - this._x = Math.atan2( - m23, m33 ); - this._z = Math.atan2( - m12, m11 ); + } - } else { + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) { - this._x = Math.atan2( m32, m22 ); - this._z = 0; + console.warn( 'Material: onBeforeRender() has been removed.' ); // @deprecated, r166 - } + } - } else if ( order === 'YXZ' ) { - this._x = Math.asin( - clamp( m23, - 1, 1 ) ); + } - if ( Math.abs( m23 ) < 0.99999 ) { + class MeshBasicMaterial extends Material { - this._y = Math.atan2( m13, m33 ); - this._z = Math.atan2( m21, m22 ); + constructor( parameters ) { - } else { + super(); - this._y = Math.atan2( - m31, m11 ); - this._z = 0; + this.isMeshBasicMaterial = true; - } + this.type = 'MeshBasicMaterial'; - } else if ( order === 'ZXY' ) { + this.color = new Color( 0xffffff ); // emissive - this._x = Math.asin( clamp( m32, - 1, 1 ) ); + this.map = null; - if ( Math.abs( m32 ) < 0.99999 ) { + this.lightMap = null; + this.lightMapIntensity = 1.0; - this._y = Math.atan2( - m31, m33 ); - this._z = Math.atan2( - m12, m22 ); + this.aoMap = null; + this.aoMapIntensity = 1.0; - } else { + this.specularMap = null; - this._y = 0; - this._z = Math.atan2( m21, m11 ); + this.alphaMap = null; - } + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - } else if ( order === 'ZYX' ) { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - this._y = Math.asin( - clamp( m31, - 1, 1 ) ); + this.fog = true; - if ( Math.abs( m31 ) < 0.99999 ) { + this.setValues( parameters ); - this._x = Math.atan2( m32, m33 ); - this._z = Math.atan2( m21, m11 ); + } - } else { + copy( source ) { - this._x = 0; - this._z = Math.atan2( - m12, m22 ); + super.copy( source ); - } + this.color.copy( source.color ); - } else if ( order === 'YZX' ) { + this.map = source.map; - this._z = Math.asin( clamp( m21, - 1, 1 ) ); + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - if ( Math.abs( m21 ) < 0.99999 ) { + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - this._x = Math.atan2( - m23, m22 ); - this._y = Math.atan2( - m31, m11 ); + this.specularMap = source.specularMap; - } else { + this.alphaMap = source.alphaMap; - this._x = 0; - this._y = Math.atan2( m13, m33 ); + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + 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; - } else if ( order === 'XZY' ) { + this.fog = source.fog; - this._z = Math.asin( - clamp( m12, - 1, 1 ) ); + return this; - if ( Math.abs( m12 ) < 0.99999 ) { + } - this._x = Math.atan2( m32, m22 ); - this._y = Math.atan2( m13, m11 ); + } - } else { + const _vector$9 = /*@__PURE__*/ new Vector3(); + const _vector2$1 = /*@__PURE__*/ new Vector2(); - this._x = Math.atan2( - m23, m33 ); - this._y = 0; + class BufferAttribute { - } + constructor( array, itemSize, normalized = false ) { - } else { + if ( Array.isArray( array ) ) { - console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ); + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); } - this._order = order; - - if ( update !== false ) this.onChangeCallback(); - - return this; + this.isBufferAttribute = true; - }, + this.name = ''; - setFromQuaternion: function () { + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized; - var matrix = new Matrix4(); + this.usage = StaticDrawUsage; + this._updateRange = { offset: 0, count: - 1 }; + this.updateRanges = []; + this.gpuType = FloatType; - return function setFromQuaternion( q, order, update ) { + this.version = 0; - matrix.makeRotationFromQuaternion( q ); + } - return this.setFromRotationMatrix( matrix, order, update ); + onUploadCallback() {} - }; + set needsUpdate( value ) { - }(), + if ( value === true ) this.version ++; - setFromVector3: function ( v, order ) { + } - return this.set( v.x, v.y, v.z, order || this._order ); + get updateRange() { - }, + warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 + return this._updateRange; - reorder: function () { + } - // WARNING: this discards revolution information -bhouston + setUsage( value ) { - var q = new Quaternion(); + this.usage = value; - return function reorder( newOrder ) { + return this; - q.setFromEuler( this ); + } - return this.setFromQuaternion( q, newOrder ); + addUpdateRange( start, count ) { - }; + this.updateRanges.push( { start, count } ); - }(), + } - equals: function ( euler ) { + clearUpdateRanges() { - return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); + this.updateRanges.length = 0; - }, + } - fromArray: function ( array ) { + copy( source ) { - this._x = array[ 0 ]; - this._y = array[ 1 ]; - this._z = array[ 2 ]; - if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; + 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.onChangeCallback(); + this.usage = source.usage; + this.gpuType = source.gpuType; return this; - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._order; - - return array; - - }, - - toVector3: function ( optionalResult ) { + } - if ( optionalResult ) { + copyAt( index1, attribute, index2 ) { - return optionalResult.set( this._x, this._y, this._z ); + index1 *= this.itemSize; + index2 *= attribute.itemSize; - } else { + for ( let i = 0, l = this.itemSize; i < l; i ++ ) { - return new Vector3( this._x, this._y, this._z ); + this.array[ index1 + i ] = attribute.array[ index2 + i ]; } - }, + return this; + + } - onChange: function ( callback ) { + copyArray( array ) { - this.onChangeCallback = callback; + this.array.set( array ); return this; - }, + } - onChangeCallback: function () {} + applyMatrix3( m ) { - } ); + if ( this.itemSize === 2 ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + for ( let i = 0, l = this.count; i < l; i ++ ) { - function Layers() { + _vector2$1.fromBufferAttribute( this, i ); + _vector2$1.applyMatrix3( m ); - this.mask = 1 | 0; + this.setXY( i, _vector2$1.x, _vector2$1.y ); - } + } - Object.assign( Layers.prototype, { + } else if ( this.itemSize === 3 ) { - set: function ( channel ) { + for ( let i = 0, l = this.count; i < l; i ++ ) { - this.mask = 1 << channel | 0; + _vector$9.fromBufferAttribute( this, i ); + _vector$9.applyMatrix3( m ); - }, + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - enable: function ( channel ) { + } - this.mask |= 1 << channel | 0; + } - }, + return this; - toggle: function ( channel ) { + } - this.mask ^= 1 << channel | 0; + applyMatrix4( m ) { - }, + for ( let i = 0, l = this.count; i < l; i ++ ) { - disable: function ( channel ) { + _vector$9.fromBufferAttribute( this, i ); - this.mask &= ~ ( 1 << channel | 0 ); + _vector$9.applyMatrix4( m ); - }, + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - test: function ( layers ) { + } - return ( this.mask & layers.mask ) !== 0; + return this; } - } ); + applyNormalMatrix( m ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author elephantatwork / www.elephantatwork.ch - */ + for ( let i = 0, l = this.count; i < l; i ++ ) { - var object3DId = 0; + _vector$9.fromBufferAttribute( this, i ); - function Object3D() { + _vector$9.applyNormalMatrix( m ); - Object.defineProperty( this, 'id', { value: object3DId ++ } ); + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - this.uuid = _Math.generateUUID(); + } - this.name = ''; - this.type = 'Object3D'; + return this; - this.parent = null; - this.children = []; + } - this.up = Object3D.DefaultUp.clone(); + transformDirection( m ) { - var position = new Vector3(); - var rotation = new Euler(); - var quaternion = new Quaternion(); - var scale = new Vector3( 1, 1, 1 ); + for ( let i = 0, l = this.count; i < l; i ++ ) { - function onRotationChange() { + _vector$9.fromBufferAttribute( this, i ); - quaternion.setFromEuler( rotation, false ); + _vector$9.transformDirection( m ); - } + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); - function onQuaternionChange() { + } - rotation.setFromQuaternion( quaternion, undefined, false ); + return this; } - rotation.onChange( onRotationChange ); - quaternion.onChange( onQuaternionChange ); + set( value, offset = 0 ) { - Object.defineProperties( this, { - position: { - enumerable: true, - value: position - }, - rotation: { - enumerable: true, - value: rotation - }, - quaternion: { - enumerable: true, - value: quaternion - }, - scale: { - enumerable: true, - value: scale - }, - modelViewMatrix: { - value: new Matrix4() - }, - normalMatrix: { - value: new Matrix3() - } - } ); + // Matching BufferAttribute constructor, do not normalize the array. + this.array.set( value, offset ); - this.matrix = new Matrix4(); - this.matrixWorld = new Matrix4(); + return this; - this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; - this.matrixWorldNeedsUpdate = false; + } - this.layers = new Layers(); - this.visible = true; + getComponent( index, component ) { - this.castShadow = false; - this.receiveShadow = false; + let value = this.array[ index * this.itemSize + component ]; - this.frustumCulled = true; - this.renderOrder = 0; + if ( this.normalized ) value = denormalize( value, this.array ); - this.userData = {}; + return value; - } + } - Object3D.DefaultUp = new Vector3( 0, 1, 0 ); - Object3D.DefaultMatrixAutoUpdate = true; + setComponent( index, component, value ) { - Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + if ( this.normalized ) value = normalize( value, this.array ); - constructor: Object3D, + this.array[ index * this.itemSize + component ] = value; - isObject3D: true, + return this; - onBeforeRender: function () {}, - onAfterRender: function () {}, + } - applyMatrix: function ( matrix ) { + getX( index ) { - this.matrix.multiplyMatrices( matrix, this.matrix ); + let x = this.array[ index * this.itemSize ]; - this.matrix.decompose( this.position, this.quaternion, this.scale ); + if ( this.normalized ) x = denormalize( x, this.array ); - }, + return x; - applyQuaternion: function ( q ) { + } - this.quaternion.premultiply( q ); + setX( index, x ) { - return this; + if ( this.normalized ) x = normalize( x, this.array ); - }, + this.array[ index * this.itemSize ] = x; - setRotationFromAxisAngle: function ( axis, angle ) { + return this; - // assumes axis is normalized + } - this.quaternion.setFromAxisAngle( axis, angle ); + getY( index ) { - }, + let y = this.array[ index * this.itemSize + 1 ]; - setRotationFromEuler: function ( euler ) { + if ( this.normalized ) y = denormalize( y, this.array ); - this.quaternion.setFromEuler( euler, true ); + return y; - }, + } - setRotationFromMatrix: function ( m ) { + setY( index, y ) { - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + if ( this.normalized ) y = normalize( y, this.array ); - this.quaternion.setFromRotationMatrix( m ); + this.array[ index * this.itemSize + 1 ] = y; - }, + return this; - setRotationFromQuaternion: function ( q ) { + } - // assumes q is normalized + getZ( index ) { - this.quaternion.copy( q ); + let z = this.array[ index * this.itemSize + 2 ]; - }, + if ( this.normalized ) z = denormalize( z, this.array ); - rotateOnAxis: function () { + return z; - // rotate object on axis in object space - // axis is assumed to be normalized + } - var q1 = new Quaternion(); + setZ( index, z ) { - return function rotateOnAxis( axis, angle ) { + if ( this.normalized ) z = normalize( z, this.array ); - q1.setFromAxisAngle( axis, angle ); + this.array[ index * this.itemSize + 2 ] = z; - this.quaternion.multiply( q1 ); + return this; - return this; + } - }; + getW( index ) { - }(), + let w = this.array[ index * this.itemSize + 3 ]; - rotateOnWorldAxis: function () { + if ( this.normalized ) w = denormalize( w, this.array ); - // rotate object on axis in world space - // axis is assumed to be normalized - // method assumes no rotated parent + return w; - var q1 = new Quaternion(); + } - return function rotateOnWorldAxis( axis, angle ) { + setW( index, w ) { - q1.setFromAxisAngle( axis, angle ); + if ( this.normalized ) w = normalize( w, this.array ); - this.quaternion.premultiply( q1 ); + this.array[ index * this.itemSize + 3 ] = w; - return this; + return this; - }; + } - }(), + setXY( index, x, y ) { - rotateX: function () { + index *= this.itemSize; - var v1 = new Vector3( 1, 0, 0 ); + if ( this.normalized ) { - return function rotateX( angle ) { + x = normalize( x, this.array ); + y = normalize( y, this.array ); - return this.rotateOnAxis( v1, angle ); + } - }; + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; - }(), + return this; - rotateY: function () { + } - var v1 = new Vector3( 0, 1, 0 ); + setXYZ( index, x, y, z ) { - return function rotateY( angle ) { + index *= this.itemSize; - return this.rotateOnAxis( v1, angle ); + if ( this.normalized ) { - }; + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); - }(), + } - rotateZ: function () { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; - var v1 = new Vector3( 0, 0, 1 ); + return this; - return function rotateZ( angle ) { + } - return this.rotateOnAxis( v1, angle ); + setXYZW( index, x, y, z, w ) { - }; + index *= this.itemSize; - }(), + if ( this.normalized ) { - translateOnAxis: function () { + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); - // translate object by distance along axis in object space - // axis is assumed to be normalized + } - var v1 = new Vector3(); + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + this.array[ index + 3 ] = w; - return function translateOnAxis( axis, distance ) { + return this; - v1.copy( axis ).applyQuaternion( this.quaternion ); + } - this.position.add( v1.multiplyScalar( distance ) ); + onUpload( callback ) { - return this; + this.onUploadCallback = callback; - }; + return this; - }(), + } - translateX: function () { + clone() { - var v1 = new Vector3( 1, 0, 0 ); + return new this.constructor( this.array, this.itemSize ).copy( this ); - return function translateX( distance ) { + } - return this.translateOnAxis( v1, distance ); + 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; - translateY: function () { + return data; - var v1 = new Vector3( 0, 1, 0 ); + } - return function translateY( distance ) { + } - return this.translateOnAxis( v1, distance ); + class Uint16BufferAttribute extends BufferAttribute { - }; + constructor( array, itemSize, normalized ) { - }(), + super( new Uint16Array( array ), itemSize, normalized ); - translateZ: function () { + } - var v1 = new Vector3( 0, 0, 1 ); + } - return function translateZ( distance ) { + class Uint32BufferAttribute extends BufferAttribute { - return this.translateOnAxis( v1, distance ); + constructor( array, itemSize, normalized ) { - }; + super( new Uint32Array( array ), itemSize, normalized ); - }(), + } - localToWorld: function ( vector ) { + } - return vector.applyMatrix4( this.matrixWorld ); - }, + class Float32BufferAttribute extends BufferAttribute { - worldToLocal: function () { + constructor( array, itemSize, normalized ) { - var m1 = new Matrix4(); + super( new Float32Array( array ), itemSize, normalized ); - return function worldToLocal( vector ) { + } - return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) ); + } - }; + let _id$2 = 0; - }(), + const _m1$2 = /*@__PURE__*/ new Matrix4(); + const _obj = /*@__PURE__*/ new Object3D(); + const _offset = /*@__PURE__*/ new Vector3(); + const _box$2 = /*@__PURE__*/ new Box3(); + const _boxMorphTargets = /*@__PURE__*/ new Box3(); + const _vector$8 = /*@__PURE__*/ new Vector3(); - lookAt: function () { + class BufferGeometry extends EventDispatcher { - // This method does not support objects with rotated and/or translated parent(s) + constructor() { - var m1 = new Matrix4(); - var vector = new Vector3(); + super(); - return function lookAt( x, y, z ) { + this.isBufferGeometry = true; - if ( x.isVector3 ) { + Object.defineProperty( this, 'id', { value: _id$2 ++ } ); - vector.copy( x ); + this.uuid = generateUUID(); - } else { - - vector.set( x, y, z ); + this.name = ''; + this.type = 'BufferGeometry'; - } + this.index = null; + this.attributes = {}; - if ( this.isCamera ) { + this.morphAttributes = {}; + this.morphTargetsRelative = false; - m1.lookAt( this.position, vector, this.up ); + this.groups = []; - } else { + this.boundingBox = null; + this.boundingSphere = null; - m1.lookAt( vector, this.position, this.up ); + this.drawRange = { start: 0, count: Infinity }; - } + this.userData = {}; - this.quaternion.setFromRotationMatrix( m1 ); + } - }; + getIndex() { - }(), + return this.index; - add: function ( object ) { + } - if ( arguments.length > 1 ) { + setIndex( index ) { - for ( var i = 0; i < arguments.length; i ++ ) { + if ( Array.isArray( index ) ) { - this.add( arguments[ i ] ); + this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - } + } else { - return this; + this.index = index; } - if ( object === this ) { - - console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); - return this; + return this; - } + } - if ( ( object && object.isObject3D ) ) { + getAttribute( name ) { - if ( object.parent !== null ) { + return this.attributes[ name ]; - object.parent.remove( object ); + } - } + setAttribute( name, attribute ) { - object.parent = this; - object.dispatchEvent( { type: 'added' } ); + this.attributes[ name ] = attribute; - this.children.push( object ); + return this; - } else { + } - console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); + deleteAttribute( name ) { - } + delete this.attributes[ name ]; return this; - }, - - remove: function ( object ) { + } - if ( arguments.length > 1 ) { + hasAttribute( name ) { - for ( var i = 0; i < arguments.length; i ++ ) { + return this.attributes[ name ] !== undefined; - this.remove( arguments[ i ] ); + } - } + addGroup( start, count, materialIndex = 0 ) { - return this; + this.groups.push( { - } + start: start, + count: count, + materialIndex: materialIndex - var index = this.children.indexOf( object ); + } ); - if ( index !== - 1 ) { + } - object.parent = null; + clearGroups() { - object.dispatchEvent( { type: 'removed' } ); + this.groups = []; - this.children.splice( index, 1 ); + } - } + setDrawRange( start, count ) { - return this; + this.drawRange.start = start; + this.drawRange.count = count; - }, + } - getObjectById: function ( id ) { + applyMatrix4( matrix ) { - return this.getObjectByProperty( 'id', id ); + const position = this.attributes.position; - }, + if ( position !== undefined ) { - getObjectByName: function ( name ) { + position.applyMatrix4( matrix ); - return this.getObjectByProperty( 'name', name ); + position.needsUpdate = true; - }, + } - getObjectByProperty: function ( name, value ) { + const normal = this.attributes.normal; - if ( this[ name ] === value ) return this; + if ( normal !== undefined ) { - for ( var i = 0, l = this.children.length; i < l; i ++ ) { + const normalMatrix = new Matrix3().getNormalMatrix( matrix ); - var child = this.children[ i ]; - var object = child.getObjectByProperty( name, value ); + normal.applyNormalMatrix( normalMatrix ); - if ( object !== undefined ) { + normal.needsUpdate = true; - return object; + } - } + const tangent = this.attributes.tangent; - } + if ( tangent !== undefined ) { - return undefined; + tangent.transformDirection( matrix ); - }, + tangent.needsUpdate = true; - getWorldPosition: function ( optionalTarget ) { + } - var result = optionalTarget || new Vector3(); + if ( this.boundingBox !== null ) { - this.updateMatrixWorld( true ); + this.computeBoundingBox(); - return result.setFromMatrixPosition( this.matrixWorld ); + } - }, + if ( this.boundingSphere !== null ) { - getWorldQuaternion: function () { + this.computeBoundingSphere(); - var position = new Vector3(); - var scale = new Vector3(); + } - return function getWorldQuaternion( optionalTarget ) { + return this; - var result = optionalTarget || new Quaternion(); + } - this.updateMatrixWorld( true ); + applyQuaternion( q ) { - this.matrixWorld.decompose( position, result, scale ); + _m1$2.makeRotationFromQuaternion( q ); - return result; + this.applyMatrix4( _m1$2 ); - }; + return this; - }(), + } - getWorldRotation: function () { + rotateX( angle ) { - var quaternion = new Quaternion(); + // rotate geometry around world x-axis - return function getWorldRotation( optionalTarget ) { + _m1$2.makeRotationX( angle ); - var result = optionalTarget || new Euler(); + this.applyMatrix4( _m1$2 ); - this.getWorldQuaternion( quaternion ); + return this; - return result.setFromQuaternion( quaternion, this.rotation.order, false ); + } - }; + rotateY( angle ) { - }(), + // rotate geometry around world y-axis - getWorldScale: function () { + _m1$2.makeRotationY( angle ); - var position = new Vector3(); - var quaternion = new Quaternion(); + this.applyMatrix4( _m1$2 ); - return function getWorldScale( optionalTarget ) { + return this; - var result = optionalTarget || new Vector3(); + } - this.updateMatrixWorld( true ); + rotateZ( angle ) { - this.matrixWorld.decompose( position, quaternion, result ); + // rotate geometry around world z-axis - return result; + _m1$2.makeRotationZ( angle ); - }; + this.applyMatrix4( _m1$2 ); - }(), + return this; - getWorldDirection: function () { + } - var quaternion = new Quaternion(); + translate( x, y, z ) { - return function getWorldDirection( optionalTarget ) { + // translate geometry - var result = optionalTarget || new Vector3(); + _m1$2.makeTranslation( x, y, z ); - this.getWorldQuaternion( quaternion ); + this.applyMatrix4( _m1$2 ); - return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); + return this; - }; + } - }(), + scale( x, y, z ) { - raycast: function () {}, + // scale geometry - traverse: function ( callback ) { + _m1$2.makeScale( x, y, z ); - callback( this ); + this.applyMatrix4( _m1$2 ); - var children = this.children; + return this; - for ( var i = 0, l = children.length; i < l; i ++ ) { + } - children[ i ].traverse( callback ); + lookAt( vector ) { - } + _obj.lookAt( vector ); - }, + _obj.updateMatrix(); - traverseVisible: function ( callback ) { + this.applyMatrix4( _obj.matrix ); - if ( this.visible === false ) return; + return this; - callback( this ); + } - var children = this.children; + center() { - for ( var i = 0, l = children.length; i < l; i ++ ) { + this.computeBoundingBox(); - children[ i ].traverseVisible( callback ); + this.boundingBox.getCenter( _offset ).negate(); - } + this.translate( _offset.x, _offset.y, _offset.z ); - }, + return this; - traverseAncestors: function ( callback ) { + } - var parent = this.parent; + setFromPoints( points ) { - if ( parent !== null ) { + const position = []; - callback( parent ); + for ( let i = 0, l = points.length; i < l; i ++ ) { - parent.traverseAncestors( callback ); + const point = points[ i ]; + position.push( point.x, point.y, point.z || 0 ); } - }, + this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - updateMatrix: function () { + return this; - this.matrix.compose( this.position, this.quaternion, this.scale ); + } - this.matrixWorldNeedsUpdate = true; + computeBoundingBox() { - }, + if ( this.boundingBox === null ) { - updateMatrixWorld: function ( force ) { + this.boundingBox = new Box3(); - if ( this.matrixAutoUpdate ) this.updateMatrix(); + } - if ( this.matrixWorldNeedsUpdate || force ) { + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; - if ( this.parent === null ) { + if ( position && position.isGLBufferAttribute ) { - this.matrixWorld.copy( this.matrix ); + console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); - } else { + this.boundingBox.set( + new Vector3( - Infinity, - Infinity, - Infinity ), + new Vector3( + Infinity, + Infinity, + Infinity ) + ); - this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + return; - } + } - this.matrixWorldNeedsUpdate = false; + if ( position !== undefined ) { - force = true; + this.boundingBox.setFromBufferAttribute( position ); - } + // process morph attributes if present - // update children + if ( morphAttributesPosition ) { - var children = this.children; + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { - for ( var i = 0, l = children.length; i < l; i ++ ) { + const morphAttribute = morphAttributesPosition[ i ]; + _box$2.setFromBufferAttribute( morphAttribute ); - children[ i ].updateMatrixWorld( force ); + if ( this.morphTargetsRelative ) { - } + _vector$8.addVectors( this.boundingBox.min, _box$2.min ); + this.boundingBox.expandByPoint( _vector$8 ); - }, + _vector$8.addVectors( this.boundingBox.max, _box$2.max ); + this.boundingBox.expandByPoint( _vector$8 ); + + } else { - toJSON: function ( meta ) { + this.boundingBox.expandByPoint( _box$2.min ); + this.boundingBox.expandByPoint( _box$2.max ); - // meta is a string when called from JSON.stringify - var isRootObject = ( meta === undefined || typeof meta === 'string' ); + } - var output = {}; + } - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { + } - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {}, - shapes: {} - }; + } else { - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; + this.boundingBox.makeEmpty(); } - // standard Object3D serialization + if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - var object = {}; + console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); - 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 ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; + } - object.matrix = this.matrix.toArray(); + computeBoundingSphere() { - // + if ( this.boundingSphere === null ) { - function serialize( library, element ) { + this.boundingSphere = new Sphere(); - if ( library[ element.uuid ] === undefined ) { + } - library[ element.uuid ] = element.toJSON( meta ); + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; - } + if ( position && position.isGLBufferAttribute ) { - return element.uuid; + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); + + this.boundingSphere.set( new Vector3(), Infinity ); + + return; } - if ( this.geometry !== undefined ) { + if ( position ) { - object.geometry = serialize( meta.geometries, this.geometry ); + // first, find the center of the bounding sphere - var parameters = this.geometry.parameters; + const center = this.boundingSphere.center; - if ( parameters !== undefined && parameters.shapes !== undefined ) { + _box$2.setFromBufferAttribute( position ); - var shapes = parameters.shapes; + // process morph attributes if present - if ( Array.isArray( shapes ) ) { + if ( morphAttributesPosition ) { - for ( var i = 0, l = shapes.length; i < l; i ++ ) { + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { - var shape = shapes[ i ]; + const morphAttribute = morphAttributesPosition[ i ]; + _boxMorphTargets.setFromBufferAttribute( morphAttribute ); - serialize( meta.shapes, shape ); + if ( this.morphTargetsRelative ) { - } + _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); + _box$2.expandByPoint( _vector$8 ); - } else { + _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); + _box$2.expandByPoint( _vector$8 ); - serialize( meta.shapes, shapes ); + } else { + + _box$2.expandByPoint( _boxMorphTargets.min ); + _box$2.expandByPoint( _boxMorphTargets.max ); + + } } } - } + _box$2.getCenter( center ); - if ( this.material !== undefined ) { + // second, try to find a boundingSphere with a radius smaller than the + // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - if ( Array.isArray( this.material ) ) { + let maxRadiusSq = 0; - var uuids = []; + for ( let i = 0, il = position.count; i < il; i ++ ) { - for ( var i = 0, l = this.material.length; i < l; i ++ ) { + _vector$8.fromBufferAttribute( position, i ); - uuids.push( serialize( meta.materials, this.material[ i ] ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); - } + } - object.material = uuids; + // process morph attributes if present - } else { + if ( morphAttributesPosition ) { - object.material = serialize( meta.materials, this.material ); + 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 ( this.children.length > 0 ) { + if ( morphTargetsRelative ) { - object.children = []; + _offset.fromBufferAttribute( position, j ); + _vector$8.add( _offset ); - for ( var i = 0; i < this.children.length; i ++ ) { + } - object.children.push( this.children[ i ].toJSON( meta ).object ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + + } + + } } - } + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - if ( isRootObject ) { + if ( isNaN( this.boundingSphere.radius ) ) { - var geometries = extractFromCache( meta.geometries ); - var materials = extractFromCache( meta.materials ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - var shapes = extractFromCache( meta.shapes ); + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); - 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; + } } - output.object = object; + } - return output; + computeTangents() { - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { + const index = this.index; + const attributes = this.attributes; - var values = []; - for ( var key in cache ) { + // based on http://www.terathon.com/code/tangent.html + // (per vertex tangents) - var data = cache[ key ]; - delete data.metadata; - values.push( data ); + if ( index === null || + attributes.position === undefined || + attributes.normal === undefined || + attributes.uv === undefined ) { - } - return values; + console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); + return; } - }, + const positionAttribute = attributes.position; + const normalAttribute = attributes.normal; + const uvAttribute = attributes.uv; - clone: function ( recursive ) { + if ( this.hasAttribute( 'tangent' ) === false ) { - return new this.constructor().copy( this, recursive ); + this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) ); - }, + } - copy: function ( source, recursive ) { + const tangentAttribute = this.getAttribute( 'tangent' ); - if ( recursive === undefined ) recursive = true; + const tan1 = [], tan2 = []; - this.name = source.name; + for ( let i = 0; i < positionAttribute.count; i ++ ) { - this.up.copy( source.up ); + tan1[ i ] = new Vector3(); + tan2[ i ] = new Vector3(); - this.position.copy( source.position ); - this.quaternion.copy( source.quaternion ); - this.scale.copy( source.scale ); + } - this.matrix.copy( source.matrix ); - this.matrixWorld.copy( source.matrixWorld ); + const vA = new Vector3(), + vB = new Vector3(), + vC = new Vector3(), - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; + uvA = new Vector2(), + uvB = new Vector2(), + uvC = new Vector2(), - this.layers.mask = source.layers.mask; - this.visible = source.visible; + sdir = new Vector3(), + tdir = new Vector3(); - this.castShadow = source.castShadow; - this.receiveShadow = source.receiveShadow; + function handleTriangle( a, b, c ) { - this.frustumCulled = source.frustumCulled; - this.renderOrder = source.renderOrder; + vA.fromBufferAttribute( positionAttribute, a ); + vB.fromBufferAttribute( positionAttribute, b ); + vC.fromBufferAttribute( positionAttribute, c ); - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + uvA.fromBufferAttribute( uvAttribute, a ); + uvB.fromBufferAttribute( uvAttribute, b ); + uvC.fromBufferAttribute( uvAttribute, c ); - if ( recursive === true ) { + vB.sub( vA ); + vC.sub( vA ); - for ( var i = 0; i < source.children.length; i ++ ) { + uvB.sub( uvA ); + uvC.sub( uvA ); - var child = source.children[ i ]; - this.add( child.clone() ); + const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); - } + // silently ignore degenerate uv triangles having coincident or colinear vertices - } + if ( ! isFinite( r ) ) return; - return this; + 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[ a ].add( sdir ); + tan1[ b ].add( sdir ); + tan1[ c ].add( sdir ); - } ); + tan2[ a ].add( tdir ); + tan2[ b ].add( tdir ); + tan2[ c ].add( tdir ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author WestLangley / http://github.com/WestLangley - */ + } - function Camera() { + let groups = this.groups; - Object3D.call( this ); + if ( groups.length === 0 ) { - this.type = 'Camera'; + groups = [ { + start: 0, + count: index.count + } ]; - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); + } - } + for ( let i = 0, il = groups.length; i < il; ++ i ) { - Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { + const group = groups[ i ]; - constructor: Camera, + const start = group.start; + const count = group.count; - isCamera: true, + for ( let j = start, jl = start + count; j < jl; j += 3 ) { + + handleTriangle( + index.getX( j + 0 ), + index.getX( j + 1 ), + index.getX( j + 2 ) + ); - copy: function ( source, recursive ) { + } - Object3D.prototype.copy.call( this, source, recursive ); + } - this.matrixWorldInverse.copy( source.matrixWorldInverse ); - this.projectionMatrix.copy( source.projectionMatrix ); + const tmp = new Vector3(), tmp2 = new Vector3(); + const n = new Vector3(), n2 = new Vector3(); - return this; + function handleVertex( v ) { - }, + n.fromBufferAttribute( normalAttribute, v ); + n2.copy( n ); - getWorldDirection: function () { + const t = tan1[ v ]; - var quaternion = new Quaternion(); + // Gram-Schmidt orthogonalize - return function getWorldDirection( optionalTarget ) { + tmp.copy( t ); + tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); - var result = optionalTarget || new Vector3(); + // Calculate handedness - this.getWorldQuaternion( quaternion ); + tmp2.crossVectors( n2, t ); + const test = tmp2.dot( tan2[ v ] ); + const w = ( test < 0.0 ) ? - 1.0 : 1.0; - return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); + tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w ); - }; + } - }(), + for ( let i = 0, il = groups.length; i < il; ++ i ) { - updateMatrixWorld: function ( force ) { + const group = groups[ i ]; - Object3D.prototype.updateMatrixWorld.call( this, force ); + const start = group.start; + const count = group.count; - this.matrixWorldInverse.getInverse( this.matrixWorld ); + for ( let j = start, jl = start + count; j < jl; j += 3 ) { - }, + handleVertex( index.getX( j + 0 ) ); + handleVertex( index.getX( j + 1 ) ); + handleVertex( index.getX( j + 2 ) ); - clone: function () { + } - return new this.constructor().copy( this ); + } } - } ); + computeVertexNormals() { - /** - * @author alteredq / http://alteredqualia.com/ - * @author arose / http://github.com/arose - */ + const index = this.index; + const positionAttribute = this.getAttribute( 'position' ); - function OrthographicCamera( left, right, top, bottom, near, far ) { + if ( positionAttribute !== undefined ) { - Camera.call( this ); + let normalAttribute = this.getAttribute( 'normal' ); - this.type = 'OrthographicCamera'; + if ( normalAttribute === undefined ) { - this.zoom = 1; - this.view = null; + normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); + this.setAttribute( 'normal', normalAttribute ); - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; + } else { - this.near = ( near !== undefined ) ? near : 0.1; - this.far = ( far !== undefined ) ? far : 2000; + // reset existing normals to zero - this.updateProjectionMatrix(); + for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { - } + normalAttribute.setXYZ( i, 0, 0, 0 ); - OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + } - constructor: OrthographicCamera, + } - isOrthographicCamera: true, + 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(); - copy: function ( source, recursive ) { + // indexed elements - Camera.prototype.copy.call( this, source, recursive ); + if ( index ) { - this.left = source.left; - this.right = source.right; - this.top = source.top; - this.bottom = source.bottom; - this.near = source.near; - this.far = source.far; + for ( let i = 0, il = index.count; i < il; i += 3 ) { - this.zoom = source.zoom; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + const vA = index.getX( i + 0 ); + const vB = index.getX( i + 1 ); + const vC = index.getX( i + 2 ); - return this; + pA.fromBufferAttribute( positionAttribute, vA ); + pB.fromBufferAttribute( positionAttribute, vB ); + pC.fromBufferAttribute( positionAttribute, vC ); - }, + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { + nA.fromBufferAttribute( normalAttribute, vA ); + nB.fromBufferAttribute( normalAttribute, vB ); + nC.fromBufferAttribute( normalAttribute, vC ); - if ( this.view === null ) { + nA.add( cb ); + nB.add( cb ); + nC.add( cb ); - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; + 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 ); - } + } - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; + } else { - this.updateProjectionMatrix(); + // non-indexed elements (unconnected triangle soup) - }, + for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { - clearViewOffset: function () { + pA.fromBufferAttribute( positionAttribute, i + 0 ); + pB.fromBufferAttribute( positionAttribute, i + 1 ); + pC.fromBufferAttribute( positionAttribute, i + 2 ); - if ( this.view !== null ) { + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - this.view.enabled = false; + 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.updateProjectionMatrix(); + } - }, + this.normalizeNormals(); - updateProjectionMatrix: function () { + normalAttribute.needsUpdate = true; - var dx = ( this.right - this.left ) / ( 2 * this.zoom ); - var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - var cx = ( this.right + this.left ) / 2; - var cy = ( this.top + this.bottom ) / 2; + } - var left = cx - dx; - var right = cx + dx; - var top = cy + dy; - var bottom = cy - dy; + } - if ( this.view !== null && this.view.enabled ) { + normalizeNormals() { - var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); - var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); - var scaleW = ( this.right - this.left ) / this.view.width; - var scaleH = ( this.top - this.bottom ) / this.view.height; + const normals = this.attributes.normal; - left += scaleW * ( this.view.offsetX / zoomW ); - right = left + scaleW * ( this.view.width / zoomW ); - top -= scaleH * ( this.view.offsetY / zoomH ); - bottom = top - scaleH * ( this.view.height / zoomH ); + for ( let i = 0, il = normals.count; i < il; i ++ ) { - } + _vector$8.fromBufferAttribute( normals, i ); - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); + _vector$8.normalize(); - }, + normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); - toJSON: function ( meta ) { + } - var data = Object3D.prototype.toJSON.call( this, 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; + toNonIndexed() { - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + function convertBufferAttribute( attribute, indices ) { - return data; + const array = attribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; - } + const array2 = new array.constructor( indices.length * itemSize ); - } ); + let index = 0, index2 = 0; - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + for ( let i = 0, l = indices.length; i < l; i ++ ) { + + if ( attribute.isInterleavedBufferAttribute ) { - function Face3( a, b, c, normal, color, materialIndex ) { + index = indices[ i ] * attribute.data.stride + attribute.offset; - this.a = a; - this.b = b; - this.c = c; + } else { - this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); - this.vertexNormals = Array.isArray( normal ) ? normal : []; + index = indices[ i ] * itemSize; - this.color = ( color && color.isColor ) ? color : new Color(); - this.vertexColors = Array.isArray( color ) ? color : []; + } - this.materialIndex = materialIndex !== undefined ? materialIndex : 0; + for ( let j = 0; j < itemSize; j ++ ) { - } + array2[ index2 ++ ] = array[ index ++ ]; - Object.assign( Face3.prototype, { + } - clone: function () { + } - return new this.constructor().copy( this ); + return new BufferAttribute( array2, itemSize, normalized ); - }, + } - copy: function ( source ) { + // - this.a = source.a; - this.b = source.b; - this.c = source.c; + if ( this.index === null ) { - this.normal.copy( source.normal ); - this.color.copy( source.color ); + console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); + return this; - this.materialIndex = source.materialIndex; + } - for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { + const geometry2 = new BufferGeometry(); - this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); + const indices = this.index.array; + const attributes = this.attributes; - } + // attributes - for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { + for ( const name in attributes ) { - this.vertexColors[ i ] = source.vertexColors[ i ].clone(); + const attribute = attributes[ name ]; - } + const newAttribute = convertBufferAttribute( attribute, indices ); - return this; + geometry2.setAttribute( name, newAttribute ); - } + } - } ); + // morph attributes - /** - * @author mrdoob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author bhouston / http://clara.io - */ + const morphAttributes = this.morphAttributes; - var geometryId = 0; // Geometry uses even numbers as Id + for ( const name in morphAttributes ) { - function Geometry() { + const morphArray = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - Object.defineProperty( this, 'id', { value: geometryId += 2 } ); + for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { - this.uuid = _Math.generateUUID(); + const attribute = morphAttribute[ i ]; - this.name = ''; - this.type = 'Geometry'; + const newAttribute = convertBufferAttribute( attribute, indices ); - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; + morphArray.push( newAttribute ); - this.morphTargets = []; - this.morphNormals = []; + } - this.skinWeights = []; - this.skinIndices = []; + geometry2.morphAttributes[ name ] = morphArray; - this.lineDistances = []; + } - this.boundingBox = null; - this.boundingSphere = null; + geometry2.morphTargetsRelative = this.morphTargetsRelative; - // update flags + // groups - this.elementsNeedUpdate = false; - this.verticesNeedUpdate = false; - this.uvsNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.lineDistancesNeedUpdate = false; - this.groupsNeedUpdate = false; + const groups = this.groups; - } + for ( let i = 0, l = groups.length; i < l; i ++ ) { - Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + const group = groups[ i ]; + geometry2.addGroup( group.start, group.count, group.materialIndex ); - constructor: Geometry, + } - isGeometry: true, + return geometry2; - applyMatrix: function ( matrix ) { + } - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); + toJSON() { - for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { + const data = { + metadata: { + version: 4.6, + type: 'BufferGeometry', + generator: 'BufferGeometry.toJSON' + } + }; - var vertex = this.vertices[ i ]; - vertex.applyMatrix4( matrix ); + // standard BufferGeometry serialization - } + 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; - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { + if ( this.parameters !== undefined ) { - var face = this.faces[ i ]; - face.normal.applyMatrix3( normalMatrix ).normalize(); + const parameters = this.parameters; - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { + for ( const key in parameters ) { - face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; } + return data; + } - if ( this.boundingBox !== null ) { + // for simplicity the code assumes attributes are not shared across geometries, see #15811 - this.computeBoundingBox(); + data.data = { attributes: {} }; - } + const index = this.index; - if ( this.boundingSphere !== null ) { + if ( index !== null ) { - this.computeBoundingSphere(); + data.data.index = { + type: index.array.constructor.name, + array: Array.prototype.slice.call( index.array ) + }; } - this.verticesNeedUpdate = true; - this.normalsNeedUpdate = true; - - return this; + const attributes = this.attributes; - }, + for ( const key in attributes ) { - rotateX: function () { + const attribute = attributes[ key ]; - // rotate geometry around world x-axis + data.data.attributes[ key ] = attribute.toJSON( data.data ); - var m1 = new Matrix4(); + } - return function rotateX( angle ) { + const morphAttributes = {}; + let hasMorphAttributes = false; - m1.makeRotationX( angle ); + for ( const key in this.morphAttributes ) { - this.applyMatrix( m1 ); + const attributeArray = this.morphAttributes[ key ]; - return this; + const array = []; - }; + for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { - }(), + const attribute = attributeArray[ i ]; - rotateY: function () { + array.push( attribute.toJSON( data.data ) ); - // rotate geometry around world y-axis + } - var m1 = new Matrix4(); + if ( array.length > 0 ) { - return function rotateY( angle ) { + morphAttributes[ key ] = array; - m1.makeRotationY( angle ); + hasMorphAttributes = true; - this.applyMatrix( m1 ); + } - return this; + } - }; + if ( hasMorphAttributes ) { - }(), + data.data.morphAttributes = morphAttributes; + data.data.morphTargetsRelative = this.morphTargetsRelative; - rotateZ: function () { + } - // rotate geometry around world z-axis + const groups = this.groups; - var m1 = new Matrix4(); + if ( groups.length > 0 ) { - return function rotateZ( angle ) { + data.data.groups = JSON.parse( JSON.stringify( groups ) ); - m1.makeRotationZ( angle ); + } - this.applyMatrix( m1 ); + const boundingSphere = this.boundingSphere; - return this; + if ( boundingSphere !== null ) { - }; + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; - }(), + } - translate: function () { + return data; - // translate geometry + } - var m1 = new Matrix4(); + clone() { - return function translate( x, y, z ) { + return new this.constructor().copy( this ); - m1.makeTranslation( x, y, z ); + } - this.applyMatrix( m1 ); + copy( source ) { - return this; + // reset - }; + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; - }(), + // used for storing cloned, shared data - scale: function () { + const data = {}; - // scale geometry + // name - var m1 = new Matrix4(); + this.name = source.name; - return function scale( x, y, z ) { + // index - m1.makeScale( x, y, z ); + const index = source.index; - this.applyMatrix( m1 ); + if ( index !== null ) { - return this; + this.setIndex( index.clone( data ) ); - }; + } - }(), + // attributes - lookAt: function () { + const attributes = source.attributes; - var obj = new Object3D(); + for ( const name in attributes ) { - return function lookAt( vector ) { + const attribute = attributes[ name ]; + this.setAttribute( name, attribute.clone( data ) ); - obj.lookAt( vector ); + } - obj.updateMatrix(); + // morph attributes - this.applyMatrix( obj.matrix ); + const morphAttributes = source.morphAttributes; - }; + for ( const name in morphAttributes ) { - }(), + const array = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - fromBufferGeometry: function ( geometry ) { + for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { - var scope = this; + array.push( morphAttribute[ i ].clone( data ) ); - var indices = geometry.index !== null ? geometry.index.array : undefined; - var attributes = geometry.attributes; + } - var positions = attributes.position.array; - var normals = attributes.normal !== undefined ? attributes.normal.array : undefined; - var colors = attributes.color !== undefined ? attributes.color.array : undefined; - var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined; - var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined; + this.morphAttributes[ name ] = array; - if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; + } - var tempNormals = []; - var tempUVs = []; - var tempUVs2 = []; + this.morphTargetsRelative = source.morphTargetsRelative; - for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { + // groups - scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); + const groups = source.groups; - if ( normals !== undefined ) { + for ( let i = 0, l = groups.length; i < l; i ++ ) { - tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); + const group = groups[ i ]; + this.addGroup( group.start, group.count, group.materialIndex ); - } + } - if ( colors !== undefined ) { + // bounding box - scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); + const boundingBox = source.boundingBox; - } + if ( boundingBox !== null ) { - if ( uvs !== undefined ) { + this.boundingBox = boundingBox.clone(); - tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); + } - } + // bounding sphere - if ( uvs2 !== undefined ) { + const boundingSphere = source.boundingSphere; - tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); + if ( boundingSphere !== null ) { - } + this.boundingSphere = boundingSphere.clone(); } - function addFace( a, b, c, materialIndex ) { + // draw range - var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; - var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; - var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); + // user data - scope.faces.push( face ); + this.userData = source.userData; - if ( uvs !== undefined ) { + return this; - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); + } - } + dispose() { - if ( uvs2 !== undefined ) { + this.dispatchEvent( { type: 'dispose' } ); - scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); + } - } + } - } + const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); + const _ray$3 = /*@__PURE__*/ new Ray(); + const _sphere$6 = /*@__PURE__*/ new Sphere(); + const _sphereHitAt = /*@__PURE__*/ new Vector3(); - var groups = geometry.groups; + const _vA$1 = /*@__PURE__*/ new Vector3(); + const _vB$1 = /*@__PURE__*/ new Vector3(); + const _vC$1 = /*@__PURE__*/ new Vector3(); - if ( groups.length > 0 ) { + const _tempA = /*@__PURE__*/ new Vector3(); + const _morphA = /*@__PURE__*/ new Vector3(); - for ( var i = 0; i < groups.length; i ++ ) { + const _uvA$1 = /*@__PURE__*/ new Vector2(); + const _uvB$1 = /*@__PURE__*/ new Vector2(); + const _uvC$1 = /*@__PURE__*/ new Vector2(); - var group = groups[ i ]; + const _normalA = /*@__PURE__*/ new Vector3(); + const _normalB = /*@__PURE__*/ new Vector3(); + const _normalC = /*@__PURE__*/ new Vector3(); - var start = group.start; - var count = group.count; + const _intersectionPoint = /*@__PURE__*/ new Vector3(); + const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); - for ( var j = start, jl = start + count; j < jl; j += 3 ) { + class Mesh extends Object3D { - if ( indices !== undefined ) { + constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { - addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); + super(); - } else { + this.isMesh = true; - addFace( j, j + 1, j + 2, group.materialIndex ); + this.type = 'Mesh'; - } + this.geometry = geometry; + this.material = material; - } + this.updateMorphTargets(); - } + } - } else { + copy( source, recursive ) { - if ( indices !== undefined ) { + super.copy( source, recursive ); - for ( var i = 0; i < indices.length; i += 3 ) { + if ( source.morphTargetInfluences !== undefined ) { - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); + this.morphTargetInfluences = source.morphTargetInfluences.slice(); - } + } - } else { + if ( source.morphTargetDictionary !== undefined ) { - for ( var i = 0; i < positions.length / 3; i += 3 ) { + this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); - addFace( i, i + 1, i + 2 ); + } - } + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - } + return this; - } + } - this.computeFaceNormals(); + updateMorphTargets() { - if ( geometry.boundingBox !== null ) { + const geometry = this.geometry; - this.boundingBox = geometry.boundingBox.clone(); + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - } + if ( keys.length > 0 ) { - if ( geometry.boundingSphere !== null ) { + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - this.boundingSphere = geometry.boundingSphere.clone(); + if ( morphAttribute !== undefined ) { - } + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - return this; + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - }, + const name = morphAttribute[ m ].name || String( m ); - center: function () { + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - this.computeBoundingBox(); + } - var offset = this.boundingBox.getCenter().negate(); + } - this.translate( offset.x, offset.y, offset.z ); + } - return offset; + } - }, + getVertexPosition( index, target ) { - normalize: function () { + const geometry = this.geometry; + const position = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; - this.computeBoundingSphere(); + target.fromBufferAttribute( position, index ); - var center = this.boundingSphere.center; - var radius = this.boundingSphere.radius; + const morphInfluences = this.morphTargetInfluences; - var s = radius === 0 ? 1 : 1.0 / radius; + if ( morphPosition && morphInfluences ) { - var matrix = new Matrix4(); - matrix.set( - s, 0, 0, - s * center.x, - 0, s, 0, - s * center.y, - 0, 0, s, - s * center.z, - 0, 0, 0, 1 - ); + _morphA.set( 0, 0, 0 ); - this.applyMatrix( matrix ); + for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { - return this; + const influence = morphInfluences[ i ]; + const morphAttribute = morphPosition[ i ]; - }, + if ( influence === 0 ) continue; - computeFaceNormals: function () { + _tempA.fromBufferAttribute( morphAttribute, index ); - var cb = new Vector3(), ab = new Vector3(); + if ( morphTargetsRelative ) { - for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { + _morphA.addScaledVector( _tempA, influence ); - var face = this.faces[ f ]; + } else { - var vA = this.vertices[ face.a ]; - var vB = this.vertices[ face.b ]; - var vC = this.vertices[ face.c ]; + _morphA.addScaledVector( _tempA.sub( target ), influence ); - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + } - cb.normalize(); + } - face.normal.copy( cb ); + target.add( _morphA ); } - }, + return target; - computeVertexNormals: function ( areaWeighted ) { + } - if ( areaWeighted === undefined ) areaWeighted = true; + raycast( raycaster, intersects ) { - var v, vl, f, fl, face, vertices; + const geometry = this.geometry; + const material = this.material; + const matrixWorld = this.matrixWorld; - vertices = new Array( this.vertices.length ); + if ( material === undefined ) return; - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + // test with bounding sphere in world space - vertices[ v ] = new Vector3(); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - } + _sphere$6.copy( geometry.boundingSphere ); + _sphere$6.applyMatrix4( matrixWorld ); - if ( areaWeighted ) { + // check distance from ray origin to bounding sphere - // vertex normals weighted by triangle areas - // http://www.iquilezles.org/www/articles/normals/normals.htm + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); - var vA, vB, vC; - var cb = new Vector3(), ab = new Vector3(); + if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; - face = this.faces[ f ]; + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; + } - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + // convert ray to local space of mesh - vertices[ face.a ].add( cb ); - vertices[ face.b ].add( cb ); - vertices[ face.c ].add( cb ); + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); - } + // test with bounding box in local space - } else { + if ( geometry.boundingBox !== null ) { - this.computeFaceNormals(); + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + } - face = this.faces[ f ]; + // test for intersections with geometry - vertices[ face.a ].add( face.normal ); - vertices[ face.b ].add( face.normal ); - vertices[ face.c ].add( face.normal ); + this._computeIntersections( raycaster, intersects, _ray$3 ); - } + } - } + _computeIntersections( raycaster, intersects, rayLocalSpace ) { - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + let intersection; - vertices[ v ].normalize(); + const geometry = this.geometry; + const material = this.material; - } + const index = geometry.index; + const position = geometry.attributes.position; + const uv = geometry.attributes.uv; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; + const groups = geometry.groups; + const drawRange = geometry.drawRange; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + if ( index !== null ) { - face = this.faces[ f ]; + // indexed buffer geometry - var vertexNormals = face.vertexNormals; + if ( Array.isArray( material ) ) { - if ( vertexNormals.length === 3 ) { + for ( let i = 0, il = groups.length; i < il; i ++ ) { - vertexNormals[ 0 ].copy( vertices[ face.a ] ); - vertexNormals[ 1 ].copy( vertices[ face.b ] ); - vertexNormals[ 2 ].copy( vertices[ face.c ] ); + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - } else { + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); - vertexNormals[ 0 ] = vertices[ face.a ].clone(); - vertexNormals[ 1 ] = vertices[ face.b ].clone(); - vertexNormals[ 2 ] = vertices[ face.c ].clone(); + for ( let j = start, jl = end; j < jl; j += 3 ) { - } + const a = index.getX( j ); + const b = index.getX( j + 1 ); + const c = index.getX( j + 2 ); - } + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - if ( this.faces.length > 0 ) { + if ( intersection ) { - this.normalsNeedUpdate = true; + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); - } + } - }, + } - computeFlatVertexNormals: function () { + } - var f, fl, face; + } else { - this.computeFaceNormals(); + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + for ( let i = start, il = end; i < il; i += 3 ) { - face = this.faces[ f ]; + const a = index.getX( i ); + const b = index.getX( i + 1 ); + const c = index.getX( i + 2 ); - var vertexNormals = face.vertexNormals; + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - if ( vertexNormals.length === 3 ) { + if ( intersection ) { - vertexNormals[ 0 ].copy( face.normal ); - vertexNormals[ 1 ].copy( face.normal ); - vertexNormals[ 2 ].copy( face.normal ); + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics + intersects.push( intersection ); - } else { + } - vertexNormals[ 0 ] = face.normal.clone(); - vertexNormals[ 1 ] = face.normal.clone(); - vertexNormals[ 2 ] = face.normal.clone(); + } } - } + } else if ( position !== undefined ) { - if ( this.faces.length > 0 ) { + // non-indexed buffer geometry - this.normalsNeedUpdate = true; + if ( Array.isArray( material ) ) { - } + for ( let i = 0, il = groups.length; i < il; i ++ ) { - }, + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - computeMorphNormals: function () { + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); - var i, il, f, fl, face; + for ( let j = start, jl = end; j < jl; j += 3 ) { - // save original normals - // - create temp variables on first access - // otherwise just copy (for faster repeated calls) + const a = j; + const b = j + 1; + const c = j + 2; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - face = this.faces[ f ]; + if ( intersection ) { - if ( ! face.__originalFaceNormal ) { + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); - face.__originalFaceNormal = face.normal.clone(); + } - } else { + } - face.__originalFaceNormal.copy( face.normal ); + } - } + } else { - if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; + const start = Math.max( 0, drawRange.start ); + const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); - for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { + for ( let i = start, il = end; i < il; i += 3 ) { - if ( ! face.__originalVertexNormals[ i ] ) { + const a = i; + const b = i + 1; + const c = i + 2; - face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); - } else { + if ( intersection ) { + + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics + intersects.push( intersection ); - face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); + } } @@ -11852,5087 +11423,5573 @@ var ROS3D = (function (exports, ROSLIB) { } - // use temp geometry to compute face and vertex normals for each morph - - var tmpGeo = new Geometry(); - tmpGeo.faces = this.faces; - - for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { - - // create on first access - - if ( ! this.morphNormals[ i ] ) { + } - this.morphNormals[ i ] = {}; - this.morphNormals[ i ].faceNormals = []; - this.morphNormals[ i ].vertexNormals = []; + } - var dstNormalsFace = this.morphNormals[ i ].faceNormals; - var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; + function checkIntersection$1( object, material, raycaster, ray, pA, pB, pC, point ) { - var faceNormal, vertexNormals; + let intersect; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + if ( material.side === BackSide ) { - faceNormal = new Vector3(); - vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; + intersect = ray.intersectTriangle( pC, pB, pA, true, point ); - dstNormalsFace.push( faceNormal ); - dstNormalsVertex.push( vertexNormals ); + } else { - } + intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); - } + } - var morphNormals = this.morphNormals[ i ]; + if ( intersect === null ) return null; - // set vertices to morph target + _intersectionPointWorld.copy( point ); + _intersectionPointWorld.applyMatrix4( object.matrixWorld ); - tmpGeo.vertices = this.morphTargets[ i ].vertices; + const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); - // compute morph normals + if ( distance < raycaster.near || distance > raycaster.far ) return null; - tmpGeo.computeFaceNormals(); - tmpGeo.computeVertexNormals(); + return { + distance: distance, + point: _intersectionPointWorld.clone(), + object: object + }; - // store morph normals + } - var faceNormal, vertexNormals; + function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + object.getVertexPosition( a, _vA$1 ); + object.getVertexPosition( b, _vB$1 ); + object.getVertexPosition( c, _vC$1 ); - face = this.faces[ f ]; + const intersection = checkIntersection$1( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); - faceNormal = morphNormals.faceNormals[ f ]; - vertexNormals = morphNormals.vertexNormals[ f ]; + if ( intersection ) { - faceNormal.copy( face.normal ); + if ( uv ) { - vertexNormals.a.copy( face.vertexNormals[ 0 ] ); - vertexNormals.b.copy( face.vertexNormals[ 1 ] ); - vertexNormals.c.copy( face.vertexNormals[ 2 ] ); + _uvA$1.fromBufferAttribute( uv, a ); + _uvB$1.fromBufferAttribute( uv, b ); + _uvC$1.fromBufferAttribute( uv, c ); - } + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); } - // restore original normals + if ( uv1 ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + _uvA$1.fromBufferAttribute( uv1, a ); + _uvB$1.fromBufferAttribute( uv1, b ); + _uvC$1.fromBufferAttribute( uv1, c ); - face = this.faces[ f ]; - - face.normal = face.__originalFaceNormal; - face.vertexNormals = face.__originalVertexNormals; + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); } - }, - - computeLineDistances: function () { + if ( normal ) { - var d = 0; - var vertices = this.vertices; + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); - for ( var i = 0, il = vertices.length; i < il; i ++ ) { + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); - if ( i > 0 ) { + if ( intersection.normal.dot( ray.direction ) > 0 ) { - d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); + intersection.normal.multiplyScalar( - 1 ); } - this.lineDistances[ i ] = d; - } - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } + const face = { + a: a, + b: b, + c: c, + normal: new Vector3(), + materialIndex: 0 + }; - this.boundingBox.setFromPoints( this.vertices ); + Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); - }, + intersection.face = face; - computeBoundingSphere: function () { + } - if ( this.boundingSphere === null ) { + return intersection; - this.boundingSphere = new Sphere(); + } - } + class BoxGeometry extends BufferGeometry { - this.boundingSphere.setFromPoints( this.vertices ); + constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { - }, + super(); - merge: function ( geometry, matrix, materialIndexOffset ) { + this.type = 'BoxGeometry'; - if ( ! ( geometry && geometry.isGeometry ) ) { + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); - return; + const scope = this; - } + // segments - var normalMatrix, - vertexOffset = this.vertices.length, - vertices1 = this.vertices, - vertices2 = geometry.vertices, - faces1 = this.faces, - faces2 = geometry.faces, - uvs1 = this.faceVertexUvs[ 0 ], - uvs2 = geometry.faceVertexUvs[ 0 ], - colors1 = this.colors, - colors2 = geometry.colors; + widthSegments = Math.floor( widthSegments ); + heightSegments = Math.floor( heightSegments ); + depthSegments = Math.floor( depthSegments ); - if ( materialIndexOffset === undefined ) materialIndexOffset = 0; + // buffers - if ( matrix !== undefined ) { + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - normalMatrix = new Matrix3().getNormalMatrix( matrix ); + // helper variables - } + let numberOfVertices = 0; + let groupStart = 0; - // vertices + // build each side of the box geometry - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { + buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px + buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx + buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py + buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny + buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz + buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz - var vertex = vertices2[ i ]; + // build geometry - var vertexCopy = vertex.clone(); + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); + function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { - vertices1.push( vertexCopy ); + const segmentWidth = width / gridX; + const segmentHeight = height / gridY; - } + const widthHalf = width / 2; + const heightHalf = height / 2; + const depthHalf = depth / 2; - // colors + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; - for ( var i = 0, il = colors2.length; i < il; i ++ ) { + let vertexCounter = 0; + let groupCount = 0; - colors1.push( colors2[ i ].clone() ); + const vector = new Vector3(); - } + // generate vertices, normals and uvs - // faces + for ( let iy = 0; iy < gridY1; iy ++ ) { - for ( i = 0, il = faces2.length; i < il; i ++ ) { + const y = iy * segmentHeight - heightHalf; - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; + for ( let ix = 0; ix < gridX1; ix ++ ) { - faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - faceCopy.normal.copy( face.normal ); + const x = ix * segmentWidth - widthHalf; - if ( normalMatrix !== undefined ) { + // set values to correct vector component - faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); + vector[ u ] = x * udir; + vector[ v ] = y * vdir; + vector[ w ] = depthHalf; - } + // now apply vector to vertex buffer - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { + vertices.push( vector.x, vector.y, vector.z ); - normal = faceVertexNormals[ j ].clone(); + // set values to correct vector component - if ( normalMatrix !== undefined ) { + vector[ u ] = 0; + vector[ v ] = 0; + vector[ w ] = depth > 0 ? 1 : - 1; - normal.applyMatrix3( normalMatrix ).normalize(); + // now apply vector to normal buffer - } + normals.push( vector.x, vector.y, vector.z ); - faceCopy.vertexNormals.push( normal ); + // uvs - } + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - faceCopy.color.copy( face.color ); + // counters - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { + vertexCounter += 1; - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); + } } - faceCopy.materialIndex = face.materialIndex + materialIndexOffset; - - faces1.push( faceCopy ); + // indices - } + // 1. you need three indices to draw a single face + // 2. a single segment consists of two faces + // 3. so we need to generate six (2*3) indices per segment - // uvs + for ( let iy = 0; iy < gridY; iy ++ ) { - for ( i = 0, il = uvs2.length; i < il; i ++ ) { + for ( let ix = 0; ix < gridX; ix ++ ) { - var uv = uvs2[ i ], uvCopy = []; + const a = numberOfVertices + ix + gridX1 * iy; + const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); + const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; - if ( uv === undefined ) { + // faces - continue; + indices.push( a, b, d ); + indices.push( b, c, d ); - } + // increase counter - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { + groupCount += 6; - uvCopy.push( uv[ j ].clone() ); + } } - uvs1.push( uvCopy ); + // add a group to the geometry. this will ensure multi material support - } + scope.addGroup( groupStart, groupCount, materialIndex ); - }, + // calculate new start value for groups - mergeMesh: function ( mesh ) { + groupStart += groupCount; - if ( ! ( mesh && mesh.isMesh ) ) { + // update total number of vertices - console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); - return; + numberOfVertices += vertexCounter; } - mesh.matrixAutoUpdate && mesh.updateMatrix(); - - this.merge( mesh.geometry, mesh.matrix ); - - }, + } - /* - * Checks for duplicate vertices with hashmap. - * Duplicated vertices are removed - * and faces' vertices are updated. - */ + copy( source ) { - mergeVertices: function () { + super.copy( source ); - var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], changes = []; + this.parameters = Object.assign( {}, source.parameters ); - var v, key; - var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001 - var precision = Math.pow( 10, precisionPoints ); - var i, il, face; - var indices, j, jl; + return this; - for ( i = 0, il = this.vertices.length; i < il; i ++ ) { + } - v = this.vertices[ i ]; - key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); + static fromJSON( data ) { - if ( verticesMap[ key ] === undefined ) { + return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); - verticesMap[ key ] = i; - unique.push( this.vertices[ i ] ); - changes[ i ] = unique.length - 1; + } - } else { + } - //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); - changes[ i ] = changes[ verticesMap[ key ] ]; + /** + * Uniform Utilities + */ - } + function cloneUniforms( src ) { - } + const dst = {}; + for ( const u in src ) { - // if faces are completely degenerate after merging vertices, we - // have to remove them from the geometry. - var faceIndicesToRemove = []; + dst[ u ] = {}; - for ( i = 0, il = this.faces.length; i < il; i ++ ) { + for ( const p in src[ u ] ) { - face = this.faces[ i ]; + const property = src[ u ][ p ]; - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; + if ( property && ( property.isColor || + property.isMatrix3 || property.isMatrix4 || + property.isVector2 || property.isVector3 || property.isVector4 || + property.isTexture || property.isQuaternion ) ) { - indices = [ face.a, face.b, face.c ]; + if ( property.isRenderTargetTexture ) { - // if any duplicate vertices are found in a Face3 - // we have to remove the face as nothing can be saved - for ( var n = 0; n < 3; n ++ ) { + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; - if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { + } else { - faceIndicesToRemove.push( i ); - break; + dst[ u ][ p ] = property.clone(); } - } - - } - - for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { + } else if ( Array.isArray( property ) ) { - var idx = faceIndicesToRemove[ i ]; + dst[ u ][ p ] = property.slice(); - this.faces.splice( idx, 1 ); - - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { + } else { - this.faceVertexUvs[ j ].splice( idx, 1 ); + dst[ u ][ p ] = property; } } - // Use unique set of vertices - - var diff = this.vertices.length - unique.length; - this.vertices = unique; - return diff; + } - }, + return dst; - setFromPoints: function ( points ) { + } - this.vertices = []; + function mergeUniforms( uniforms ) { - for ( var i = 0, l = points.length; i < l; i ++ ) { + const merged = {}; - var point = points[ i ]; - this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); + for ( let u = 0; u < uniforms.length; u ++ ) { - } + const tmp = cloneUniforms( uniforms[ u ] ); - return this; + for ( const p in tmp ) { - }, + merged[ p ] = tmp[ p ]; - sortFacesByMaterialIndex: function () { + } - var faces = this.faces; - var length = faces.length; + } - // tag faces + return merged; - for ( var i = 0; i < length; i ++ ) { + } - faces[ i ]._id = i; + function cloneUniformsGroups( src ) { - } + const dst = []; - // sort faces + for ( let u = 0; u < src.length; u ++ ) { - function materialIndexSort( a, b ) { + dst.push( src[ u ].clone() ); - return a.materialIndex - b.materialIndex; + } - } + return dst; - faces.sort( materialIndexSort ); + } - // sort uvs + function getUnlitUniformColorSpace( renderer ) { - var uvs1 = this.faceVertexUvs[ 0 ]; - var uvs2 = this.faceVertexUvs[ 1 ]; + const currentRenderTarget = renderer.getRenderTarget(); - var newUvs1, newUvs2; + if ( currentRenderTarget === null ) { - if ( uvs1 && uvs1.length === length ) newUvs1 = []; - if ( uvs2 && uvs2.length === length ) newUvs2 = []; + // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 + return renderer.outputColorSpace; - for ( var i = 0; i < length; i ++ ) { + } - var id = faces[ i ]._id; + // https://github.com/mrdoob/three.js/issues/27868 + if ( currentRenderTarget.isXRRenderTarget === true ) { - if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); - if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); + return currentRenderTarget.texture.colorSpace; - } + } - if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; - if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; + return ColorManagement.workingColorSpace; - }, + } - toJSON: function () { + // Legacy - var data = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON' - } - }; + const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; - // standard Geometry serialization + var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; - if ( this.parameters !== undefined ) { + class ShaderMaterial extends Material { - var parameters = this.parameters; + constructor( parameters ) { - for ( var key in parameters ) { + super(); - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + this.isShaderMaterial = true; - } + this.type = 'ShaderMaterial'; - return data; + this.defines = {}; + this.uniforms = {}; + this.uniformsGroups = []; - } + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; - var vertices = []; + this.linewidth = 1; - for ( var i = 0; i < this.vertices.length; i ++ ) { + this.wireframe = false; + this.wireframeLinewidth = 1; - var vertex = this.vertices[ i ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + this.fog = false; // set to use scene fog + this.lights = false; // set to use scene lights + this.clipping = false; // set to use user-defined clipping planes - } + this.forceSinglePass = true; - var faces = []; - var normals = []; - var normalsHash = {}; - var colors = []; - var colorsHash = {}; - var uvs = []; - var uvsHash = {}; + this.extensions = { + clipCullDistance: false, // set to use vertex shader clipping + multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID + }; - for ( var i = 0; i < this.faces.length; i ++ ) { + // When rendered geometry doesn't include these attributes but the material does, + // use these default values in WebGL. This avoids errors when buffer data is missing. + this.defaultAttributeValues = { + 'color': [ 1, 1, 1 ], + 'uv': [ 0, 0 ], + 'uv1': [ 0, 0 ] + }; - var face = this.faces[ i ]; + this.index0AttributeName = undefined; + this.uniformsNeedUpdate = false; - var hasMaterial = true; - var hasFaceUv = false; // deprecated - var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined; - var hasFaceNormal = face.normal.length() > 0; - var hasFaceVertexNormal = face.vertexNormals.length > 0; - var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1; - var hasFaceVertexColor = face.vertexColors.length > 0; + this.glslVersion = null; - var faceType = 0; + if ( parameters !== undefined ) { - faceType = setBit( faceType, 0, 0 ); // isQuad - faceType = setBit( faceType, 1, hasMaterial ); - faceType = setBit( faceType, 2, hasFaceUv ); - faceType = setBit( faceType, 3, hasFaceVertexUv ); - faceType = setBit( faceType, 4, hasFaceNormal ); - faceType = setBit( faceType, 5, hasFaceVertexNormal ); - faceType = setBit( faceType, 6, hasFaceColor ); - faceType = setBit( faceType, 7, hasFaceVertexColor ); + this.setValues( parameters ); - faces.push( faceType ); - faces.push( face.a, face.b, face.c ); - faces.push( face.materialIndex ); + } - if ( hasFaceVertexUv ) { + } - var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; + copy( source ) { - faces.push( - getUvIndex( faceVertexUvs[ 0 ] ), - getUvIndex( faceVertexUvs[ 1 ] ), - getUvIndex( faceVertexUvs[ 2 ] ) - ); + super.copy( source ); - } + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; - if ( hasFaceNormal ) { + this.uniforms = cloneUniforms( source.uniforms ); + this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); - faces.push( getNormalIndex( face.normal ) ); + this.defines = Object.assign( {}, source.defines ); - } + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; - if ( hasFaceVertexNormal ) { + this.fog = source.fog; + this.lights = source.lights; + this.clipping = source.clipping; - var vertexNormals = face.vertexNormals; + this.extensions = Object.assign( {}, source.extensions ); - faces.push( - getNormalIndex( vertexNormals[ 0 ] ), - getNormalIndex( vertexNormals[ 1 ] ), - getNormalIndex( vertexNormals[ 2 ] ) - ); + this.glslVersion = source.glslVersion; - } + return this; - if ( hasFaceColor ) { + } - faces.push( getColorIndex( face.color ) ); + toJSON( meta ) { - } + const data = super.toJSON( meta ); - if ( hasFaceVertexColor ) { + data.glslVersion = this.glslVersion; + data.uniforms = {}; - var vertexColors = face.vertexColors; + for ( const name in this.uniforms ) { - faces.push( - getColorIndex( vertexColors[ 0 ] ), - getColorIndex( vertexColors[ 1 ] ), - getColorIndex( vertexColors[ 2 ] ) - ); + const uniform = this.uniforms[ name ]; + const value = uniform.value; - } + if ( value && value.isTexture ) { - } + data.uniforms[ name ] = { + type: 't', + value: value.toJSON( meta ).uuid + }; - function setBit( value, position, enabled ) { + } else if ( value && value.isColor ) { - return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); + data.uniforms[ name ] = { + type: 'c', + value: value.getHex() + }; - } + } else if ( value && value.isVector2 ) { - function getNormalIndex( normal ) { + data.uniforms[ name ] = { + type: 'v2', + value: value.toArray() + }; - var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); + } else if ( value && value.isVector3 ) { - if ( normalsHash[ hash ] !== undefined ) { + data.uniforms[ name ] = { + type: 'v3', + value: value.toArray() + }; - return normalsHash[ hash ]; + } else if ( value && value.isVector4 ) { - } + data.uniforms[ name ] = { + type: 'v4', + value: value.toArray() + }; - normalsHash[ hash ] = normals.length / 3; - normals.push( normal.x, normal.y, normal.z ); + } else if ( value && value.isMatrix3 ) { - return normalsHash[ hash ]; + data.uniforms[ name ] = { + type: 'm3', + value: value.toArray() + }; - } + } else if ( value && value.isMatrix4 ) { - function getColorIndex( color ) { + data.uniforms[ name ] = { + type: 'm4', + value: value.toArray() + }; - var hash = color.r.toString() + color.g.toString() + color.b.toString(); + } else { - if ( colorsHash[ hash ] !== undefined ) { + data.uniforms[ name ] = { + value: value + }; - return colorsHash[ hash ]; + // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far } - colorsHash[ hash ] = colors.length; - colors.push( color.getHex() ); - - return colorsHash[ hash ]; - } - function getUvIndex( uv ) { + if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; - var hash = uv.x.toString() + uv.y.toString(); + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; - if ( uvsHash[ hash ] !== undefined ) { + data.lights = this.lights; + data.clipping = this.clipping; - return uvsHash[ hash ]; - - } + const extensions = {}; - uvsHash[ hash ] = uvs.length / 2; - uvs.push( uv.x, uv.y ); + for ( const key in this.extensions ) { - return uvsHash[ hash ]; + if ( this.extensions[ key ] === true ) extensions[ key ] = true; } - data.data = {}; - - data.data.vertices = vertices; - data.data.normals = normals; - if ( colors.length > 0 ) data.data.colors = colors; - if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility - data.data.faces = faces; + if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; return data; - }, + } - clone: function () { + } - /* - // Handle primitives + class Camera extends Object3D { - var parameters = this.parameters; + constructor() { - if ( parameters !== undefined ) { + super(); - var values = []; + this.isCamera = true; - for ( var key in parameters ) { + this.type = 'Camera'; - values.push( parameters[ key ] ); + this.matrixWorldInverse = new Matrix4(); - } + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + this.coordinateSystem = WebGLCoordinateSystem; - } + } - return new this.constructor().copy( this ); - */ + copy( source, recursive ) { - return new Geometry().copy( this ); + super.copy( source, recursive ); - }, + this.matrixWorldInverse.copy( source.matrixWorldInverse ); - copy: function ( source ) { + this.projectionMatrix.copy( source.projectionMatrix ); + this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); - var i, il, j, jl, k, kl; + this.coordinateSystem = source.coordinateSystem; - // reset + return this; - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - this.morphTargets = []; - this.morphNormals = []; - this.skinWeights = []; - this.skinIndices = []; - this.lineDistances = []; - this.boundingBox = null; - this.boundingSphere = null; + } - // name + getWorldDirection( target ) { - this.name = source.name; + return super.getWorldDirection( target ).negate(); - // vertices + } - var vertices = source.vertices; + updateMatrixWorld( force ) { - for ( i = 0, il = vertices.length; i < il; i ++ ) { + super.updateMatrixWorld( force ); - this.vertices.push( vertices[ i ].clone() ); + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); - } + } - // colors + updateWorldMatrix( updateParents, updateChildren ) { - var colors = source.colors; + super.updateWorldMatrix( updateParents, updateChildren ); - for ( i = 0, il = colors.length; i < il; i ++ ) { + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); - this.colors.push( colors[ i ].clone() ); + } - } + clone() { - // faces + return new this.constructor().copy( this ); - var faces = source.faces; + } - for ( i = 0, il = faces.length; i < il; i ++ ) { + } - this.faces.push( faces[ i ].clone() ); + const _v3$1 = /*@__PURE__*/ new Vector3(); + const _minTarget = /*@__PURE__*/ new Vector2(); + const _maxTarget = /*@__PURE__*/ new Vector2(); - } - // face vertex uvs + class PerspectiveCamera extends Camera { - for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { + constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { - var faceVertexUvs = source.faceVertexUvs[ i ]; + super(); - if ( this.faceVertexUvs[ i ] === undefined ) { + this.isPerspectiveCamera = true; - this.faceVertexUvs[ i ] = []; + this.type = 'PerspectiveCamera'; - } + this.fov = fov; + this.zoom = 1; - for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { + this.near = near; + this.far = far; + this.focus = 10; - var uvs = faceVertexUvs[ j ], uvsCopy = []; + this.aspect = aspect; + this.view = null; - for ( k = 0, kl = uvs.length; k < kl; k ++ ) { + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - var uv = uvs[ k ]; + this.updateProjectionMatrix(); - uvsCopy.push( uv.clone() ); + } - } + copy( source, recursive ) { - this.faceVertexUvs[ i ].push( uvsCopy ); + super.copy( source, recursive ); - } + this.fov = source.fov; + this.zoom = source.zoom; - } + this.near = source.near; + this.far = source.far; + this.focus = source.focus; - // morph targets + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - var morphTargets = source.morphTargets; + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; - for ( i = 0, il = morphTargets.length; i < il; i ++ ) { + return this; - var morphTarget = {}; - morphTarget.name = morphTargets[ i ].name; + } - // vertices + /** + * Sets the FOV by focal length in respect to the current .filmGauge. + * + * The default film gauge is 35, so that the focal length can be specified for + * a 35mm (full frame) camera. + * + * Values for focal length and film gauge must have the same unit. + */ + setFocalLength( focalLength ) { - if ( morphTargets[ i ].vertices !== undefined ) { + /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ + const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - morphTarget.vertices = []; + this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.updateProjectionMatrix(); - for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { + } - morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); + /** + * Calculates the focal length from the current .fov and .filmGauge. + */ + getFocalLength() { - } + const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); - } + return 0.5 * this.getFilmHeight() / vExtentSlope; - // normals + } - if ( morphTargets[ i ].normals !== undefined ) { + getEffectiveFOV() { - morphTarget.normals = []; + return RAD2DEG * 2 * Math.atan( + Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); - for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { + } - morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); + getFilmWidth() { - } + // film not completely covered in portrait format (aspect < 1) + return this.filmGauge * Math.min( this.aspect, 1 ); - } + } - this.morphTargets.push( morphTarget ); + getFilmHeight() { - } + // film not completely covered in landscape format (aspect > 1) + return this.filmGauge / Math.max( this.aspect, 1 ); - // morph normals + } - var morphNormals = source.morphNormals; + /** + * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction. + * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle. + */ + getViewBounds( distance, minTarget, maxTarget ) { - for ( i = 0, il = morphNormals.length; i < il; i ++ ) { + _v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); - var morphNormal = {}; + minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); - // vertex normals + _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); - if ( morphNormals[ i ].vertexNormals !== undefined ) { + maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); - morphNormal.vertexNormals = []; + } - for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { + /** + * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction. + * Copies the result into the target Vector2, where x is width and y is height. + */ + getViewSize( distance, target ) { - var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; - var destVertexNormal = {}; + this.getViewBounds( distance, _minTarget, _maxTarget ); - destVertexNormal.a = srcVertexNormal.a.clone(); - destVertexNormal.b = srcVertexNormal.b.clone(); - destVertexNormal.c = srcVertexNormal.c.clone(); + return target.subVectors( _maxTarget, _minTarget ); - morphNormal.vertexNormals.push( destVertexNormal ); + } - } + /** + * Sets an offset in a larger frustum. This is useful for multi-window or + * multi-monitor/multi-machine setups. + * + * For example, if you have 3x2 monitors and each monitor is 1920x1080 and + * the monitors are in grid like this + * + * +---+---+---+ + * | A | B | C | + * +---+---+---+ + * | D | E | F | + * +---+---+---+ + * + * then for each monitor you would call it like this + * + * const w = 1920; + * const h = 1080; + * const fullWidth = w * 3; + * const fullHeight = h * 2; + * + * --A-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); + * --B-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); + * --C-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); + * --D-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); + * --E-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); + * --F-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); + * + * Note there is no reason monitors have to be the same size or in a grid. + */ + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - } + this.aspect = fullWidth / fullHeight; + + if ( this.view === null ) { - // face normals + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - if ( morphNormals[ i ].faceNormals !== undefined ) { + } - morphNormal.faceNormals = []; + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { + this.updateProjectionMatrix(); - morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); + } - } + clearViewOffset() { - } + if ( this.view !== null ) { - this.morphNormals.push( morphNormal ); + this.view.enabled = false; } - // skin weights + this.updateProjectionMatrix(); + + } + + updateProjectionMatrix() { - var skinWeights = source.skinWeights; + 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 ) { - for ( i = 0, il = skinWeights.length; i < il; i ++ ) { + const fullWidth = view.fullWidth, + fullHeight = view.fullHeight; - this.skinWeights.push( skinWeights[ i ].clone() ); + left += view.offsetX * width / fullWidth; + top -= view.offsetY * height / fullHeight; + width *= view.width / fullWidth; + height *= view.height / fullHeight; } - // skin indices + const skew = this.filmOffset; + if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); - var skinIndices = source.skinIndices; + this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); - for ( i = 0, il = skinIndices.length; i < il; i ++ ) { + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - this.skinIndices.push( skinIndices[ i ].clone() ); + } - } + toJSON( meta ) { - // line distances + const data = super.toJSON( meta ); - var lineDistances = source.lineDistances; + data.object.fov = this.fov; + data.object.zoom = this.zoom; - for ( i = 0, il = lineDistances.length; i < il; i ++ ) { + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; - this.lineDistances.push( lineDistances[ i ] ); + data.object.aspect = this.aspect; - } + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - // bounding box + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; - var boundingBox = source.boundingBox; + return data; - if ( boundingBox !== null ) { + } - this.boundingBox = boundingBox.clone(); + } - } + const fov = - 90; // negative fov is not an error + const aspect = 1; - // bounding sphere + class CubeCamera extends Object3D { - var boundingSphere = source.boundingSphere; + constructor( near, far, renderTarget ) { - if ( boundingSphere !== null ) { + super(); - this.boundingSphere = boundingSphere.clone(); + this.type = 'CubeCamera'; - } + this.renderTarget = renderTarget; + this.coordinateSystem = null; + this.activeMipmapLevel = 0; - // update flags + const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); + cameraPX.layers = this.layers; + this.add( cameraPX ); - this.elementsNeedUpdate = source.elementsNeedUpdate; - this.verticesNeedUpdate = source.verticesNeedUpdate; - this.uvsNeedUpdate = source.uvsNeedUpdate; - this.normalsNeedUpdate = source.normalsNeedUpdate; - this.colorsNeedUpdate = source.colorsNeedUpdate; - this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate; - this.groupsNeedUpdate = source.groupsNeedUpdate; + const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); + cameraNX.layers = this.layers; + this.add( cameraNX ); - return this; + const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); + cameraPY.layers = this.layers; + this.add( cameraPY ); - }, + const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); + cameraNY.layers = this.layers; + this.add( cameraNY ); - dispose: function () { + const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraPZ.layers = this.layers; + this.add( cameraPZ ); - this.dispatchEvent( { type: 'dispose' } ); + const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraNZ.layers = this.layers; + this.add( cameraNZ ); } - } ); + updateCoordinateSystem() { - /** - * @author mrdoob / http://mrdoob.com/ - */ + const coordinateSystem = this.coordinateSystem; - function BufferAttribute( array, itemSize, normalized ) { + const cameras = this.children.concat(); - if ( Array.isArray( array ) ) { + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } + for ( const camera of cameras ) this.remove( camera ); - this.uuid = _Math.generateUUID(); - this.name = ''; + if ( coordinateSystem === WebGLCoordinateSystem ) { - this.array = array; - this.itemSize = itemSize; - this.count = array !== undefined ? array.length / itemSize : 0; - this.normalized = normalized === true; + cameraPX.up.set( 0, 1, 0 ); + cameraPX.lookAt( 1, 0, 0 ); - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; + cameraNX.up.set( 0, 1, 0 ); + cameraNX.lookAt( - 1, 0, 0 ); - this.onUploadCallback = function () {}; + cameraPY.up.set( 0, 0, - 1 ); + cameraPY.lookAt( 0, 1, 0 ); - this.version = 0; + cameraNY.up.set( 0, 0, 1 ); + cameraNY.lookAt( 0, - 1, 0 ); - } + cameraPZ.up.set( 0, 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); - Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { + cameraNZ.up.set( 0, 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); - set: function ( value ) { + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - if ( value === true ) this.version ++; + cameraPX.up.set( 0, - 1, 0 ); + cameraPX.lookAt( - 1, 0, 0 ); - } + cameraNX.up.set( 0, - 1, 0 ); + cameraNX.lookAt( 1, 0, 0 ); - } ); + cameraPY.up.set( 0, 0, 1 ); + cameraPY.lookAt( 0, 1, 0 ); - Object.assign( BufferAttribute.prototype, { + cameraNY.up.set( 0, 0, - 1 ); + cameraNY.lookAt( 0, - 1, 0 ); - isBufferAttribute: true, + cameraPZ.up.set( 0, - 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); - setArray: function ( array ) { + cameraNZ.up.set( 0, - 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); - if ( Array.isArray( array ) ) { + } else { - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); } - this.count = array !== undefined ? array.length / this.itemSize : 0; - this.array = array; + for ( const camera of cameras ) { - }, + this.add( camera ); - setDynamic: function ( value ) { + camera.updateMatrixWorld(); - this.dynamic = value; + } - return this; + } - }, + update( renderer, scene ) { - copy: function ( source ) { + if ( this.parent === null ) this.updateMatrixWorld(); - this.array = new source.array.constructor( source.array ); - this.itemSize = source.itemSize; - this.count = source.count; - this.normalized = source.normalized; + const { renderTarget, activeMipmapLevel } = this; - this.dynamic = source.dynamic; + if ( this.coordinateSystem !== renderer.coordinateSystem ) { - return this; + this.coordinateSystem = renderer.coordinateSystem; - }, + this.updateCoordinateSystem(); - copyAt: function ( index1, attribute, index2 ) { + } - index1 *= this.itemSize; - index2 *= attribute.itemSize; + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; - for ( var i = 0, l = this.itemSize; i < l; i ++ ) { + const currentRenderTarget = renderer.getRenderTarget(); + const currentActiveCubeFace = renderer.getActiveCubeFace(); + const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); - this.array[ index1 + i ] = attribute.array[ index2 + i ]; + const currentXrEnabled = renderer.xr.enabled; - } + renderer.xr.enabled = false; - return this; + const generateMipmaps = renderTarget.texture.generateMipmaps; - }, + renderTarget.texture.generateMipmaps = false; - copyArray: function ( array ) { + renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); + renderer.render( scene, cameraPX ); - this.array.set( array ); + renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); + renderer.render( scene, cameraNX ); - return this; + renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); + renderer.render( scene, cameraPY ); - }, + renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); + renderer.render( scene, cameraNY ); - copyColorsArray: function ( colors ) { + renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); + renderer.render( scene, cameraPZ ); - var array = this.array, offset = 0; + // mipmaps are generated during the last call of render() + // at this point, all sides of the cube render target are defined - for ( var i = 0, l = colors.length; i < l; i ++ ) { + renderTarget.texture.generateMipmaps = generateMipmaps; - var color = colors[ i ]; + renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); + renderer.render( scene, cameraNZ ); - if ( color === undefined ) { + renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); - console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); - color = new Color(); + renderer.xr.enabled = currentXrEnabled; - } + renderTarget.texture.needsPMREMUpdate = true; - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; + } - } + } - return this; + class CubeTexture extends Texture { - }, + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { - copyIndicesArray: function ( indices ) { + images = images !== undefined ? images : []; + mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - var array = this.array, offset = 0; + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); - for ( var i = 0, l = indices.length; i < l; i ++ ) { + this.isCubeTexture = true; - var index = indices[ i ]; + this.flipY = false; - array[ offset ++ ] = index.a; - array[ offset ++ ] = index.b; - array[ offset ++ ] = index.c; + } - } + get images() { - return this; + return this.image; - }, + } - copyVector2sArray: function ( vectors ) { + set images( value ) { - var array = this.array, offset = 0; + this.image = value; - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + } - var vector = vectors[ i ]; + } - if ( vector === undefined ) { + class WebGLCubeRenderTarget extends WebGLRenderTarget { - console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); - vector = new Vector2(); + constructor( size = 1, options = {} ) { - } + super( size, size, options ); - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; + this.isWebGLCubeRenderTarget = true; - } + const image = { width: size, height: size, depth: 1 }; + const images = [ image, image, image, image, image, image ]; - return this; + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); - }, + // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) + // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, + // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. - copyVector3sArray: function ( vectors ) { + // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped + // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture + // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). - var array = this.array, offset = 0; + this.texture.isRenderTargetTexture = true; - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - var vector = vectors[ i ]; + } - if ( vector === undefined ) { + fromEquirectangularTexture( renderer, texture ) { - console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); - vector = new Vector3(); + this.texture.type = texture.type; + this.texture.colorSpace = texture.colorSpace; - } + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; + const shader = { - } + uniforms: { + tEquirect: { value: null }, + }, - return this; + vertexShader: /* glsl */` - }, + varying vec3 vWorldDirection; - copyVector4sArray: function ( vectors ) { + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { - var array = this.array, offset = 0; + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + } - var vector = vectors[ i ]; + void main() { - if ( vector === undefined ) { + vWorldDirection = transformDirection( position, modelMatrix ); - console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); - vector = new Vector4(); + #include + #include } + `, - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; + fragmentShader: /* glsl */` - } + uniform sampler2D tEquirect; - return this; + varying vec3 vWorldDirection; - }, + #include - set: function ( value, offset ) { + void main() { - if ( offset === undefined ) offset = 0; + vec3 direction = normalize( vWorldDirection ); - this.array.set( value, offset ); + vec2 sampleUV = equirectUv( direction ); - return this; + gl_FragColor = texture2D( tEquirect, sampleUV ); - }, + } + ` + }; - getX: function ( index ) { + const geometry = new BoxGeometry( 5, 5, 5 ); - return this.array[ index * this.itemSize ]; + const material = new ShaderMaterial( { - }, + name: 'CubemapFromEquirect', - setX: function ( index, x ) { + uniforms: cloneUniforms( shader.uniforms ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide, + blending: NoBlending - this.array[ index * this.itemSize ] = x; + } ); - return this; + material.uniforms.tEquirect.value = texture; - }, + const mesh = new Mesh( geometry, material ); - getY: function ( index ) { + const currentMinFilter = texture.minFilter; - return this.array[ index * this.itemSize + 1 ]; + // Avoid blurred poles + if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; - }, + const camera = new CubeCamera( 1, 10, this ); + camera.update( renderer, mesh ); - setY: function ( index, y ) { + texture.minFilter = currentMinFilter; - this.array[ index * this.itemSize + 1 ] = y; + mesh.geometry.dispose(); + mesh.material.dispose(); return this; - }, + } - getZ: function ( index ) { + clear( renderer, color, depth, stencil ) { - return this.array[ index * this.itemSize + 2 ]; + const currentRenderTarget = renderer.getRenderTarget(); - }, + for ( let i = 0; i < 6; i ++ ) { - setZ: function ( index, z ) { + renderer.setRenderTarget( this, i ); - this.array[ index * this.itemSize + 2 ] = z; + renderer.clear( color, depth, stencil ); - return this; + } - }, + renderer.setRenderTarget( currentRenderTarget ); - getW: function ( index ) { + } - return this.array[ index * this.itemSize + 3 ]; + } - }, + const _vector1 = /*@__PURE__*/ new Vector3(); + const _vector2 = /*@__PURE__*/ new Vector3(); + const _normalMatrix = /*@__PURE__*/ new Matrix3(); - setW: function ( index, w ) { + class Plane { - this.array[ index * this.itemSize + 3 ] = w; + constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { - return this; + this.isPlane = true; - }, + // normal is assumed to be normalized - setXY: function ( index, x, y ) { + this.normal = normal; + this.constant = constant; - index *= this.itemSize; + } - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; + set( normal, constant ) { + + this.normal.copy( normal ); + this.constant = constant; return this; - }, + } - setXYZ: function ( index, x, y, z ) { + setComponents( x, y, z, w ) { - index *= this.itemSize; + this.normal.set( x, y, z ); + this.constant = w; - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; + return this; + + } + + setFromNormalAndCoplanarPoint( normal, point ) { + + this.normal.copy( normal ); + this.constant = - point.dot( this.normal ); return this; - }, + } - setXYZW: function ( index, x, y, z, w ) { + setFromCoplanarPoints( a, b, c ) { - index *= this.itemSize; + const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - this.array[ index + 3 ] = w; + // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? + + this.setFromNormalAndCoplanarPoint( normal, a ); return this; - }, + } - onUpload: function ( callback ) { + copy( plane ) { - this.onUploadCallback = callback; + this.normal.copy( plane.normal ); + this.constant = plane.constant; return this; - }, + } - clone: function () { + normalize() { - return new this.constructor( this.array, this.itemSize ).copy( this ); + // Note: will lead to a divide by zero if the plane is invalid. + + const inverseNormalLength = 1.0 / this.normal.length(); + this.normal.multiplyScalar( inverseNormalLength ); + this.constant *= inverseNormalLength; + + return this; } - } ); + negate() { - // + this.constant *= - 1; + this.normal.negate(); - function Int8BufferAttribute( array, itemSize, normalized ) { + return this; - BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized ); + } - } + distanceToPoint( point ) { - Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; + return this.normal.dot( point ) + this.constant; + } - function Uint8BufferAttribute( array, itemSize, normalized ) { + distanceToSphere( sphere ) { - BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized ); + return this.distanceToPoint( sphere.center ) - sphere.radius; - } + } - Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; + projectPoint( point, target ) { + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); - function Uint8ClampedBufferAttribute( array, itemSize, normalized ) { + } - BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized ); + intersectLine( line, target ) { - } + const direction = line.delta( _vector1 ); - Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; + const denominator = this.normal.dot( direction ); + if ( denominator === 0 ) { - function Int16BufferAttribute( array, itemSize, normalized ) { + // line is coplanar, return origin + if ( this.distanceToPoint( line.start ) === 0 ) { - BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized ); + return target.copy( line.start ); - } + } - Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; + // Unsure if this is the correct method to handle this case. + return null; + } - function Uint16BufferAttribute( array, itemSize, normalized ) { + const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); + if ( t < 0 || t > 1 ) { - } + return null; - Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; + } + return target.copy( line.start ).addScaledVector( direction, t ); - function Int32BufferAttribute( array, itemSize, normalized ) { + } - BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized ); + intersectsLine( line ) { - } + // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. - Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; + const startSign = this.distanceToPoint( line.start ); + const endSign = this.distanceToPoint( line.end ); + return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); - function Uint32BufferAttribute( array, itemSize, normalized ) { + } - BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized ); + intersectsBox( box ) { - } + return box.intersectsPlane( this ); - Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; + } + intersectsSphere( sphere ) { - function Float32BufferAttribute( array, itemSize, normalized ) { + return sphere.intersectsPlane( this ); - BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized ); + } - } + coplanarPoint( target ) { - Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; + return target.copy( this.normal ).multiplyScalar( - this.constant ); + } - function Float64BufferAttribute( array, itemSize, normalized ) { + applyMatrix4( matrix, optionalNormalMatrix ) { - BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized ); + const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); - } + const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); - Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; + const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - /** - * @author mrdoob / http://mrdoob.com/ - */ + this.constant = - referencePoint.dot( normal ); - function DirectGeometry() { + return this; - this.indices = []; - this.vertices = []; - this.normals = []; - this.colors = []; - this.uvs = []; - this.uvs2 = []; + } - this.groups = []; + translate( offset ) { - this.morphTargets = {}; + this.constant -= offset.dot( this.normal ); - this.skinWeights = []; - this.skinIndices = []; + return this; - // this.lineDistances = []; + } - this.boundingBox = null; - this.boundingSphere = null; + equals( plane ) { - // update flags + return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); - this.verticesNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.uvsNeedUpdate = false; - this.groupsNeedUpdate = false; + } - } + clone() { - Object.assign( DirectGeometry.prototype, { + return new this.constructor().copy( this ); - computeGroups: function ( geometry ) { + } - var group; - var groups = []; - var materialIndex = undefined; + } - var faces = geometry.faces; + const _sphere$5 = /*@__PURE__*/ new Sphere(); + const _vector$7 = /*@__PURE__*/ new Vector3(); - for ( var i = 0; i < faces.length; i ++ ) { + class Frustum { - var face = faces[ i ]; + constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { - // materials + this.planes = [ p0, p1, p2, p3, p4, p5 ]; - if ( face.materialIndex !== materialIndex ) { + } - materialIndex = face.materialIndex; + set( p0, p1, p2, p3, p4, p5 ) { - if ( group !== undefined ) { + const planes = this.planes; - group.count = ( i * 3 ) - group.start; - groups.push( group ); + 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; - group = { - start: i * 3, - materialIndex: materialIndex - }; + } - } + copy( frustum ) { - } + const planes = this.planes; - if ( group !== undefined ) { + for ( let i = 0; i < 6; i ++ ) { - group.count = ( i * 3 ) - group.start; - groups.push( group ); + planes[ i ].copy( frustum.planes[ i ] ); } - this.groups = groups; - - }, + return this; - fromGeometry: function ( geometry ) { + } - var faces = geometry.faces; - var vertices = geometry.vertices; - var faceVertexUvs = geometry.faceVertexUvs; + setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { - var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; + const planes = this.planes; + const me = m.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 ]; - // morphs + 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(); - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; + if ( coordinateSystem === WebGLCoordinateSystem ) { - var morphTargetsPosition; + planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); - if ( morphTargetsLength > 0 ) { + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - morphTargetsPosition = []; + planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); - for ( var i = 0; i < morphTargetsLength; i ++ ) { + } else { - morphTargetsPosition[ i ] = []; + throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); - } + } - this.morphTargets.position = morphTargetsPosition; + return this; - } + } - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; + intersectsObject( object ) { - var morphTargetsNormal; + if ( object.boundingSphere !== undefined ) { - if ( morphNormalsLength > 0 ) { + if ( object.boundingSphere === null ) object.computeBoundingSphere(); - morphTargetsNormal = []; + _sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); - for ( var i = 0; i < morphNormalsLength; i ++ ) { + } else { - morphTargetsNormal[ i ] = []; + const geometry = object.geometry; - } + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - this.morphTargets.normal = morphTargetsNormal; + _sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); } - // skins - - var skinIndices = geometry.skinIndices; - var skinWeights = geometry.skinWeights; + return this.intersectsSphere( _sphere$5 ); - var hasSkinIndices = skinIndices.length === vertices.length; - var hasSkinWeights = skinWeights.length === vertices.length; + } - // + intersectsSprite( sprite ) { - for ( var i = 0; i < faces.length; i ++ ) { + _sphere$5.center.set( 0, 0, 0 ); + _sphere$5.radius = 0.7071067811865476; + _sphere$5.applyMatrix4( sprite.matrixWorld ); - var face = faces[ i ]; + return this.intersectsSphere( _sphere$5 ); - this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); + } - var vertexNormals = face.vertexNormals; + intersectsSphere( sphere ) { - if ( vertexNormals.length === 3 ) { + const planes = this.planes; + const center = sphere.center; + const negRadius = - sphere.radius; - this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); + for ( let i = 0; i < 6; i ++ ) { - } else { + const distance = planes[ i ].distanceToPoint( center ); - var normal = face.normal; + if ( distance < negRadius ) { - this.normals.push( normal, normal, normal ); + return false; } - var vertexColors = face.vertexColors; - - if ( vertexColors.length === 3 ) { - - this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - - } else { - - var color = face.color; + } - this.colors.push( color, color, color ); + return true; - } + } - if ( hasFaceVertexUv === true ) { + intersectsBox( box ) { - var vertexUvs = faceVertexUvs[ 0 ][ i ]; + const planes = this.planes; - if ( vertexUvs !== undefined ) { + for ( let i = 0; i < 6; i ++ ) { - this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + const plane = planes[ i ]; - } else { + // corner at max distance - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', 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; - this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); + if ( plane.distanceToPoint( _vector$7 ) < 0 ) { - } + return false; } - if ( hasFaceVertexUv2 === true ) { + } - var vertexUvs = faceVertexUvs[ 1 ][ i ]; + return true; - if ( vertexUvs !== undefined ) { + } - this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + containsPoint( point ) { - } else { + const planes = this.planes; - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); + for ( let i = 0; i < 6; i ++ ) { - this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); + if ( planes[ i ].distanceToPoint( point ) < 0 ) { - } + return false; } - // morphs + } - for ( var j = 0; j < morphTargetsLength; j ++ ) { + return true; - var morphTarget = morphTargets[ j ].vertices; + } - morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); + clone() { - } + return new this.constructor().copy( this ); - for ( var j = 0; j < morphNormalsLength; j ++ ) { + } - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; + } - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); + function WebGLAnimation() { - } + let context = null; + let isAnimating = false; + let animationLoop = null; + let requestId = null; - // skins + function onAnimationFrame( time, frame ) { - if ( hasSkinIndices ) { + animationLoop( time, frame ); - this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); + requestId = context.requestAnimationFrame( onAnimationFrame ); - } + } - if ( hasSkinWeights ) { + return { - this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); + start: function () { - } + if ( isAnimating === true ) return; + if ( animationLoop === null ) return; - } + requestId = context.requestAnimationFrame( onAnimationFrame ); - this.computeGroups( geometry ); + isAnimating = true; - this.verticesNeedUpdate = geometry.verticesNeedUpdate; - this.normalsNeedUpdate = geometry.normalsNeedUpdate; - this.colorsNeedUpdate = geometry.colorsNeedUpdate; - this.uvsNeedUpdate = geometry.uvsNeedUpdate; - this.groupsNeedUpdate = geometry.groupsNeedUpdate; + }, - return this; + stop: function () { - } + context.cancelAnimationFrame( requestId ); - } ); + isAnimating = false; - /** - * @author mrdoob / http://mrdoob.com/ - */ + }, - function arrayMax( array ) { + setAnimationLoop: function ( callback ) { - if ( array.length === 0 ) return - Infinity; + animationLoop = callback; - var max = array[ 0 ]; + }, - for ( var i = 1, l = array.length; i < l; ++ i ) { + setContext: function ( value ) { - if ( array[ i ] > max ) max = array[ i ]; + context = value; - } + } - return max; + }; } - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + function WebGLAttributes( gl ) { - var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id + const buffers = new WeakMap(); - function BufferGeometry() { + function createBuffer( attribute, bufferType ) { - Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } ); + const array = attribute.array; + const usage = attribute.usage; + const size = array.byteLength; - this.uuid = _Math.generateUUID(); + const buffer = gl.createBuffer(); - this.name = ''; - this.type = 'BufferGeometry'; + gl.bindBuffer( bufferType, buffer ); + gl.bufferData( bufferType, array, usage ); - this.index = null; - this.attributes = {}; + attribute.onUploadCallback(); - this.morphAttributes = {}; + let type; - this.groups = []; + if ( array instanceof Float32Array ) { - this.boundingBox = null; - this.boundingSphere = null; + type = gl.FLOAT; - this.drawRange = { start: 0, count: Infinity }; + } else if ( array instanceof Uint16Array ) { - } + if ( attribute.isFloat16BufferAttribute ) { - BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + type = gl.HALF_FLOAT; - constructor: BufferGeometry, + } else { - isBufferGeometry: true, + type = gl.UNSIGNED_SHORT; - getIndex: function () { + } - return this.index; + } else if ( array instanceof Int16Array ) { - }, + type = gl.SHORT; - setIndex: function ( index ) { + } else if ( array instanceof Uint32Array ) { - if ( Array.isArray( index ) ) { + type = gl.UNSIGNED_INT; - this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); + } else if ( array instanceof Int32Array ) { - } else { + type = gl.INT; - this.index = index; + } else if ( array instanceof Int8Array ) { - } + type = gl.BYTE; - }, + } else if ( array instanceof Uint8Array ) { - addAttribute: function ( name, attribute ) { + type = gl.UNSIGNED_BYTE; - if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { + } else if ( array instanceof Uint8ClampedArray ) { - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); + type = gl.UNSIGNED_BYTE; - this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); + } else { - return; + throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); } - if ( name === 'index' ) { - - console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); - this.setIndex( attribute ); - - return; + return { + buffer: buffer, + type: type, + bytesPerElement: array.BYTES_PER_ELEMENT, + version: attribute.version, + size: size + }; - } + } - this.attributes[ name ] = attribute; + function updateBuffer( buffer, attribute, bufferType ) { - return this; + const array = attribute.array; + const updateRange = attribute._updateRange; // @deprecated, r159 + const updateRanges = attribute.updateRanges; - }, + gl.bindBuffer( bufferType, buffer ); - getAttribute: function ( name ) { + if ( updateRange.count === - 1 && updateRanges.length === 0 ) { - return this.attributes[ name ]; + // Not using update ranges + gl.bufferSubData( bufferType, 0, array ); - }, + } - removeAttribute: function ( name ) { + if ( updateRanges.length !== 0 ) { - delete this.attributes[ name ]; + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { - return this; + const range = updateRanges[ i ]; - }, + gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, + array, range.start, range.count ); - addGroup: function ( start, count, materialIndex ) { + } - this.groups.push( { + attribute.clearUpdateRanges(); - start: start, - count: count, - materialIndex: materialIndex !== undefined ? materialIndex : 0 + } - } ); + // @deprecated, r159 + if ( updateRange.count !== - 1 ) { - }, + gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, + array, updateRange.offset, updateRange.count ); - clearGroups: function () { + updateRange.count = - 1; // reset range - this.groups = []; + } - }, + attribute.onUploadCallback(); - setDrawRange: function ( start, count ) { + } - this.drawRange.start = start; - this.drawRange.count = count; + // - }, + function get( attribute ) { - applyMatrix: function ( matrix ) { + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - var position = this.attributes.position; + return buffers.get( attribute ); - if ( position !== undefined ) { + } - matrix.applyToBufferAttribute( position ); - position.needsUpdate = true; + function remove( attribute ) { - } + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - var normal = this.attributes.normal; + const data = buffers.get( attribute ); - if ( normal !== undefined ) { + if ( data ) { - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); + gl.deleteBuffer( data.buffer ); - normalMatrix.applyToBufferAttribute( normal ); - normal.needsUpdate = true; + buffers.delete( attribute ); } - if ( this.boundingBox !== null ) { + } - this.computeBoundingBox(); + function update( attribute, bufferType ) { - } + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - if ( this.boundingSphere !== null ) { + if ( attribute.isGLBufferAttribute ) { - this.computeBoundingSphere(); + const cached = buffers.get( attribute ); - } + if ( ! cached || cached.version < attribute.version ) { - return this; + buffers.set( attribute, { + buffer: attribute.buffer, + type: attribute.type, + bytesPerElement: attribute.elementSize, + version: attribute.version + } ); - }, + } - rotateX: function () { + return; - // rotate geometry around world x-axis + } - var m1 = new Matrix4(); + const data = buffers.get( attribute ); - return function rotateX( angle ) { + if ( data === undefined ) { - m1.makeRotationX( angle ); + buffers.set( attribute, createBuffer( attribute, bufferType ) ); - this.applyMatrix( m1 ); + } else if ( data.version < attribute.version ) { - return this; + if ( data.size !== attribute.array.byteLength ) { - }; + throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' ); - }(), + } - rotateY: function () { + updateBuffer( data.buffer, attribute, bufferType ); - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); + data.version = attribute.version; - return this; + } - }; + } - }(), + return { - rotateZ: function () { + get: get, + remove: remove, + update: update - // rotate geometry around world z-axis + }; - var m1 = new Matrix4(); + } - return function rotateZ( angle ) { + class PlaneGeometry extends BufferGeometry { - m1.makeRotationZ( angle ); + constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { - this.applyMatrix( m1 ); + super(); - return this; + this.type = 'PlaneGeometry'; + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments }; - }(), + const width_half = width / 2; + const height_half = height / 2; - translate: function () { + const gridX = Math.floor( widthSegments ); + const gridY = Math.floor( heightSegments ); - // translate geometry + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; - var m1 = new Matrix4(); + const segment_width = width / gridX; + const segment_height = height / gridY; - return function translate( x, y, z ) { + // - m1.makeTranslation( x, y, z ); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - this.applyMatrix( m1 ); + for ( let iy = 0; iy < gridY1; iy ++ ) { - return this; + const y = iy * segment_height - height_half; - }; + for ( let ix = 0; ix < gridX1; ix ++ ) { - }(), + const x = ix * segment_width - width_half; - scale: function () { + vertices.push( x, - y, 0 ); - // scale geometry + normals.push( 0, 0, 1 ); - var m1 = new Matrix4(); + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - return function scale( x, y, z ) { + } - m1.makeScale( x, y, z ); + } - this.applyMatrix( m1 ); + for ( let iy = 0; iy < gridY; iy ++ ) { - return this; + for ( let ix = 0; ix < gridX; ix ++ ) { - }; + const a = ix + gridX1 * iy; + const b = ix + gridX1 * ( iy + 1 ); + const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = ( ix + 1 ) + gridX1 * iy; - }(), + indices.push( a, b, d ); + indices.push( b, c, d ); - lookAt: function () { + } - var obj = new Object3D(); + } - return function lookAt( vector ) { + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - obj.lookAt( vector ); + } - obj.updateMatrix(); + copy( source ) { - this.applyMatrix( obj.matrix ); + super.copy( source ); - }; + this.parameters = Object.assign( {}, source.parameters ); - }(), + return this; - center: function () { + } - this.computeBoundingBox(); + static fromJSON( data ) { - var offset = this.boundingBox.getCenter().negate(); + return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); - this.translate( offset.x, offset.y, offset.z ); + } - return offset; + } - }, + var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif"; - setFromObject: function ( object ) { + var alphahash_pars_fragment = "#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif"; - // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); + var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; - var geometry = object.geometry; + var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - if ( object.isPoints || object.isLine ) { + var alphatest_fragment = "#ifdef USE_ALPHATEST\n\t#ifdef ALPHA_TO_COVERAGE\n\tdiffuseColor.a = smoothstep( alphaTest, alphaTest + fwidth( diffuseColor.a ), diffuseColor.a );\n\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\tif ( diffuseColor.a < alphaTest ) discard;\n\t#endif\n#endif"; - var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); - var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); + var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; - this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); - this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); + var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; - if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { + var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; - var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); + var batching_pars_vertex = "#ifdef USE_BATCHING\n\t#if ! defined( GL_ANGLE_multi_draw )\n\t#define gl_DrawID _gl_DrawID\n\tuniform int _gl_DrawID;\n\t#endif\n\tuniform highp sampler2D batchingTexture;\n\tuniform highp usampler2D batchingIdTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n\tfloat getIndirectIndex( const in int i ) {\n\t\tint size = textureSize( batchingIdTexture, 0 ).x;\n\t\tint x = i % size;\n\t\tint y = i / size;\n\t\treturn float( texelFetch( batchingIdTexture, ivec2( x, y ), 0 ).r );\n\t}\n#endif\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec3 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb;\n\t}\n#endif"; - this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); + var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( getIndirectIndex( gl_DrawID ) );\n#endif"; - } + var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif"; - if ( geometry.boundingSphere !== null ) { + var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; - this.boundingSphere = geometry.boundingSphere.clone(); + var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated"; - } + var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.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\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; - if ( geometry.boundingBox !== null ) { + var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; - this.boundingBox = geometry.boundingBox.clone(); + var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif"; - } + var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; - } else if ( object.isMesh ) { + var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; - if ( geometry && geometry.isGeometry ) { + var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; - this.fromGeometry( geometry ); + var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; - } + var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; - } + var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif"; - return this; + var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.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\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; - setFromPoints: function ( points ) { + var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; - var position = []; + var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; - for ( var i = 0, l = points.length; i < l; i ++ ) { + var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; - var point = points[ i ]; - position.push( point.x, point.y, point.z || 0 ); + var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; - } + var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; - this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); + var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; - return this; + var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; - }, + var colorspace_pars_fragment = "\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn 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}"; - updateFromObject: function ( object ) { + var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; - var geometry = object.geometry; + var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; - if ( object.isMesh ) { + var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif"; - var direct = geometry.__directGeometry; + var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif"; - if ( geometry.elementsNeedUpdate === true ) { + var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif"; - direct = undefined; - geometry.elementsNeedUpdate = false; + var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; - } + var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; - if ( direct === undefined ) { + var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"; - return this.fromGeometry( geometry ); + var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif"; - } + var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; - direct.verticesNeedUpdate = geometry.verticesNeedUpdate; - direct.normalsNeedUpdate = geometry.normalsNeedUpdate; - direct.colorsNeedUpdate = geometry.colorsNeedUpdate; - direct.uvsNeedUpdate = geometry.uvsNeedUpdate; - direct.groupsNeedUpdate = geometry.groupsNeedUpdate; + var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; - geometry.verticesNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.groupsNeedUpdate = false; + var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; - geometry = direct; + var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; - } + var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; - var attribute; + var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; - if ( geometry.verticesNeedUpdate === true ) { + var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; - attribute = this.attributes.position; + var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon"; - if ( attribute !== undefined ) { + var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; - attribute.copyVector3sArray( geometry.vertices ); - attribute.needsUpdate = true; + var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; - } + var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; - geometry.verticesNeedUpdate = false; + var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; - } + var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; - if ( geometry.normalsNeedUpdate === true ) { + var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; - attribute = this.attributes.normal; + var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif"; - if ( attribute !== undefined ) { + var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; - attribute.copyVector3sArray( geometry.normals ); - attribute.needsUpdate = true; + var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; - } + var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; - geometry.normalsNeedUpdate = false; + var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif"; - } + var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = 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\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; - if ( geometry.colorsNeedUpdate === true ) { + var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; - attribute = this.attributes.color; + var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; - if ( attribute !== undefined ) { + var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - attribute.copyColorsArray( geometry.colors ); - attribute.needsUpdate = true; + var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; - } + var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; - geometry.colorsNeedUpdate = false; + var morphinstance_vertex = "#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif"; - } + var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif"; - if ( geometry.uvsNeedUpdate ) { + var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; - attribute = this.attributes.uv; + var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif"; - if ( attribute !== undefined ) { + var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; - attribute.copyVector2sArray( geometry.uvs ); - attribute.needsUpdate = true; + var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;"; - } + var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; - geometry.uvsNeedUpdate = false; + var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; - } + var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; - if ( geometry.lineDistancesNeedUpdate ) { + var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; - attribute = this.attributes.lineDistance; + var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; - if ( attribute !== undefined ) { + var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif"; - attribute.copyArray( geometry.lineDistances ); - attribute.needsUpdate = true; + var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; - } + var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; - geometry.lineDistancesNeedUpdate = false; + var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; - } + var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; - if ( geometry.groupsNeedUpdate ) { + var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn 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\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; - geometry.computeGroups( object.geometry ); - this.groups = geometry.groups; + var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; - geometry.groupsNeedUpdate = false; + var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; - } + var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; - return this; + var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; - }, + var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; - fromGeometry: function ( geometry ) { + var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; - geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); + var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif"; - return this.fromDirectGeometry( geometry.__directGeometry ); + var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; - }, + var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; - fromDirectGeometry: function ( geometry ) { + var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}"; - var positions = new Float32Array( geometry.vertices.length * 3 ); - this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); + var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; - if ( geometry.normals.length > 0 ) { + var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif"; - var normals = new Float32Array( geometry.normals.length * 3 ); - this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); + var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif"; - } + var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; - if ( geometry.colors.length > 0 ) { + var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; - var colors = new Float32Array( geometry.colors.length * 3 ); - this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); + var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; - } + var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; - if ( geometry.uvs.length > 0 ) { + 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\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - var uvs = new Float32Array( geometry.uvs.length * 2 ); - this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); + var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; - } + var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; - if ( geometry.uvs2.length > 0 ) { + var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); + var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - } + var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; - if ( geometry.indices.length > 0 ) { + var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); + const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; - } + const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; - // groups + const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; - this.groups = geometry.groups; + const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; - // morphs + const vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; - for ( var name in geometry.morphTargets ) { + const fragment$f = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}"; - var array = []; - var morphTargets = geometry.morphTargets[ name ]; + const vertex$e = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}"; - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { + const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}"; - var morphTarget = morphTargets[ i ]; + const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}"; - var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); + const 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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; - array.push( attribute.copyVector3sArray( morphTarget ) ); + const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}"; - } + const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; - this.morphAttributes[ name ] = array; + const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } + const 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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - // skinning + const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - if ( geometry.skinIndices.length > 0 ) { + const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); + const vertex$9 = "#define LAMBERT\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } + const fragment$9 = "#define LAMBERT\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - if ( geometry.skinWeights.length > 0 ) { + const 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 \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; - var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); + const 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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } + const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; - // + const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; - if ( geometry.boundingSphere !== null ) { + const 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - this.boundingSphere = geometry.boundingSphere.clone(); + const 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - } + const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; - if ( geometry.boundingBox !== null ) { + const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - this.boundingBox = geometry.boundingBox.clone(); + const 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; - } + const 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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - return this; + const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - }, + const fragment$3 = "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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - computeBoundingBox: function () { + const vertex$2 = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - if ( this.boundingBox === null ) { + const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; - this.boundingBox = new Box3(); + const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"; - } + const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - var position = this.attributes.position; + const ShaderChunk = { + alphahash_fragment: alphahash_fragment, + alphahash_pars_fragment: alphahash_pars_fragment, + alphamap_fragment: alphamap_fragment, + alphamap_pars_fragment: alphamap_pars_fragment, + alphatest_fragment: alphatest_fragment, + alphatest_pars_fragment: alphatest_pars_fragment, + aomap_fragment: aomap_fragment, + aomap_pars_fragment: aomap_pars_fragment, + batching_pars_vertex: batching_pars_vertex, + batching_vertex: batching_vertex, + begin_vertex: begin_vertex, + beginnormal_vertex: beginnormal_vertex, + bsdfs: bsdfs, + iridescence_fragment: iridescence_fragment, + bumpmap_pars_fragment: bumpmap_pars_fragment, + clipping_planes_fragment: clipping_planes_fragment, + clipping_planes_pars_fragment: clipping_planes_pars_fragment, + clipping_planes_pars_vertex: clipping_planes_pars_vertex, + clipping_planes_vertex: clipping_planes_vertex, + color_fragment: color_fragment, + color_pars_fragment: color_pars_fragment, + color_pars_vertex: color_pars_vertex, + color_vertex: color_vertex, + common: common, + cube_uv_reflection_fragment: cube_uv_reflection_fragment, + defaultnormal_vertex: defaultnormal_vertex, + displacementmap_pars_vertex: displacementmap_pars_vertex, + displacementmap_vertex: displacementmap_vertex, + emissivemap_fragment: emissivemap_fragment, + emissivemap_pars_fragment: emissivemap_pars_fragment, + colorspace_fragment: colorspace_fragment, + colorspace_pars_fragment: colorspace_pars_fragment, + envmap_fragment: envmap_fragment, + envmap_common_pars_fragment: envmap_common_pars_fragment, + envmap_pars_fragment: envmap_pars_fragment, + envmap_pars_vertex: envmap_pars_vertex, + envmap_physical_pars_fragment: envmap_physical_pars_fragment, + envmap_vertex: envmap_vertex, + fog_vertex: fog_vertex, + fog_pars_vertex: fog_pars_vertex, + fog_fragment: fog_fragment, + fog_pars_fragment: fog_pars_fragment, + gradientmap_pars_fragment: gradientmap_pars_fragment, + lightmap_pars_fragment: lightmap_pars_fragment, + lights_lambert_fragment: lights_lambert_fragment, + lights_lambert_pars_fragment: lights_lambert_pars_fragment, + lights_pars_begin: lights_pars_begin, + lights_toon_fragment: lights_toon_fragment, + lights_toon_pars_fragment: lights_toon_pars_fragment, + lights_phong_fragment: lights_phong_fragment, + lights_phong_pars_fragment: lights_phong_pars_fragment, + lights_physical_fragment: lights_physical_fragment, + lights_physical_pars_fragment: lights_physical_pars_fragment, + lights_fragment_begin: lights_fragment_begin, + lights_fragment_maps: lights_fragment_maps, + lights_fragment_end: lights_fragment_end, + logdepthbuf_fragment: logdepthbuf_fragment, + logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, + logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, + logdepthbuf_vertex: logdepthbuf_vertex, + map_fragment: map_fragment, + map_pars_fragment: map_pars_fragment, + map_particle_fragment: map_particle_fragment, + map_particle_pars_fragment: map_particle_pars_fragment, + metalnessmap_fragment: metalnessmap_fragment, + metalnessmap_pars_fragment: metalnessmap_pars_fragment, + morphinstance_vertex: morphinstance_vertex, + morphcolor_vertex: morphcolor_vertex, + morphnormal_vertex: morphnormal_vertex, + morphtarget_pars_vertex: morphtarget_pars_vertex, + morphtarget_vertex: morphtarget_vertex, + normal_fragment_begin: normal_fragment_begin, + normal_fragment_maps: normal_fragment_maps, + normal_pars_fragment: normal_pars_fragment, + normal_pars_vertex: normal_pars_vertex, + normal_vertex: normal_vertex, + normalmap_pars_fragment: normalmap_pars_fragment, + clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, + clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, + clearcoat_pars_fragment: clearcoat_pars_fragment, + iridescence_pars_fragment: iridescence_pars_fragment, + opaque_fragment: opaque_fragment, + packing: packing, + premultiplied_alpha_fragment: premultiplied_alpha_fragment, + project_vertex: project_vertex, + dithering_fragment: dithering_fragment, + dithering_pars_fragment: dithering_pars_fragment, + roughnessmap_fragment: roughnessmap_fragment, + roughnessmap_pars_fragment: roughnessmap_pars_fragment, + shadowmap_pars_fragment: shadowmap_pars_fragment, + shadowmap_pars_vertex: shadowmap_pars_vertex, + shadowmap_vertex: shadowmap_vertex, + shadowmask_pars_fragment: shadowmask_pars_fragment, + skinbase_vertex: skinbase_vertex, + skinning_pars_vertex: skinning_pars_vertex, + skinning_vertex: skinning_vertex, + skinnormal_vertex: skinnormal_vertex, + specularmap_fragment: specularmap_fragment, + specularmap_pars_fragment: specularmap_pars_fragment, + tonemapping_fragment: tonemapping_fragment, + tonemapping_pars_fragment: tonemapping_pars_fragment, + transmission_fragment: transmission_fragment, + transmission_pars_fragment: transmission_pars_fragment, + uv_pars_fragment: uv_pars_fragment, + uv_pars_vertex: uv_pars_vertex, + uv_vertex: uv_vertex, + worldpos_vertex: worldpos_vertex, - if ( position !== undefined ) { + background_vert: vertex$h, + background_frag: fragment$h, + backgroundCube_vert: vertex$g, + backgroundCube_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 + }; - this.boundingBox.setFromBufferAttribute( position ); + /** + * Uniforms library for shared webgl shaders + */ - } else { + const UniformsLib = { - this.boundingBox.makeEmpty(); + common: { - } + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, - if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { + map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, - console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, - } + alphaTest: { value: 0 } }, - computeBoundingSphere: function () { - - var box = new Box3(); - var vector = new Vector3(); + specularmap: { - return function computeBoundingSphere() { + specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } - if ( this.boundingSphere === null ) { + }, - this.boundingSphere = new Sphere(); + envmap: { - } + envMap: { value: null }, + envMapRotation: { value: /*@__PURE__*/ new Matrix3() }, + flipEnvMap: { value: - 1 }, + reflectivity: { value: 1.0 }, // basic, lambert, phong + ior: { value: 1.5 }, // physical + refractionRatio: { value: 0.98 }, // basic, lambert, phong - var position = this.attributes.position; + }, - if ( position ) { + aomap: { - var center = this.boundingSphere.center; + aoMap: { value: null }, + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } - box.setFromBufferAttribute( position ); - box.getCenter( center ); + }, - // hoping to find a boundingSphere with a radius smaller than the - // boundingSphere of the boundingBox: sqrt(3) smaller in the best case + lightmap: { - var maxRadiusSq = 0; + lightMap: { value: null }, + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } - for ( var i = 0, il = position.count; i < il; i ++ ) { + }, - vector.x = position.getX( i ); - vector.y = position.getY( i ); - vector.z = position.getZ( i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + bumpmap: { - } + bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + bumpScale: { value: 1 } - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + }, - if ( isNaN( this.boundingSphere.radius ) ) { + normalmap: { - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); + normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } - } + }, - } + displacementmap: { - }; + displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + displacementScale: { value: 1 }, + displacementBias: { value: 0 } - }(), + }, - computeFaceNormals: function () { + emissivemap: { - // backwards compatibility + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, - computeVertexNormals: function () { - - var index = this.index; - var attributes = this.attributes; - var groups = this.groups; + metalnessmap: { - if ( attributes.position ) { + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } - var positions = attributes.position.array; + }, - if ( attributes.normal === undefined ) { + roughnessmap: { - this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } - } else { + }, - // reset existing normals to zero + gradientmap: { - var array = attributes.normal.array; + gradientMap: { value: null } - for ( var i = 0, il = array.length; i < il; i ++ ) { + }, - array[ i ] = 0; + fog: { - } + fogDensity: { value: 0.00025 }, + fogNear: { value: 1 }, + fogFar: { value: 2000 }, + fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } - } + }, - var normals = attributes.normal.array; + lights: { - var vA, vB, vC; - var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); - var cb = new Vector3(), ab = new Vector3(); + ambientLightColor: { value: [] }, - // indexed elements + lightProbe: { value: [] }, - if ( index ) { + directionalLights: { value: [], properties: { + direction: {}, + color: {} + } }, - var indices = index.array; + directionalLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, - if ( groups.length === 0 ) { + directionalShadowMap: { value: [] }, + directionalShadowMatrix: { value: [] }, - this.addGroup( 0, indices.length ); + spotLights: { value: [], properties: { + color: {}, + position: {}, + direction: {}, + distance: {}, + coneCos: {}, + penumbraCos: {}, + decay: {} + } }, - } + spotLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, - for ( var j = 0, jl = groups.length; j < jl; ++ j ) { + spotLightMap: { value: [] }, + spotShadowMap: { value: [] }, + spotLightMatrix: { value: [] }, - var group = groups[ j ]; + pointLights: { value: [], properties: { + color: {}, + position: {}, + decay: {}, + distance: {} + } }, - var start = group.start; - var count = group.count; + pointLightShadows: { value: [], properties: { + shadowIntensity: 1, + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} + } }, - for ( var i = start, il = start + count; i < il; i += 3 ) { + pointShadowMap: { value: [] }, + pointShadowMatrix: { value: [] }, - vA = indices[ i + 0 ] * 3; - vB = indices[ i + 1 ] * 3; - vC = indices[ i + 2 ] * 3; + hemisphereLights: { value: [], properties: { + direction: {}, + skyColor: {}, + groundColor: {} + } }, - pA.fromArray( positions, vA ); - pB.fromArray( positions, vB ); - pC.fromArray( positions, vC ); + // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src + rectAreaLights: { value: [], properties: { + color: {}, + position: {}, + width: {}, + height: {} + } }, - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); + ltc_1: { value: null }, + ltc_2: { value: null } - normals[ vA ] += cb.x; - normals[ vA + 1 ] += cb.y; - normals[ vA + 2 ] += cb.z; + }, - normals[ vB ] += cb.x; - normals[ vB + 1 ] += cb.y; - normals[ vB + 2 ] += cb.z; + points: { - normals[ vC ] += cb.x; - normals[ vC + 1 ] += cb.y; - normals[ vC + 2 ] += cb.z; + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, + size: { value: 1.0 }, + scale: { value: 1.0 }, + map: { value: null }, + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 }, + uvTransform: { value: /*@__PURE__*/ new Matrix3() } - } + }, - } + sprite: { - } else { + diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, + opacity: { value: 1.0 }, + center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, + rotation: { value: 0.0 }, + map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } - // non-indexed elements (unconnected triangle soup) + } - for ( var i = 0, il = positions.length; i < il; i += 9 ) { + }; - pA.fromArray( positions, i ); - pB.fromArray( positions, i + 3 ); - pC.fromArray( positions, i + 6 ); + const ShaderLib = { - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); + basic: { - normals[ i ] = cb.x; - normals[ i + 1 ] = cb.y; - normals[ i + 2 ] = cb.z; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.fog + ] ), - normals[ i + 3 ] = cb.x; - normals[ i + 4 ] = cb.y; - normals[ i + 5 ] = cb.z; + vertexShader: ShaderChunk.meshbasic_vert, + fragmentShader: ShaderChunk.meshbasic_frag - normals[ i + 6 ] = cb.x; - normals[ i + 7 ] = cb.y; - normals[ i + 8 ] = cb.z; + }, - } + lambert: { + 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 Color( 0x000000 ) } } + ] ), - this.normalizeNormals(); - - attributes.normal.needsUpdate = true; - - } + vertexShader: ShaderChunk.meshlambert_vert, + fragmentShader: ShaderChunk.meshlambert_frag }, - merge: function ( geometry, offset ) { + phong: { - if ( ! ( geometry && geometry.isBufferGeometry ) ) { + 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 Color( 0x000000 ) }, + specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, + shininess: { value: 30 } + } + ] ), - console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); - return; + vertexShader: ShaderChunk.meshphong_vert, + fragmentShader: ShaderChunk.meshphong_frag - } + }, - if ( offset === undefined ) offset = 0; + standard: { - var attributes = this.attributes; + 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 Color( 0x000000 ) }, + roughness: { value: 1.0 }, + metalness: { value: 0.0 }, + envMapIntensity: { value: 1 } + } + ] ), - for ( var key in attributes ) { + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag - if ( geometry.attributes[ key ] === undefined ) continue; + }, - var attribute1 = attributes[ key ]; - var attributeArray1 = attribute1.array; + toon: { - var attribute2 = geometry.attributes[ key ]; - var attributeArray2 = attribute2.array; + 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 Color( 0x000000 ) } + } + ] ), - var attributeSize = attribute2.itemSize; + vertexShader: ShaderChunk.meshtoon_vert, + fragmentShader: ShaderChunk.meshtoon_frag - for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { + }, - attributeArray1[ j ] = attributeArray2[ i ]; + matcap: { + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.fog, + { + matcap: { value: null } } + ] ), - } - - return this; + vertexShader: ShaderChunk.meshmatcap_vert, + fragmentShader: ShaderChunk.meshmatcap_frag }, - normalizeNormals: function () { + points: { - var vector = new Vector3(); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.points, + UniformsLib.fog + ] ), - return function normalizeNormals() { + vertexShader: ShaderChunk.points_vert, + fragmentShader: ShaderChunk.points_frag - var normals = this.attributes.normal; + }, - for ( var i = 0, il = normals.count; i < il; i ++ ) { + dashed: { - vector.x = normals.getX( i ); - vector.y = normals.getY( i ); - vector.z = normals.getZ( i ); + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.fog, + { + scale: { value: 1 }, + dashSize: { value: 1 }, + totalSize: { value: 2 } + } + ] ), - vector.normalize(); + vertexShader: ShaderChunk.linedashed_vert, + fragmentShader: ShaderChunk.linedashed_frag - normals.setXYZ( i, vector.x, vector.y, vector.z ); + }, - } + depth: { - }; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.displacementmap + ] ), - }(), + vertexShader: ShaderChunk.depth_vert, + fragmentShader: ShaderChunk.depth_frag - toNonIndexed: function () { + }, - if ( this.index === null ) { + normal: { - console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); - return this; + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + { + opacity: { value: 1.0 } + } + ] ), - } + vertexShader: ShaderChunk.meshnormal_vert, + fragmentShader: ShaderChunk.meshnormal_frag - var geometry2 = new BufferGeometry(); + }, - var indices = this.index.array; - var attributes = this.attributes; + sprite: { - for ( var name in attributes ) { + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.sprite, + UniformsLib.fog + ] ), - var attribute = attributes[ name ]; + vertexShader: ShaderChunk.sprite_vert, + fragmentShader: ShaderChunk.sprite_frag - var array = attribute.array; - var itemSize = attribute.itemSize; + }, - var array2 = new array.constructor( indices.length * itemSize ); + background: { - var index = 0, index2 = 0; + uniforms: { + uvTransform: { value: /*@__PURE__*/ new Matrix3() }, + t2D: { value: null }, + backgroundIntensity: { value: 1 } + }, - for ( var i = 0, l = indices.length; i < l; i ++ ) { + vertexShader: ShaderChunk.background_vert, + fragmentShader: ShaderChunk.background_frag - index = indices[ i ] * itemSize; + }, - for ( var j = 0; j < itemSize; j ++ ) { + backgroundCube: { - array2[ index2 ++ ] = array[ index ++ ]; + uniforms: { + envMap: { value: null }, + flipEnvMap: { value: - 1 }, + backgroundBlurriness: { value: 0 }, + backgroundIntensity: { value: 1 }, + backgroundRotation: { value: /*@__PURE__*/ new Matrix3() } + }, - } + vertexShader: ShaderChunk.backgroundCube_vert, + fragmentShader: ShaderChunk.backgroundCube_frag - } + }, - geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); + cube: { - } + uniforms: { + tCube: { value: null }, + tFlip: { value: - 1 }, + opacity: { value: 1.0 } + }, - return geometry2; + vertexShader: ShaderChunk.cube_vert, + fragmentShader: ShaderChunk.cube_frag }, - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'BufferGeometry', - generator: 'BufferGeometry.toJSON' - } - }; + equirect: { - // standard BufferGeometry serialization + uniforms: { + tEquirect: { value: null }, + }, - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + vertexShader: ShaderChunk.equirect_vert, + fragmentShader: ShaderChunk.equirect_frag - if ( this.parameters !== undefined ) { + }, - var parameters = this.parameters; + distanceRGBA: { - for ( var key in parameters ) { + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.common, + UniformsLib.displacementmap, + { + referencePosition: { value: /*@__PURE__*/ new Vector3() }, + nearDistance: { value: 1 }, + farDistance: { value: 1000 } + } + ] ), - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + vertexShader: ShaderChunk.distanceRGBA_vert, + fragmentShader: ShaderChunk.distanceRGBA_frag - } + }, - return data; + shadow: { - } + uniforms: /*@__PURE__*/ mergeUniforms( [ + UniformsLib.lights, + UniformsLib.fog, + { + color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, + opacity: { value: 1.0 } + }, + ] ), - data.data = { attributes: {} }; + vertexShader: ShaderChunk.shadow_vert, + fragmentShader: ShaderChunk.shadow_frag - var index = this.index; + } - if ( index !== null ) { + }; - var array = Array.prototype.slice.call( index.array ); - - data.data.index = { - type: index.array.constructor.name, - array: array - }; + ShaderLib.physical = { + uniforms: /*@__PURE__*/ mergeUniforms( [ + ShaderLib.standard.uniforms, + { + clearcoat: { value: 0 }, + clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, + clearcoatRoughness: { value: 0 }, + clearcoatRoughnessMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + dispersion: { value: 0 }, + iridescence: { value: 0 }, + iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + iridescenceIOR: { value: 1.3 }, + iridescenceThicknessMinimum: { value: 100 }, + iridescenceThicknessMaximum: { value: 400 }, + iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + sheen: { value: 0 }, + sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, + sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + sheenRoughness: { value: 1 }, + sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + transmission: { value: 0 }, + transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, + transmissionSamplerMap: { value: null }, + thickness: { value: 0 }, + thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + attenuationDistance: { value: 0 }, + attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, + specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, + specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, } + ] ), + + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag - var attributes = this.attributes; + }; - for ( var key in attributes ) { + const _rgb = { r: 0, b: 0, g: 0 }; + const _e1$1 = /*@__PURE__*/ new Euler(); + const _m1$1 = /*@__PURE__*/ new Matrix4(); - var attribute = attributes[ key ]; + function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { - var array = Array.prototype.slice.call( attribute.array ); + const clearColor = new Color( 0x000000 ); + let clearAlpha = alpha === true ? 0 : 1; - data.data.attributes[ key ] = { - itemSize: attribute.itemSize, - type: attribute.array.constructor.name, - array: array, - normalized: attribute.normalized - }; + let planeMesh; + let boxMesh; - } + let currentBackground = null; + let currentBackgroundVersion = 0; + let currentTonemapping = null; - var groups = this.groups; + function getBackground( scene ) { - if ( groups.length > 0 ) { + let background = scene.isScene === true ? scene.background : null; - data.data.groups = JSON.parse( JSON.stringify( groups ) ); + if ( background && background.isTexture ) { + + const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background + background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); } - var boundingSphere = this.boundingSphere; + return background; - if ( boundingSphere !== null ) { + } - data.data.boundingSphere = { - center: boundingSphere.center.toArray(), - radius: boundingSphere.radius - }; + function render( scene ) { + + let forceClear = false; + const background = getBackground( scene ); + + if ( background === null ) { + + setClear( clearColor, clearAlpha ); + + } else if ( background && background.isColor ) { + + setClear( background, 1 ); + forceClear = true; } - return data; + const environmentBlendMode = renderer.xr.getEnvironmentBlendMode(); - }, + if ( environmentBlendMode === 'additive' ) { - clone: function () { + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); - /* - // Handle primitives + } else if ( environmentBlendMode === 'alpha-blend' ) { - var parameters = this.parameters; + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); - if ( parameters !== undefined ) { + } - var values = []; + if ( renderer.autoClear || forceClear ) { - for ( var key in parameters ) { + // buffers might not be writable which is required to ensure a correct clear - values.push( parameters[ key ] ); + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); - } + renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + } - } + } - return new this.constructor().copy( this ); - */ + function addToRenderList( renderList, scene ) { - return new BufferGeometry().copy( this ); + const background = getBackground( scene ); - }, + if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { - copy: function ( source ) { + if ( boxMesh === undefined ) { - var name, i, l; + boxMesh = new Mesh( + new BoxGeometry( 1, 1, 1 ), + new ShaderMaterial( { + name: 'BackgroundCubeMaterial', + uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), + vertexShader: ShaderLib.backgroundCube.vertexShader, + fragmentShader: ShaderLib.backgroundCube.fragmentShader, + side: BackSide, + depthTest: false, + depthWrite: false, + fog: false + } ) + ); - // reset + boxMesh.geometry.deleteAttribute( 'normal' ); + boxMesh.geometry.deleteAttribute( 'uv' ); - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; + boxMesh.onBeforeRender = function ( renderer, scene, camera ) { - // name + this.matrixWorld.copyPosition( camera.matrixWorld ); - this.name = source.name; + }; - // index + // add "envMap" material property so the renderer can evaluate it like for built-in materials + Object.defineProperty( boxMesh.material, 'envMap', { - var index = source.index; + get: function () { - if ( index !== null ) { + return this.uniforms.envMap.value; - this.setIndex( index.clone() ); + } - } + } ); - // attributes + objects.update( boxMesh ); - var attributes = source.attributes; + } - for ( name in attributes ) { + _e1$1.copy( scene.backgroundRotation ); - var attribute = attributes[ name ]; - this.addAttribute( name, attribute.clone() ); + // accommodate left-handed frame + _e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1; - } + if ( background.isCubeTexture && background.isRenderTargetTexture === false ) { - // morph attributes + // environment maps which are not cube render targets or PMREMs follow a different convention + _e1$1.y *= - 1; + _e1$1.z *= - 1; - var morphAttributes = source.morphAttributes; + } - for ( name in morphAttributes ) { + boxMesh.material.uniforms.envMap.value = background; + boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; + boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; + boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; + boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) ); + boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; - var array = []; - var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes + if ( currentBackground !== background || + currentBackgroundVersion !== background.version || + currentTonemapping !== renderer.toneMapping ) { - for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { + boxMesh.material.needsUpdate = true; - array.push( morphAttribute[ i ].clone() ); + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; } - this.morphAttributes[ name ] = array; + boxMesh.layers.enableAll(); - } + // push to the pre-sorted opaque render list + renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); - // groups + } else if ( background && background.isTexture ) { - var groups = source.groups; + if ( planeMesh === undefined ) { - for ( i = 0, l = groups.length; i < l; i ++ ) { + 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 + } ) + ); - var group = groups[ i ]; - this.addGroup( group.start, group.count, group.materialIndex ); + planeMesh.geometry.deleteAttribute( 'normal' ); - } + // add "map" material property so the renderer can evaluate it like for built-in materials + Object.defineProperty( planeMesh.material, 'map', { - // bounding box + get: function () { - var boundingBox = source.boundingBox; + return this.uniforms.t2D.value; - if ( boundingBox !== null ) { + } - this.boundingBox = boundingBox.clone(); + } ); - } + objects.update( planeMesh ); - // bounding sphere + } - var boundingSphere = source.boundingSphere; + planeMesh.material.uniforms.t2D.value = background; + planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; + planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; - if ( boundingSphere !== null ) { + if ( background.matrixAutoUpdate === true ) { - this.boundingSphere = boundingSphere.clone(); + background.updateMatrix(); - } + } - // draw range + planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); - this.drawRange.start = source.drawRange.start; - this.drawRange.count = source.drawRange.count; + if ( currentBackground !== background || + currentBackgroundVersion !== background.version || + currentTonemapping !== renderer.toneMapping ) { - return this; + planeMesh.material.needsUpdate = true; - }, + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; + + } - dispose: function () { + planeMesh.layers.enableAll(); - this.dispatchEvent( { type: 'dispose' } ); + // push to the pre-sorted opaque render list + renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); + + } } - } ); + function setClear( color, alpha ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); - // BoxGeometry + state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); - function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { + } - Geometry.call( this ); + return { - this.type = 'BoxGeometry'; + getClearColor: function () { - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; + return clearColor; - this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); - this.mergeVertices(); + }, + setClearColor: function ( color, alpha = 1 ) { - } + clearColor.set( color ); + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); - BoxGeometry.prototype = Object.create( Geometry.prototype ); - BoxGeometry.prototype.constructor = BoxGeometry; + }, + getClearAlpha: function () { - // BoxBufferGeometry + return clearAlpha; - function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { + }, + setClearAlpha: function ( alpha ) { - BufferGeometry.call( this ); + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); - this.type = 'BoxBufferGeometry'; + }, + render: render, + addToRenderList: addToRenderList - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments }; - var scope = this; + } + + function WebGLBindingStates( gl, attributes ) { - width = width || 1; - height = height || 1; - depth = depth || 1; + const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - // segments + const bindingStates = {}; - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; + const defaultState = createBindingState( null ); + let currentState = defaultState; + let forceUpdate = false; - // buffers + function setup( object, material, program, geometry, index ) { - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + let updateBuffers = false; - // helper variables + const state = getBindingState( geometry, program, material ); - var numberOfVertices = 0; - var groupStart = 0; + if ( currentState !== state ) { - // build each side of the box geometry + currentState = state; + bindVertexArrayObject( currentState.object ); - buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px - buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx - buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py - buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny - buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz - buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz + } - // build geometry + updateBuffers = needsUpdate( object, geometry, program, index ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + if ( updateBuffers ) saveCache( object, geometry, program, index ); - function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { + if ( index !== null ) { - var segmentWidth = width / gridX; - var segmentHeight = height / gridY; + attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; + } - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; + if ( updateBuffers || forceUpdate ) { - var vertexCounter = 0; - var groupCount = 0; + forceUpdate = false; - var ix, iy; + setupVertexAttributes( object, material, program, geometry ); - var vector = new Vector3(); + if ( index !== null ) { - // generate vertices, normals and uvs + gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); - for ( iy = 0; iy < gridY1; iy ++ ) { + } - var y = iy * segmentHeight - heightHalf; + } - for ( ix = 0; ix < gridX1; ix ++ ) { + } - var x = ix * segmentWidth - widthHalf; + function createVertexArrayObject() { - // set values to correct vector component + return gl.createVertexArray(); - vector[ u ] = x * udir; - vector[ v ] = y * vdir; - vector[ w ] = depthHalf; + } - // now apply vector to vertex buffer + function bindVertexArrayObject( vao ) { - vertices.push( vector.x, vector.y, vector.z ); + return gl.bindVertexArray( vao ); - // set values to correct vector component + } - vector[ u ] = 0; - vector[ v ] = 0; - vector[ w ] = depth > 0 ? 1 : - 1; + function deleteVertexArrayObject( vao ) { - // now apply vector to normal buffer + return gl.deleteVertexArray( vao ); - normals.push( vector.x, vector.y, vector.z ); + } - // uvs + function getBindingState( geometry, program, material ) { - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); + const wireframe = ( material.wireframe === true ); - // counters + let programMap = bindingStates[ geometry.id ]; - vertexCounter += 1; + if ( programMap === undefined ) { - } + programMap = {}; + bindingStates[ geometry.id ] = programMap; } - // indices + let stateMap = programMap[ program.id ]; - // 1. you need three indices to draw a single face - // 2. a single segment consists of two faces - // 3. so we need to generate six (2*3) indices per segment + if ( stateMap === undefined ) { - for ( iy = 0; iy < gridY; iy ++ ) { + stateMap = {}; + programMap[ program.id ] = stateMap; - for ( ix = 0; ix < gridX; ix ++ ) { + } - var a = numberOfVertices + ix + gridX1 * iy; - var b = numberOfVertices + ix + gridX1 * ( iy + 1 ); - var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; + let state = stateMap[ wireframe ]; - // faces + if ( state === undefined ) { - indices.push( a, b, d ); - indices.push( b, c, d ); + state = createBindingState( createVertexArrayObject() ); + stateMap[ wireframe ] = state; - // increase counter + } - groupCount += 6; + return state; - } + } - } + function createBindingState( vao ) { - // add a group to the geometry. this will ensure multi material support + const newAttributes = []; + const enabledAttributes = []; + const attributeDivisors = []; - scope.addGroup( groupStart, groupCount, materialIndex ); + for ( let i = 0; i < maxVertexAttributes; i ++ ) { - // calculate new start value for groups + newAttributes[ i ] = 0; + enabledAttributes[ i ] = 0; + attributeDivisors[ i ] = 0; - groupStart += groupCount; + } - // update total number of vertices + return { - numberOfVertices += vertexCounter; + // for backward compatibility on non-VAO support browser + geometry: null, + program: null, + wireframe: false, - } + newAttributes: newAttributes, + enabledAttributes: enabledAttributes, + attributeDivisors: attributeDivisors, + object: vao, + attributes: {}, + index: null - } + }; - BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; + } - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + function needsUpdate( object, geometry, program, index ) { - // PlaneGeometry + const cachedAttributes = currentState.attributes; + const geometryAttributes = geometry.attributes; - function PlaneGeometry( width, height, widthSegments, heightSegments ) { + let attributesNum = 0; - Geometry.call( this ); + const programAttributes = program.getAttributes(); - this.type = 'PlaneGeometry'; + for ( const name in programAttributes ) { - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; + const programAttribute = programAttributes[ name ]; - this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); - this.mergeVertices(); + if ( programAttribute.location >= 0 ) { - } + const cachedAttribute = cachedAttributes[ name ]; + let geometryAttribute = geometryAttributes[ name ]; - PlaneGeometry.prototype = Object.create( Geometry.prototype ); - PlaneGeometry.prototype.constructor = PlaneGeometry; + if ( geometryAttribute === undefined ) { - // PlaneBufferGeometry + if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; - function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { + } - BufferGeometry.call( this ); + if ( cachedAttribute === undefined ) return true; - this.type = 'PlaneBufferGeometry'; + if ( cachedAttribute.attribute !== geometryAttribute ) return true; - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; + if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; - width = width || 1; - height = height || 1; + attributesNum ++; - var width_half = width / 2; - var height_half = height / 2; + } - var gridX = Math.floor( widthSegments ) || 1; - var gridY = Math.floor( heightSegments ) || 1; + } - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; + if ( currentState.attributesNum !== attributesNum ) return true; - var segment_width = width / gridX; - var segment_height = height / gridY; + if ( currentState.index !== index ) return true; - var ix, iy; + return false; - // buffers + } - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + function saveCache( object, geometry, program, index ) { - // generate vertices, normals and uvs + const cache = {}; + const attributes = geometry.attributes; + let attributesNum = 0; - for ( iy = 0; iy < gridY1; iy ++ ) { + const programAttributes = program.getAttributes(); - var y = iy * segment_height - height_half; + for ( const name in programAttributes ) { - for ( ix = 0; ix < gridX1; ix ++ ) { + const programAttribute = programAttributes[ name ]; - var x = ix * segment_width - width_half; + if ( programAttribute.location >= 0 ) { - vertices.push( x, - y, 0 ); + let attribute = attributes[ name ]; - normals.push( 0, 0, 1 ); + if ( attribute === undefined ) { - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); + if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; - } + } - } + const data = {}; + data.attribute = attribute; - // indices + if ( attribute && attribute.data ) { - for ( iy = 0; iy < gridY; iy ++ ) { + data.data = attribute.data; - for ( ix = 0; ix < gridX; ix ++ ) { + } - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; + cache[ name ] = data; - // faces + attributesNum ++; - indices.push( a, b, d ); - indices.push( b, c, d ); + } } + currentState.attributes = cache; + currentState.attributesNum = attributesNum; + + currentState.index = index; + } - // build geometry + function initAttributes() { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + const newAttributes = currentState.newAttributes; - } + for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { - PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; + newAttributes[ i ] = 0; - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * depthTest: , - * depthWrite: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: - * } - */ + } - function MeshBasicMaterial( parameters ) { + } - Material.call( this ); + function enableAttribute( attribute ) { - this.type = 'MeshBasicMaterial'; + enableAttributeAndDivisor( attribute, 0 ); - this.color = new Color( 0xffffff ); // emissive + } - this.map = null; + function enableAttributeAndDivisor( attribute, meshPerAttribute ) { - this.lightMap = null; - this.lightMapIntensity = 1.0; + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + const attributeDivisors = currentState.attributeDivisors; - this.aoMap = null; - this.aoMapIntensity = 1.0; + newAttributes[ attribute ] = 1; - this.specularMap = null; + if ( enabledAttributes[ attribute ] === 0 ) { - this.alphaMap = null; + gl.enableVertexAttribArray( attribute ); + enabledAttributes[ attribute ] = 1; - 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'; + if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { - this.skinning = false; - this.morphTargets = false; + gl.vertexAttribDivisor( attribute, meshPerAttribute ); + attributeDivisors[ attribute ] = meshPerAttribute; - this.lights = false; + } - this.setValues( parameters ); + } - } + function disableUnusedAttributes() { - MeshBasicMaterial.prototype = Object.create( Material.prototype ); - MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; - MeshBasicMaterial.prototype.isMeshBasicMaterial = true; + for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { - MeshBasicMaterial.prototype.copy = function ( source ) { + if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { - Material.prototype.copy.call( this, source ); + gl.disableVertexAttribArray( i ); + enabledAttributes[ i ] = 0; - 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; + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { - this.specularMap = source.specularMap; + if ( integer === true ) { - this.alphaMap = source.alphaMap; + gl.vertexAttribIPointer( index, size, type, stride, offset ); - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + } else { - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; + } - return this; + } - }; + function setupVertexAttributes( object, material, program, geometry ) { - /** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * defines: { "label" : "value" }, - * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } }, - * - * fragmentShader: , - * vertexShader: , - * - * wireframe: , - * wireframeLinewidth: , - * - * lights: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + initAttributes(); - function ShaderMaterial( parameters ) { + const geometryAttributes = geometry.attributes; - Material.call( this ); + const programAttributes = program.getAttributes(); - this.type = 'ShaderMaterial'; + const materialDefaultAttributeValues = material.defaultAttributeValues; - this.defines = {}; - this.uniforms = {}; + for ( const name in programAttributes ) { - this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'; - this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'; + const programAttribute = programAttributes[ name ]; - this.linewidth = 1; + if ( programAttribute.location >= 0 ) { - this.wireframe = false; - this.wireframeLinewidth = 1; + let geometryAttribute = geometryAttributes[ name ]; - this.fog = false; // set to use scene fog - this.lights = false; // set to use scene lights - this.clipping = false; // set to use user-defined clipping planes + if ( geometryAttribute === undefined ) { - this.skinning = false; // set to use skinning attribute streams - this.morphTargets = false; // set to use morph targets - this.morphNormals = false; // set to use morph normals + if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; + if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; - this.extensions = { - derivatives: false, // set to use derivatives - fragDepth: false, // set to use fragment depth values - drawBuffers: false, // set to use draw buffers - shaderTextureLOD: false // set to use shader texture LOD - }; + } - // When rendered geometry doesn't include these attributes but the material does, - // use these default values in WebGL. This avoids errors when buffer data is missing. - this.defaultAttributeValues = { - 'color': [ 1, 1, 1 ], - 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] - }; + if ( geometryAttribute !== undefined ) { - this.index0AttributeName = undefined; + const normalized = geometryAttribute.normalized; + const size = geometryAttribute.itemSize; - if ( parameters !== undefined ) { + const attribute = attributes.get( geometryAttribute ); - if ( parameters.attributes !== undefined ) { + // TODO Attribute may not be available on context restore - console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); + if ( attribute === undefined ) continue; - } + const buffer = attribute.buffer; + const type = attribute.type; + const bytesPerElement = attribute.bytesPerElement; - this.setValues( parameters ); + // check for integer attributes - } + const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ); - } + if ( geometryAttribute.isInterleavedBufferAttribute ) { - ShaderMaterial.prototype = Object.create( Material.prototype ); - ShaderMaterial.prototype.constructor = ShaderMaterial; + const data = geometryAttribute.data; + const stride = data.stride; + const offset = geometryAttribute.offset; - ShaderMaterial.prototype.isShaderMaterial = true; + if ( data.isInstancedInterleavedBuffer ) { - ShaderMaterial.prototype.copy = function ( source ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - Material.prototype.copy.call( this, source ); + enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); - this.fragmentShader = source.fragmentShader; - this.vertexShader = source.vertexShader; + } - this.uniforms = UniformsUtils.clone( source.uniforms ); + if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { - this.defines = source.defines; + geometry._maxInstanceCount = data.meshPerAttribute * data.count; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; + } - this.lights = source.lights; - this.clipping = source.clipping; + } else { - this.skinning = source.skinning; + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + enableAttribute( programAttribute.location + i ); - this.extensions = source.extensions; + } - return this; + } - }; + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); - ShaderMaterial.prototype.toJSON = function ( meta ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - var data = Material.prototype.toJSON.call( this, meta ); + vertexAttribPointer( + programAttribute.location + i, + size / programAttribute.locationSize, + type, + normalized, + stride * bytesPerElement, + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer + ); - data.uniforms = this.uniforms; - data.vertexShader = this.vertexShader; - data.fragmentShader = this.fragmentShader; + } - return data; + } else { - }; + if ( geometryAttribute.isInstancedBufferAttribute ) { - /** - * @author bhouston / http://clara.io - */ + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - function Ray( origin, direction ) { + enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); - this.origin = ( origin !== undefined ) ? origin : new Vector3(); - this.direction = ( direction !== undefined ) ? direction : new Vector3(); + } - } + if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { - Object.assign( Ray.prototype, { + geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; - set: function ( origin, direction ) { + } - this.origin.copy( origin ); - this.direction.copy( direction ); + } else { - return this; + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - }, + enableAttribute( programAttribute.location + i ); - clone: function () { + } - return new this.constructor().copy( this ); + } - }, + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); - copy: function ( ray ) { + for ( let i = 0; i < programAttribute.locationSize; i ++ ) { - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); + vertexAttribPointer( + programAttribute.location + i, + size / programAttribute.locationSize, + type, + normalized, + size * bytesPerElement, + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer + ); - return this; + } - }, + } - at: function ( t, optionalTarget ) { + } else if ( materialDefaultAttributeValues !== undefined ) { - var result = optionalTarget || new Vector3(); + const value = materialDefaultAttributeValues[ name ]; - return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); + if ( value !== undefined ) { - }, + switch ( value.length ) { - lookAt: function ( v ) { + case 2: + gl.vertexAttrib2fv( programAttribute.location, value ); + break; - this.direction.copy( v ).sub( this.origin ).normalize(); + case 3: + gl.vertexAttrib3fv( programAttribute.location, value ); + break; - return this; + case 4: + gl.vertexAttrib4fv( programAttribute.location, value ); + break; - }, + default: + gl.vertexAttrib1fv( programAttribute.location, value ); - recast: function () { + } - var v1 = new Vector3(); + } - return function recast( t ) { + } - this.origin.copy( this.at( t, v1 ) ); + } - return this; + } - }; + disableUnusedAttributes(); - }(), + } - closestPointToPoint: function ( point, optionalTarget ) { + function dispose() { - var result = optionalTarget || new Vector3(); - result.subVectors( point, this.origin ); - var directionDistance = result.dot( this.direction ); + reset(); - if ( directionDistance < 0 ) { + for ( const geometryId in bindingStates ) { - return result.copy( this.origin ); + const programMap = bindingStates[ geometryId ]; - } + for ( const programId in programMap ) { - return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + const stateMap = programMap[ programId ]; - }, + for ( const wireframe in stateMap ) { - distanceToPoint: function ( point ) { + deleteVertexArrayObject( stateMap[ wireframe ].object ); - return Math.sqrt( this.distanceSqToPoint( point ) ); + delete stateMap[ wireframe ]; - }, + } - distanceSqToPoint: function () { + delete programMap[ programId ]; - var v1 = new Vector3(); + } - return function distanceSqToPoint( point ) { + delete bindingStates[ geometryId ]; - var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); + } - // point behind the ray + } - if ( directionDistance < 0 ) { + function releaseStatesOfGeometry( geometry ) { - return this.origin.distanceToSquared( point ); + if ( bindingStates[ geometry.id ] === undefined ) return; - } + const programMap = bindingStates[ geometry.id ]; - v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + for ( const programId in programMap ) { - return v1.distanceToSquared( point ); + const stateMap = programMap[ programId ]; - }; + for ( const wireframe in stateMap ) { - }(), + deleteVertexArrayObject( stateMap[ wireframe ].object ); - distanceSqToSegment: function () { + delete stateMap[ wireframe ]; - var segCenter = new Vector3(); - var segDir = new Vector3(); - var diff = new Vector3(); + } - return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + delete programMap[ programId ]; - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h - // It returns the min distance between the ray and the segment - // defined by v0 and v1 - // It can also set two optional targets : - // - The closest point on the ray - // - The closest point on the segment + } - segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - segDir.copy( v1 ).sub( v0 ).normalize(); - diff.copy( this.origin ).sub( segCenter ); + delete bindingStates[ geometry.id ]; - var segExtent = v0.distanceTo( v1 ) * 0.5; - var a01 = - this.direction.dot( segDir ); - var b0 = diff.dot( this.direction ); - var b1 = - diff.dot( segDir ); - var c = diff.lengthSq(); - var det = Math.abs( 1 - a01 * a01 ); - var s0, s1, sqrDist, extDet; + } - if ( det > 0 ) { + function releaseStatesOfProgram( program ) { - // The ray and segment are not parallel. + for ( const geometryId in bindingStates ) { - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; + const programMap = bindingStates[ geometryId ]; - if ( s0 >= 0 ) { + if ( programMap[ program.id ] === undefined ) continue; - if ( s1 >= - extDet ) { + const stateMap = programMap[ program.id ]; - if ( s1 <= extDet ) { + for ( const wireframe in stateMap ) { - // region 0 - // Minimum at interior points of ray and segment. + deleteVertexArrayObject( stateMap[ wireframe ].object ); - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + delete stateMap[ wireframe ]; - } else { + } - // region 1 + delete programMap[ program.id ]; - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + } - } + } - } else { + function reset() { - // region 5 + resetDefaultState(); + forceUpdate = true; - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + if ( currentState === defaultState ) return; - } + currentState = defaultState; + bindVertexArrayObject( currentState.object ); - } else { + } - if ( s1 <= - extDet ) { + // for backward-compatibility - // region 4 + function resetDefaultState() { - 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 ) + c; + defaultState.geometry = null; + defaultState.program = null; + defaultState.wireframe = false; - } else if ( s1 <= extDet ) { + } - // region 3 + return { - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; + setup: setup, + reset: reset, + resetDefaultState: resetDefaultState, + dispose: dispose, + releaseStatesOfGeometry: releaseStatesOfGeometry, + releaseStatesOfProgram: releaseStatesOfProgram, - } else { + initAttributes: initAttributes, + enableAttribute: enableAttribute, + disableUnusedAttributes: disableUnusedAttributes - // region 2 + }; - 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 ) + c; + } - } + function WebGLBufferRenderer( gl, extensions, info ) { - } + let mode; - } else { + function setMode( value ) { - // Ray and segment are parallel. + mode = value; - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + } - } + function render( start, count ) { - if ( optionalPointOnRay ) { + gl.drawArrays( mode, start, count ); - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + info.update( count, mode, 1 ); - } + } - if ( optionalPointOnSegment ) { + function renderInstances( start, count, primcount ) { - optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); + if ( primcount === 0 ) return; - } + gl.drawArraysInstanced( mode, start, count, primcount ); - return sqrDist; + info.update( count, mode, primcount ); - }; + } - }(), + function renderMultiDraw( starts, counts, drawCount ) { - intersectSphere: function () { + if ( drawCount === 0 ) return; - var v1 = new Vector3(); + const extension = extensions.get( 'WEBGL_multi_draw' ); + extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); - return function intersectSphere( sphere, optionalTarget ) { + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - v1.subVectors( sphere.center, this.origin ); - var tca = v1.dot( this.direction ); - var d2 = v1.dot( v1 ) - tca * tca; - var radius2 = sphere.radius * sphere.radius; + elementCount += counts[ i ]; - if ( d2 > radius2 ) return null; + } - var thc = Math.sqrt( radius2 - d2 ); + info.update( elementCount, mode, 1 ); - // t0 = first intersect point - entrance on front of sphere - var t0 = tca - thc; + } - // t1 = second intersect point - exit point on back of sphere - var t1 = tca + thc; + function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + if ( drawCount === 0 ) return; - // test to see if t0 is behind the ray: - // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, - // in order to always return an intersect point that is in front of the ray. - if ( t0 < 0 ) return this.at( t1, optionalTarget ); + const extension = extensions.get( 'WEBGL_multi_draw' ); - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, optionalTarget ); + if ( extension === null ) { - }; + for ( let i = 0; i < starts.length; i ++ ) { - }(), + renderInstances( starts[ i ], counts[ i ], primcount[ i ] ); - intersectsSphere: function ( sphere ) { + } - return this.distanceToPoint( sphere.center ) <= sphere.radius; + } else { - }, + extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount ); - distanceToPlane: function ( plane ) { + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - var denominator = plane.normal.dot( this.direction ); + elementCount += counts[ i ]; - if ( denominator === 0 ) { + } - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { + for ( let i = 0; i < primcount.length; i ++ ) { - return 0; + info.update( elementCount, mode, primcount[ i ] ); } - // Null is preferable to undefined since undefined means.... it is undefined + } - return null; + } - } + // - var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; + this.setMode = setMode; + this.render = render; + this.renderInstances = renderInstances; + this.renderMultiDraw = renderMultiDraw; + this.renderMultiDrawInstances = renderMultiDrawInstances; - // Return if the ray never intersects the plane + } - return t >= 0 ? t : null; + function WebGLCapabilities( gl, extensions, parameters, utils ) { - }, + let maxAnisotropy; - intersectPlane: function ( plane, optionalTarget ) { + function getMaxAnisotropy() { - var t = this.distanceToPlane( plane ); + if ( maxAnisotropy !== undefined ) return maxAnisotropy; - if ( t === null ) { + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { - return null; + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); - } + maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); - return this.at( t, optionalTarget ); + } else { - }, + maxAnisotropy = 0; - intersectsPlane: function ( plane ) { + } - // check if the ray lies on the plane first + return maxAnisotropy; - var distToPoint = plane.distanceToPoint( this.origin ); + } - if ( distToPoint === 0 ) { + function textureFormatReadable( textureFormat ) { - return true; + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + + return false; } - var denominator = plane.normal.dot( this.direction ); + return true; - if ( denominator * distToPoint < 0 ) { + } - return true; + function textureTypeReadable( textureType ) { - } + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ); - // ray origin is behind the plane (and is pointing behind it) + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + textureType !== FloatType && ! halfFloatSupportedByExt ) { - return false; + return false; - }, + } - intersectBox: function ( box, optionalTarget ) { + return true; - var tmin, tmax, tymin, tymax, tzmin, tzmax; + } - var invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; + function getMaxPrecision( precision ) { - var origin = this.origin; + if ( precision === 'highp' ) { - if ( invdirx >= 0 ) { + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { - tmin = ( box.min.x - origin.x ) * invdirx; - tmax = ( box.max.x - origin.x ) * invdirx; + return 'highp'; - } else { + } - tmin = ( box.max.x - origin.x ) * invdirx; - tmax = ( box.min.x - origin.x ) * invdirx; + precision = 'mediump'; } - if ( invdiry >= 0 ) { + if ( precision === 'mediump' ) { - tymin = ( box.min.y - origin.y ) * invdiry; - tymax = ( box.max.y - origin.y ) * invdiry; + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { - } else { + return 'mediump'; - tymin = ( box.max.y - origin.y ) * invdiry; - tymax = ( box.min.y - origin.y ) * invdiry; + } } - if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; + return 'lowp'; - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN + } - if ( tymin > tmin || tmin !== tmin ) tmin = tymin; + let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; + const maxPrecision = getMaxPrecision( precision ); - if ( tymax < tmax || tmax !== tmax ) tmax = tymax; + if ( maxPrecision !== precision ) { - if ( invdirz >= 0 ) { + console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); + precision = maxPrecision; - tzmin = ( box.min.z - origin.z ) * invdirz; - tzmax = ( box.max.z - origin.z ) * invdirz; + } - } else { + const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; - tzmin = ( box.max.z - origin.z ) * invdirz; - tzmax = ( box.min.z - origin.z ) * invdirz; + 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 ); - if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; + const vertexTextures = maxVertexTextures > 0; - if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + const maxSamples = gl.getParameter( gl.MAX_SAMPLES ); - if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + return { - //return point closest to the ray (positive side) + isWebGL2: true, // keeping this for backwards compatibility - if ( tmax < 0 ) return null; + getMaxAnisotropy: getMaxAnisotropy, + getMaxPrecision: getMaxPrecision, - return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); + textureFormatReadable: textureFormatReadable, + textureTypeReadable: textureTypeReadable, - }, + precision: precision, + logarithmicDepthBuffer: logarithmicDepthBuffer, - intersectsBox: ( function () { + maxTextures: maxTextures, + maxVertexTextures: maxVertexTextures, + maxTextureSize: maxTextureSize, + maxCubemapSize: maxCubemapSize, - var v = new Vector3(); + maxAttributes: maxAttributes, + maxVertexUniforms: maxVertexUniforms, + maxVaryings: maxVaryings, + maxFragmentUniforms: maxFragmentUniforms, - return function intersectsBox( box ) { + vertexTextures: vertexTextures, - return this.intersectBox( box, v ) !== null; + maxSamples: maxSamples - }; + }; - } )(), + } - intersectTriangle: function () { + function WebGLClipping( properties ) { - // Compute the offset origin, edges, and normal. - var diff = new Vector3(); - var edge1 = new Vector3(); - var edge2 = new Vector3(); - var normal = new Vector3(); + const scope = this; - return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { + let globalState = null, + numGlobalPlanes = 0, + localClippingEnabled = false, + renderingShadows = false; - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + const plane = new Plane(), + viewNormalMatrix = new Matrix3(), - edge1.subVectors( b, a ); - edge2.subVectors( c, a ); - normal.crossVectors( edge1, edge2 ); + uniform = { value: null, needsUpdate: false }; - // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, - // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by - // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) - // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) - // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) - var DdN = this.direction.dot( normal ); - var sign; + this.uniform = uniform; + this.numPlanes = 0; + this.numIntersection = 0; - if ( DdN > 0 ) { + this.init = function ( planes, enableLocalClipping ) { - if ( backfaceCulling ) return null; - sign = 1; + const enabled = + planes.length !== 0 || + enableLocalClipping || + // enable state of previous frame - the clipping code has to + // run another frame in order to reset the state: + numGlobalPlanes !== 0 || + localClippingEnabled; - } else if ( DdN < 0 ) { + localClippingEnabled = enableLocalClipping; - sign = - 1; - DdN = - DdN; + numGlobalPlanes = planes.length; - } else { + return enabled; - return null; + }; - } + this.beginShadows = function () { - diff.subVectors( this.origin, a ); - var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); + renderingShadows = true; + projectPlanes( null ); - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { + }; - return null; + this.endShadows = function () { - } + renderingShadows = false; - var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); + }; - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { + this.setGlobalState = function ( planes, camera ) { - return null; + globalState = projectPlanes( planes, camera, 0 ); - } + }; - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { + this.setState = function ( material, camera, useCache ) { - return null; + const planes = material.clippingPlanes, + clipIntersection = material.clipIntersection, + clipShadows = material.clipShadows; - } + const materialProperties = properties.get( material ); - // Line intersects triangle, check if ray does. - var QdN = - sign * diff.dot( normal ); + if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { - // t < 0, no intersection - if ( QdN < 0 ) { + // there's no local clipping - return null; + if ( renderingShadows ) { - } + // there's no global clipping - // Ray intersects triangle. - return this.at( QdN / DdN, optionalTarget ); + projectPlanes( null ); - }; + } else { - }(), + resetGlobalState(); - applyMatrix4: function ( matrix4 ) { + } - this.origin.applyMatrix4( matrix4 ); - this.direction.transformDirection( matrix4 ); + } else { - return this; + const nGlobal = renderingShadows ? 0 : numGlobalPlanes, + lGlobal = nGlobal * 4; - }, + let dstArray = materialProperties.clippingState || null; - equals: function ( ray ) { + uniform.value = dstArray; // ensure unique state - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); + dstArray = projectPlanes( planes, camera, lGlobal, useCache ); - } + for ( let i = 0; i !== lGlobal; ++ i ) { - } ); + dstArray[ i ] = globalState[ i ]; - /** - * @author bhouston / http://clara.io - */ + } - function Line3( start, end ) { + materialProperties.clippingState = dstArray; + this.numIntersection = clipIntersection ? this.numPlanes : 0; + this.numPlanes += nGlobal; - this.start = ( start !== undefined ) ? start : new Vector3(); - this.end = ( end !== undefined ) ? end : new Vector3(); + } - } - Object.assign( Line3.prototype, { + }; - set: function ( start, end ) { + function resetGlobalState() { - this.start.copy( start ); - this.end.copy( end ); + if ( uniform.value !== globalState ) { - return this; + uniform.value = globalState; + uniform.needsUpdate = numGlobalPlanes > 0; - }, + } - clone: function () { + scope.numPlanes = numGlobalPlanes; + scope.numIntersection = 0; - return new this.constructor().copy( this ); + } - }, + function projectPlanes( planes, camera, dstOffset, skipTransform ) { - copy: function ( line ) { + const nPlanes = planes !== null ? planes.length : 0; + let dstArray = null; - this.start.copy( line.start ); - this.end.copy( line.end ); + if ( nPlanes !== 0 ) { - return this; + dstArray = uniform.value; - }, + if ( skipTransform !== true || dstArray === null ) { - getCenter: function ( optionalTarget ) { + const flatSize = dstOffset + nPlanes * 4, + viewMatrix = camera.matrixWorldInverse; - var result = optionalTarget || new Vector3(); - return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); + viewNormalMatrix.getNormalMatrix( viewMatrix ); - }, + if ( dstArray === null || dstArray.length < flatSize ) { - delta: function ( optionalTarget ) { + dstArray = new Float32Array( flatSize ); - var result = optionalTarget || new Vector3(); - return result.subVectors( this.end, this.start ); + } - }, + for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { - distanceSq: function () { + plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); - return this.start.distanceToSquared( this.end ); + plane.normal.toArray( dstArray, i4 ); + dstArray[ i4 + 3 ] = plane.constant; - }, + } - distance: function () { + } - return this.start.distanceTo( this.end ); + uniform.value = dstArray; + uniform.needsUpdate = true; - }, + } - at: function ( t, optionalTarget ) { + scope.numPlanes = nPlanes; + scope.numIntersection = 0; - var result = optionalTarget || new Vector3(); + return dstArray; - return this.delta( result ).multiplyScalar( t ).add( this.start ); + } - }, + } - closestPointToPointParameter: function () { + function WebGLCubeMaps( renderer ) { - var startP = new Vector3(); - var startEnd = new Vector3(); + let cubemaps = new WeakMap(); - return function closestPointToPointParameter( point, clampToLine ) { + function mapTextureMapping( texture, mapping ) { - startP.subVectors( point, this.start ); - startEnd.subVectors( this.end, this.start ); + if ( mapping === EquirectangularReflectionMapping ) { - var startEnd2 = startEnd.dot( startEnd ); - var startEnd_startP = startEnd.dot( startP ); + texture.mapping = CubeReflectionMapping; - var t = startEnd_startP / startEnd2; + } else if ( mapping === EquirectangularRefractionMapping ) { - if ( clampToLine ) { + texture.mapping = CubeRefractionMapping; - t = _Math.clamp( t, 0, 1 ); + } - } + return texture; - return t; + } - }; + function get( texture ) { - }(), + if ( texture && texture.isTexture ) { - closestPointToPoint: function ( point, clampToLine, optionalTarget ) { + const mapping = texture.mapping; - var t = this.closestPointToPointParameter( point, clampToLine ); + if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { - var result = optionalTarget || new Vector3(); + if ( cubemaps.has( texture ) ) { - return this.delta( result ).multiplyScalar( t ).add( this.start ); + const cubemap = cubemaps.get( texture ).texture; + return mapTextureMapping( cubemap, texture.mapping ); - }, + } else { - applyMatrix4: function ( matrix ) { + const image = texture.image; - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); + if ( image && image.height > 0 ) { - return this; + const renderTarget = new WebGLCubeRenderTarget( image.height ); + renderTarget.fromEquirectangularTexture( renderer, texture ); + cubemaps.set( texture, renderTarget ); - }, + texture.addEventListener( 'dispose', onTextureDispose ); - equals: function ( line ) { + return mapTextureMapping( renderTarget.texture, texture.mapping ); - return line.start.equals( this.start ) && line.end.equals( this.end ); + } else { - } + // image not yet ready. try the conversion next frame - } ); + return null; - /** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ + } - function Triangle( a, b, c ) { + } - this.a = ( a !== undefined ) ? a : new Vector3(); - this.b = ( b !== undefined ) ? b : new Vector3(); - this.c = ( c !== undefined ) ? c : new Vector3(); + } - } + } - Object.assign( Triangle, { + return texture; - normal: function () { + } - var v0 = new Vector3(); + function onTextureDispose( event ) { - return function normal( a, b, c, optionalTarget ) { + const texture = event.target; - var result = optionalTarget || new Vector3(); + texture.removeEventListener( 'dispose', onTextureDispose ); - result.subVectors( c, b ); - v0.subVectors( a, b ); - result.cross( v0 ); + const cubemap = cubemaps.get( texture ); - var resultLengthSq = result.lengthSq(); - if ( resultLengthSq > 0 ) { + if ( cubemap !== undefined ) { - return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); + cubemaps.delete( texture ); + cubemap.dispose(); - } + } - return result.set( 0, 0, 0 ); + } - }; + function dispose() { - }(), + cubemaps = new WeakMap(); - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - barycoordFromPoint: function () { + } - var v0 = new Vector3(); - var v1 = new Vector3(); - var v2 = new Vector3(); + return { + get: get, + dispose: dispose + }; - return function barycoordFromPoint( point, a, b, c, optionalTarget ) { + } - v0.subVectors( c, a ); - v1.subVectors( b, a ); - v2.subVectors( point, a ); + class OrthographicCamera extends Camera { - var dot00 = v0.dot( v0 ); - var dot01 = v0.dot( v1 ); - var dot02 = v0.dot( v2 ); - var dot11 = v1.dot( v1 ); - var dot12 = v1.dot( v2 ); + constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { - var denom = ( dot00 * dot11 - dot01 * dot01 ); + super(); - var result = optionalTarget || new Vector3(); + this.isOrthographicCamera = true; - // collinear or singular triangle - if ( denom === 0 ) { + this.type = 'OrthographicCamera'; - // arbitrary location outside of triangle? - // not sure if this is the best idea, maybe should be returning undefined - return result.set( - 2, - 1, - 1 ); + this.zoom = 1; + this.view = null; - } + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; - var invDenom = 1 / denom; - var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + this.near = near; + this.far = far; - // barycentric coordinates must always sum to 1 - return result.set( 1 - u - v, v, u ); + this.updateProjectionMatrix(); - }; + } - }(), + copy( source, recursive ) { - containsPoint: function () { + super.copy( source, recursive ); - var v1 = new Vector3(); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; - return function containsPoint( point, a, b, c ) { + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); + return this; - return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); + } - }; + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - }() + if ( this.view === null ) { - } ); + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - Object.assign( Triangle.prototype, { + } - set: function ( a, b, c ) { + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); + this.updateProjectionMatrix(); - return this; + } - }, + clearViewOffset() { - setFromPointsAndIndices: function ( points, i0, i1, i2 ) { + if ( this.view !== null ) { - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); + this.view.enabled = false; - return this; + } - }, + this.updateProjectionMatrix(); - clone: function () { + } - return new this.constructor().copy( this ); + 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; - copy: function ( triangle ) { + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); + if ( this.view !== null && this.view.enabled ) { - return this; + 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; - area: function () { + } - var v0 = new Vector3(); - var v1 = new Vector3(); + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); - return function area() { + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - v0.subVectors( this.c, this.b ); - v1.subVectors( this.a, this.b ); + } - return v0.cross( v1 ).length() * 0.5; + 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; - midpoint: function ( optionalTarget ) { + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - var result = optionalTarget || new Vector3(); - return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + return data; - }, + } - normal: function ( optionalTarget ) { + } - return Triangle.normal( this.a, this.b, this.c, optionalTarget ); + const LOD_MIN = 4; + + // The standard deviations (radians) associated with the extra mips. These are + // chosen to approximate a Trowbridge-Reitz distribution function times the + // geometric shadowing function. These sigma values squared must match the + // variance #defines in cube_uv_reflection_fragment.glsl.js. + const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; + + // The maximum length of the blur for loop. Smaller sigmas will use fewer + // samples and exit early, but not recompile the shader. + const MAX_SAMPLES = 20; + + const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); + const _clearColor = /*@__PURE__*/ new Color(); + let _oldTarget = null; + let _oldActiveCubeFace = 0; + let _oldActiveMipmapLevel = 0; + let _oldXrEnabled = false; + + // Golden Ratio + const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; + const INV_PHI = 1 / PHI; + + // Vertices of a dodecahedron (except the opposites, which represent the + // same axis), used as axis directions evenly spread on a sphere. + const _axisDirections = [ + /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), + /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( - 1, 1, 1 ), + /*@__PURE__*/ new Vector3( 1, 1, 1 ) ]; + + /** + * This class generates a Prefiltered, Mipmapped Radiance Environment Map + * (PMREM) from a cubeMap environment texture. This allows different levels of + * blur to be quickly accessed based on material roughness. It is packed into a + * special CubeUV format that allows us to perform custom interpolation so that + * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap + * chain, it only goes down to the LOD_MIN level (above), and then creates extra + * even more filtered 'mips' at the same LOD_MIN resolution, associated with + * higher roughness levels. In this way we maintain resolution to smoothly + * interpolate diffuse lighting while limiting sampling computation. + * + * Paper: Fast, Accurate Image-Based Lighting + * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view + */ - }, + class PMREMGenerator { - plane: function ( optionalTarget ) { + constructor( renderer ) { - var result = optionalTarget || new Plane(); + this._renderer = renderer; + this._pingPongRenderTarget = null; - return result.setFromCoplanarPoints( this.a, this.b, this.c ); + this._lodMax = 0; + this._cubeSize = 0; + this._lodPlanes = []; + this._sizeLods = []; + this._sigmas = []; - }, + this._blurMaterial = null; + this._cubemapMaterial = null; + this._equirectMaterial = null; - barycoordFromPoint: function ( point, optionalTarget ) { + this._compileMaterial( this._blurMaterial ); - return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); + } - }, + /** + * Generates a PMREM from a supplied Scene, which can be faster than using an + * image if networking bandwidth is low. Optional sigma specifies a blur radius + * in radians to be applied to the scene before PMREM generation. Optional near + * and far planes ensure the scene is rendered in its entirety (the cubeCamera + * is placed at the origin). + */ + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { - containsPoint: function ( point ) { + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + _oldXrEnabled = this._renderer.xr.enabled; - return Triangle.containsPoint( point, this.a, this.b, this.c ); + this._renderer.xr.enabled = false; - }, + this._setSize( 256 ); - closestPointToPoint: function () { + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; - var plane = new Plane(); - var edgeList = [ new Line3(), new Line3(), new Line3() ]; - var projectedPoint = new Vector3(); - var closestPoint = new Vector3(); + this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); - return function closestPointToPoint( point, optionalTarget ) { + if ( sigma > 0 ) { - var result = optionalTarget || new Vector3(); - var minDistance = Infinity; + this._blur( cubeUVRenderTarget, 0, 0, sigma ); - // project the point onto the plane of the triangle + } - plane.setFromCoplanarPoints( this.a, this.b, this.c ); - plane.projectPoint( point, projectedPoint ); + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); - // check if the projection lies within the triangle + return cubeUVRenderTarget; - if ( this.containsPoint( projectedPoint ) === true ) { + } - // if so, this is the closest point + /** + * Generates a PMREM from an equirectangular texture, which can be either LDR + * or HDR. The ideal input image size is 1k (1024 x 512), + * as this matches best with the 256 x 256 cubemap output. + * The smallest supported equirectangular image size is 64 x 32. + */ + fromEquirectangular( equirectangular, renderTarget = null ) { - result.copy( projectedPoint ); + return this._fromTexture( equirectangular, renderTarget ); - } else { + } - // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices + /** + * Generates a PMREM from an cubemap texture, which can be either LDR + * or HDR. The ideal input cube size is 256 x 256, + * as this matches best with the 256 x 256 cubemap output. + * The smallest supported cube size is 16 x 16. + */ + fromCubemap( cubemap, renderTarget = null ) { - edgeList[ 0 ].set( this.a, this.b ); - edgeList[ 1 ].set( this.b, this.c ); - edgeList[ 2 ].set( this.c, this.a ); + return this._fromTexture( cubemap, renderTarget ); - for ( var i = 0; i < edgeList.length; i ++ ) { + } - edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); + /** + * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + compileCubemapShader() { - var distance = projectedPoint.distanceToSquared( closestPoint ); + if ( this._cubemapMaterial === null ) { - if ( distance < minDistance ) { + this._cubemapMaterial = _getCubemapMaterial(); + this._compileMaterial( this._cubemapMaterial ); - minDistance = distance; + } - result.copy( closestPoint ); + } - } + /** + * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + compileEquirectangularShader() { - } + if ( this._equirectMaterial === null ) { - } + this._equirectMaterial = _getEquirectMaterial(); + this._compileMaterial( this._equirectMaterial ); - return result; + } - }; + } - }(), + /** + * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, + * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on + * one of them will cause any others to also become unusable. + */ + dispose() { - equals: function ( triangle ) { + this._dispose(); - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); + if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); } - } ); + // private interface - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author jonobr1 / http://jonobr1.com/ - */ + _setSize( cubeSize ) { - function Mesh( geometry, material ) { + this._lodMax = Math.floor( Math.log2( cubeSize ) ); + this._cubeSize = Math.pow( 2, this._lodMax ); - Object3D.call( this ); + } - this.type = 'Mesh'; + _dispose() { - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); + if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); - this.drawMode = TrianglesDrawMode; + if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); - this.updateMorphTargets(); + for ( let i = 0; i < this._lodPlanes.length; i ++ ) { - } + this._lodPlanes[ i ].dispose(); - Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: Mesh, + } - isMesh: true, + _cleanup( outputTarget ) { - setDrawMode: function ( value ) { + this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); + this._renderer.xr.enabled = _oldXrEnabled; - this.drawMode = value; + outputTarget.scissorTest = false; + _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); - }, + } - copy: function ( source ) { + _fromTexture( texture, renderTarget ) { - Object3D.prototype.copy.call( this, source ); + if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { - this.drawMode = source.drawMode; + this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); - if ( source.morphTargetInfluences !== undefined ) { + } else { // Equirectangular - this.morphTargetInfluences = source.morphTargetInfluences.slice(); + this._setSize( texture.image.width / 4 ); } - if ( source.morphTargetDictionary !== undefined ) { + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + _oldXrEnabled = this._renderer.xr.enabled; - this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); + this._renderer.xr.enabled = false; - } + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV( texture, cubeUVRenderTarget ); + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); - return this; + return cubeUVRenderTarget; - }, + } - updateMorphTargets: function () { + _allocateTargets() { - var geometry = this.geometry; - var m, ml, name; + const width = 3 * Math.max( this._cubeSize, 16 * 7 ); + const height = 4 * this._cubeSize; - if ( geometry.isBufferGeometry ) { + const params = { + magFilter: LinearFilter, + minFilter: LinearFilter, + generateMipmaps: false, + type: HalfFloatType, + format: RGBAFormat, + colorSpace: LinearSRGBColorSpace, + depthBuffer: false + }; - var morphAttributes = geometry.morphAttributes; - var keys = Object.keys( morphAttributes ); + const cubeUVRenderTarget = _createRenderTarget( width, height, params ); - if ( keys.length > 0 ) { + if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { - var morphAttribute = morphAttributes[ keys[ 0 ] ]; + if ( this._pingPongRenderTarget !== null ) { - if ( morphAttribute !== undefined ) { + this._dispose(); - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; + } - for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { + this._pingPongRenderTarget = _createRenderTarget( width, height, params ); - name = morphAttribute[ m ].name || String( m ); + const { _lodMax } = this; + ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; + this._blurMaterial = _getBlurShader( _lodMax, width, height ); - } + } - } + return cubeUVRenderTarget; - } + } - } else { + _compileMaterial( material ) { - var morphTargets = geometry.morphTargets; + const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); + this._renderer.compile( tmpMesh, _flatCamera ); - if ( morphTargets !== undefined && morphTargets.length > 0 ) { + } - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; + _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { - for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { + const fov = 90; + const aspect = 1; + const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); + const upSign = [ 1, - 1, 1, 1, 1, 1 ]; + const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; + const renderer = this._renderer; - name = morphTargets[ m ].name || String( m ); + const originalAutoClear = renderer.autoClear; + const toneMapping = renderer.toneMapping; + renderer.getClearColor( _clearColor ); - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; + 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 ) { - raycast: ( function () { + if ( background.isColor ) { - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + backgroundMaterial.color.copy( background ); + scene.background = null; + useSolidColor = true; - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); + } - var tempA = new Vector3(); - var tempB = new Vector3(); - var tempC = new Vector3(); + } else { - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + backgroundMaterial.color.copy( _clearColor ); + useSolidColor = true; - var barycoord = new Vector3(); + } - var intersectionPoint = new Vector3(); - var intersectionPointWorld = new Vector3(); + for ( let i = 0; i < 6; i ++ ) { - function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { + const col = i % 3; - Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); + if ( col === 0 ) { - uv1.multiplyScalar( barycoord.x ); - uv2.multiplyScalar( barycoord.y ); - uv3.multiplyScalar( barycoord.z ); + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); - uv1.add( uv2 ).add( uv3 ); + } else if ( col === 1 ) { - return uv1.clone(); + cubeCamera.up.set( 0, 0, upSign[ i ] ); + cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); - } + } else { - function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); - var intersect; + } - if ( material.side === BackSide ) { + const size = this._cubeSize; - intersect = ray.intersectTriangle( pC, pB, pA, true, point ); + _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); - } else { + renderer.setRenderTarget( cubeUVRenderTarget ); - intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); + if ( useSolidColor ) { + + renderer.render( backgroundBox, cubeCamera ); } - if ( intersect === null ) return null; + renderer.render( scene, cubeCamera ); - intersectionPointWorld.copy( point ); - intersectionPointWorld.applyMatrix4( object.matrixWorld ); + } - var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); + backgroundBox.geometry.dispose(); + backgroundBox.material.dispose(); - if ( distance < raycaster.near || distance > raycaster.far ) return null; + renderer.toneMapping = toneMapping; + renderer.autoClear = originalAutoClear; + scene.background = background; - return { - distance: distance, - point: intersectionPointWorld.clone(), - object: object - }; + } - } + _textureToCubeUV( texture, cubeUVRenderTarget ) { - function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { + const renderer = this._renderer; - vA.fromBufferAttribute( position, a ); - vB.fromBufferAttribute( position, b ); - vC.fromBufferAttribute( position, c ); + const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); - var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); + if ( isCubeTexture ) { - if ( intersection ) { + if ( this._cubemapMaterial === null ) { - if ( uv ) { + this._cubemapMaterial = _getCubemapMaterial(); - uvA.fromBufferAttribute( uv, a ); - uvB.fromBufferAttribute( uv, b ); - uvC.fromBufferAttribute( uv, c ); + } - intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); + this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; - } + } else { - intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); - intersection.faceIndex = a; + if ( this._equirectMaterial === null ) { - } + this._equirectMaterial = _getEquirectMaterial(); - return intersection; + } } - return function raycast( raycaster, intersects ) { + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + const mesh = new Mesh( this._lodPlanes[ 0 ], material ); - var geometry = this.geometry; - var material = this.material; - var matrixWorld = this.matrixWorld; + const uniforms = material.uniforms; - if ( material === undefined ) return; + uniforms[ 'envMap' ].value = texture; - // Checking boundingSphere distance to ray + const size = this._cubeSize; - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); + renderer.setRenderTarget( cubeUVRenderTarget ); + renderer.render( mesh, _flatCamera ); - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; + } - // + _applyPMREM( cubeUVRenderTarget ) { - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + const n = this._lodPlanes.length; - // Check boundingBox before continuing + for ( let i = 1; i < n; i ++ ) { - if ( geometry.boundingBox !== null ) { + const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); - if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; + const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; - } + this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); - var intersection; + } - if ( geometry.isBufferGeometry ) { + renderer.autoClear = autoClear; - var a, b, c; - var index = geometry.index; - var position = geometry.attributes.position; - var uv = geometry.attributes.uv; - var i, l; + } - if ( index !== null ) { + /** + * This is a two-pass Gaussian blur for a cubemap. Normally this is done + * vertically and horizontally, but this breaks down on a cube. Here we apply + * the blur latitudinally (around the poles), and then longitudinally (towards + * the poles) to approximate the orthogonally-separable blur. It is least + * accurate at the poles, but still does a decent job. + */ + _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { - // indexed buffer geometry + const pingPongRenderTarget = this._pingPongRenderTarget; - for ( i = 0, l = index.count; i < l; i += 3 ) { + this._halfBlur( + cubeUVRenderTarget, + pingPongRenderTarget, + lodIn, + lodOut, + sigma, + 'latitudinal', + poleAxis ); - a = index.getX( i ); - b = index.getX( i + 1 ); - c = index.getX( i + 2 ); + this._halfBlur( + pingPongRenderTarget, + cubeUVRenderTarget, + lodOut, + lodOut, + sigma, + 'longitudinal', + poleAxis ); - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); + } - if ( intersection ) { - - intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics - intersects.push( intersection ); - - } - - } - - } else if ( position !== undefined ) { + _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { - // non-indexed buffer geometry + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; - for ( i = 0, l = position.count; i < l; i += 3 ) { + if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { - a = i; - b = i + 1; - c = i + 2; + console.error( + 'blur direction must be either latitudinal or longitudinal!' ); - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { + } - intersection.index = a; // triangle number in positions buffer semantics - intersects.push( intersection ); + // Number of standard deviations at which to cut off the discrete approximation. + 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 ) { - } else if ( geometry.isGeometry ) { + console.warn( `sigmaRadians, ${ + sigmaRadians}, is too large and will clip, as it requested ${ + samples} samples when the maximum is set to ${MAX_SAMPLES}` ); - var fvA, fvB, fvC; - var isMultiMaterial = Array.isArray( material ); + } - var vertices = geometry.vertices; - var faces = geometry.faces; - var uvs; + const weights = []; + let sum = 0; - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; + for ( let i = 0; i < MAX_SAMPLES; ++ i ) { - for ( var f = 0, fl = faces.length; f < fl; f ++ ) { + const x = i / sigmaPixels; + const weight = Math.exp( - x * x / 2 ); + weights.push( weight ); - var face = faces[ f ]; - var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; + if ( i === 0 ) { - if ( faceMaterial === undefined ) continue; + sum += weight; - fvA = vertices[ face.a ]; - fvB = vertices[ face.b ]; - fvC = vertices[ face.c ]; + } else if ( i < samples ) { - if ( faceMaterial.morphTargets === true ) { + sum += 2 * weight; - var morphTargets = geometry.morphTargets; - var morphInfluences = this.morphTargetInfluences; + } - vA.set( 0, 0, 0 ); - vB.set( 0, 0, 0 ); - vC.set( 0, 0, 0 ); + } - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { + for ( let i = 0; i < weights.length; i ++ ) { - var influence = morphInfluences[ t ]; + weights[ i ] = weights[ i ] / sum; - if ( influence === 0 ) continue; + } - var targets = morphTargets[ t ].vertices; + blurUniforms[ 'envMap' ].value = targetIn.texture; + blurUniforms[ 'samples' ].value = samples; + blurUniforms[ 'weights' ].value = weights; + blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; - vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); - vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); - vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); + if ( poleAxis ) { - } + blurUniforms[ 'poleAxis' ].value = poleAxis; - vA.add( fvA ); - vB.add( fvB ); - vC.add( fvC ); + } - fvA = vA; - fvB = vB; - fvC = vC; + const { _lodMax } = this; + blurUniforms[ 'dTheta' ].value = radiansPerPixel; + blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; - } + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); - intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); + _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( targetOut ); + renderer.render( blurMesh, _flatCamera ); - if ( intersection ) { + } - if ( uvs && uvs[ f ] ) { + } - var uvs_f = uvs[ f ]; - uvA.copy( uvs_f[ 0 ] ); - uvB.copy( uvs_f[ 1 ] ); - uvC.copy( uvs_f[ 2 ] ); - intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); - } + function _createPlanes( lodMax ) { - intersection.face = face; - intersection.faceIndex = f; - intersects.push( intersection ); + 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.0 / sizeLod; - }() ), + if ( i > lodMax - LOD_MIN ) { - clone: function () { + sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; - return new this.constructor( this.geometry, this.material ).copy( this ); + } else if ( i === 0 ) { - } + sigma = 0; - } ); + } - /** - * @author mrdoob / http://mrdoob.com/ - */ + sigmas.push( sigma ); - function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) { + const texelSize = 1.0 / ( sizeLod - 2 ); + const min = - texelSize; + const max = 1 + texelSize; + const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; - var clearColor = new Color( 0x000000 ); - var clearAlpha = 0; + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; - var planeCamera, planeMesh; - var boxMesh; + const position = new Float32Array( positionSize * vertices * cubeFaces ); + const uv = new Float32Array( uvSize * vertices * cubeFaces ); + const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); - function render( renderList, scene, camera, forceClear ) { + for ( let face = 0; face < cubeFaces; face ++ ) { - var background = scene.background; + const x = ( face % 3 ) * 2 / 3 - 1; + const y = face > 2 ? 0 : - 1; + const coordinates = [ + x, y, 0, + x + 2 / 3, y, 0, + x + 2 / 3, y + 1, 0, + x, y, 0, + x + 2 / 3, y + 1, 0, + x, y + 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 ); - if ( background === null ) { + } - setClear( clearColor, clearAlpha ); + 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 ); - } else if ( background && background.isColor ) { + if ( lod > LOD_MIN ) { - setClear( background, 1 ); - forceClear = true; + lod --; } - if ( renderer.autoClear || forceClear ) { + } - renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); + return { lodPlanes, sizeLods, sigmas }; - } + } - if ( background && background.isCubeTexture ) { + function _createRenderTarget( width, height, params ) { - if ( boxMesh === undefined ) { + const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; + cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; - boxMesh = new Mesh( - new BoxBufferGeometry( 1, 1, 1 ), - new ShaderMaterial( { - uniforms: ShaderLib.cube.uniforms, - vertexShader: ShaderLib.cube.vertexShader, - fragmentShader: ShaderLib.cube.fragmentShader, - side: BackSide, - depthTest: true, - depthWrite: false, - fog: false - } ) - ); + } - boxMesh.geometry.removeAttribute( 'normal' ); - boxMesh.geometry.removeAttribute( 'uv' ); + function _setViewport( target, x, y, width, height ) { - boxMesh.onBeforeRender = function ( renderer, scene, camera ) { + target.viewport.set( x, y, width, height ); + target.scissor.set( x, y, width, height ); - this.matrixWorld.copyPosition( camera.matrixWorld ); + } - }; + function _getBlurShader( lodMax, width, height ) { - geometries.update( boxMesh.geometry ); + const weights = new Float32Array( MAX_SAMPLES ); + const poleAxis = new Vector3( 0, 1, 0 ); + const shaderMaterial = new ShaderMaterial( { - } + name: 'SphericalGaussianBlur', - boxMesh.material.uniforms.tCube.value = background; + defines: { + 'n': MAX_SAMPLES, + 'CUBEUV_TEXEL_WIDTH': 1.0 / width, + 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, + 'CUBEUV_MAX_MIP': `${lodMax}.0`, + }, - renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); + uniforms: { + 'envMap': { value: null }, + 'samples': { value: 1 }, + 'weights': { value: weights }, + 'latitudinal': { value: false }, + 'dTheta': { value: 0 }, + 'mipInt': { value: 0 }, + 'poleAxis': { value: poleAxis } + }, - } else if ( background && background.isTexture ) { + vertexShader: _getCommonVertexShader(), - if ( planeCamera === undefined ) { + fragmentShader: /* glsl */` - planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); + precision mediump float; + precision mediump int; - planeMesh = new Mesh( - new PlaneBufferGeometry( 2, 2 ), - new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) - ); + varying vec3 vOutputDirection; - geometries.update( planeMesh.geometry ); + 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 - planeMesh.material.map = background; + vec3 getSample( float theta, vec3 axis ) { - // TODO Push this to renderList + float cosTheta = cos( theta ); + // Rodrigues' axis-angle rotation + vec3 sampleDirection = vOutputDirection * cosTheta + + cross( axis, vOutputDirection ) * sin( theta ) + + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); - renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); + return bilinearCubeUV( envMap, sampleDirection, mipInt ); } - } + void main() { - function setClear( color, alpha ) { + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); - state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { - } + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); - return { + } - getClearColor: function () { + axis = normalize( axis ); - return clearColor; + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); - }, - setClearColor: function ( color, alpha ) { + for ( int i = 1; i < n; i++ ) { - clearColor.set( color ); - clearAlpha = alpha !== undefined ? alpha : 1; - setClear( clearColor, clearAlpha ); + if ( i >= samples ) { - }, - getClearAlpha: function () { + break; - return clearAlpha; + } - }, - setClearAlpha: function ( alpha ) { + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); - clearAlpha = alpha; - setClear( clearColor, clearAlpha ); + } - }, - render: render + } + `, - }; + blending: NoBlending, + depthTest: false, + depthWrite: false - } + } ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + return shaderMaterial; - function painterSortStable( a, b ) { + } - if ( a.renderOrder !== b.renderOrder ) { + function _getEquirectMaterial() { - return a.renderOrder - b.renderOrder; + return new ShaderMaterial( { - } else if ( a.program && b.program && a.program !== b.program ) { + name: 'EquirectangularToCubeUV', - return a.program.id - b.program.id; + uniforms: { + 'envMap': { value: null } + }, - } else if ( a.material.id !== b.material.id ) { + vertexShader: _getCommonVertexShader(), - return a.material.id - b.material.id; + fragmentShader: /* glsl */` - } else if ( a.z !== b.z ) { + precision mediump float; + precision mediump int; - return a.z - b.z; + varying vec3 vOutputDirection; - } else { + uniform sampler2D envMap; - return a.id - b.id; + #include - } + void main() { - } + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); - function reversePainterSortStable( a, b ) { + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); - if ( a.renderOrder !== b.renderOrder ) { + } + `, - return a.renderOrder - b.renderOrder; + blending: NoBlending, + depthTest: false, + depthWrite: false - } if ( a.z !== b.z ) { + } ); - return b.z - a.z; + } - } else { + function _getCubemapMaterial() { - return a.id - b.id; + return new ShaderMaterial( { - } + name: 'CubemapToCubeUV', - } + uniforms: { + 'envMap': { value: null }, + 'flipEnvMap': { value: - 1 } + }, - function WebGLRenderList() { + vertexShader: _getCommonVertexShader(), - var renderItems = []; - var renderItemsIndex = 0; + fragmentShader: /* glsl */` - var opaque = []; - var transparent = []; + precision mediump float; + precision mediump int; - function init() { + uniform float flipEnvMap; - renderItemsIndex = 0; + varying vec3 vOutputDirection; - opaque.length = 0; - transparent.length = 0; + uniform samplerCube envMap; - } + void main() { - function push( object, geometry, material, z, group ) { + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); - var renderItem = renderItems[ renderItemsIndex ]; + } + `, - if ( renderItem === undefined ) { + blending: NoBlending, + depthTest: false, + depthWrite: false - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - program: material.program, - renderOrder: object.renderOrder, - z: z, - group: group - }; + } ); - renderItems[ renderItemsIndex ] = renderItem; + } - } else { + function _getCommonVertexShader() { - renderItem.id = object.id; - renderItem.object = object; - renderItem.geometry = geometry; - renderItem.material = material; - renderItem.program = material.program; - renderItem.renderOrder = object.renderOrder; - renderItem.z = z; - renderItem.group = group; + return /* glsl */` - } + precision mediump float; + precision mediump int; - ( material.transparent === true ? transparent : opaque ).push( renderItem ); + attribute float faceIndex; - renderItemsIndex ++; + varying vec3 vOutputDirection; - } + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { - function sort() { + uv = 2.0 * uv - 1.0; - if ( opaque.length > 1 ) opaque.sort( painterSortStable ); - if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable ); + vec3 direction = vec3( uv, 1.0 ); - } + if ( face == 0.0 ) { - return { - opaque: opaque, - transparent: transparent, + direction = direction.zyx; // ( 1, v, u ) pos x - init: init, - push: push, + } else if ( face == 1.0 ) { - sort: sort - }; + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y - } + } else if ( face == 2.0 ) { - function WebGLRenderLists() { + direction.x *= -1.0; // ( -u, v, 1 ) pos z - var lists = {}; + } else if ( face == 3.0 ) { - function get( scene, camera ) { + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x - var hash = scene.id + ',' + camera.id; - var list = lists[ hash ]; + } else if ( face == 4.0 ) { - if ( list === undefined ) { + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y - // console.log( 'THREE.WebGLRenderLists:', hash ); + } else if ( face == 5.0 ) { - list = new WebGLRenderList(); - lists[ hash ] = list; + direction.z *= -1.0; // ( u, v, -1 ) neg z } - return list; + return direction; } - function dispose() { + void main() { - lists = {}; + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); } - - return { - get: get, - dispose: dispose - }; + `; } - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function absNumericalSort( a, b ) { + function WebGLCubeUVMaps( renderer ) { - return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); + let cubeUVmaps = new WeakMap(); - } - - function WebGLMorphtargets( gl ) { + let pmremGenerator = null; - var influencesList = {}; - var morphInfluences = new Float32Array( 8 ); + function get( texture ) { - function update( object, geometry, material, program ) { + if ( texture && texture.isTexture ) { - var objectInfluences = object.morphTargetInfluences; + const mapping = texture.mapping; - var length = objectInfluences.length; + const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); + const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); - var influences = influencesList[ geometry.id ]; + // equirect/cube map to cubeUV conversion - if ( influences === undefined ) { + if ( isEquirectMap || isCubeMap ) { - // initialise list + let renderTarget = cubeUVmaps.get( texture ); - influences = []; + const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0; - for ( var i = 0; i < length; i ++ ) { + if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) { - influences[ i ] = [ i, 0 ]; + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); - } + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); + renderTarget.texture.pmremVersion = texture.pmremVersion; - influencesList[ geometry.id ] = influences; + cubeUVmaps.set( texture, renderTarget ); - } + return renderTarget.texture; - var morphTargets = material.morphTargets && geometry.morphAttributes.position; - var morphNormals = material.morphNormals && geometry.morphAttributes.normal; + } else { - // Remove current morphAttributes + if ( renderTarget !== undefined ) { - for ( var i = 0; i < length; i ++ ) { + return renderTarget.texture; - var influence = influences[ i ]; + } else { - if ( influence[ 1 ] !== 0 ) { + const image = texture.image; - if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i ); - if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i ); + if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { - } + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); - } + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); + renderTarget.texture.pmremVersion = texture.pmremVersion; - // Collect influences + cubeUVmaps.set( texture, renderTarget ); - for ( var i = 0; i < length; i ++ ) { + texture.addEventListener( 'dispose', onTextureDispose ); - var influence = influences[ i ]; + return renderTarget.texture; - influence[ 0 ] = i; - influence[ 1 ] = objectInfluences[ i ]; + } else { - } + // image not yet ready. try the conversion next frame - influences.sort( absNumericalSort ); + return null; - // Add morphAttributes + } - for ( var i = 0; i < 8; i ++ ) { + } - var influence = influences[ i ]; + } - if ( influence ) { + } - var index = influence[ 0 ]; - var value = influence[ 1 ]; + } - if ( value ) { + return texture; - if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); - if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); + } - morphInfluences[ i ] = value; - continue; + function isCubeTextureComplete( image ) { - } + let count = 0; + const length = 6; - } + for ( let i = 0; i < length; i ++ ) { - morphInfluences[ i ] = 0; + if ( image[ i ] !== undefined ) count ++; } - program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); + return count === length; + } - return { + function onTextureDispose( event ) { - update: update + const texture = event.target; - }; + texture.removeEventListener( 'dispose', onTextureDispose ); - } + const cubemapUV = cubeUVmaps.get( texture ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + if ( cubemapUV !== undefined ) { - function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { + cubeUVmaps.delete( texture ); + cubemapUV.dispose(); - var mode; + } - function setMode( value ) { + } - mode = value; + function dispose() { - } + cubeUVmaps = new WeakMap(); - var type, bytesPerElement; + if ( pmremGenerator !== null ) { - function setIndex( value ) { + pmremGenerator.dispose(); + pmremGenerator = null; - type = value.type; - bytesPerElement = value.bytesPerElement; + } } - function render( start, count ) { + return { + get: get, + dispose: dispose + }; - gl.drawElements( mode, count, type, start * bytesPerElement ); + } - infoRender.calls ++; - infoRender.vertices += count; + function WebGLExtensions( gl ) { - if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; - else if ( mode === gl.POINTS ) infoRender.points += count; + const extensions = {}; - } + function getExtension( name ) { - function renderInstances( geometry, start, count ) { + if ( extensions[ name ] !== undefined ) { - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + return extensions[ name ]; - if ( extension === null ) { + } - console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + let extension; - } + switch ( name ) { - extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); + case 'WEBGL_depth_texture': + extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); + break; - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; + 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; - if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; - else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; + 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 ); - this.setMode = setMode; - this.setIndex = setIndex; - this.render = render; - this.renderInstances = renderInstances; + } - } + extensions[ name ] = extension; - /** - * @author mrdoob / http://mrdoob.com/ - */ + return extension; - function WebGLBufferRenderer( gl, extensions, infoRender ) { + } - var mode; + return { - function setMode( value ) { + has: function ( name ) { - mode = value; + return getExtension( name ) !== null; - } + }, - function render( start, count ) { + init: function () { - gl.drawArrays( mode, start, count ); + getExtension( 'EXT_color_buffer_float' ); + getExtension( 'WEBGL_clip_cull_distance' ); + getExtension( 'OES_texture_float_linear' ); + getExtension( 'EXT_color_buffer_half_float' ); + getExtension( 'WEBGL_multisampled_render_to_texture' ); + getExtension( 'WEBGL_render_shared_exponent' ); - infoRender.calls ++; - infoRender.vertices += count; + }, - if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; - else if ( mode === gl.POINTS ) infoRender.points += count; + get: function ( name ) { - } + const extension = getExtension( name ); - function renderInstances( geometry, start, count ) { + if ( extension === null ) { - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + warnOnce( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); - if ( extension === null ) { + } - console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + return extension; } - var position = geometry.attributes.position; + }; - if ( position.isInterleavedBufferAttribute ) { + } - count = position.data.count; + function WebGLGeometries( gl, attributes, info, bindingStates ) { - extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount ); + const geometries = {}; + const wireframeAttributes = new WeakMap(); - } else { - - extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount ); - - } - - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; - - if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; - else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; - - } - - // + function onGeometryDispose( event ) { - this.setMode = setMode; - this.render = render; - this.renderInstances = renderInstances; + const geometry = event.target; - } + if ( geometry.index !== null ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + attributes.remove( geometry.index ); - function WebGLGeometries( gl, attributes, infoMemory ) { + } - var geometries = {}; - var wireframeAttributes = {}; + for ( const name in geometry.attributes ) { - function onGeometryDispose( event ) { + attributes.remove( geometry.attributes[ name ] ); - var geometry = event.target; - var buffergeometry = geometries[ geometry.id ]; + } - if ( buffergeometry.index !== null ) { + for ( const name in geometry.morphAttributes ) { - attributes.remove( buffergeometry.index ); + const array = geometry.morphAttributes[ name ]; - } + for ( let i = 0, l = array.length; i < l; i ++ ) { - for ( var name in buffergeometry.attributes ) { + attributes.remove( array[ i ] ); - attributes.remove( buffergeometry.attributes[ name ] ); + } } @@ -16940,76 +16997,50 @@ var ROS3D = (function (exports, ROSLIB) { delete geometries[ geometry.id ]; - // TODO Remove duplicate code - - var attribute = wireframeAttributes[ geometry.id ]; + const attribute = wireframeAttributes.get( geometry ); if ( attribute ) { attributes.remove( attribute ); - delete wireframeAttributes[ geometry.id ]; + wireframeAttributes.delete( geometry ); } - attribute = wireframeAttributes[ buffergeometry.id ]; + bindingStates.releaseStatesOfGeometry( geometry ); - if ( attribute ) { + if ( geometry.isInstancedBufferGeometry === true ) { - attributes.remove( attribute ); - delete wireframeAttributes[ buffergeometry.id ]; + delete geometry._maxInstanceCount; } // - infoMemory.geometries --; + info.memory.geometries --; } function get( object, geometry ) { - var buffergeometry = geometries[ geometry.id ]; - - if ( buffergeometry ) return buffergeometry; + if ( geometries[ geometry.id ] === true ) return geometry; geometry.addEventListener( 'dispose', onGeometryDispose ); - if ( geometry.isBufferGeometry ) { - - buffergeometry = geometry; - - } else if ( geometry.isGeometry ) { - - if ( geometry._bufferGeometry === undefined ) { - - geometry._bufferGeometry = new BufferGeometry().setFromObject( object ); - - } - - buffergeometry = geometry._bufferGeometry; - - } - - geometries[ geometry.id ] = buffergeometry; + geometries[ geometry.id ] = true; - infoMemory.geometries ++; + info.memory.geometries ++; - return buffergeometry; + return geometry; } function update( geometry ) { - var index = geometry.index; - var geometryAttributes = geometry.attributes; - - if ( index !== null ) { - - attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); + const geometryAttributes = geometry.attributes; - } + // Updating index buffer in VAO now. See WebGLBindingStates. - for ( var name in geometryAttributes ) { + for ( const name in geometryAttributes ) { attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); @@ -17017,13 +17048,13 @@ var ROS3D = (function (exports, ROSLIB) { // morph targets - var morphAttributes = geometry.morphAttributes; + const morphAttributes = geometry.morphAttributes; - for ( var name in morphAttributes ) { + for ( const name in morphAttributes ) { - var array = morphAttributes[ name ]; + const array = morphAttributes[ name ]; - for ( var i = 0, l = array.length; i < l; i ++ ) { + for ( let i = 0, l = array.length; i < l; i ++ ) { attributes.update( array[ i ], gl.ARRAY_BUFFER ); @@ -17033,58 +17064,94 @@ var ROS3D = (function (exports, ROSLIB) { } - function getWireframeAttribute( geometry ) { - - var attribute = wireframeAttributes[ geometry.id ]; - - if ( attribute ) return attribute; + function updateWireframeAttribute( geometry ) { - var indices = []; + const indices = []; - var geometryIndex = geometry.index; - var geometryAttributes = geometry.attributes; - - // console.time( 'wireframe' ); + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; + let version = 0; if ( geometryIndex !== null ) { - var array = geometryIndex.array; + const array = geometryIndex.array; + version = geometryIndex.version; - for ( var i = 0, l = array.length; i < l; i += 3 ) { + for ( let i = 0, l = array.length; i < l; i += 3 ) { - var a = array[ i + 0 ]; - var b = array[ i + 1 ]; - var c = array[ i + 2 ]; + const a = array[ i + 0 ]; + const b = array[ i + 1 ]; + const c = array[ i + 2 ]; indices.push( a, b, b, c, c, a ); } - } else { + } else if ( geometryPosition !== undefined ) { - var array = geometryAttributes.position.array; + const array = geometryPosition.array; + version = geometryPosition.version; - for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { + for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { - var a = i + 0; - var b = i + 1; - var c = i + 2; + const a = i + 0; + const b = i + 1; + const c = i + 2; indices.push( a, b, b, c, c, a ); } + } else { + + return; + } - // console.timeEnd( 'wireframe' ); + const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + attribute.version = version; + + // Updating index buffer in VAO now. See WebGLBindingStates + + // + + 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 the attribute is obsolete, create a new one + + if ( currentAttribute.version < geometryIndex.version ) { + + updateWireframeAttribute( geometry ); + + } + + } - attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + } else { - attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER ); + updateWireframeAttribute( geometry ); - wireframeAttributes[ geometry.id ] = attribute; + } - return attribute; + return wireframeAttributes.get( geometry ); } @@ -17099,1731 +17166,1615 @@ var ROS3D = (function (exports, ROSLIB) { } - /** - * @author mrdoob / http://mrdoob.com/ - */ + function WebGLIndexedBufferRenderer( gl, extensions, info ) { - function UniformsCache() { + let mode; - var lights = {}; + function setMode( value ) { - return { + mode = value; - get: function ( light ) { + } - if ( lights[ light.id ] !== undefined ) { + let type, bytesPerElement; - return lights[ light.id ]; + function setIndex( value ) { - } + type = value.type; + bytesPerElement = value.bytesPerElement; - var uniforms; + } - switch ( light.type ) { + function render( start, count ) { - case 'DirectionalLight': - uniforms = { - direction: new Vector3(), - color: new Color(), + gl.drawElements( mode, count, type, start * bytesPerElement ); - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; + info.update( count, mode, 1 ); - case 'SpotLight': - uniforms = { - position: new Vector3(), - direction: new Vector3(), - color: new Color(), - distance: 0, - coneCos: 0, - penumbraCos: 0, - decay: 0, + } - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; + function renderInstances( start, count, primcount ) { - case 'PointLight': - uniforms = { - position: new Vector3(), - color: new Color(), - distance: 0, - decay: 0, + if ( primcount === 0 ) return; - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2(), - shadowCameraNear: 1, - shadowCameraFar: 1000 - }; - break; + gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount ); - case 'HemisphereLight': - uniforms = { - direction: new Vector3(), - skyColor: new Color(), - groundColor: new Color() - }; - break; + info.update( count, mode, primcount ); - case 'RectAreaLight': - uniforms = { - color: new Color(), - position: new Vector3(), - halfWidth: new Vector3(), - halfHeight: new Vector3() - // TODO (abelnation): set RectAreaLight shadow uniforms - }; - break; + } - } + function renderMultiDraw( starts, counts, drawCount ) { - lights[ light.id ] = uniforms; + if ( drawCount === 0 ) return; - return uniforms; + const extension = extensions.get( 'WEBGL_multi_draw' ); + extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount ); + + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { + + elementCount += counts[ i ]; } - }; + info.update( elementCount, mode, 1 ); - } - function WebGLLights() { + } - var cache = new UniformsCache(); + function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { - var state = { + if ( drawCount === 0 ) return; - hash: '', + const extension = extensions.get( 'WEBGL_multi_draw' ); - ambient: [ 0, 0, 0 ], - directional: [], - directionalShadowMap: [], - directionalShadowMatrix: [], - spot: [], - spotShadowMap: [], - spotShadowMatrix: [], - rectArea: [], - point: [], - pointShadowMap: [], - pointShadowMatrix: [], - hemi: [] + if ( extension === null ) { - }; + for ( let i = 0; i < starts.length; i ++ ) { - var vector3 = new Vector3(); - var matrix4 = new Matrix4(); - var matrix42 = new Matrix4(); + renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] ); - function setup( lights, shadows, camera ) { + } - var r = 0, g = 0, b = 0; + } else { - var directionalLength = 0; - var pointLength = 0; - var spotLength = 0; - var rectAreaLength = 0; - var hemiLength = 0; + extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount ); - var viewMatrix = camera.matrixWorldInverse; + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { - for ( var i = 0, l = lights.length; i < l; i ++ ) { + elementCount += counts[ i ]; - var light = lights[ i ]; + } - var color = light.color; - var intensity = light.intensity; - var distance = light.distance; + for ( let i = 0; i < primcount.length; i ++ ) { - var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; + info.update( elementCount, mode, primcount[ i ] ); - if ( light.isAmbientLight ) { + } - r += color.r * intensity; - g += color.g * intensity; - b += color.b * intensity; + } - } else if ( light.isDirectionalLight ) { + } - var uniforms = cache.get( light ); + // - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); + this.setMode = setMode; + this.setIndex = setIndex; + this.render = render; + this.renderInstances = renderInstances; + this.renderMultiDraw = renderMultiDraw; + this.renderMultiDrawInstances = renderMultiDrawInstances; - uniforms.shadow = light.castShadow; + } - if ( light.castShadow ) { + function WebGLInfo( gl ) { - var shadow = light.shadow; + const memory = { + geometries: 0, + textures: 0 + }; - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; + const render = { + frame: 0, + calls: 0, + triangles: 0, + points: 0, + lines: 0 + }; - } + function update( count, mode, instanceCount ) { - state.directionalShadowMap[ directionalLength ] = shadowMap; - state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - state.directional[ directionalLength ] = uniforms; + render.calls ++; - directionalLength ++; + switch ( mode ) { - } else if ( light.isSpotLight ) { + case gl.TRIANGLES: + render.triangles += instanceCount * ( count / 3 ); + break; - var uniforms = cache.get( light ); + case gl.LINES: + render.lines += instanceCount * ( count / 2 ); + break; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + case gl.LINE_STRIP: + render.lines += instanceCount * ( count - 1 ); + break; - uniforms.color.copy( color ).multiplyScalar( intensity ); - uniforms.distance = distance; + case gl.LINE_LOOP: + render.lines += instanceCount * count; + break; - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); + case gl.POINTS: + render.points += instanceCount * count; + break; - uniforms.coneCos = Math.cos( light.angle ); - uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + default: + console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); + break; - uniforms.shadow = light.castShadow; + } - if ( light.castShadow ) { + } - var shadow = light.shadow; + function reset() { - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; + render.calls = 0; + render.triangles = 0; + render.points = 0; + render.lines = 0; - } + } - state.spotShadowMap[ spotLength ] = shadowMap; - state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; - state.spot[ spotLength ] = uniforms; + return { + memory: memory, + render: render, + programs: null, + autoReset: true, + reset: reset, + update: update + }; - spotLength ++; + } - } else if ( light.isRectAreaLight ) { + function WebGLMorphtargets( gl, capabilities, textures ) { - var uniforms = cache.get( light ); + const morphTextures = new WeakMap(); + const morph = new Vector4(); - // (a) intensity controls irradiance of entire light - uniforms.color - .copy( color ) - .multiplyScalar( intensity / ( light.width * light.height ) ); + function update( object, geometry, program ) { - // (b) intensity controls the radiance per light area - // uniforms.color.copy( color ).multiplyScalar( intensity ); + const objectInfluences = object.morphTargetInfluences; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + // the following encodes morph targets into an array of data textures. Each layer represents a single morph target. - // extract local rotation of light to derive width/height half vectors - matrix42.identity(); - matrix4.copy( light.matrixWorld ); - matrix4.premultiply( viewMatrix ); - matrix42.extractRotation( matrix4 ); + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); - uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); + let entry = morphTextures.get( geometry ); - uniforms.halfWidth.applyMatrix4( matrix42 ); - uniforms.halfHeight.applyMatrix4( matrix42 ); + if ( entry === undefined || entry.count !== morphTargetsCount ) { - // TODO (abelnation): RectAreaLight distance? - // uniforms.distance = distance; + if ( entry !== undefined ) entry.texture.dispose(); - state.rectArea[ rectAreaLength ] = uniforms; + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.morphAttributes.normal !== undefined; + const hasMorphColors = geometry.morphAttributes.color !== undefined; - rectAreaLength ++; + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; - } else if ( light.isPointLight ) { + let vertexDataCount = 0; - var uniforms = cache.get( light ); + if ( hasMorphPosition === true ) vertexDataCount = 1; + if ( hasMorphNormals === true ) vertexDataCount = 2; + if ( hasMorphColors === true ) vertexDataCount = 3; - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); + let width = geometry.attributes.position.count * vertexDataCount; + let height = 1; - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.distance = light.distance; - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + if ( width > capabilities.maxTextureSize ) { - uniforms.shadow = light.castShadow; + height = Math.ceil( width / capabilities.maxTextureSize ); + width = capabilities.maxTextureSize; - if ( light.castShadow ) { + } - var shadow = light.shadow; + const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - uniforms.shadowCameraNear = shadow.camera.near; - uniforms.shadowCameraFar = shadow.camera.far; + const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); + texture.type = FloatType; + texture.needsUpdate = true; - } + // fill buffer - state.pointShadowMap[ pointLength ] = shadowMap; - state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - state.point[ pointLength ] = uniforms; + const vertexDataStride = vertexDataCount * 4; - pointLength ++; + for ( let i = 0; i < morphTargetsCount; i ++ ) { - } else if ( light.isHemisphereLight ) { + const morphTarget = morphTargets[ i ]; + const morphNormal = morphNormals[ i ]; + const morphColor = morphColors[ i ]; - var uniforms = cache.get( light ); + const offset = width * height * 4 * i; - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - uniforms.direction.transformDirection( viewMatrix ); - uniforms.direction.normalize(); + for ( let j = 0; j < morphTarget.count; j ++ ) { - uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); - uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); + const stride = j * vertexDataStride; - state.hemi[ hemiLength ] = uniforms; + if ( hasMorphPosition === true ) { - hemiLength ++; + morph.fromBufferAttribute( morphTarget, j ); - } + buffer[ offset + stride + 0 ] = morph.x; + buffer[ offset + stride + 1 ] = morph.y; + buffer[ offset + stride + 2 ] = morph.z; + buffer[ offset + stride + 3 ] = 0; - } + } - state.ambient[ 0 ] = r; - state.ambient[ 1 ] = g; - state.ambient[ 2 ] = b; + if ( hasMorphNormals === true ) { - state.directional.length = directionalLength; - state.spot.length = spotLength; - state.rectArea.length = rectAreaLength; - state.point.length = pointLength; - state.hemi.length = hemiLength; + morph.fromBufferAttribute( morphNormal, j ); - // TODO (sam-g-steel) why aren't we using join - state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; + buffer[ offset + stride + 4 ] = morph.x; + buffer[ offset + stride + 5 ] = morph.y; + buffer[ offset + stride + 6 ] = morph.z; + buffer[ offset + stride + 7 ] = 0; - } + } - return { - setup: setup, - state: state - }; + if ( hasMorphColors === true ) { - } + morph.fromBufferAttribute( morphColor, j ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + 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; - function WebGLObjects( geometries, infoRender ) { + } - var updateList = {}; + } - function update( object ) { + } - var frame = infoRender.frame; + entry = { + count: morphTargetsCount, + texture: texture, + size: new Vector2( width, height ) + }; - var geometry = object.geometry; - var buffergeometry = geometries.get( object, geometry ); + morphTextures.set( geometry, entry ); - // Update once per frame + function disposeTexture() { - if ( updateList[ buffergeometry.id ] !== frame ) { + texture.dispose(); - if ( geometry.isGeometry ) { + morphTextures.delete( geometry ); - buffergeometry.updateFromObject( object ); + geometry.removeEventListener( 'dispose', disposeTexture ); } - geometries.update( buffergeometry ); - - updateList[ buffergeometry.id ] = frame; + geometry.addEventListener( 'dispose', disposeTexture ); } - return buffergeometry; + // + if ( object.isInstancedMesh === true && object.morphTexture !== null ) { - } + program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures ); + + } else { - function clear() { + let morphInfluencesSum = 0; - updateList = {}; + 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 ); } return { - update: update, - clear: clear + update: update }; } - /** - * @author mrdoob / http://mrdoob.com/ - */ + function WebGLObjects( gl, geometries, attributes, info ) { - function addLineNumbers( string ) { + let updateMap = new WeakMap(); - var lines = string.split( '\n' ); + function update( object ) { - for ( var i = 0; i < lines.length; i ++ ) { + const frame = info.render.frame; - lines[ i ] = ( i + 1 ) + ': ' + lines[ i ]; + const geometry = object.geometry; + const buffergeometry = geometries.get( object, geometry ); - } + // Update once per frame - return lines.join( '\n' ); + if ( updateMap.get( buffergeometry ) !== frame ) { - } + geometries.update( buffergeometry ); - function WebGLShader( gl, type, string ) { + updateMap.set( buffergeometry, frame ); - var shader = gl.createShader( type ); + } - gl.shaderSource( shader, string ); - gl.compileShader( shader ); + if ( object.isInstancedMesh ) { - if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { + if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { - console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); + object.addEventListener( 'dispose', onInstancedMeshDispose ); - } + } - if ( gl.getShaderInfoLog( shader ) !== '' ) { + if ( updateMap.get( object ) !== frame ) { - console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) ); + attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); - } + if ( object.instanceColor !== null ) { - // --enable-privileged-webgl-extension - // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); + attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); - return shader; + } - } + updateMap.set( object, frame ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + } - var programIdCount = 0; - - function getEncodingComponents( encoding ) { - - switch ( encoding ) { - - case LinearEncoding: - return [ 'Linear', '( value )' ]; - case sRGBEncoding: - return [ 'sRGB', '( value )' ]; - case RGBEEncoding: - return [ 'RGBE', '( value )' ]; - case RGBM7Encoding: - return [ 'RGBM', '( value, 7.0 )' ]; - case RGBM16Encoding: - return [ 'RGBM', '( value, 16.0 )' ]; - case RGBDEncoding: - return [ 'RGBD', '( value, 256.0 )' ]; - case GammaEncoding: - return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; - default: - throw new Error( 'unsupported encoding: ' + encoding ); + } - } + if ( object.isSkinnedMesh ) { - } + const skeleton = object.skeleton; - function getTexelDecodingFunction( functionName, encoding ) { + if ( updateMap.get( skeleton ) !== frame ) { - var components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }'; + skeleton.update(); - } + updateMap.set( skeleton, frame ); - function getTexelEncodingFunction( functionName, encoding ) { + } - var components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; + } - } + return buffergeometry; - function getToneMappingFunction( functionName, toneMapping ) { + } - var toneMappingName; + function dispose() { - switch ( toneMapping ) { + updateMap = new WeakMap(); - case LinearToneMapping: - toneMappingName = 'Linear'; - break; + } - case ReinhardToneMapping: - toneMappingName = 'Reinhard'; - break; + function onInstancedMeshDispose( event ) { - case Uncharted2ToneMapping: - toneMappingName = 'Uncharted2'; - break; + const instancedMesh = event.target; - case CineonToneMapping: - toneMappingName = 'OptimizedCineon'; - break; + instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); - default: - throw new Error( 'unsupported toneMapping: ' + toneMapping ); + attributes.remove( instancedMesh.instanceMatrix ); + + if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); } - return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; + return { + + update: update, + dispose: dispose + + }; } - function generateExtensions( extensions, parameters, rendererExtensions ) { + class DepthTexture extends Texture { - extensions = extensions || {}; + constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) { - var chunks = [ - ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', - ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '', - ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '', - ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '' - ]; + if ( format !== DepthFormat && format !== DepthStencilFormat ) { - return chunks.filter( filterEmptyLine ).join( '\n' ); + throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); - } + } - function generateDefines( defines ) { + if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; + if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; - var chunks = []; + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - for ( var name in defines ) { + this.isDepthTexture = true; - var value = defines[ name ]; + this.image = { width: width, height: height }; - if ( value === false ) continue; + this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; + this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; - chunks.push( '#define ' + name + ' ' + value ); + this.flipY = false; + this.generateMipmaps = false; + + this.compareFunction = null; } - return chunks.join( '\n' ); - } + copy( source ) { - function fetchAttributeLocations( gl, program ) { + super.copy( source ); - var attributes = {}; + this.compareFunction = source.compareFunction; - var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); + return this; - for ( var i = 0; i < n; i ++ ) { + } - var info = gl.getActiveAttrib( program, i ); - var name = info.name; + toJSON( meta ) { - // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); + const data = super.toJSON( meta ); - attributes[ name ] = gl.getAttribLocation( program, name ); + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; - } + return data; - return attributes; + } } - function filterEmptyLine( string ) { - - return string !== ''; + /** + * Uniforms of a program. + * Those form a tree structure with a special top-level container for the root, + * which you get by calling 'new WebGLUniforms( gl, program )'. + * + * + * Properties of inner nodes including the top-level container: + * + * .seq - array of nested uniforms + * .map - nested uniforms by name + * + * + * Methods of all nodes except the top-level container: + * + * .setValue( gl, value, [textures] ) + * + * uploads a uniform value(s) + * the 'textures' parameter is needed for sampler uniforms + * + * + * Static methods of the top-level container (textures factorizations): + * + * .upload( gl, seq, values, textures ) + * + * sets uniforms in 'seq' to 'values[id].value' + * + * .seqWithValue( seq, values ) : filteredSeq + * + * filters 'seq' entries with corresponding entry in values + * + * + * Methods of the top-level container (textures factorizations): + * + * .setValue( gl, name, value, textures ) + * + * sets uniform with name 'name' to 'value' + * + * .setOptional( gl, obj, prop ) + * + * like .set for an optional property of the object + * + */ - } - function replaceLightNums( string, parameters ) { + const emptyTexture = /*@__PURE__*/ new Texture(); - 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 ); + const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 ); - } + const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); + const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); + const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); - function parseIncludes( string ) { + // --- Utilities --- - var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm; + // Array Caches (provide typed arrays for temporary by size) - function replace( match, include ) { + const arrayCacheF32 = []; + const arrayCacheI32 = []; - var replace = ShaderChunk[ include ]; + // Float32Array caches used for uploading Matrix uniforms - if ( replace === undefined ) { + const mat4array = new Float32Array( 16 ); + const mat3array = new Float32Array( 9 ); + const mat2array = new Float32Array( 4 ); - throw new Error( 'Can not resolve #include <' + include + '>' ); + // Flattening for arrays of vectors and matrices - } + function flatten( array, nBlocks, blockSize ) { - return parseIncludes( replace ); + const firstElem = array[ 0 ]; - } + if ( firstElem <= 0 || firstElem > 0 ) return array; + // unoptimized: ! isNaN( firstElem ) + // see http://jacksondunstan.com/articles/983 - return string.replace( pattern, replace ); + const n = nBlocks * blockSize; + let r = arrayCacheF32[ n ]; - } + if ( r === undefined ) { - function unrollLoops( string ) { + r = new Float32Array( n ); + arrayCacheF32[ n ] = r; - var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; + } - function replace( match, start, end, snippet ) { + if ( nBlocks !== 0 ) { - var unroll = ''; + firstElem.toArray( r, 0 ); - for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) { + for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { - unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' ); + offset += blockSize; + array[ i ].toArray( r, offset ); } - return unroll; - } - return string.replace( pattern, replace ); + return r; } - function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { - - var gl = renderer.context; + function arraysEqual( a, b ) { - var defines = material.defines; + if ( a.length !== b.length ) return false; - var vertexShader = shader.vertexShader; - var fragmentShader = shader.fragmentShader; + for ( let i = 0, l = a.length; i < l; i ++ ) { - var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; - - if ( parameters.shadowMapType === PCFShadowMap ) { + if ( a[ i ] !== b[ i ] ) return false; - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; + } - } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { + return true; - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; + } - } + function copyArray( a, b ) { - var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; - var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + for ( let i = 0, l = b.length; i < l; i ++ ) { - if ( parameters.envMap ) { + a[ i ] = b[ i ]; - switch ( material.envMap.mapping ) { + } - case CubeReflectionMapping: - case CubeRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - break; + } - case CubeUVReflectionMapping: - case CubeUVRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; - break; + // Texture unit allocation - case EquirectangularReflectionMapping: - case EquirectangularRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; - break; + function allocTexUnits( textures, n ) { - case SphericalReflectionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; - break; + let r = arrayCacheI32[ n ]; - } + if ( r === undefined ) { - switch ( material.envMap.mapping ) { + r = new Int32Array( n ); + arrayCacheI32[ n ] = r; - case CubeRefractionMapping: - case EquirectangularRefractionMapping: - envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; - break; + } - } + for ( let i = 0; i !== n; ++ i ) { - switch ( material.combine ) { + r[ i ] = textures.allocateTextureUnit(); - case MultiplyOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; - break; + } - case MixOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; - break; + return r; - case AddOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; - break; + } - } + // --- Setters --- - } + // Note: Defining these methods externally, because they come in a bunch + // and this way their names minify. - var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; + // Single scalar - // console.log( 'building new program ' ); + function setValueV1f( gl, v ) { - // + const cache = this.cache; - var customExtensions = generateExtensions( material.extensions, parameters, extensions ); + if ( cache[ 0 ] === v ) return; - var customDefines = generateDefines( defines ); + gl.uniform1f( this.addr, v ); - // + cache[ 0 ] = v; - var program = gl.createProgram(); + } - var prefixVertex, prefixFragment; + // Single float vector (from flat array or THREE.VectorN) - if ( material.isRawShaderMaterial ) { + function setValueV2f( gl, v ) { - prefixVertex = [ + const cache = this.cache; - customDefines + if ( v.x !== undefined ) { - ].filter( filterEmptyLine ).join( '\n' ); + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - if ( prefixVertex.length > 0 ) { + gl.uniform2f( this.addr, v.x, v.y ); - prefixVertex += '\n'; + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; } - prefixFragment = [ + } else { - customExtensions, - customDefines + if ( arraysEqual( cache, v ) ) return; - ].filter( filterEmptyLine ).join( '\n' ); + gl.uniform2fv( this.addr, v ); - if ( prefixFragment.length > 0 ) { + copyArray( cache, v ); - prefixFragment += '\n'; + } - } + } - } else { + function setValueV3f( gl, v ) { - prefixVertex = [ + const cache = this.cache; - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', + if ( v.x !== undefined ) { - '#define SHADER_NAME ' + shader.name, + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - customDefines, + gl.uniform3f( this.addr, v.x, v.y, v.z ); - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - '#define GAMMA_FACTOR ' + gammaFactorDefine, + } - '#define MAX_BONES ' + parameters.maxBones, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', + } else if ( v.r !== undefined ) { - 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.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', + if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { - parameters.flatShading ? '#define FLAT_SHADED' : '', + gl.uniform3f( this.addr, v.r, v.g, v.b ); - parameters.skinning ? '#define USE_SKINNING' : '', - parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', + cache[ 0 ] = v.r; + cache[ 1 ] = v.g; + cache[ 2 ] = v.b; - parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', - parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', + } - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, + } else { - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + if ( arraysEqual( cache, v ) ) return; - parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + gl.uniform3fv( this.addr, v ); - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + copyArray( cache, v ); - 'uniform mat4 modelMatrix;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform mat4 viewMatrix;', - 'uniform mat3 normalMatrix;', - 'uniform vec3 cameraPosition;', + } - 'attribute vec3 position;', - 'attribute vec3 normal;', - 'attribute vec2 uv;', + } - '#ifdef USE_COLOR', + function setValueV4f( gl, v ) { - ' attribute vec3 color;', + const cache = this.cache; - '#endif', + if ( v.x !== undefined ) { - '#ifdef USE_MORPHTARGETS', + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - ' attribute vec3 morphTarget0;', - ' attribute vec3 morphTarget1;', - ' attribute vec3 morphTarget2;', - ' attribute vec3 morphTarget3;', + gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); - ' #ifdef USE_MORPHNORMALS', + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; - ' attribute vec3 morphNormal0;', - ' attribute vec3 morphNormal1;', - ' attribute vec3 morphNormal2;', - ' attribute vec3 morphNormal3;', + } - ' #else', + } else { - ' attribute vec3 morphTarget4;', - ' attribute vec3 morphTarget5;', - ' attribute vec3 morphTarget6;', - ' attribute vec3 morphTarget7;', + if ( arraysEqual( cache, v ) ) return; - ' #endif', + gl.uniform4fv( this.addr, v ); - '#endif', + copyArray( cache, v ); - '#ifdef USE_SKINNING', + } - ' attribute vec4 skinIndex;', - ' attribute vec4 skinWeight;', + } - '#endif', + // Single matrix (from flat array or THREE.MatrixN) - '\n' + function setValueM2( gl, v ) { - ].filter( filterEmptyLine ).join( '\n' ); + const cache = this.cache; + const elements = v.elements; - prefixFragment = [ + if ( elements === undefined ) { - customExtensions, + if ( arraysEqual( cache, v ) ) return; - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', + gl.uniformMatrix2fv( this.addr, false, v ); - '#define SHADER_NAME ' + shader.name, + copyArray( cache, v ); - customDefines, + } else { - parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', + if ( arraysEqual( cache, elements ) ) return; - '#define GAMMA_FACTOR ' + gammaFactorDefine, + mat2array.set( elements ); - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', + gl.uniformMatrix2fv( this.addr, false, mat2array ); - parameters.map ? '#define USE_MAP' : '', - parameters.envMap ? '#define USE_ENVMAP' : '', - parameters.envMap ? '#define ' + envMapTypeDefine : '', - parameters.envMap ? '#define ' + envMapModeDefine : '', - parameters.envMap ? '#define ' + envMapBlendingDefine : '', - 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.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', + copyArray( cache, elements ); - parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', + } - parameters.flatShading ? '#define FLAT_SHADED' : '', + } - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', + function setValueM3( gl, v ) { - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, - '#define UNION_CLIPPING_PLANES ' + ( parameters.numClippingPlanes - parameters.numClipIntersection ), + const cache = this.cache; + const elements = v.elements; - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + if ( elements === undefined ) { - parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', + if ( arraysEqual( cache, v ) ) return; - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + gl.uniformMatrix3fv( this.addr, false, v ); - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + copyArray( cache, v ); - parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', + } else { - 'uniform mat4 viewMatrix;', - 'uniform vec3 cameraPosition;', + if ( arraysEqual( cache, elements ) ) return; - ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', - ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below - ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', + mat3array.set( elements ); - parameters.dithering ? '#define DITHERING' : '', + gl.uniformMatrix3fv( this.addr, false, mat3array ); - ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below - parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', - parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', - parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', - parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '', + copyArray( cache, elements ); - parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '', + } - '\n' + } - ].filter( filterEmptyLine ).join( '\n' ); + function setValueM4( gl, v ) { - } + const cache = this.cache; + const elements = v.elements; - vertexShader = parseIncludes( vertexShader ); - vertexShader = replaceLightNums( vertexShader, parameters ); + if ( elements === undefined ) { - fragmentShader = parseIncludes( fragmentShader ); - fragmentShader = replaceLightNums( fragmentShader, parameters ); + if ( arraysEqual( cache, v ) ) return; - if ( ! material.isShaderMaterial ) { + gl.uniformMatrix4fv( this.addr, false, v ); - vertexShader = unrollLoops( vertexShader ); - fragmentShader = unrollLoops( fragmentShader ); + copyArray( cache, v ); - } + } else { - var vertexGlsl = prefixVertex + vertexShader; - var fragmentGlsl = prefixFragment + fragmentShader; + if ( arraysEqual( cache, elements ) ) return; - // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); + mat4array.set( elements ); - var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); - var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); + gl.uniformMatrix4fv( this.addr, false, mat4array ); - gl.attachShader( program, glVertexShader ); - gl.attachShader( program, glFragmentShader ); + copyArray( cache, elements ); - // Force a particular attribute to index 0. + } - if ( material.index0AttributeName !== undefined ) { + } - gl.bindAttribLocation( program, 0, material.index0AttributeName ); + // Single integer / boolean - } else if ( parameters.morphTargets === true ) { + function setValueV1i( gl, v ) { - // programs with morphTargets displace position out of attribute 0 - gl.bindAttribLocation( program, 0, 'position' ); + const cache = this.cache; - } + if ( cache[ 0 ] === v ) return; - gl.linkProgram( program ); + gl.uniform1i( this.addr, v ); + + cache[ 0 ] = v; + + } + + // Single integer / boolean vector (from flat array or THREE.VectorN) + + function setValueV2i( gl, v ) { - var programLog = gl.getProgramInfoLog( program ); - var vertexLog = gl.getShaderInfoLog( glVertexShader ); - var fragmentLog = gl.getShaderInfoLog( glFragmentShader ); + const cache = this.cache; - var runnable = true; - var haveDiagnostics = true; + if ( v.x !== undefined ) { - // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) ); - // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) ); + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { + gl.uniform2i( this.addr, v.x, v.y ); - runnable = false; + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog ); + } - } else if ( programLog !== '' ) { + } else { - console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); + if ( arraysEqual( cache, v ) ) return; - } else if ( vertexLog === '' || fragmentLog === '' ) { + gl.uniform2iv( this.addr, v ); - haveDiagnostics = false; + copyArray( cache, v ); } - if ( haveDiagnostics ) { + } + + function setValueV3i( gl, v ) { - this.diagnostics = { + const cache = this.cache; - runnable: runnable, - material: material, + if ( v.x !== undefined ) { - programLog: programLog, + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - vertexShader: { + gl.uniform3i( this.addr, v.x, v.y, v.z ); - log: vertexLog, - prefix: prefixVertex + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - }, + } - fragmentShader: { + } else { - log: fragmentLog, - prefix: prefixFragment + if ( arraysEqual( cache, v ) ) return; - } + gl.uniform3iv( this.addr, v ); - }; + copyArray( cache, v ); } - // clean up + } - gl.deleteShader( glVertexShader ); - gl.deleteShader( glFragmentShader ); + function setValueV4i( gl, v ) { - // set up caching for uniform locations + const cache = this.cache; - var cachedUniforms; + if ( v.x !== undefined ) { - this.getUniforms = function () { + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - if ( cachedUniforms === undefined ) { + gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); - cachedUniforms = new WebGLUniforms( gl, program, renderer ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; } - return cachedUniforms; - - }; + } else { - // set up caching for attribute locations + if ( arraysEqual( cache, v ) ) return; - var cachedAttributes; + gl.uniform4iv( this.addr, v ); - this.getAttributes = function () { + copyArray( cache, v ); - if ( cachedAttributes === undefined ) { + } - cachedAttributes = fetchAttributeLocations( gl, program ); + } - } + // Single unsigned integer - return cachedAttributes; + function setValueV1ui( gl, v ) { - }; + const cache = this.cache; - // free resource + if ( cache[ 0 ] === v ) return; - this.destroy = function () { + gl.uniform1ui( this.addr, v ); - gl.deleteProgram( program ); - this.program = undefined; + cache[ 0 ] = v; - }; + } - // DEPRECATED + // Single unsigned integer vector (from flat array or THREE.VectorN) - Object.defineProperties( this, { + function setValueV2ui( gl, v ) { - uniforms: { - get: function () { + const cache = this.cache; - console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' ); - return this.getUniforms(); + if ( v.x !== undefined ) { - } - }, + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { - attributes: { - get: function () { + gl.uniform2ui( this.addr, v.x, v.y ); - console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' ); - return this.getAttributes(); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; - } } - } ); + } else { + if ( arraysEqual( cache, v ) ) return; - // + gl.uniform2uiv( this.addr, v ); - this.id = programIdCount ++; - this.code = code; - this.usedTimes = 1; - this.program = program; - this.vertexShader = glVertexShader; - this.fragmentShader = glFragmentShader; + copyArray( cache, v ); - return this; + } } - /** - * @author mrdoob / http://mrdoob.com/ - */ + function setValueV3ui( gl, v ) { - function WebGLPrograms( renderer, extensions, capabilities ) { + const cache = this.cache; - var programs = []; + if ( v.x !== undefined ) { - var shaderIDs = { - MeshDepthMaterial: 'depth', - MeshDistanceMaterial: 'distanceRGBA', - MeshNormalMaterial: 'normal', - MeshBasicMaterial: 'basic', - MeshLambertMaterial: 'lambert', - MeshPhongMaterial: 'phong', - MeshToonMaterial: 'phong', - MeshStandardMaterial: 'physical', - MeshPhysicalMaterial: 'physical', - LineBasicMaterial: 'basic', - LineDashedMaterial: 'dashed', - PointsMaterial: 'points', - ShadowMaterial: 'shadow' - }; + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { - var parameterNames = [ - "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", - "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", - "roughnessMap", "metalnessMap", "gradientMap", - "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", - "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", - "maxBones", "useVertexTexture", "morphTargets", "morphNormals", - "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", - "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", - "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', - "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering" - ]; + gl.uniform3ui( this.addr, v.x, v.y, v.z ); + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; - function allocateBones( object ) { + } - var skeleton = object.skeleton; - var bones = skeleton.bones; + } else { - if ( capabilities.floatVertexTextures ) { + if ( arraysEqual( cache, v ) ) return; - return 1024; + gl.uniform3uiv( this.addr, v ); - } else { + copyArray( cache, v ); - // default for when object is not specified - // ( for example when prebuilding shader to be used with multiple objects ) - // - // - leave some extra space for other uniforms - // - limit here is ANGLE's 254 max uniform vectors - // (up to 54 should be safe) + } - var nVertexUniforms = capabilities.maxVertexUniforms; - var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 ); + } - var maxBones = Math.min( nVertexMatrices, bones.length ); + function setValueV4ui( gl, v ) { - if ( maxBones < bones.length ) { + const cache = this.cache; - console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' ); - return 0; + if ( v.x !== undefined ) { - } + if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { - return maxBones; + gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); + + cache[ 0 ] = v.x; + cache[ 1 ] = v.y; + cache[ 2 ] = v.z; + cache[ 3 ] = v.w; } + } else { + + if ( arraysEqual( cache, v ) ) return; + + gl.uniform4uiv( this.addr, v ); + + copyArray( cache, v ); + } - function getTextureEncodingFromMap( map, gammaOverrideLinear ) { + } - var encoding; - if ( ! map ) { + // Single texture (2D / Cube) - encoding = LinearEncoding; + function setValueT1( gl, v, textures ) { - } else if ( map.isTexture ) { + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - encoding = map.encoding; + if ( cache[ 0 ] !== unit ) { - } else if ( map.isWebGLRenderTarget ) { + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." ); - encoding = map.texture.encoding; + } - } + let emptyTexture2D; - // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point. - if ( encoding === LinearEncoding && gammaOverrideLinear ) { + if ( this.type === gl.SAMPLER_2D_SHADOW ) { - encoding = GammaEncoding; + emptyShadowTexture.compareFunction = LessEqualCompare; // #28670 + emptyTexture2D = emptyShadowTexture; - } + } else { - return encoding; + emptyTexture2D = emptyTexture; } - this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { + textures.setTexture2D( v || emptyTexture2D, unit ); - var shaderID = shaderIDs[ material.type ]; + } - // heuristics to create shader parameters according to lights in the scene - // (not to blow over maxLights budget) + function setValueT3D1( gl, v, textures ) { - var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; - var precision = capabilities.precision; + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - if ( material.precision !== null ) { + if ( cache[ 0 ] !== unit ) { - precision = capabilities.getMaxPrecision( material.precision ); + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - if ( precision !== material.precision ) { + } - console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); + textures.setTexture3D( v || empty3dTexture, unit ); - } + } - } + function setValueT6( gl, v, textures ) { - var currentRenderTarget = renderer.getRenderTarget(); + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - var parameters = { + if ( cache[ 0 ] !== unit ) { - shaderID: shaderID, + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - precision: precision, - supportsVertexTextures: capabilities.vertexTextures, - outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ), - map: !! material.map, - mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ), - envMap: !! material.envMap, - envMapMode: material.envMap && material.envMap.mapping, - envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ), - envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ), - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ), - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - alphaMap: !! material.alphaMap, - - gradientMap: !! material.gradientMap, + } - combine: material.combine, + textures.setTextureCube( v || emptyCubeTexture, unit ); - vertexColors: material.vertexColors, + } - fog: !! fog, - useFog: material.fog, - fogExp: ( fog && fog.isFogExp2 ), + function setValueT2DArray1( gl, v, textures ) { - flatShading: material.flatShading, + const cache = this.cache; + const unit = textures.allocateTextureUnit(); - sizeAttenuation: material.sizeAttenuation, - logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, + if ( cache[ 0 ] !== unit ) { - skinning: material.skinning && maxBones > 0, - maxBones: maxBones, - useVertexTexture: capabilities.floatVertexTextures, + gl.uniform1i( this.addr, unit ); + cache[ 0 ] = unit; - morphTargets: material.morphTargets, - morphNormals: material.morphNormals, - maxMorphTargets: renderer.maxMorphTargets, - maxMorphNormals: renderer.maxMorphNormals, + } - numDirLights: lights.directional.length, - numPointLights: lights.point.length, - numSpotLights: lights.spot.length, - numRectAreaLights: lights.rectArea.length, - numHemiLights: lights.hemi.length, + textures.setTexture2DArray( v || emptyArrayTexture, unit ); - numClippingPlanes: nClipPlanes, - numClipIntersection: nClipIntersection, + } - dithering: material.dithering, + // Helper to pick the right setter for the singular case - shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, - shadowMapType: renderer.shadowMap.type, + function getSingularSetter( type ) { - toneMapping: renderer.toneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + switch ( type ) { - premultipliedAlpha: material.premultipliedAlpha, + case 0x1406: return setValueV1f; // FLOAT + case 0x8b50: return setValueV2f; // _VEC2 + case 0x8b51: return setValueV3f; // _VEC3 + case 0x8b52: return setValueV4f; // _VEC4 - alphaTest: material.alphaTest, - doubleSided: material.side === DoubleSide, - flipSided: material.side === BackSide, + case 0x8b5a: return setValueM2; // _MAT2 + case 0x8b5b: return setValueM3; // _MAT3 + case 0x8b5c: return setValueM4; // _MAT4 - depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false + case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL + case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 + case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 + case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 - }; + case 0x1405: return setValueV1ui; // UINT + case 0x8dc6: return setValueV2ui; // _VEC2 + case 0x8dc7: return setValueV3ui; // _VEC3 + case 0x8dc8: return setValueV4ui; // _VEC4 - return parameters; + case 0x8b5e: // SAMPLER_2D + case 0x8d66: // SAMPLER_EXTERNAL_OES + case 0x8dca: // INT_SAMPLER_2D + case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D + case 0x8b62: // SAMPLER_2D_SHADOW + return setValueT1; - }; + case 0x8b5f: // SAMPLER_3D + case 0x8dcb: // INT_SAMPLER_3D + case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D + return setValueT3D1; - this.getProgramCode = function ( material, parameters ) { + case 0x8b60: // SAMPLER_CUBE + case 0x8dcc: // INT_SAMPLER_CUBE + case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE + case 0x8dc5: // SAMPLER_CUBE_SHADOW + return setValueT6; - var array = []; + case 0x8dc1: // SAMPLER_2D_ARRAY + case 0x8dcf: // INT_SAMPLER_2D_ARRAY + case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY + case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW + return setValueT2DArray1; - if ( parameters.shaderID ) { + } - array.push( parameters.shaderID ); + } - } else { - array.push( material.fragmentShader ); - array.push( material.vertexShader ); + // Array of scalars - } + function setValueV1fArray( gl, v ) { - if ( material.defines !== undefined ) { + gl.uniform1fv( this.addr, v ); - for ( var name in material.defines ) { + } - array.push( name ); - array.push( material.defines[ name ] ); + // Array of vectors (from flat array or array of THREE.VectorN) - } + function setValueV2fArray( gl, v ) { - } + const data = flatten( v, this.size, 2 ); - for ( var i = 0; i < parameterNames.length; i ++ ) { + gl.uniform2fv( this.addr, data ); - array.push( parameters[ parameterNames[ i ] ] ); + } - } + function setValueV3fArray( gl, v ) { - array.push( material.onBeforeCompile.toString() ); + const data = flatten( v, this.size, 3 ); - array.push( renderer.gammaOutput ); + gl.uniform3fv( this.addr, data ); - return array.join(); + } - }; + function setValueV4fArray( gl, v ) { - this.acquireProgram = function ( material, shader, parameters, code ) { + const data = flatten( v, this.size, 4 ); - var program; + gl.uniform4fv( this.addr, data ); - // Check if code has been already compiled - for ( var p = 0, pl = programs.length; p < pl; p ++ ) { + } - var programInfo = programs[ p ]; + // Array of matrices (from flat array or array of THREE.MatrixN) - if ( programInfo.code === code ) { + function setValueM2Array( gl, v ) { - program = programInfo; - ++ program.usedTimes; + const data = flatten( v, this.size, 4 ); - break; + gl.uniformMatrix2fv( this.addr, false, data ); - } + } - } + function setValueM3Array( gl, v ) { - if ( program === undefined ) { + const data = flatten( v, this.size, 9 ); - program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); - programs.push( program ); + gl.uniformMatrix3fv( this.addr, false, data ); - } + } - return program; + function setValueM4Array( gl, v ) { - }; + const data = flatten( v, this.size, 16 ); - this.releaseProgram = function ( program ) { + gl.uniformMatrix4fv( this.addr, false, data ); - if ( -- program.usedTimes === 0 ) { + } - // Remove from unordered set - var i = programs.indexOf( program ); - programs[ i ] = programs[ programs.length - 1 ]; - programs.pop(); + // Array of integer / boolean - // Free WebGL resources - program.destroy(); + function setValueV1iArray( gl, v ) { - } + gl.uniform1iv( this.addr, v ); - }; + } + + // Array of integer / boolean vectors (from flat array) - // Exposed for resource monitoring & error feedback via renderer.info: - this.programs = programs; + function setValueV2iArray( gl, v ) { + + gl.uniform2iv( this.addr, v ); } - /** - * @author mrdoob / http://mrdoob.com/ - */ + function setValueV3iArray( gl, v ) { - function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) { + gl.uniform3iv( this.addr, v ); - var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof window.WebGL2RenderingContext ); - var _videoTextures = {}; + } - // + function setValueV4iArray( gl, v ) { - function clampToMaxSize( image, maxSize ) { + gl.uniform4iv( this.addr, v ); - if ( image.width > maxSize || image.height > maxSize ) { + } - // Warning: Scaling through the canvas will only work with images that use - // premultiplied alpha. + // Array of unsigned integer - var scale = maxSize / Math.max( image.width, image.height ); + function setValueV1uiArray( gl, v ) { - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = Math.floor( image.width * scale ); - canvas.height = Math.floor( image.height * scale ); + gl.uniform1uiv( this.addr, v ); - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height ); + } - console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); + // Array of unsigned integer vectors (from flat array) - return canvas; + function setValueV2uiArray( gl, v ) { - } + gl.uniform2uiv( this.addr, v ); - return image; + } - } + function setValueV3uiArray( gl, v ) { - function isPowerOfTwo( image ) { + gl.uniform3uiv( this.addr, v ); - return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height ); + } - } + function setValueV4uiArray( gl, v ) { - function makePowerOfTwo( image ) { + gl.uniform4uiv( this.addr, v ); - if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) { + } - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = _Math.floorPowerOfTwo( image.width ); - canvas.height = _Math.floorPowerOfTwo( image.height ); - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, canvas.width, canvas.height ); + // Array of textures (2D / 3D / Cube / 2DArray) - console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); + function setValueT1Array( gl, v, textures ) { - return canvas; + const cache = this.cache; - } + const n = v.length; - return image; + const units = allocTexUnits( textures, n ); - } + if ( ! arraysEqual( cache, units ) ) { - function textureNeedsPowerOfTwo( texture ) { + gl.uniform1iv( this.addr, units ); - return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || - ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); + copyArray( cache, units ); } - function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { + for ( let i = 0; i !== n; ++ i ) { - return texture.generateMipmaps && isPowerOfTwo && - texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); } - // Fallback filters for non-power-of-2 textures + } - function filterFallback( f ) { + function setValueT3DArray( gl, v, textures ) { - if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) { + const cache = this.cache; - return _gl.NEAREST; + const n = v.length; - } + const units = allocTexUnits( textures, n ); - return _gl.LINEAR; + if ( ! arraysEqual( cache, units ) ) { - } + gl.uniform1iv( this.addr, units ); - // + copyArray( cache, units ); - function onTextureDispose( event ) { + } - var texture = event.target; + for ( let i = 0; i !== n; ++ i ) { - texture.removeEventListener( 'dispose', onTextureDispose ); + textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); - deallocateTexture( texture ); + } - if ( texture.isVideoTexture ) { + } - delete _videoTextures[ texture.id ]; + function setValueT6Array( gl, v, textures ) { - } + const cache = this.cache; - infoMemory.textures --; + const n = v.length; - } + const units = allocTexUnits( textures, n ); - function onRenderTargetDispose( event ) { + if ( ! arraysEqual( cache, units ) ) { - var renderTarget = event.target; + gl.uniform1iv( this.addr, units ); - renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); + copyArray( cache, units ); - deallocateRenderTarget( renderTarget ); + } - infoMemory.textures --; + for ( let i = 0; i !== n; ++ i ) { - } + textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); - // + } - function deallocateTexture( texture ) { + } - var textureProperties = properties.get( texture ); + function setValueT2DArrayArray( gl, v, textures ) { - if ( texture.image && textureProperties.__image__webglTextureCube ) { + const cache = this.cache; - // cube texture + const n = v.length; - _gl.deleteTexture( textureProperties.__image__webglTextureCube ); + const units = allocTexUnits( textures, n ); - } else { + if ( ! arraysEqual( cache, units ) ) { - // 2D texture + gl.uniform1iv( this.addr, units ); - if ( textureProperties.__webglInit === undefined ) return; + copyArray( cache, units ); - _gl.deleteTexture( textureProperties.__webglTexture ); + } - } + for ( let i = 0; i !== n; ++ i ) { - // remove all webgl properties - properties.remove( texture ); + textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); } - function deallocateRenderTarget( renderTarget ) { + } + + + // Helper to pick the right setter for a pure (bottom-level) array - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); + function getPureArraySetter( type ) { - if ( ! renderTarget ) return; + switch ( type ) { - if ( textureProperties.__webglTexture !== undefined ) { + case 0x1406: return setValueV1fArray; // FLOAT + case 0x8b50: return setValueV2fArray; // _VEC2 + case 0x8b51: return setValueV3fArray; // _VEC3 + case 0x8b52: return setValueV4fArray; // _VEC4 - _gl.deleteTexture( textureProperties.__webglTexture ); + case 0x8b5a: return setValueM2Array; // _MAT2 + case 0x8b5b: return setValueM3Array; // _MAT3 + case 0x8b5c: return setValueM4Array; // _MAT4 - } + case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL + case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 + case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 + case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 - if ( renderTarget.depthTexture ) { + case 0x1405: return setValueV1uiArray; // UINT + case 0x8dc6: return setValueV2uiArray; // _VEC2 + case 0x8dc7: return setValueV3uiArray; // _VEC3 + case 0x8dc8: return setValueV4uiArray; // _VEC4 - renderTarget.depthTexture.dispose(); + case 0x8b5e: // SAMPLER_2D + case 0x8d66: // SAMPLER_EXTERNAL_OES + case 0x8dca: // INT_SAMPLER_2D + case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D + case 0x8b62: // SAMPLER_2D_SHADOW + return setValueT1Array; - } + case 0x8b5f: // SAMPLER_3D + case 0x8dcb: // INT_SAMPLER_3D + case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D + return setValueT3DArray; - if ( renderTarget.isWebGLRenderTargetCube ) { + case 0x8b60: // SAMPLER_CUBE + case 0x8dcc: // INT_SAMPLER_CUBE + case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE + case 0x8dc5: // SAMPLER_CUBE_SHADOW + return setValueT6Array; - for ( var i = 0; i < 6; i ++ ) { + case 0x8dc1: // SAMPLER_2D_ARRAY + case 0x8dcf: // INT_SAMPLER_2D_ARRAY + case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY + case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW + return setValueT2DArrayArray; - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); + } - } + } - } else { + // --- Uniform Classes --- - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); + class SingleUniform { - } + constructor( id, activeInfo, addr ) { - properties.remove( renderTarget.texture ); - properties.remove( renderTarget ); + this.id = id; + this.addr = addr; + this.cache = []; + this.type = activeInfo.type; + this.setValue = getSingularSetter( activeInfo.type ); + + // this.path = activeInfo.name; // DEBUG } - // + } + class PureArrayUniform { + constructor( id, activeInfo, addr ) { - function setTexture2D( texture, slot ) { + this.id = id; + this.addr = addr; + this.cache = []; + this.type = activeInfo.type; + this.size = activeInfo.size; + this.setValue = getPureArraySetter( activeInfo.type ); - var textureProperties = properties.get( texture ); + // this.path = activeInfo.name; // DEBUG - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + } - var image = texture.image; + } - if ( image === undefined ) { + class StructuredUniform { - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture ); + constructor( id ) { - } else if ( image.complete === false ) { + this.id = id; - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture ); + this.seq = []; + this.map = {}; - } else { + } - uploadTexture( textureProperties, texture, slot ); - return; + setValue( gl, value, textures ) { - } + const seq = this.seq; - } + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); + const u = seq[ i ]; + u.setValue( gl, value[ u.id ], textures ); + + } } - function setTextureCube( texture, slot ) { + } - var textureProperties = properties.get( texture ); + // --- Top-level --- - if ( texture.image.length === 6 ) { + // Parser - builds up the property tree from the path strings - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + const RePathPart = /(\w+)(\])?(\[|\.)?/g; - if ( ! textureProperties.__image__webglTextureCube ) { + // extracts + // - the identifier (member name or array index) + // - followed by an optional right bracket (found when array index) + // - followed by an optional left bracket or dot (type of subscript) + // + // Note: These portions can be read in a non-overlapping fashion and + // allow straightforward parsing of the hierarchy that WebGL encodes + // in the uniform names. - texture.addEventListener( 'dispose', onTextureDispose ); + function addUniform( container, uniformObject ) { - textureProperties.__image__webglTextureCube = _gl.createTexture(); + container.seq.push( uniformObject ); + container.map[ uniformObject.id ] = uniformObject; - infoMemory.textures ++; + } - } + function parseUniform( activeInfo, addr, container ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); + const path = activeInfo.name, + pathLength = path.length; - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + // reset RegExp object, because of the early exit of a previous run + RePathPart.lastIndex = 0; - var isCompressed = ( texture && texture.isCompressedTexture ); - var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); + while ( true ) { - var cubeImage = []; + const match = RePathPart.exec( path ), + matchEnd = RePathPart.lastIndex; - for ( var i = 0; i < 6; i ++ ) { + let id = match[ 1 ]; + const idIsIndex = match[ 2 ] === ']', + subscript = match[ 3 ]; - if ( ! isCompressed && ! isDataTexture ) { + if ( idIsIndex ) id = id | 0; // convert to integer - cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize ); + if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { - } else { + // bare name or "pure" bottom-level array "[0]" suffix - cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; + addUniform( container, subscript === undefined ? + new SingleUniform( id, activeInfo, addr ) : + new PureArrayUniform( id, activeInfo, addr ) ); - } + break; - } + } else { - var image = cubeImage[ 0 ], - isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); + // step into inner node / create it in case it doesn't exist - setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); + const map = container.map; + let next = map[ id ]; - for ( var i = 0; i < 6; i ++ ) { + if ( next === undefined ) { - if ( ! isCompressed ) { + next = new StructuredUniform( id ); + addUniform( container, next ); - if ( isDataTexture ) { + } - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); + container = next; - } else { + } - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] ); + } - } + } - } else { + // Root Container - var mipmap, mipmaps = cubeImage[ i ].mipmaps; + class WebGLUniforms { - for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) { + constructor( gl, program ) { - mipmap = mipmaps[ j ]; + this.seq = []; + this.map = {}; - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { + const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { + for ( let i = 0; i < n; ++ i ) { - state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + const info = gl.getActiveUniform( program, i ), + addr = gl.getUniformLocation( program, info.name ); - } else { + parseUniform( info, addr, this ); - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); + } - } + } - } else { + setValue( gl, name, value, textures ) { - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + const u = this.map[ name ]; - } + if ( u !== undefined ) u.setValue( gl, value, textures ); - } + } - } + setOptional( gl, object, name ) { - } + const v = object[ name ]; - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { + if ( v !== undefined ) this.setValue( gl, name, v ); - _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); + } - } + static upload( gl, seq, values, textures ) { - textureProperties.__version = texture.version; + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - if ( texture.onUpdate ) texture.onUpdate( texture ); + const u = seq[ i ], + v = values[ u.id ]; - } else { + if ( v.needsUpdate !== false ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); + // note: always updating when .needsUpdate is undefined + u.setValue( gl, v.value, textures ); } @@ -18831,6443 +18782,6894 @@ var ROS3D = (function (exports, ROSLIB) { } - function setTextureCubeDynamic( texture, slot ) { + static seqWithValue( seq, values ) { - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture ); + const r = []; - } + for ( let i = 0, n = seq.length; i !== n; ++ i ) { - function setTextureParameters( textureType, texture, isPowerOfTwoImage ) { + const u = seq[ i ]; + if ( u.id in values ) r.push( u ); - var extension; + } - if ( isPowerOfTwoImage ) { + return r; - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); + } - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) ); + } - } else { + function WebGLShader( gl, type, string ) { - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); + const shader = gl.createShader( type ); - if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { + gl.shaderSource( shader, string ); + gl.compileShader( shader ); - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture ); + return shader; - } + } - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); + // From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ + const COMPLETION_STATUS_KHR = 0x91B1; - if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { + let programIdCount = 0; - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture ); + 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 ); - extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + for ( let i = from; i < to; i ++ ) { - if ( extension ) { + const line = i + 1; + lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); - if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return; - if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return; + } - if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { + return lines2.join( '\n' ); - _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); - properties.get( texture ).__currentAnisotropy = texture.anisotropy; + } - } + function getEncodingComponents( colorSpace ) { - } + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const encodingPrimaries = ColorManagement.getPrimaries( colorSpace ); - } + let gamutMapping; - function uploadTexture( textureProperties, texture, slot ) { + if ( workingPrimaries === encodingPrimaries ) { - if ( textureProperties.__webglInit === undefined ) { + gamutMapping = ''; - textureProperties.__webglInit = true; + } else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) { - texture.addEventListener( 'dispose', onTextureDispose ); + gamutMapping = 'LinearDisplayP3ToLinearSRGB'; - textureProperties.__webglTexture = _gl.createTexture(); + } else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) { - if ( texture.isVideoTexture ) { + gamutMapping = 'LinearSRGBToLinearDisplayP3'; - _videoTextures[ texture.id ] = texture; + } - } + switch ( colorSpace ) { - infoMemory.textures ++; + case LinearSRGBColorSpace: + case LinearDisplayP3ColorSpace: + return [ gamutMapping, 'LinearTransferOETF' ]; - } + case SRGBColorSpace: + case DisplayP3ColorSpace: + return [ gamutMapping, 'sRGBTransferOETF' ]; - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); + default: + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); + return [ gamutMapping, 'LinearTransferOETF' ]; - _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 ); + } - var image = clampToMaxSize( texture.image, capabilities.maxTextureSize ); + } - if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) { + function getShaderErrors( gl, shader, type ) { - image = makePowerOfTwo( image ); + const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); + const errors = gl.getShaderInfoLog( shader ).trim(); - } + if ( status && errors === '' ) return ''; - var isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); + const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); + if ( errorMatches ) { - setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); + // --enable-privileged-webgl-extension + // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - var mipmap, mipmaps = texture.mipmaps; + const errorLine = parseInt( errorMatches[ 1 ] ); + return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); - if ( texture.isDepthTexture ) { + } else { - // populate depth texture with dummy data + return errors; - var internalFormat = _gl.DEPTH_COMPONENT; + } - if ( texture.type === FloatType ) { + } - if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); - internalFormat = _gl.DEPTH_COMPONENT32F; + function getTexelEncodingFunction( functionName, colorSpace ) { - } else if ( _isWebGL2 ) { + const components = getEncodingComponents( colorSpace ); + return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`; - // WebGL 2.0 requires signed internalformat for glTexImage2D - internalFormat = _gl.DEPTH_COMPONENT16; + } - } + function getToneMappingFunction( functionName, toneMapping ) { - if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) { + let toneMappingName; - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { + switch ( toneMapping ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); + case LinearToneMapping: + toneMappingName = 'Linear'; + break; - texture.type = UnsignedShortType; - glType = utils.convert( texture.type ); + case ReinhardToneMapping: + toneMappingName = 'Reinhard'; + break; - } + case CineonToneMapping: + toneMappingName = 'OptimizedCineon'; + break; - } + case ACESFilmicToneMapping: + toneMappingName = 'ACESFilmic'; + break; - // Depth stencil textures need the DEPTH_STENCIL internal format - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.format === DepthStencilFormat ) { + case AgXToneMapping: + toneMappingName = 'AgX'; + break; - internalFormat = _gl.DEPTH_STENCIL; + case NeutralToneMapping: + toneMappingName = 'Neutral'; + break; - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedInt248Type ) { + case CustomToneMapping: + toneMappingName = 'Custom'; + break; - console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); + default: + console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); + toneMappingName = 'Linear'; - texture.type = UnsignedInt248Type; - glType = utils.convert( texture.type ); + } - } + return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; - } + } - state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null ); + const _v0$1 = /*@__PURE__*/ new Vector3(); - } else if ( texture.isDataTexture ) { + function getLuminanceFunction() { - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels + ColorManagement.getLuminanceCoefficients( _v0$1 ); - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { + const r = _v0$1.x.toFixed( 4 ); + const g = _v0$1.y.toFixed( 4 ); + const b = _v0$1.z.toFixed( 4 ); - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + return [ - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + 'float luminance( const in vec3 rgb ) {', - } + ` const vec3 weights = vec3( ${ r }, ${ g }, ${ b } );`, - texture.generateMipmaps = false; + ' return dot( weights, rgb );', - } else { + '}' - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data ); + ].join( '\n' ); - } + } - } else if ( texture.isCompressedTexture ) { + function generateVertexExtensions( parameters ) { - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + const chunks = [ + parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '', + parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '', + ]; - mipmap = mipmaps[ i ]; + return chunks.filter( filterEmptyLine ).join( '\n' ); - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { + } - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { + function generateDefines( defines ) { - state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + const chunks = []; - } else { + for ( const name in defines ) { - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); + const value = defines[ name ]; - } + if ( value === false ) continue; - } else { + chunks.push( '#define ' + name + ' ' + value ); - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + } - } + return chunks.join( '\n' ); - } + } - } else { + function fetchAttributeLocations( gl, program ) { - // regular Texture (image, video, canvas) + const attributes = {}; - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels + const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { + for ( let i = 0; i < n; i ++ ) { - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { + const info = gl.getActiveAttrib( program, i ); + const name = info.name; - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap ); + 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; - } + // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); - texture.generateMipmaps = false; + attributes[ name ] = { + type: info.type, + location: gl.getAttribLocation( program, name ), + locationSize: locationSize + }; - } else { - - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image ); + } - } + return attributes; - } + } - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); + function filterEmptyLine( string ) { - textureProperties.__version = texture.version; + return string !== ''; - if ( texture.onUpdate ) texture.onUpdate( texture ); + } - } + function replaceLightNums( string, parameters ) { - // Render targets + const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; - // Setup storage for target texture and bind it to correct framebuffer - function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { + return string + .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) + .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) + .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) + .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) + .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_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) + .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) + .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); - var glFormat = utils.convert( renderTarget.texture.format ); - var glType = utils.convert( renderTarget.texture.type ); - state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); + } - } + function replaceClippingPlaneNums( string, parameters ) { - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer - function setupRenderBufferStorage( renderbuffer, renderTarget ) { + return string + .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) + .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); - _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); + } - if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { + // Resolve Includes - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); + const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; - } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { + function resolveIncludes( string ) { - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); + return string.replace( includePattern, includeReplacer ); - } else { + } - // FIXME: We don't support !depth !stencil - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height ); + const shaderChunkMap = new Map(); - } + function includeReplacer( match, include ) { - _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); + let string = ShaderChunk[ include ]; - } + if ( string === undefined ) { - // Setup resources for a Depth Texture for a FBO (needs an extension) - function setupDepthTexture( framebuffer, renderTarget ) { + const newInclude = shaderChunkMap.get( include ); - var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); + if ( newInclude !== undefined ) { - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + string = ShaderChunk[ newInclude ]; + console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); - if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { + } else { - throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); + throw new Error( 'Can not resolve #include <' + include + '>' ); } - // upload an empty depth texture with framebuffer size - 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; + return resolveIncludes( string ); - } + } - setTexture2D( renderTarget.depthTexture, 0 ); + // Unroll Loops - var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + const 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; - if ( renderTarget.depthTexture.format === DepthFormat ) { + function unrollLoops( string ) { - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + return string.replace( unrollLoopPattern, loopReplacer ); - } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { + } - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + function loopReplacer( match, start, end, snippet ) { - } else { + let string = ''; - throw new Error( 'Unknown depthTexture format' ); + for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { - } + string += snippet + .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) + .replace( /UNROLLED_LOOP_INDEX/g, i ); } - // Setup GL resources for a non-texture depth buffer - function setupDepthRenderbuffer( renderTarget ) { - - var renderTargetProperties = properties.get( renderTarget ); + return string; - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); + } - if ( renderTarget.depthTexture ) { + // - if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); + function generatePrecision( parameters ) { - setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); + let precisionstring = `precision ${parameters.precision} float; + precision ${parameters.precision} int; + precision ${parameters.precision} sampler2D; + precision ${parameters.precision} samplerCube; + precision ${parameters.precision} sampler3D; + precision ${parameters.precision} sampler2DArray; + precision ${parameters.precision} sampler2DShadow; + precision ${parameters.precision} samplerCubeShadow; + precision ${parameters.precision} sampler2DArrayShadow; + precision ${parameters.precision} isampler2D; + precision ${parameters.precision} isampler3D; + precision ${parameters.precision} isamplerCube; + precision ${parameters.precision} isampler2DArray; + precision ${parameters.precision} usampler2D; + precision ${parameters.precision} usampler3D; + precision ${parameters.precision} usamplerCube; + precision ${parameters.precision} usampler2DArray; + `; - } else { + if ( parameters.precision === 'highp' ) { - if ( isCube ) { + precisionstring += '\n#define HIGH_PRECISION'; - renderTargetProperties.__webglDepthbuffer = []; + } else if ( parameters.precision === 'mediump' ) { - for ( var i = 0; i < 6; i ++ ) { + precisionstring += '\n#define MEDIUM_PRECISION'; - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); - renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget ); + } else if ( parameters.precision === 'lowp' ) { - } + precisionstring += '\n#define LOW_PRECISION'; - } else { + } - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget ); + return precisionstring; - } + } - } + function generateShadowMapTypeDefine( parameters ) { - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); + let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; - } + if ( parameters.shadowMapType === PCFShadowMap ) { - // Set up GL resources for the render target - function setupRenderTarget( renderTarget ) { + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); + } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { - renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; - textureProperties.__webglTexture = _gl.createTexture(); + } else if ( parameters.shadowMapType === VSMShadowMap ) { - infoMemory.textures ++; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); + } - // Setup framebuffer + return shadowMapTypeDefine; - if ( isCube ) { + } - renderTargetProperties.__webglFramebuffer = []; + function generateEnvMapTypeDefine( parameters ) { - for ( var i = 0; i < 6; i ++ ) { + let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); + if ( parameters.envMap ) { - } + switch ( parameters.envMapMode ) { - } else { + case CubeReflectionMapping: + case CubeRefractionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; + break; - renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); + case CubeUVReflectionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; + break; } - // Setup color buffer - - if ( isCube ) { + } - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo ); + return envMapTypeDefine; - for ( var i = 0; i < 6; i ++ ) { + } - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i ); + function generateEnvMapModeDefine( parameters ) { - } + let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); + if ( parameters.envMap ) { - } else { + switch ( parameters.envMapMode ) { - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); + case CubeRefractionMapping: - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); - state.bindTexture( _gl.TEXTURE_2D, null ); + envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; + break; } - // Setup depth and stencil buffers + } - if ( renderTarget.depthBuffer ) { + return envMapModeDefine; - setupDepthRenderbuffer( renderTarget ); + } - } + function generateEnvMapBlendingDefine( parameters ) { - } + let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; - function updateRenderTargetMipmap( renderTarget ) { + if ( parameters.envMap ) { - var texture = renderTarget.texture; - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); + switch ( parameters.combine ) { - if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { + case MultiplyOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + break; - var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; - var webglTexture = properties.get( texture ).__webglTexture; + case MixOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; + break; - state.bindTexture( target, webglTexture ); - _gl.generateMipmap( target ); - state.bindTexture( target, null ); + case AddOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; + break; } } - function updateVideoTextures() { + return envMapBlendingDefine; - for ( var id in _videoTextures ) { + } - _videoTextures[ id ].update(); + function generateCubeUVSize( parameters ) { - } + const imageHeight = parameters.envMapCubeUVHeight; - } + if ( imageHeight === null ) return null; - this.setTexture2D = setTexture2D; - this.setTextureCube = setTextureCube; - this.setTextureCubeDynamic = setTextureCubeDynamic; - this.setupRenderTarget = setupRenderTarget; - this.updateRenderTargetMipmap = updateRenderTargetMipmap; - this.updateVideoTextures = updateVideoTextures; + const maxMip = Math.log2( imageHeight ) - 2; - } + const texelHeight = 1.0 / imageHeight; - /** - * @author fordacious / fordacious.github.io - */ + const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); - function WebGLProperties() { + return { texelWidth, texelHeight, maxMip }; - var properties = {}; + } - function get( object ) { + function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { - var uuid = object.uuid; - var map = properties[ uuid ]; + // TODO Send this event to Three.js DevTools + // console.log( 'WebGLProgram', cacheKey ); - if ( map === undefined ) { + const gl = renderer.getContext(); - map = {}; - properties[ uuid ] = map; + const defines = parameters.defines; - } + let vertexShader = parameters.vertexShader; + let fragmentShader = parameters.fragmentShader; - return map; + const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); + const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); + const envMapModeDefine = generateEnvMapModeDefine( parameters ); + const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); + const envMapCubeUVSize = generateCubeUVSize( parameters ); - } + const customVertexExtensions = generateVertexExtensions( parameters ); - function remove( object ) { + const customDefines = generateDefines( defines ); - delete properties[ object.uuid ]; + const program = gl.createProgram(); - } + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; - function clear() { + if ( parameters.isRawShaderMaterial ) { - properties = {}; + prefixVertex = [ - } + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - return { - get: get, - remove: remove, - clear: clear - }; + customDefines - } + ].filter( filterEmptyLine ).join( '\n' ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + if ( prefixVertex.length > 0 ) { - function WebGLState( gl, extensions, utils ) { + prefixVertex += '\n'; - function ColorBuffer() { + } - var locked = false; + prefixFragment = [ - var color = new Vector4(); - var currentColorMask = null; - var currentColorClear = new Vector4( 0, 0, 0, 0 ); + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - return { + customDefines - setMask: function ( colorMask ) { + ].filter( filterEmptyLine ).join( '\n' ); - if ( currentColorMask !== colorMask && ! locked ) { + if ( prefixFragment.length > 0 ) { - gl.colorMask( colorMask, colorMask, colorMask, colorMask ); - currentColorMask = colorMask; + prefixFragment += '\n'; - } + } - }, + } else { - setLocked: function ( lock ) { + prefixVertex = [ - locked = lock; + generatePrecision( parameters ), - }, + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - setClear: function ( r, g, b, a, premultipliedAlpha ) { + customDefines, - if ( premultipliedAlpha === true ) { + parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', + parameters.batching ? '#define USE_BATCHING' : '', + parameters.batchingColor ? '#define USE_BATCHING_COLOR' : '', + parameters.instancing ? '#define USE_INSTANCING' : '', + parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', + parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '', - r *= a; g *= a; b *= a; + 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.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', - color.set( r, g, b, a ); + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', - if ( currentColorClear.equals( color ) === false ) { + parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', + parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', + parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', - gl.clearColor( r, g, b, a ); - currentColorClear.copy( color ); + parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', + parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - } + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', - }, + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', + parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.alphaHash ? '#define USE_ALPHAHASH' : '', - reset: function () { + parameters.transmission ? '#define USE_TRANSMISSION' : '', + parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', + parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - locked = false; + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', - currentColorMask = null; - currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state + // - } + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', - }; + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', - } + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', - function DepthBuffer() { + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', - var locked = false; + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', - var currentDepthMask = null; - var currentDepthFunc = null; - var currentDepthClear = null; + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', - return { + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', - setTest: function ( depthTest ) { + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', - if ( depthTest ) { + // - enable( gl.DEPTH_TEST ); + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', + parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', - } else { + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', - disable( gl.DEPTH_TEST ); + 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 ) ? '#define USE_MORPHCOLORS' : '', + ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', + ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - setMask: function ( depthMask ) { + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - if ( currentDepthMask !== depthMask && ! locked ) { + parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', - gl.depthMask( depthMask ); - currentDepthMask = depthMask; + parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', - } + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - }, + 'uniform mat4 modelMatrix;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'uniform mat4 viewMatrix;', + 'uniform mat3 normalMatrix;', + 'uniform vec3 cameraPosition;', + 'uniform bool isOrthographic;', - setFunc: function ( depthFunc ) { + '#ifdef USE_INSTANCING', - if ( currentDepthFunc !== depthFunc ) { + ' attribute mat4 instanceMatrix;', - if ( depthFunc ) { + '#endif', - switch ( depthFunc ) { + '#ifdef USE_INSTANCING_COLOR', - case NeverDepth: + ' attribute vec3 instanceColor;', - gl.depthFunc( gl.NEVER ); - break; + '#endif', - case AlwaysDepth: + '#ifdef USE_INSTANCING_MORPH', - gl.depthFunc( gl.ALWAYS ); - break; + ' uniform sampler2D morphTexture;', - case LessDepth: + '#endif', - gl.depthFunc( gl.LESS ); - break; + 'attribute vec3 position;', + 'attribute vec3 normal;', + 'attribute vec2 uv;', - case LessEqualDepth: + '#ifdef USE_UV1', - gl.depthFunc( gl.LEQUAL ); - break; + ' attribute vec2 uv1;', - case EqualDepth: + '#endif', - gl.depthFunc( gl.EQUAL ); - break; + '#ifdef USE_UV2', - case GreaterEqualDepth: + ' attribute vec2 uv2;', - gl.depthFunc( gl.GEQUAL ); - break; + '#endif', - case GreaterDepth: + '#ifdef USE_UV3', - gl.depthFunc( gl.GREATER ); - break; + ' attribute vec2 uv3;', - case NotEqualDepth: + '#endif', - gl.depthFunc( gl.NOTEQUAL ); - break; + '#ifdef USE_TANGENT', - default: + ' attribute vec4 tangent;', - gl.depthFunc( gl.LEQUAL ); + '#endif', - } + '#if defined( USE_COLOR_ALPHA )', - } else { + ' attribute vec4 color;', - gl.depthFunc( gl.LEQUAL ); + '#elif defined( USE_COLOR )', - } + ' attribute vec3 color;', - currentDepthFunc = depthFunc; + '#endif', - } + '#ifdef USE_SKINNING', - }, + ' attribute vec4 skinIndex;', + ' attribute vec4 skinWeight;', - setLocked: function ( lock ) { + '#endif', - locked = lock; + '\n' - }, + ].filter( filterEmptyLine ).join( '\n' ); - setClear: function ( depth ) { + prefixFragment = [ - if ( currentDepthClear !== depth ) { + generatePrecision( parameters ), - gl.clearDepth( depth ); - currentDepthClear = depth; + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, - } + customDefines, - }, + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', - reset: function () { + parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '', + 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.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', - locked = false; + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', - currentDepthMask = null; - currentDepthFunc = null; - currentDepthClear = null; + parameters.clearcoat ? '#define USE_CLEARCOAT' : '', + parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', + parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', + parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', - } + parameters.dispersion ? '#define USE_DISPERSION' : '', - }; + parameters.iridescence ? '#define USE_IRIDESCENCE' : '', + parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', + parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - } + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', - function StencilBuffer() { + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', + parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - var locked = false; + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.alphaTest ? '#define USE_ALPHATEST' : '', + parameters.alphaHash ? '#define USE_ALPHAHASH' : '', - var currentStencilMask = null; - var currentStencilFunc = null; - var currentStencilRef = null; - var currentStencilFuncMask = null; - var currentStencilFail = null; - var currentStencilZFail = null; - var currentStencilZPass = null; - var currentStencilClear = null; + parameters.sheen ? '#define USE_SHEEN' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', - return { + parameters.transmission ? '#define USE_TRANSMISSION' : '', + parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', + parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - setTest: function ( stencilTest ) { + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', + parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '', + parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', - if ( stencilTest ) { + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', - enable( gl.STENCIL_TEST ); + parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', - } else { + parameters.flatShading ? '#define FLAT_SHADED' : '', - disable( gl.STENCIL_TEST ); + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - } + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - }, + parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - setMask: function ( stencilMask ) { + parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', - if ( currentStencilMask !== stencilMask && ! locked ) { + parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - gl.stencilMask( stencilMask ); - currentStencilMask = stencilMask; + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - } + 'uniform mat4 viewMatrix;', + 'uniform vec3 cameraPosition;', + 'uniform bool isOrthographic;', - }, + ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', + ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below + ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', - setFunc: function ( stencilFunc, stencilRef, stencilMask ) { + parameters.dithering ? '#define DITHERING' : '', + parameters.opaque ? '#define OPAQUE' : '', - if ( currentStencilFunc !== stencilFunc || - currentStencilRef !== stencilRef || - currentStencilFuncMask !== stencilMask ) { + ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), + getLuminanceFunction(), - gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); + parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', - currentStencilFunc = stencilFunc; - currentStencilRef = stencilRef; - currentStencilFuncMask = stencilMask; + '\n' - } + ].filter( filterEmptyLine ).join( '\n' ); - }, + } - setOp: function ( stencilFail, stencilZFail, stencilZPass ) { + vertexShader = resolveIncludes( vertexShader ); + vertexShader = replaceLightNums( vertexShader, parameters ); + vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); - if ( currentStencilFail !== stencilFail || - currentStencilZFail !== stencilZFail || - currentStencilZPass !== stencilZPass ) { + fragmentShader = resolveIncludes( fragmentShader ); + fragmentShader = replaceLightNums( fragmentShader, parameters ); + fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); - gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); + vertexShader = unrollLoops( vertexShader ); + fragmentShader = unrollLoops( fragmentShader ); - currentStencilFail = stencilFail; - currentStencilZFail = stencilZFail; - currentStencilZPass = stencilZPass; + if ( parameters.isRawShaderMaterial !== true ) { - } + // GLSL 3.0 conversion for built-in materials and ShaderMaterial - }, + versionString = '#version 300 es\n'; - setLocked: function ( lock ) { + prefixVertex = [ + customVertexExtensions, + '#define attribute in', + '#define varying out', + '#define texture2D texture' + ].join( '\n' ) + '\n' + prefixVertex; - locked = lock; + 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; - }, + // console.log( '*VERTEX*', vertexGlsl ); + // console.log( '*FRAGMENT*', fragmentGlsl ); - setClear: function ( stencil ) { + const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); + const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); - if ( currentStencilClear !== stencil ) { + gl.attachShader( program, glVertexShader ); + gl.attachShader( program, glFragmentShader ); - gl.clearStencil( stencil ); - currentStencilClear = stencil; + // Force a particular attribute to index 0. - } + if ( parameters.index0AttributeName !== undefined ) { - }, + gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); - reset: function () { + } else if ( parameters.morphTargets === true ) { - locked = false; + // programs with morphTargets displace position out of attribute 0 + gl.bindAttribLocation( program, 0, 'position' ); - currentStencilMask = null; - currentStencilFunc = null; - currentStencilRef = null; - currentStencilFuncMask = null; - currentStencilFail = null; - currentStencilZFail = null; - currentStencilZPass = null; - currentStencilClear = null; + } - } + gl.linkProgram( program ); - }; + function onFirstUse( self ) { - } + // check for link errors + if ( renderer.debug.checkShaderErrors ) { - // + const programLog = gl.getProgramInfoLog( program ).trim(); + const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); + const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); - var colorBuffer = new ColorBuffer(); - var depthBuffer = new DepthBuffer(); - var stencilBuffer = new StencilBuffer(); + let runnable = true; + let haveDiagnostics = true; - var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var newAttributes = new Uint8Array( maxVertexAttributes ); - var enabledAttributes = new Uint8Array( maxVertexAttributes ); - var attributeDivisors = new Uint8Array( maxVertexAttributes ); + if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { - var capabilities = {}; + runnable = false; - var compressedTextureFormats = null; + if ( typeof renderer.debug.onShaderError === 'function' ) { - var currentProgram = null; + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); - var currentBlending = null; - var currentBlendEquation = null; - var currentBlendSrc = null; - var currentBlendDst = null; - var currentBlendEquationAlpha = null; - var currentBlendSrcAlpha = null; - var currentBlendDstAlpha = null; - var currentPremultipledAlpha = false; + } else { - var currentFlipSided = null; - var currentCullFace = null; + // default error reporting - var currentLineWidth = null; + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); - var currentPolygonOffsetFactor = null; - var currentPolygonOffsetUnits = null; + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Material Name: ' + self.name + '\n' + + 'Material Type: ' + self.type + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); - var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); + } - var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] ); - var lineWidthAvailable = parseFloat( version ) >= 1.0; + } else if ( programLog !== '' ) { - var currentTextureSlot = null; - var currentBoundTextures = {}; + console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); - var currentScissor = new Vector4(); - var currentViewport = new Vector4(); + } else if ( vertexLog === '' || fragmentLog === '' ) { - function createTexture( type, target, count ) { + haveDiagnostics = false; - var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. - var texture = gl.createTexture(); + } - gl.bindTexture( type, texture ); - gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); + if ( haveDiagnostics ) { - for ( var i = 0; i < count; i ++ ) { + self.diagnostics = { - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + runnable: runnable, - } + programLog: programLog, - return texture; + vertexShader: { - } + log: vertexLog, + prefix: prefixVertex - var 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 ); + }, - // init + fragmentShader: { - colorBuffer.setClear( 0, 0, 0, 1 ); - depthBuffer.setClear( 1 ); - stencilBuffer.setClear( 0 ); + log: fragmentLog, + prefix: prefixFragment - enable( gl.DEPTH_TEST ); - depthBuffer.setFunc( LessEqualDepth ); + } - setFlipSided( false ); - setCullFace( CullFaceBack ); - enable( gl.CULL_FACE ); + }; - enable( gl.BLEND ); - setBlending( NormalBlending ); + } - // + } - function initAttributes() { + // Clean up - for ( var i = 0, l = newAttributes.length; i < l; i ++ ) { + // Crashes in iOS9 and iOS10. #18402 + // gl.detachShader( program, glVertexShader ); + // gl.detachShader( program, glFragmentShader ); - newAttributes[ i ] = 0; + gl.deleteShader( glVertexShader ); + gl.deleteShader( glFragmentShader ); - } + cachedUniforms = new WebGLUniforms( gl, program ); + cachedAttributes = fetchAttributeLocations( gl, program ); } - function enableAttribute( attribute ) { + // set up caching for uniform locations - newAttributes[ attribute ] = 1; + let cachedUniforms; - if ( enabledAttributes[ attribute ] === 0 ) { + this.getUniforms = function () { - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; + if ( cachedUniforms === undefined ) { + + // Populates cachedUniforms and cachedAttributes + onFirstUse( this ); } - if ( attributeDivisors[ attribute ] !== 0 ) { + return cachedUniforms; - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + }; - extension.vertexAttribDivisorANGLE( attribute, 0 ); - attributeDivisors[ attribute ] = 0; + // set up caching for attribute locations - } + let cachedAttributes; - } + this.getAttributes = function () { - function enableAttributeAndDivisor( attribute, meshPerAttribute ) { + if ( cachedAttributes === undefined ) { - newAttributes[ attribute ] = 1; + // Populates cachedAttributes and cachedUniforms + onFirstUse( this ); - if ( enabledAttributes[ attribute ] === 0 ) { + } - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; + return cachedAttributes; - } + }; - if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { + // indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported, + // flag the program as ready immediately. It may cause a stall when it's first used. - var extension = extensions.get( 'ANGLE_instanced_arrays' ); + let programReady = ( parameters.rendererExtensionParallelShaderCompile === false ); - extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute ); - attributeDivisors[ attribute ] = meshPerAttribute; + this.isReady = function () { - } + if ( programReady === false ) { - } + programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR ); - function disableUnusedAttributes() { + } - for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) { + return programReady; - if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { + }; - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; + // free resource - } + this.destroy = function () { - } + bindingStates.releaseStatesOfProgram( this ); - } + gl.deleteProgram( program ); + this.program = undefined; - function enable( id ) { + }; - if ( capabilities[ id ] !== true ) { + // - gl.enable( id ); - capabilities[ id ] = true; + this.type = parameters.shaderType; + this.name = parameters.shaderName; + this.id = programIdCount ++; + this.cacheKey = cacheKey; + this.usedTimes = 1; + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; - } + return this; - } + } - function disable( id ) { + let _id$1 = 0; - if ( capabilities[ id ] !== false ) { + class WebGLShaderCache { - gl.disable( id ); - capabilities[ id ] = false; + constructor() { - } + this.shaderCache = new Map(); + this.materialCache = new Map(); } - function getCompressedTextureFormats() { + update( material ) { - if ( compressedTextureFormats === null ) { + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; - compressedTextureFormats = []; + const vertexShaderStage = this._getShaderStage( vertexShader ); + const fragmentShaderStage = this._getShaderStage( fragmentShader ); - if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) || - extensions.get( 'WEBGL_compressed_texture_s3tc' ) || - extensions.get( 'WEBGL_compressed_texture_etc1' ) ) { + const materialShaders = this._getShaderCacheForMaterial( material ); - var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS ); + if ( materialShaders.has( vertexShaderStage ) === false ) { - for ( var i = 0; i < formats.length; i ++ ) { + materialShaders.add( vertexShaderStage ); + vertexShaderStage.usedTimes ++; - compressedTextureFormats.push( formats[ i ] ); + } - } + if ( materialShaders.has( fragmentShaderStage ) === false ) { - } + materialShaders.add( fragmentShaderStage ); + fragmentShaderStage.usedTimes ++; } - return compressedTextureFormats; + return this; } - function useProgram( program ) { + remove( material ) { - if ( currentProgram !== program ) { + const materialShaders = this.materialCache.get( material ); - gl.useProgram( program ); + for ( const shaderStage of materialShaders ) { - currentProgram = program; + shaderStage.usedTimes --; - return true; + if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); } - return false; + this.materialCache.delete( material ); + + return this; } - function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { + getVertexShaderID( material ) { - if ( blending !== NoBlending ) { + return this._getShaderStage( material.vertexShader ).id; - enable( gl.BLEND ); + } - } else { + getFragmentShaderID( material ) { - disable( gl.BLEND ); + return this._getShaderStage( material.fragmentShader ).id; - } + } - if ( blending !== CustomBlending ) { + dispose() { - if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { + this.shaderCache.clear(); + this.materialCache.clear(); - switch ( blending ) { + } - case AdditiveBlending: + _getShaderCacheForMaterial( material ) { - if ( premultipliedAlpha ) { + const cache = this.materialCache; + let set = cache.get( material ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); + if ( set === undefined ) { - } else { + set = new Set(); + cache.set( material, set ); - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + } - } - break; + return set; - case SubtractiveBlending: + } - if ( premultipliedAlpha ) { + _getShaderStage( code ) { - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); + const cache = this.shaderCache; + let stage = cache.get( code ); - } else { + if ( stage === undefined ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); + stage = new WebGLShaderStage( code ); + cache.set( code, stage ); - } - break; + } - case MultiplyBlending: + return stage; - if ( premultipliedAlpha ) { + } - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + } - } else { + class WebGLShaderStage { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + constructor( code ) { - } - break; + this.id = _id$1 ++; - default: + this.code = code; + this.usedTimes = 0; - if ( premultipliedAlpha ) { + } - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + } - } else { + function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); + const _activeChannels = new Set(); + const programs = []; - } + const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const SUPPORTS_VERTEX_TEXTURES = 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' + }; - currentBlendEquation = null; - currentBlendSrc = null; - currentBlendDst = null; - currentBlendEquationAlpha = null; - currentBlendSrcAlpha = null; - currentBlendDstAlpha = null; + function getChannel( value ) { - } else { + _activeChannels.add( value ); - blendEquationAlpha = blendEquationAlpha || blendEquation; - blendSrcAlpha = blendSrcAlpha || blendSrc; - blendDstAlpha = blendDstAlpha || blendDst; + if ( value === 0 ) return 'uv'; - if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { + return `uv${ value }`; - gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); + } - currentBlendEquation = blendEquation; - currentBlendEquationAlpha = blendEquationAlpha; + function getParameters( material, lights, shadows, scene, object ) { - } + const fog = scene.fog; + const geometry = object.geometry; + const environment = material.isMeshStandardMaterial ? scene.environment : null; - if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { + const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null; - gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); + const shaderID = shaderIDs[ material.type ]; - currentBlendSrc = blendSrc; - currentBlendDst = blendDst; - currentBlendSrcAlpha = blendSrcAlpha; - currentBlendDstAlpha = blendDstAlpha; + // heuristics to create shader parameters according to lights in the scene + // (not to blow over maxLights budget) + + 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.' ); } } - currentBlending = blending; - currentPremultipledAlpha = premultipliedAlpha; + // - } + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - function setMaterial( material, frontFaceCW ) { + let morphTextureStride = 0; - material.side === DoubleSide - ? disable( gl.CULL_FACE ) - : enable( gl.CULL_FACE ); + if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; + if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; + if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; - var flipSided = ( material.side === BackSide ); - if ( frontFaceCW ) flipSided = ! flipSided; + // - setFlipSided( flipSided ); + let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; - material.transparent === true - ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ) - : setBlending( NoBlending ); + if ( shaderID ) { - depthBuffer.setFunc( material.depthFunc ); - depthBuffer.setTest( material.depthTest ); - depthBuffer.setMask( material.depthWrite ); - colorBuffer.setMask( material.colorWrite ); + const shader = ShaderLib[ shaderID ]; - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + vertexShader = shader.vertexShader; + fragmentShader = shader.fragmentShader; - } + } else { - // + vertexShader = material.vertexShader; + fragmentShader = material.fragmentShader; - function setFlipSided( flipSided ) { + _customShaders.update( material ); - if ( currentFlipSided !== flipSided ) { + customVertexShaderID = _customShaders.getVertexShaderID( material ); + customFragmentShaderID = _customShaders.getFragmentShaderID( material ); - if ( flipSided ) { + } - gl.frontFace( gl.CW ); + const currentRenderTarget = renderer.getRenderTarget(); - } else { + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + const IS_BATCHEDMESH = object.isBatchedMesh === true; - gl.frontFace( gl.CCW ); + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; - } + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; - currentFlipSided = flipSided; + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_DISPERSION = material.dispersion > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; - } + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; - } + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; - function setCullFace( cullFace ) { + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; - if ( cullFace !== CullFaceNone ) { + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; - enable( gl.CULL_FACE ); + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; - if ( cullFace !== currentCullFace ) { + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; - if ( cullFace === CullFaceBack ) { + const HAS_GRADIENTMAP = !! material.gradientMap; - gl.cullFace( gl.BACK ); + const HAS_ALPHAMAP = !! material.alphaMap; - } else if ( cullFace === CullFaceFront ) { + const HAS_ALPHATEST = material.alphaTest > 0; - gl.cullFace( gl.FRONT ); + const HAS_ALPHAHASH = !! material.alphaHash; - } else { + const HAS_EXTENSIONS = !! material.extensions; - gl.cullFace( gl.FRONT_AND_BACK ); + let toneMapping = NoToneMapping; - } + if ( material.toneMapped ) { - } + if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) { - } else { + toneMapping = renderer.toneMapping; - disable( gl.CULL_FACE ); + } } - currentCullFace = cullFace; + const parameters = { - } + shaderID: shaderID, + shaderType: material.type, + shaderName: material.name, - function setLineWidth( width ) { + vertexShader: vertexShader, + fragmentShader: fragmentShader, + defines: material.defines, - if ( width !== currentLineWidth ) { + customVertexShaderID: customVertexShaderID, + customFragmentShaderID: customFragmentShaderID, - if ( lineWidthAvailable ) gl.lineWidth( width ); + isRawShaderMaterial: material.isRawShaderMaterial === true, + glslVersion: material.glslVersion, - currentLineWidth = width; + precision: precision, - } + batching: IS_BATCHEDMESH, + batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, + instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, - } + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), + alphaToCoverage: !! material.alphaToCoverage, - function setPolygonOffset( polygonOffset, factor, units ) { + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, + envMapCubeUVHeight: envMapCubeUVHeight, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - if ( polygonOffset ) { + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, - enable( gl.POLYGON_OFFSET_FILL ); + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, - if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, - gl.polygonOffset( factor, units ); + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - currentPolygonOffsetFactor = factor; - currentPolygonOffsetUnits = units; + dispersion: HAS_DISPERSION, - } + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, - } else { + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, - disable( gl.POLYGON_OFFSET_FILL ); + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, - } + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, - } + gradientMap: HAS_GRADIENTMAP, - function setScissorTest( scissorTest ) { + opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false, - if ( scissorTest ) { + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, + alphaHash: HAS_ALPHAHASH, - enable( gl.SCISSOR_TEST ); + combine: material.combine, - } else { + // - disable( gl.SCISSOR_TEST ); + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), - } + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), - } + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), - // texture + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), - function activeTexture( webglSlot ) { + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), - if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), - if ( currentTextureSlot !== webglSlot ) { + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), - gl.activeTexture( webglSlot ); - currentTextureSlot = webglSlot; + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), - } + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), - } + // + + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), + vertexColors: material.vertexColors, + vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - function bindTexture( webglType, webglTexture ) { + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), - if ( currentTextureSlot === null ) { + fog: !! fog, + useFog: material.fog === true, + fogExp2: ( !! fog && fog.isFogExp2 ), - activeTexture(); + flatShading: material.flatShading === true, - } + sizeAttenuation: material.sizeAttenuation === true, + logarithmicDepthBuffer: logarithmicDepthBuffer, - var boundTexture = currentBoundTextures[ currentTextureSlot ]; + skinning: object.isSkinnedMesh === true, - if ( boundTexture === undefined ) { + morphTargets: geometry.morphAttributes.position !== undefined, + morphNormals: geometry.morphAttributes.normal !== undefined, + morphColors: geometry.morphAttributes.color !== undefined, + morphTargetsCount: morphTargetsCount, + morphTextureStride: morphTextureStride, - boundTexture = { type: undefined, texture: undefined }; - currentBoundTextures[ currentTextureSlot ] = boundTexture; + numDirLights: lights.directional.length, + numPointLights: lights.point.length, + numSpotLights: lights.spot.length, + numSpotLightMaps: lights.spotLightMap.length, + numRectAreaLights: lights.rectArea.length, + numHemiLights: lights.hemi.length, - } + numDirLightShadows: lights.directionalShadowMap.length, + numPointLightShadows: lights.pointShadowMap.length, + numSpotLightShadows: lights.spotShadowMap.length, + numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, - if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { + numLightProbes: lights.numLightProbes, - gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); + numClippingPlanes: clipping.numPlanes, + numClipIntersection: clipping.numIntersection, - boundTexture.type = webglType; - boundTexture.texture = webglTexture; + dithering: material.dithering, - } + shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, + shadowMapType: renderer.shadowMap.type, - } + toneMapping: toneMapping, - function compressedTexImage2D() { + decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ), - try { + premultipliedAlpha: material.premultipliedAlpha, - gl.compressedTexImage2D.apply( gl, arguments ); + doubleSided: material.side === DoubleSide, + flipSided: material.side === BackSide, - } catch ( error ) { + useDepthPacking: material.depthPacking >= 0, + depthPacking: material.depthPacking || 0, - console.error( 'THREE.WebGLState:', error ); + index0AttributeName: material.index0AttributeName, - } + extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ), + extensionMultiDraw: ( HAS_EXTENSIONS && material.extensions.multiDraw === true || IS_BATCHEDMESH ) && extensions.has( 'WEBGL_multi_draw' ), - } + rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ), - function texImage2D() { + customProgramCacheKey: material.customProgramCacheKey() - try { + }; - gl.texImage2D.apply( gl, arguments ); + // the usage of getChannel() determines the active texture channels for this shader - } catch ( error ) { + parameters.vertexUv1s = _activeChannels.has( 1 ); + parameters.vertexUv2s = _activeChannels.has( 2 ); + parameters.vertexUv3s = _activeChannels.has( 3 ); - console.error( 'THREE.WebGLState:', error ); + _activeChannels.clear(); - } + return parameters; } - // + function getProgramCacheKey( parameters ) { - function scissor( scissor ) { + const array = []; - if ( currentScissor.equals( scissor ) === false ) { + if ( parameters.shaderID ) { - gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); - currentScissor.copy( scissor ); + array.push( parameters.shaderID ); + + } else { + + array.push( parameters.customVertexShaderID ); + array.push( parameters.customFragmentShaderID ); } - } + if ( parameters.defines !== undefined ) { - function viewport( viewport ) { + for ( const name in parameters.defines ) { - if ( currentViewport.equals( viewport ) === false ) { + array.push( name ); + array.push( parameters.defines[ name ] ); - gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); - currentViewport.copy( viewport ); + } } - } + if ( parameters.isRawShaderMaterial === false ) { - // + getProgramCacheKeyParameters( array, parameters ); + getProgramCacheKeyBooleans( array, parameters ); + array.push( renderer.outputColorSpace ); - function reset() { + } - for ( var i = 0; i < enabledAttributes.length; i ++ ) { + array.push( parameters.customProgramCacheKey ); - if ( enabledAttributes[ i ] === 1 ) { + return array.join(); - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; + } - } + function getProgramCacheKeyParameters( array, parameters ) { + + array.push( parameters.precision ); + array.push( parameters.outputColorSpace ); + array.push( parameters.envMapMode ); + array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); + array.push( parameters.combine ); + array.push( parameters.fogExp2 ); + array.push( parameters.sizeAttenuation ); + array.push( parameters.morphTargetsCount ); + array.push( parameters.morphAttributeCount ); + array.push( parameters.numDirLights ); + array.push( parameters.numPointLights ); + array.push( parameters.numSpotLights ); + array.push( parameters.numSpotLightMaps ); + array.push( parameters.numHemiLights ); + array.push( parameters.numRectAreaLights ); + array.push( parameters.numDirLightShadows ); + array.push( parameters.numPointLightShadows ); + array.push( parameters.numSpotLightShadows ); + array.push( parameters.numSpotLightShadowsWithMaps ); + array.push( parameters.numLightProbes ); + array.push( parameters.shadowMapType ); + array.push( parameters.toneMapping ); + array.push( parameters.numClippingPlanes ); + array.push( parameters.numClipIntersection ); + array.push( parameters.depthPacking ); + + } + + function getProgramCacheKeyBooleans( array, parameters ) { + + _programLayers.disableAll(); + + if ( parameters.supportsVertexTextures ) + _programLayers.enable( 0 ); + if ( parameters.instancing ) + _programLayers.enable( 1 ); + if ( parameters.instancingColor ) + _programLayers.enable( 2 ); + if ( parameters.instancingMorph ) + _programLayers.enable( 3 ); + if ( parameters.matcap ) + _programLayers.enable( 4 ); + if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) + _programLayers.enable( 6 ); + if ( parameters.normalMapTangentSpace ) + _programLayers.enable( 7 ); + if ( parameters.clearcoat ) + _programLayers.enable( 8 ); + if ( parameters.iridescence ) + _programLayers.enable( 9 ); + if ( parameters.alphaTest ) + _programLayers.enable( 10 ); + if ( parameters.vertexColors ) + _programLayers.enable( 11 ); + if ( parameters.vertexAlphas ) + _programLayers.enable( 12 ); + if ( parameters.vertexUv1s ) + _programLayers.enable( 13 ); + if ( parameters.vertexUv2s ) + _programLayers.enable( 14 ); + if ( parameters.vertexUv3s ) + _programLayers.enable( 15 ); + if ( parameters.vertexTangents ) + _programLayers.enable( 16 ); + if ( parameters.anisotropy ) + _programLayers.enable( 17 ); + if ( parameters.alphaHash ) + _programLayers.enable( 18 ); + if ( parameters.batching ) + _programLayers.enable( 19 ); + if ( parameters.dispersion ) + _programLayers.enable( 20 ); + if ( parameters.batchingColor ) + _programLayers.enable( 21 ); + + array.push( _programLayers.mask ); + _programLayers.disableAll(); + + if ( parameters.fog ) + _programLayers.enable( 0 ); + if ( parameters.useFog ) + _programLayers.enable( 1 ); + if ( parameters.flatShading ) + _programLayers.enable( 2 ); + if ( parameters.logarithmicDepthBuffer ) + _programLayers.enable( 3 ); + if ( parameters.skinning ) + _programLayers.enable( 4 ); + if ( parameters.morphTargets ) + _programLayers.enable( 5 ); + if ( parameters.morphNormals ) + _programLayers.enable( 6 ); + if ( parameters.morphColors ) + _programLayers.enable( 7 ); + if ( parameters.premultipliedAlpha ) + _programLayers.enable( 8 ); + if ( parameters.shadowMapEnabled ) + _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.transmission ) + _programLayers.enable( 14 ); + if ( parameters.sheen ) + _programLayers.enable( 15 ); + if ( parameters.opaque ) + _programLayers.enable( 16 ); + if ( parameters.pointsUvs ) + _programLayers.enable( 17 ); + if ( parameters.decodeVideoTexture ) + _programLayers.enable( 18 ); + if ( parameters.alphaToCoverage ) + _programLayers.enable( 19 ); + + array.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 { - capabilities = {}; + uniforms = material.uniforms; - compressedTextureFormats = null; + } - currentTextureSlot = null; - currentBoundTextures = {}; + return uniforms; - currentProgram = null; + } - currentBlending = null; + function acquireProgram( parameters, cacheKey ) { - currentFlipSided = null; - currentCullFace = null; + let program; - colorBuffer.reset(); - depthBuffer.reset(); - stencilBuffer.reset(); + // Check if code has been already compiled + for ( let p = 0, pl = programs.length; p < pl; p ++ ) { - } + const preexistingProgram = programs[ p ]; - return { + if ( preexistingProgram.cacheKey === cacheKey ) { - buffers: { - color: colorBuffer, - depth: depthBuffer, - stencil: stencilBuffer - }, + program = preexistingProgram; + ++ program.usedTimes; - initAttributes: initAttributes, - enableAttribute: enableAttribute, - enableAttributeAndDivisor: enableAttributeAndDivisor, - disableUnusedAttributes: disableUnusedAttributes, - enable: enable, - disable: disable, - getCompressedTextureFormats: getCompressedTextureFormats, + break; - useProgram: useProgram, + } - setBlending: setBlending, - setMaterial: setMaterial, + } - setFlipSided: setFlipSided, - setCullFace: setCullFace, + if ( program === undefined ) { - setLineWidth: setLineWidth, - setPolygonOffset: setPolygonOffset, + program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); + programs.push( program ); - setScissorTest: setScissorTest, + } - activeTexture: activeTexture, - bindTexture: bindTexture, - compressedTexImage2D: compressedTexImage2D, - texImage2D: texImage2D, + return program; - scissor: scissor, - viewport: viewport, + } - reset: reset + function releaseProgram( program ) { - }; + if ( -- program.usedTimes === 0 ) { - } + // Remove from unordered set + const i = programs.indexOf( program ); + programs[ i ] = programs[ programs.length - 1 ]; + programs.pop(); - /** - * @author mrdoob / http://mrdoob.com/ - */ + // Free WebGL resources + program.destroy(); - function WebGLCapabilities( gl, extensions, parameters ) { + } - var maxAnisotropy; + } - function getMaxAnisotropy() { + function releaseShaderCache( material ) { - if ( maxAnisotropy !== undefined ) return maxAnisotropy; + _customShaders.remove( material ); - var extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + } - if ( extension !== null ) { + function dispose() { - maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); - - } else { - - maxAnisotropy = 0; - - } - - return maxAnisotropy; + _customShaders.dispose(); } - function getMaxPrecision( precision ) { - - if ( precision === 'highp' ) { - - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { - - return 'highp'; + return { + getParameters: getParameters, + getProgramCacheKey: getProgramCacheKey, + getUniforms: getUniforms, + acquireProgram: acquireProgram, + releaseProgram: releaseProgram, + releaseShaderCache: releaseShaderCache, + // Exposed for resource monitoring & error feedback via renderer.info: + programs: programs, + dispose: dispose + }; - } + } - precision = 'mediump'; + function WebGLProperties() { - } + let properties = new WeakMap(); - if ( precision === 'mediump' ) { + function get( object ) { - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { + let map = properties.get( object ); - return 'mediump'; + if ( map === undefined ) { - } + map = {}; + properties.set( object, map ); } - return 'lowp'; + return map; } - var precision = parameters.precision !== undefined ? parameters.precision : 'highp'; - var maxPrecision = getMaxPrecision( precision ); - - if ( maxPrecision !== precision ) { + function remove( object ) { - console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); - precision = maxPrecision; + properties.delete( object ); } - var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; - - var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); - var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); - var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); - var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); + function update( object, key, value ) { - var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); - var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); - var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); + properties.get( object )[ key ] = value; - var vertexTextures = maxVertexTextures > 0; - var floatFragmentTextures = !! extensions.get( 'OES_texture_float' ); - var floatVertexTextures = vertexTextures && floatFragmentTextures; + } - return { + function dispose() { - getMaxAnisotropy: getMaxAnisotropy, - getMaxPrecision: getMaxPrecision, + properties = new WeakMap(); - precision: precision, - logarithmicDepthBuffer: logarithmicDepthBuffer, + } - maxTextures: maxTextures, - maxVertexTextures: maxVertexTextures, - maxTextureSize: maxTextureSize, - maxCubemapSize: maxCubemapSize, + return { + get: get, + remove: remove, + update: update, + dispose: dispose + }; - maxAttributes: maxAttributes, - maxVertexUniforms: maxVertexUniforms, - maxVaryings: maxVaryings, - maxFragmentUniforms: maxFragmentUniforms, + } - vertexTextures: vertexTextures, - floatFragmentTextures: floatFragmentTextures, - floatVertexTextures: floatVertexTextures + function painterSortStable( a, b ) { - }; + if ( a.groupOrder !== b.groupOrder ) { - } + return a.groupOrder - b.groupOrder; - /** - * @author mrdoob / http://mrdoob.com/ - * @author greggman / http://games.greggman.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author tschw - */ + } else if ( a.renderOrder !== b.renderOrder ) { - function PerspectiveCamera( fov, aspect, near, far ) { + return a.renderOrder - b.renderOrder; - Camera.call( this ); + } else if ( a.material.id !== b.material.id ) { - this.type = 'PerspectiveCamera'; + return a.material.id - b.material.id; - this.fov = fov !== undefined ? fov : 50; - this.zoom = 1; + } else if ( a.z !== b.z ) { - this.near = near !== undefined ? near : 0.1; - this.far = far !== undefined ? far : 2000; - this.focus = 10; + return a.z - b.z; - this.aspect = aspect !== undefined ? aspect : 1; - this.view = null; + } else { - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + return a.id - b.id; - this.updateProjectionMatrix(); + } } - PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - - constructor: PerspectiveCamera, + function reversePainterSortStable( a, b ) { - isPerspectiveCamera: true, + if ( a.groupOrder !== b.groupOrder ) { - copy: function ( source, recursive ) { + return a.groupOrder - b.groupOrder; - Camera.prototype.copy.call( this, source, recursive ); + } else if ( a.renderOrder !== b.renderOrder ) { - this.fov = source.fov; - this.zoom = source.zoom; + return a.renderOrder - b.renderOrder; - this.near = source.near; - this.far = source.far; - this.focus = source.focus; + } else if ( a.z !== b.z ) { - this.aspect = source.aspect; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + return b.z - a.z; - this.filmGauge = source.filmGauge; - this.filmOffset = source.filmOffset; + } else { - return this; + return a.id - b.id; - }, + } - /** - * Sets the FOV by focal length in respect to the current .filmGauge. - * - * The default film gauge is 35, so that the focal length can be specified for - * a 35mm (full frame) camera. - * - * Values for focal length and film gauge must have the same unit. - */ - setFocalLength: function ( focalLength ) { + } - // see http://www.bobatkins.com/photography/technical/field_of_view.html - var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); - this.updateProjectionMatrix(); + function WebGLRenderList() { - }, + const renderItems = []; + let renderItemsIndex = 0; - /** - * Calculates the focal length from the current .fov and .filmGauge. - */ - getFocalLength: function () { + const opaque = []; + const transmissive = []; + const transparent = []; - var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); + function init() { - return 0.5 * this.getFilmHeight() / vExtentSlope; + renderItemsIndex = 0; - }, + opaque.length = 0; + transmissive.length = 0; + transparent.length = 0; - getEffectiveFOV: function () { + } - return _Math.RAD2DEG * 2 * Math.atan( - Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); + function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { - }, + let renderItem = renderItems[ renderItemsIndex ]; - getFilmWidth: function () { + if ( renderItem === undefined ) { - // film not completely covered in portrait format (aspect < 1) - return this.filmGauge * Math.min( this.aspect, 1 ); + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + groupOrder: groupOrder, + renderOrder: object.renderOrder, + z: z, + group: group + }; - }, + renderItems[ renderItemsIndex ] = renderItem; - getFilmHeight: function () { + } else { - // film not completely covered in landscape format (aspect > 1) - return this.filmGauge / Math.max( this.aspect, 1 ); + 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; - }, + } - /** - * Sets an offset in a larger frustum. This is useful for multi-window or - * multi-monitor/multi-machine setups. - * - * For example, if you have 3x2 monitors and each monitor is 1920x1080 and - * the monitors are in grid like this - * - * +---+---+---+ - * | A | B | C | - * +---+---+---+ - * | D | E | F | - * +---+---+---+ - * - * then for each monitor you would call it like this - * - * var w = 1920; - * var h = 1080; - * var fullWidth = w * 3; - * var fullHeight = h * 2; - * - * --A-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); - * - * Note there is no reason monitors have to be the same size or in a grid. - */ - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { + renderItemsIndex ++; - this.aspect = fullWidth / fullHeight; + return renderItem; - if ( this.view === null ) { + } - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; + function push( object, geometry, material, groupOrder, z, group ) { - } + const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; + if ( material.transmission > 0.0 ) { - this.updateProjectionMatrix(); + transmissive.push( renderItem ); - }, + } else if ( material.transparent === true ) { - clearViewOffset: function () { + transparent.push( renderItem ); - if ( this.view !== null ) { + } else { - this.view.enabled = false; + opaque.push( renderItem ); } - this.updateProjectionMatrix(); + } - }, + function unshift( object, geometry, material, groupOrder, z, group ) { - updateProjectionMatrix: function () { + const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); - var near = this.near, - top = near * Math.tan( - _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom, - height = 2 * top, - width = this.aspect * height, - left = - 0.5 * width, - view = this.view; + if ( material.transmission > 0.0 ) { - if ( this.view !== null && this.view.enabled ) { + transmissive.unshift( renderItem ); - var fullWidth = view.fullWidth, - fullHeight = view.fullHeight; + } else if ( material.transparent === true ) { - left += view.offsetX * width / fullWidth; - top -= view.offsetY * height / fullHeight; - width *= view.width / fullWidth; - height *= view.height / fullHeight; + transparent.unshift( renderItem ); + + } else { + + opaque.unshift( renderItem ); } - var skew = this.filmOffset; - if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); + } - this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + 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 ); - toJSON: function ( meta ) { + } - var data = Object3D.prototype.toJSON.call( this, meta ); + function finish() { - data.object.fov = this.fov; - data.object.zoom = this.zoom; + // Clear references from inactive renderItems in the list - data.object.near = this.near; - data.object.far = this.far; - data.object.focus = this.focus; + for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { - data.object.aspect = this.aspect; + const renderItem = renderItems[ i ]; - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + if ( renderItem.id === null ) break; - data.object.filmGauge = this.filmGauge; - data.object.filmOffset = this.filmOffset; + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.group = null; - return data; + } } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ + return { - function ArrayCamera( array ) { + opaque: opaque, + transmissive: transmissive, + transparent: transparent, - PerspectiveCamera.call( this ); + init: init, + push: push, + unshift: unshift, + finish: finish, - this.cameras = array || []; + sort: sort + }; } - ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + function WebGLRenderLists() { - constructor: ArrayCamera, + let lists = new WeakMap(); - isArrayCamera: true + function get( scene, renderCallDepth ) { - } ); + const listArray = lists.get( scene ); + let list; - /** - * @author mrdoob / http://mrdoob.com/ - */ + if ( listArray === undefined ) { - function WebVRManager( renderer ) { + list = new WebGLRenderList(); + lists.set( scene, [ list ] ); - var scope = this; + } else { - var device = null; - var frameData = null; + if ( renderCallDepth >= listArray.length ) { - var poseTarget = null; + list = new WebGLRenderList(); + listArray.push( list ); - if ( typeof window !== 'undefined' && 'VRFrameData' in window ) { + } else { - frameData = new window.VRFrameData(); + list = listArray[ renderCallDepth ]; - } + } - var matrixWorldInverse = new Matrix4(); + } - var cameraL = new PerspectiveCamera(); - cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); - cameraL.layers.enable( 1 ); + return list; - var cameraR = new PerspectiveCamera(); - cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); - cameraR.layers.enable( 2 ); + } - var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + function dispose() { - // + lists = new WeakMap(); - var currentSize, currentPixelRatio; + } - function onVRDisplayPresentChange() { + return { + get: get, + dispose: dispose + }; - if ( device !== null && device.isPresenting ) { + } - var eyeParameters = device.getEyeParameters( 'left' ); - var renderWidth = eyeParameters.renderWidth; - var renderHeight = eyeParameters.renderHeight; + function UniformsCache() { - currentPixelRatio = renderer.getPixelRatio(); - currentSize = renderer.getSize(); + const lights = {}; - renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); + return { - } else if ( scope.enabled ) { + get: function ( light ) { - renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); + if ( lights[ light.id ] !== undefined ) { - } + return lights[ light.id ]; - } + } - if ( typeof window !== 'undefined' ) { + let uniforms; - window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); + switch ( light.type ) { - } + case 'DirectionalLight': + uniforms = { + direction: new Vector3(), + color: new Color() + }; + break; - // + case 'SpotLight': + uniforms = { + position: new Vector3(), + direction: new Vector3(), + color: new Color(), + distance: 0, + coneCos: 0, + penumbraCos: 0, + decay: 0 + }; + break; - this.enabled = false; + case 'PointLight': + uniforms = { + position: new Vector3(), + color: new Color(), + distance: 0, + decay: 0 + }; + break; + + case 'HemisphereLight': + uniforms = { + direction: new Vector3(), + skyColor: new Color(), + groundColor: new Color() + }; + break; - this.getDevice = function () { + case 'RectAreaLight': + uniforms = { + color: new Color(), + position: new Vector3(), + halfWidth: new Vector3(), + halfHeight: new Vector3() + }; + break; - return device; + } - }; + lights[ light.id ] = uniforms; - this.setDevice = function ( value ) { + return uniforms; - if ( value !== undefined ) device = value; + } }; - this.setPoseTarget = function ( object ) { + } - if ( object !== undefined ) poseTarget = object; + function ShadowUniformsCache() { - }; + const lights = {}; - this.getCamera = function ( camera ) { + return { - if ( device === null ) return camera; + get: function ( light ) { - device.depthNear = camera.near; - device.depthFar = camera.far; + if ( lights[ light.id ] !== undefined ) { - device.getFrameData( frameData ); + return lights[ light.id ]; - // + } + + let uniforms; - var pose = frameData.pose; - var poseObject = poseTarget !== null ? poseTarget : camera; + switch ( light.type ) { - if ( pose.position !== null ) { + case 'DirectionalLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; - poseObject.position.fromArray( pose.position ); + case 'SpotLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; - } else { + case 'PointLight': + uniforms = { + shadowIntensity: 1, + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2(), + shadowCameraNear: 1, + shadowCameraFar: 1000 + }; + break; - poseObject.position.set( 0, 0, 0 ); + // TODO (abelnation): set RectAreaLight shadow uniforms - } + } - if ( pose.orientation !== null ) { + lights[ light.id ] = uniforms; - poseObject.quaternion.fromArray( pose.orientation ); + return uniforms; } - poseObject.updateMatrixWorld(); + }; - if ( device.isPresenting === false ) return camera; + } - // - cameraL.near = camera.near; - cameraR.near = camera.near; - cameraL.far = camera.far; - cameraR.far = camera.far; + let nextVersion = 0; - cameraVR.matrixWorld.copy( camera.matrixWorld ); - cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); + function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { - cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); - cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); + return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); - var parent = poseObject.parent; + } - if ( parent !== null ) { + function WebGLLights( extensions ) { - matrixWorldInverse.getInverse( parent.matrixWorld ); + const cache = new UniformsCache(); - cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); - cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); + const shadowCache = ShadowUniformsCache(); - } + const state = { - // envMap and Mirror needs camera.matrixWorld + version: 0, - cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); - cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); + hash: { + directionalLength: - 1, + pointLength: - 1, + spotLength: - 1, + rectAreaLength: - 1, + hemiLength: - 1, - cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); - cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); + numDirectionalShadows: - 1, + numPointShadows: - 1, + numSpotShadows: - 1, + numSpotMaps: - 1, - // HACK @mrdoob - // https://github.com/w3c/webvr/issues/203 + numLightProbes: - 1 + }, - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + ambient: [ 0, 0, 0 ], + probe: [], + directional: [], + directionalShadow: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotLightMap: [], + spotShadow: [], + spotShadowMap: [], + spotLightMatrix: [], + rectArea: [], + rectAreaLTC1: null, + rectAreaLTC2: null, + point: [], + pointShadow: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [], + numSpotLightShadowsWithMaps: 0, + numLightProbes: 0 - // + }; - var layers = device.getLayers(); + for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); - if ( layers.length ) { + const vector3 = new Vector3(); + const matrix4 = new Matrix4(); + const matrix42 = new Matrix4(); - var layer = layers[ 0 ]; + function setup( lights ) { - if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { + let r = 0, g = 0, b = 0; - cameraL.bounds.fromArray( layer.leftBounds ); + 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; - if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { + let numDirectionalShadows = 0; + let numPointShadows = 0; + let numSpotShadows = 0; + let numSpotMaps = 0; + let numSpotShadowsWithMaps = 0; - cameraR.bounds.fromArray( layer.rightBounds ); + let numLightProbes = 0; - } + // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] + lights.sort( shadowCastingAndTexturingLightsFirst ); - } + for ( let i = 0, l = lights.length; i < l; i ++ ) { - return cameraVR; + const light = lights[ i ]; - }; + const color = light.color; + const intensity = light.intensity; + const distance = light.distance; - this.submitFrame = function () { + const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; - if ( device && device.isPresenting ) device.submitFrame(); + if ( light.isAmbientLight ) { - }; + r += color.r * intensity; + g += color.g * intensity; + b += color.b * intensity; - this.dispose = function () { + } else if ( light.isLightProbe ) { - if ( typeof window !== 'undefined' ) { + for ( let j = 0; j < 9; j ++ ) { - window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); + state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); - } + } - }; + numLightProbes ++; - } + } else if ( light.isDirectionalLight ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + const uniforms = cache.get( light ); - function WebGLExtensions( gl ) { + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - var extensions = {}; + if ( light.castShadow ) { - return { + const shadow = light.shadow; - get: function ( name ) { + const shadowUniforms = shadowCache.get( light ); - if ( extensions[ name ] !== undefined ) { + shadowUniforms.shadowIntensity = shadow.intensity; + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; - return extensions[ name ]; + state.directionalShadow[ directionalLength ] = shadowUniforms; + state.directionalShadowMap[ directionalLength ] = shadowMap; + state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - } + numDirectionalShadows ++; - var extension; + } - switch ( name ) { + state.directional[ directionalLength ] = uniforms; - case 'WEBGL_depth_texture': - extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); - break; + directionalLength ++; - 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; + } else if ( light.isSpotLight ) { - 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; + const uniforms = cache.get( light ); - case 'WEBGL_compressed_texture_pvrtc': - extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); - break; + uniforms.position.setFromMatrixPosition( light.matrixWorld ); - case 'WEBGL_compressed_texture_etc1': - extension = gl.getExtension( 'WEBGL_compressed_texture_etc1' ); - break; + uniforms.color.copy( color ).multiplyScalar( intensity ); + uniforms.distance = distance; - default: - extension = gl.getExtension( name ); + uniforms.coneCos = Math.cos( light.angle ); + uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); + uniforms.decay = light.decay; - } + state.spot[ spotLength ] = uniforms; - if ( extension === null ) { + const shadow = light.shadow; - console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); + if ( light.map ) { - } + state.spotLightMap[ numSpotMaps ] = light.map; + numSpotMaps ++; - extensions[ name ] = extension; + // make sure the lightMatrix is up to date + // TODO : do it if required only + shadow.updateMatrices( light ); - return extension; + if ( light.castShadow ) numSpotShadowsWithMaps ++; - } + } - }; + state.spotLightMatrix[ spotLength ] = shadow.matrix; - } + if ( light.castShadow ) { - /** - * @author tschw - */ + const shadowUniforms = shadowCache.get( light ); - function WebGLClipping() { + shadowUniforms.shadowIntensity = shadow.intensity; + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; - var scope = this, + state.spotShadow[ spotLength ] = shadowUniforms; + state.spotShadowMap[ spotLength ] = shadowMap; - globalState = null, - numGlobalPlanes = 0, - localClippingEnabled = false, - renderingShadows = false, + numSpotShadows ++; - plane = new Plane(), - viewNormalMatrix = new Matrix3(), + } - uniform = { value: null, needsUpdate: false }; + spotLength ++; - this.uniform = uniform; - this.numPlanes = 0; - this.numIntersection = 0; + } else if ( light.isRectAreaLight ) { - this.init = function ( planes, enableLocalClipping, camera ) { + const uniforms = cache.get( light ); - var enabled = - planes.length !== 0 || - enableLocalClipping || - // enable state of previous frame - the clipping code has to - // run another frame in order to reset the state: - numGlobalPlanes !== 0 || - localClippingEnabled; + uniforms.color.copy( color ).multiplyScalar( intensity ); - localClippingEnabled = enableLocalClipping; + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - globalState = projectPlanes( planes, camera, 0 ); - numGlobalPlanes = planes.length; + state.rectArea[ rectAreaLength ] = uniforms; - return enabled; + rectAreaLength ++; - }; + } else if ( light.isPointLight ) { - this.beginShadows = function () { + const uniforms = cache.get( light ); - renderingShadows = true; - projectPlanes( null ); + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.distance = light.distance; + uniforms.decay = light.decay; - }; + if ( light.castShadow ) { - this.endShadows = function () { + const shadow = light.shadow; - renderingShadows = false; - resetGlobalState(); + const shadowUniforms = shadowCache.get( light ); - }; + shadowUniforms.shadowIntensity = shadow.intensity; + 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; - this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) { + state.pointShadow[ pointLength ] = shadowUniforms; + state.pointShadowMap[ pointLength ] = shadowMap; + state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { + numPointShadows ++; - // there's no local clipping + } - if ( renderingShadows ) { + state.point[ pointLength ] = uniforms; - // there's no global clipping + pointLength ++; - projectPlanes( null ); + } else if ( light.isHemisphereLight ) { - } else { + const uniforms = cache.get( light ); - resetGlobalState(); + uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); + uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); - } + state.hemi[ hemiLength ] = uniforms; - } else { + hemiLength ++; - var nGlobal = renderingShadows ? 0 : numGlobalPlanes, - lGlobal = nGlobal * 4, + } - dstArray = cache.clippingState || null; + } - uniform.value = dstArray; // ensure unique state + if ( rectAreaLength > 0 ) { - dstArray = projectPlanes( planes, camera, lGlobal, fromCache ); + if ( extensions.has( 'OES_texture_float_linear' ) === true ) { - for ( var i = 0; i !== lGlobal; ++ i ) { + state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; - dstArray[ i ] = globalState[ i ]; + } else { - } + state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; + state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; - cache.clippingState = dstArray; - this.numIntersection = clipIntersection ? this.numPlanes : 0; - this.numPlanes += nGlobal; + } } + state.ambient[ 0 ] = r; + state.ambient[ 1 ] = g; + state.ambient[ 2 ] = b; - }; + const hash = state.hash; - function resetGlobalState() { + 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 || + hash.numSpotMaps !== numSpotMaps || + hash.numLightProbes !== numLightProbes ) { - if ( uniform.value !== globalState ) { + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; - uniform.value = globalState; - uniform.needsUpdate = numGlobalPlanes > 0; + 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.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; + state.spotLightMap.length = numSpotMaps; + state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; + state.numLightProbes = numLightProbes; - } + hash.directionalLength = directionalLength; + hash.pointLength = pointLength; + hash.spotLength = spotLength; + hash.rectAreaLength = rectAreaLength; + hash.hemiLength = hemiLength; - scope.numPlanes = numGlobalPlanes; - scope.numIntersection = 0; + hash.numDirectionalShadows = numDirectionalShadows; + hash.numPointShadows = numPointShadows; + hash.numSpotShadows = numSpotShadows; + hash.numSpotMaps = numSpotMaps; - } + hash.numLightProbes = numLightProbes; - function projectPlanes( planes, camera, dstOffset, skipTransform ) { + state.version = nextVersion ++; - var nPlanes = planes !== null ? planes.length : 0, - dstArray = null; + } - if ( nPlanes !== 0 ) { + } - dstArray = uniform.value; + function setupView( lights, camera ) { - if ( skipTransform !== true || dstArray === null ) { + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; - var flatSize = dstOffset + nPlanes * 4, - viewMatrix = camera.matrixWorldInverse; + const viewMatrix = camera.matrixWorldInverse; - viewNormalMatrix.getNormalMatrix( viewMatrix ); + for ( let i = 0, l = lights.length; i < l; i ++ ) { - if ( dstArray === null || dstArray.length < flatSize ) { + const light = lights[ i ]; - dstArray = new Float32Array( flatSize ); + if ( light.isDirectionalLight ) { - } + const uniforms = state.directional[ directionalLength ]; - for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); - plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); + directionalLength ++; - plane.normal.toArray( dstArray, i4 ); - dstArray[ i4 + 3 ] = plane.constant; + } else if ( light.isSpotLight ) { - } + const uniforms = state.spot[ spotLength ]; - } + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - uniform.value = dstArray; - uniform.needsUpdate = true; - - } - - scope.numPlanes = nPlanes; - - return dstArray; - - } - - } - - /** - * @author thespite / http://www.twitter.com/thespite - */ - - function WebGLUtils( gl, extensions ) { - - function convert( p ) { - - var extension; - - if ( p === RepeatWrapping ) return gl.REPEAT; - if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE; - if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT; + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); - if ( p === NearestFilter ) return gl.NEAREST; - if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST; - if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR; + spotLength ++; - if ( p === LinearFilter ) return gl.LINEAR; - if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST; - if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR; + } else if ( light.isRectAreaLight ) { - if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; - if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; - if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; - if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5; + const uniforms = state.rectArea[ rectAreaLength ]; - if ( p === ByteType ) return gl.BYTE; - if ( p === ShortType ) return gl.SHORT; - if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; - if ( p === IntType ) return gl.INT; - if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; - if ( p === FloatType ) return gl.FLOAT; + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - if ( p === HalfFloatType ) { + // extract local rotation of light to derive width/height half vectors + matrix42.identity(); + matrix4.copy( light.matrixWorld ); + matrix4.premultiply( viewMatrix ); + matrix42.extractRotation( matrix4 ); - extension = extensions.get( 'OES_texture_half_float' ); + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - if ( extension !== null ) return extension.HALF_FLOAT_OES; + uniforms.halfWidth.applyMatrix4( matrix42 ); + uniforms.halfHeight.applyMatrix4( matrix42 ); - } + rectAreaLength ++; - if ( p === AlphaFormat ) return gl.ALPHA; - if ( p === RGBFormat ) return gl.RGB; - if ( p === RGBAFormat ) return gl.RGBA; - if ( p === LuminanceFormat ) return gl.LUMINANCE; - if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; - if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; - if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; + } else if ( light.isPointLight ) { - if ( p === AddEquation ) return gl.FUNC_ADD; - if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT; - if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT; + const uniforms = state.point[ pointLength ]; - if ( p === ZeroFactor ) return gl.ZERO; - if ( p === OneFactor ) return gl.ONE; - if ( p === SrcColorFactor ) return gl.SRC_COLOR; - if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR; - if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA; - if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA; - if ( p === DstAlphaFactor ) return gl.DST_ALPHA; - if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA; + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); - if ( p === DstColorFactor ) return gl.DST_COLOR; - if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR; - if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE; + pointLength ++; - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + } else if ( light.isHemisphereLight ) { - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + const uniforms = state.hemi[ hemiLength ]; - if ( extension !== null ) { + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + uniforms.direction.transformDirection( viewMatrix ); - 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; + hemiLength ++; } } - 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' ); + return { + setup: setup, + setupView: setupView, + state: state + }; - 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; + function WebGLRenderState( extensions ) { - } + const lights = new WebGLLights( extensions ); - } + const lightsArray = []; + const shadowsArray = []; - if ( p === RGB_ETC1_Format ) { + function init( camera ) { - extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); + state.camera = camera; - if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; + lightsArray.length = 0; + shadowsArray.length = 0; - } + } - if ( p === MinEquation || p === MaxEquation ) { + function pushLight( light ) { - extension = extensions.get( 'EXT_blend_minmax' ); + lightsArray.push( light ); - if ( extension !== null ) { + } - if ( p === MinEquation ) return extension.MIN_EXT; - if ( p === MaxEquation ) return extension.MAX_EXT; + function pushShadow( shadowLight ) { - } + shadowsArray.push( shadowLight ); - } + } - if ( p === UnsignedInt248Type ) { + function setupLights() { - extension = extensions.get( 'WEBGL_depth_texture' ); + lights.setup( lightsArray ); - if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; + } - } + function setupLightsView( camera ) { - return 0; + lights.setupView( lightsArray, camera ); } - return { convert: convert }; + const state = { + lightsArray: lightsArray, + shadowsArray: shadowsArray, - } + camera: null, - /** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - * @author tschw - */ + lights: lights, + + transmissionRenderTarget: {} + }; - function WebGLRenderer( parameters ) { + return { + init: init, + state: state, + setupLights: setupLights, + setupLightsView: setupLightsView, - console.log( 'THREE.WebGLRenderer', REVISION ); + pushLight: pushLight, + pushShadow: pushShadow + }; - parameters = parameters || {}; + } - var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ), - _context = parameters.context !== undefined ? parameters.context : null, + function WebGLRenderStates( extensions ) { - _alpha = parameters.alpha !== undefined ? parameters.alpha : false, - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default'; + let renderStates = new WeakMap(); - var lightsArray = []; - var shadowsArray = []; + function get( scene, renderCallDepth = 0 ) { - var currentRenderList = null; + const renderStateArray = renderStates.get( scene ); + let renderState; - var spritesArray = []; - var flaresArray = []; + if ( renderStateArray === undefined ) { - // public properties + renderState = new WebGLRenderState( extensions ); + renderStates.set( scene, [ renderState ] ); - this.domElement = _canvas; - this.context = null; + } else { - // clearing + if ( renderCallDepth >= renderStateArray.length ) { - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + renderState = new WebGLRenderState( extensions ); + renderStateArray.push( renderState ); - // scene graph + } else { - this.sortObjects = true; + renderState = renderStateArray[ renderCallDepth ]; - // user-defined clipping + } - this.clippingPlanes = []; - this.localClippingEnabled = false; + } - // physically based shading + return renderState; - this.gammaFactor = 2.0; // for backwards compatibility - this.gammaInput = false; - this.gammaOutput = false; + } - // physical lights + function dispose() { - this.physicallyCorrectLights = false; + renderStates = new WeakMap(); - // tone mapping + } - this.toneMapping = LinearToneMapping; - this.toneMappingExposure = 1.0; - this.toneMappingWhitePoint = 1.0; + return { + get: get, + dispose: dispose + }; - // morphs + } - this.maxMorphTargets = 8; - this.maxMorphNormals = 4; + class MeshDepthMaterial extends Material { - // internal properties + constructor( parameters ) { - var _this = this, + super(); - _isContextLost = false, + this.isMeshDepthMaterial = true; - // internal state cache + this.type = 'MeshDepthMaterial'; - _currentRenderTarget = null, - _currentFramebuffer = null, - _currentMaterialId = - 1, - _currentGeometryProgram = '', + this.depthPacking = BasicDepthPacking; - _currentCamera = null, - _currentArrayCamera = null, + this.map = null; - _currentViewport = new Vector4(), - _currentScissor = new Vector4(), - _currentScissorTest = null, + this.alphaMap = null; - // + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - _usedTextureUnits = 0, + this.wireframe = false; + this.wireframeLinewidth = 1; - // + this.setValues( parameters ); - _width = _canvas.width, - _height = _canvas.height, + } - _pixelRatio = 1, + copy( source ) { - _viewport = new Vector4( 0, 0, _width, _height ), - _scissor = new Vector4( 0, 0, _width, _height ), - _scissorTest = false, + super.copy( source ); - // frustum + this.depthPacking = source.depthPacking; - _frustum = new Frustum(), + this.map = source.map; - // clipping + this.alphaMap = source.alphaMap; - _clipping = new WebGLClipping(), - _clippingEnabled = false, - _localClippingEnabled = false, + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - // camera matrices cache + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; - _projScreenMatrix = new Matrix4(), + return this; - _vector3 = new Vector3(), + } - // info + } - _infoMemory = { - geometries: 0, - textures: 0 - }, + class MeshDistanceMaterial extends Material { - _infoRender = { + constructor( parameters ) { - frame: 0, - calls: 0, - vertices: 0, - faces: 0, - points: 0 + super(); - }; + this.isMeshDistanceMaterial = true; - this.info = { + this.type = 'MeshDistanceMaterial'; - render: _infoRender, - memory: _infoMemory, - programs: null + this.map = null; - }; + this.alphaMap = null; - function getTargetPixelRatio() { + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - return _currentRenderTarget === null ? _pixelRatio : 1; + this.setValues( parameters ); } - // initialize + copy( source ) { - var _gl; + super.copy( source ); - try { + this.map = source.map; - var contextAttributes = { - alpha: _alpha, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference - }; + this.alphaMap = source.alphaMap; - // event listeners must be registered before WebGL context is created, see #12753 + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + return this; - _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes ); + } - if ( _gl === null ) { + } - if ( _canvas.getContext( 'webgl' ) !== null ) { + const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; - } else { + function WebGLShadowMap( renderer, objects, capabilities ) { - throw new Error( 'Error creating WebGL context.' ); + let _frustum = new Frustum(); - } + const _shadowMapSize = new Vector2(), + _viewportSize = new Vector2(), - } + _viewport = new Vector4(), - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), + _distanceMaterial = new MeshDistanceMaterial(), - if ( _gl.getShaderPrecisionFormat === undefined ) { + _materialCache = {}, - _gl.getShaderPrecisionFormat = function () { + _maxTextureSize = capabilities.maxTextureSize; - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; - }; + const shadowMaterialVertical = new ShaderMaterial( { + defines: { + VSM_SAMPLES: 8 + }, + uniforms: { + shadow_pass: { value: null }, + resolution: { value: new Vector2() }, + radius: { value: 4.0 } + }, - } + vertexShader: vertex, + fragmentShader: fragment - } catch ( error ) { + } ); - console.error( 'THREE.WebGLRenderer: ' + error.message ); + 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 + ) + ); - var extensions, capabilities, state; - var properties, textures, attributes, geometries, objects, lights; - var programCache, renderLists; + const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); - var background, morphtargets, bufferRenderer, indexedBufferRenderer; - var flareRenderer, spriteRenderer; + const scope = this; - var utils; + this.enabled = false; - function initGLContext() { + this.autoUpdate = true; + this.needsUpdate = false; - extensions = new WebGLExtensions( _gl ); - extensions.get( 'WEBGL_depth_texture' ); - extensions.get( 'OES_texture_float' ); - extensions.get( 'OES_texture_float_linear' ); - extensions.get( 'OES_texture_half_float' ); - extensions.get( 'OES_texture_half_float_linear' ); - extensions.get( 'OES_standard_derivatives' ); - extensions.get( 'OES_element_index_uint' ); - extensions.get( 'ANGLE_instanced_arrays' ); + this.type = PCFShadowMap; + let _previousType = this.type; - utils = new WebGLUtils( _gl, extensions ); + this.render = function ( lights, scene, camera ) { - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + if ( scope.enabled === false ) return; + if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; - state = new WebGLState( _gl, extensions, utils ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); + if ( lights.length === 0 ) return; - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory ); - attributes = new WebGLAttributes( _gl ); - geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); - objects = new WebGLObjects( geometries, _infoRender ); - morphtargets = new WebGLMorphtargets( _gl ); - programCache = new WebGLPrograms( _this, extensions, capabilities ); - lights = new WebGLLights(); - renderLists = new WebGLRenderLists(); + const currentRenderTarget = renderer.getRenderTarget(); + const activeCubeFace = renderer.getActiveCubeFace(); + const activeMipmapLevel = renderer.getActiveMipmapLevel(); - background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha ); + const _state = renderer.state; - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); + // Set GL state for depth map. + _state.setBlending( NoBlending ); + _state.buffers.color.setClear( 1, 1, 1, 1 ); + _state.buffers.depth.setTest( true ); + _state.setScissorTest( false ); - flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities ); - spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); + // check for shadow map type changes - _this.info.programs = programCache.programs; + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); - _this.context = _gl; - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.state = state; + // render depth map - } + for ( let i = 0, il = lights.length; i < il; i ++ ) { - initGLContext(); + const light = lights[ i ]; + const shadow = light.shadow; - // vr + if ( shadow === undefined ) { - var vr = new WebVRManager( _this ); + console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); + continue; - this.vr = vr; + } - // shadow map + if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; - var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); + _shadowMapSize.copy( shadow.mapSize ); - this.shadowMap = shadowMap; + const shadowFrameExtents = shadow.getFrameExtents(); - // API + _shadowMapSize.multiply( shadowFrameExtents ); - this.getContext = function () { + _viewportSize.copy( shadow.mapSize ); - return _gl; + if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { - }; + if ( _shadowMapSize.x > _maxTextureSize ) { - this.getContextAttributes = function () { + _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); + _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; + shadow.mapSize.x = _viewportSize.x; - return _gl.getContextAttributes(); + } - }; + if ( _shadowMapSize.y > _maxTextureSize ) { - this.forceContextLoss = function () { + _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); + _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; + shadow.mapSize.y = _viewportSize.y; - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.loseContext(); + } - }; + } - this.forceContextRestore = function () { + if ( shadow.map === null || toVSM === true || fromVSM === true ) { - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.restoreContext(); + const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; - }; + if ( shadow.map !== null ) { - this.getPixelRatio = function () { + shadow.map.dispose(); - return _pixelRatio; + } - }; + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); + shadow.map.texture.name = light.name + '.shadowMap'; - this.setPixelRatio = function ( value ) { + shadow.camera.updateProjectionMatrix(); - if ( value === undefined ) return; + } - _pixelRatio = value; + renderer.setRenderTarget( shadow.map ); + renderer.clear(); - this.setSize( _width, _height, false ); + const viewportCount = shadow.getViewportCount(); - }; + for ( let vp = 0; vp < viewportCount; vp ++ ) { - this.getSize = function () { + const viewport = shadow.getViewport( vp ); - return { - width: _width, - height: _height - }; + _viewport.set( + _viewportSize.x * viewport.x, + _viewportSize.y * viewport.y, + _viewportSize.x * viewport.z, + _viewportSize.y * viewport.w + ); - }; + _state.viewport( _viewport ); - this.setSize = function ( width, height, updateStyle ) { + shadow.updateMatrices( light, vp ); - var device = vr.getDevice(); + _frustum = shadow.getFrustum(); - if ( device && device.isPresenting ) { + renderObject( scene, camera, shadow.camera, light, this.type ); - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + } - } + // do blur pass for VSM - _width = width; - _height = height; + if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { - _canvas.width = width * _pixelRatio; - _canvas.height = height * _pixelRatio; + VSMPass( shadow, camera ); - if ( updateStyle !== false ) { + } - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + shadow.needsUpdate = false; } - this.setViewport( 0, 0, width, height ); - - }; + _previousType = this.type; - this.getDrawingBufferSize = function () { + scope.needsUpdate = false; - return { - width: _width * _pixelRatio, - height: _height * _pixelRatio - }; + renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); }; - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - - _width = width; - _height = height; - - _pixelRatio = pixelRatio; + function VSMPass( shadow, camera ) { - _canvas.width = width * pixelRatio; - _canvas.height = height * pixelRatio; + const geometry = objects.update( fullScreenMesh ); - this.setViewport( 0, 0, width, height ); + if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { - }; - - this.setViewport = function ( x, y, width, height ) { + shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; - _viewport.set( x, _height - y - height, width, height ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); + shadowMaterialVertical.needsUpdate = true; + shadowMaterialHorizontal.needsUpdate = true; - }; + } - this.setScissor = function ( x, y, width, height ) { + if ( shadow.mapPass === null ) { - _scissor.set( x, _height - y - height, width, height ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); + shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); - }; + } - this.setScissorTest = function ( boolean ) { + // vertical pass - state.setScissorTest( _scissorTest = boolean ); + 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 ); - }; + // horizontal pass - // Clearing + 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 ); - this.getClearColor = function () { + } - return background.getClearColor(); + function getDepthMaterial( object, material, light, type ) { - }; + let result = null; - this.setClearColor = function () { + const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; - background.setClearColor.apply( background, arguments ); + if ( customMaterial !== undefined ) { - }; + result = customMaterial; - this.getClearAlpha = function () { + } else { - return background.getClearAlpha(); + 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 ) || + ( material.map && material.alphaTest > 0 ) ) { - this.setClearAlpha = function () { + // in this case we need a unique material instance reflecting the + // appropriate state - background.setClearAlpha.apply( background, arguments ); + const keyA = result.uuid, keyB = material.uuid; - }; + let materialsForVariant = _materialCache[ keyA ]; - this.clear = function ( color, depth, stencil ) { + if ( materialsForVariant === undefined ) { - var bits = 0; + materialsForVariant = {}; + _materialCache[ keyA ] = materialsForVariant; - if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT; - if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT; - if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT; + } - _gl.clear( bits ); + let cachedMaterial = materialsForVariant[ keyB ]; - }; + if ( cachedMaterial === undefined ) { - this.clearColor = function () { + cachedMaterial = result.clone(); + materialsForVariant[ keyB ] = cachedMaterial; + material.addEventListener( 'dispose', onMaterialDispose ); - this.clear( true, false, false ); + } - }; + result = cachedMaterial; - this.clearDepth = function () { + } - this.clear( false, true, false ); + } - }; + result.visible = material.visible; + result.wireframe = material.wireframe; - this.clearStencil = function () { + if ( type === VSMShadowMap ) { - this.clear( false, false, true ); + result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; - }; + } else { - this.clearTarget = function ( renderTarget, color, depth, stencil ) { + result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; - this.setRenderTarget( renderTarget ); - this.clear( color, depth, stencil ); + } - }; + result.alphaMap = material.alphaMap; + result.alphaTest = material.alphaTest; + result.map = material.map; - // + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; - this.dispose = function () { + result.displacementMap = material.displacementMap; + result.displacementScale = material.displacementScale; + result.displacementBias = material.displacementBias; - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; - renderLists.dispose(); + if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { - vr.dispose(); + const materialProperties = renderer.properties.get( result ); + materialProperties.light = light; - }; + } - // Events + return result; - function onContextLost( event ) { + } - event.preventDefault(); + function renderObject( object, camera, shadowCamera, light, type ) { - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + if ( object.visible === false ) return; - _isContextLost = true; + const visible = object.layers.test( camera.layers ); - } + if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - function onContextRestore( /* event */ ) { + if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - _isContextLost = false; + const geometry = objects.update( object ); + const material = object.material; - initGLContext(); + if ( Array.isArray( material ) ) { - } + const groups = geometry.groups; - function onMaterialDispose( event ) { + for ( let k = 0, kl = groups.length; k < kl; k ++ ) { - var material = event.target; + const group = groups[ k ]; + const groupMaterial = material[ group.materialIndex ]; - material.removeEventListener( 'dispose', onMaterialDispose ); + if ( groupMaterial && groupMaterial.visible ) { - deallocateMaterial( material ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); - } + object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); - // Buffer deallocation + renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - function deallocateMaterial( material ) { + object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); - releaseMaterialProgramReference( material ); + } - properties.remove( material ); + } - } + } else if ( material.visible ) { + const depthMaterial = getDepthMaterial( object, material, light, type ); - function releaseMaterialProgramReference( material ) { + object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); - var programInfo = properties.get( material ).program; + renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - material.program = undefined; + object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); - if ( programInfo !== undefined ) { + } - programCache.releaseProgram( programInfo ); + } } - } + const children = object.children; - // Buffer rendering + for ( let i = 0, l = children.length; i < l; i ++ ) { - function renderObjectImmediate( object, program, material ) { + renderObject( children[ i ], camera, shadowCamera, light, type ); - object.render( function ( object ) { + } - _this.renderBufferImmediate( object, program, material ); + } - } ); + function onMaterialDispose( event ) { - } + const material = event.target; - this.renderBufferImmediate = function ( object, program, material ) { + material.removeEventListener( 'dispose', onMaterialDispose ); - state.initAttributes(); + // make sure to remove the unique distance/depth materials used for shadow map rendering - var buffers = properties.get( object ); + for ( const id in _materialCache ) { - if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer(); - if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer(); - if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer(); - if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer(); + const cache = _materialCache[ id ]; - var programAttributes = program.getAttributes(); + const uuid = event.target.uuid; - if ( object.hasPositions ) { + if ( uuid in cache ) { - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); + const shadowMaterial = cache[ uuid ]; + shadowMaterial.dispose(); + delete cache[ uuid ]; - state.enableAttribute( programAttributes.position ); - _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 ); + } } - if ( object.hasNormals ) { + } - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal ); + } - if ( ! material.isMeshPhongMaterial && - ! material.isMeshStandardMaterial && - ! material.isMeshNormalMaterial && - material.flatShading === true ) { + function WebGLState( gl ) { - for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { + function ColorBuffer() { - var array = object.normalArray; + let locked = false; - var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3; - var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3; - var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3; + const color = new Vector4(); + let currentColorMask = null; + const currentColorClear = new Vector4( 0, 0, 0, 0 ); - array[ i + 0 ] = nx; - array[ i + 1 ] = ny; - array[ i + 2 ] = nz; + return { - array[ i + 3 ] = nx; - array[ i + 4 ] = ny; - array[ i + 5 ] = nz; + setMask: function ( colorMask ) { - array[ i + 6 ] = nx; - array[ i + 7 ] = ny; - array[ i + 8 ] = nz; + if ( currentColorMask !== colorMask && ! locked ) { - } - - } + gl.colorMask( colorMask, colorMask, colorMask, colorMask ); + currentColorMask = colorMask; - _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); + } - state.enableAttribute( programAttributes.normal ); + }, - _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 ); + setLocked: function ( lock ) { - } + locked = lock; - if ( object.hasUvs && material.map ) { + }, - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW ); + setClear: function ( r, g, b, a, premultipliedAlpha ) { - state.enableAttribute( programAttributes.uv ); + if ( premultipliedAlpha === true ) { - _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); + r *= a; g *= a; b *= a; - } + } - if ( object.hasColors && material.vertexColors !== NoColors ) { + color.set( r, g, b, a ); - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW ); + if ( currentColorClear.equals( color ) === false ) { - state.enableAttribute( programAttributes.color ); + gl.clearColor( r, g, b, a ); + currentColorClear.copy( color ); - _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 ); + } - } + }, - state.disableUnusedAttributes(); + reset: function () { - _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); + locked = false; - object.count = 0; + currentColorMask = null; + currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state - }; + } - this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { + }; - var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + } - state.setMaterial( material, frontFaceCW ); + function DepthBuffer() { - var program = setProgram( camera, fog, material, object ); - var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true ); + let locked = false; - var updateBuffers = false; + let currentDepthMask = null; + let currentDepthFunc = null; + let currentDepthClear = null; - if ( geometryProgram !== _currentGeometryProgram ) { + return { - _currentGeometryProgram = geometryProgram; - updateBuffers = true; + setTest: function ( depthTest ) { - } + if ( depthTest ) { - if ( object.morphTargetInfluences ) { + enable( gl.DEPTH_TEST ); - morphtargets.update( object, geometry, material, program ); + } else { - updateBuffers = true; + disable( gl.DEPTH_TEST ); - } + } - // + }, - var index = geometry.index; - var position = geometry.attributes.position; - var rangeFactor = 1; + setMask: function ( depthMask ) { - if ( material.wireframe === true ) { + if ( currentDepthMask !== depthMask && ! locked ) { - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; + gl.depthMask( depthMask ); + currentDepthMask = depthMask; - } + } - var attribute; - var renderer = bufferRenderer; + }, - if ( index !== null ) { + setFunc: function ( depthFunc ) { - attribute = attributes.get( index ); + if ( currentDepthFunc !== depthFunc ) { - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + switch ( depthFunc ) { - } + case NeverDepth: - if ( updateBuffers ) { + gl.depthFunc( gl.NEVER ); + break; - setupVertexAttributes( material, program, geometry ); + case AlwaysDepth: - if ( index !== null ) { + gl.depthFunc( gl.ALWAYS ); + break; - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); + case LessDepth: - } + gl.depthFunc( gl.LESS ); + break; - } + case LessEqualDepth: - // + gl.depthFunc( gl.LEQUAL ); + break; - var dataCount = 0; + case EqualDepth: - if ( index !== null ) { + gl.depthFunc( gl.EQUAL ); + break; - dataCount = index.count; + case GreaterEqualDepth: - } else if ( position !== undefined ) { + gl.depthFunc( gl.GEQUAL ); + break; - dataCount = position.count; + case GreaterDepth: - } + gl.depthFunc( gl.GREATER ); + break; - var rangeStart = geometry.drawRange.start * rangeFactor; - var rangeCount = geometry.drawRange.count * rangeFactor; + case NotEqualDepth: - var groupStart = group !== null ? group.start * rangeFactor : 0; - var groupCount = group !== null ? group.count * rangeFactor : Infinity; + gl.depthFunc( gl.NOTEQUAL ); + break; - var drawStart = Math.max( rangeStart, groupStart ); - var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1; + default: - var drawCount = Math.max( 0, drawEnd - drawStart + 1 ); + gl.depthFunc( gl.LEQUAL ); - if ( drawCount === 0 ) return; + } - // + currentDepthFunc = depthFunc; - if ( object.isMesh ) { + } - if ( material.wireframe === true ) { + }, - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); + setLocked: function ( lock ) { - } else { + locked = lock; - switch ( object.drawMode ) { + }, - case TrianglesDrawMode: - renderer.setMode( _gl.TRIANGLES ); - break; + setClear: function ( depth ) { - case TriangleStripDrawMode: - renderer.setMode( _gl.TRIANGLE_STRIP ); - break; + if ( currentDepthClear !== depth ) { - case TriangleFanDrawMode: - renderer.setMode( _gl.TRIANGLE_FAN ); - break; + gl.clearDepth( depth ); + currentDepthClear = depth; } - } + }, + reset: function () { - } else if ( object.isLine ) { + locked = false; - var lineWidth = material.linewidth; + currentDepthMask = null; + currentDepthFunc = null; + currentDepthClear = null; - if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material + } - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + }; - if ( object.isLineSegments ) { + } - renderer.setMode( _gl.LINES ); + function StencilBuffer() { - } else if ( object.isLineLoop ) { + let locked = false; - renderer.setMode( _gl.LINE_LOOP ); + let currentStencilMask = null; + let currentStencilFunc = null; + let currentStencilRef = null; + let currentStencilFuncMask = null; + let currentStencilFail = null; + let currentStencilZFail = null; + let currentStencilZPass = null; + let currentStencilClear = null; - } else { + return { - renderer.setMode( _gl.LINE_STRIP ); + setTest: function ( stencilTest ) { - } + if ( ! locked ) { - } else if ( object.isPoints ) { + if ( stencilTest ) { - renderer.setMode( _gl.POINTS ); + enable( gl.STENCIL_TEST ); - } + } else { - if ( geometry && geometry.isInstancedBufferGeometry ) { + disable( gl.STENCIL_TEST ); - if ( geometry.maxInstancedCount > 0 ) { + } - renderer.renderInstances( geometry, drawStart, drawCount ); + } - } + }, - } else { + setMask: function ( stencilMask ) { - renderer.render( drawStart, drawCount ); + if ( currentStencilMask !== stencilMask && ! locked ) { - } + gl.stencilMask( stencilMask ); + currentStencilMask = stencilMask; - }; + } - function setupVertexAttributes( material, program, geometry, startIndex ) { + }, - if ( geometry && geometry.isInstancedBufferGeometry ) { + setFunc: function ( stencilFunc, stencilRef, stencilMask ) { - if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { + if ( currentStencilFunc !== stencilFunc || + currentStencilRef !== stencilRef || + currentStencilFuncMask !== stencilMask ) { - console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; + gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); - } + currentStencilFunc = stencilFunc; + currentStencilRef = stencilRef; + currentStencilFuncMask = stencilMask; - } + } - if ( startIndex === undefined ) startIndex = 0; + }, - state.initAttributes(); + setOp: function ( stencilFail, stencilZFail, stencilZPass ) { - var geometryAttributes = geometry.attributes; + if ( currentStencilFail !== stencilFail || + currentStencilZFail !== stencilZFail || + currentStencilZPass !== stencilZPass ) { - var programAttributes = program.getAttributes(); + gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); - var materialDefaultAttributeValues = material.defaultAttributeValues; + currentStencilFail = stencilFail; + currentStencilZFail = stencilZFail; + currentStencilZPass = stencilZPass; - for ( var name in programAttributes ) { + } - var programAttribute = programAttributes[ name ]; + }, - if ( programAttribute >= 0 ) { + setLocked: function ( lock ) { - var geometryAttribute = geometryAttributes[ name ]; + locked = lock; - if ( geometryAttribute !== undefined ) { + }, - var normalized = geometryAttribute.normalized; - var size = geometryAttribute.itemSize; + setClear: function ( stencil ) { - var attribute = attributes.get( geometryAttribute ); + if ( currentStencilClear !== stencil ) { - // TODO Attribute may not be available on context restore + gl.clearStencil( stencil ); + currentStencilClear = stencil; - if ( attribute === undefined ) continue; + } - var buffer = attribute.buffer; - var type = attribute.type; - var bytesPerElement = attribute.bytesPerElement; + }, - if ( geometryAttribute.isInterleavedBufferAttribute ) { + reset: function () { - var data = geometryAttribute.data; - var stride = data.stride; - var offset = geometryAttribute.offset; + locked = false; - if ( data && data.isInstancedInterleavedBuffer ) { + currentStencilMask = null; + currentStencilFunc = null; + currentStencilRef = null; + currentStencilFuncMask = null; + currentStencilFail = null; + currentStencilZFail = null; + currentStencilZPass = null; + currentStencilClear = null; - state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute ); + } - if ( geometry.maxInstancedCount === undefined ) { + }; - geometry.maxInstancedCount = data.meshPerAttribute * data.count; + } - } + // - } else { + const colorBuffer = new ColorBuffer(); + const depthBuffer = new DepthBuffer(); + const stencilBuffer = new StencilBuffer(); - state.enableAttribute( programAttribute ); + const uboBindings = new WeakMap(); + const uboProgramMap = new WeakMap(); - } + let enabledCapabilities = {}; - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, ( startIndex * stride + offset ) * bytesPerElement ); + let currentBoundFramebuffers = {}; + let currentDrawbuffers = new WeakMap(); + let defaultDrawbuffers = []; - } else { + let currentProgram = null; - if ( geometryAttribute.isInstancedBufferAttribute ) { + 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 currentBlendColor = new Color( 0, 0, 0 ); + let currentBlendAlpha = 0; + let currentPremultipledAlpha = false; - state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute ); + let currentFlipSided = null; + let currentCullFace = null; - if ( geometry.maxInstancedCount === undefined ) { + let currentLineWidth = null; - geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; + let currentPolygonOffsetFactor = null; + let currentPolygonOffsetUnits = null; - } + const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); - } else { + let lineWidthAvailable = false; + let version = 0; + const glVersion = gl.getParameter( gl.VERSION ); - state.enableAttribute( programAttribute ); + if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { - } + version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); + lineWidthAvailable = ( version >= 1.0 ); - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * bytesPerElement ); + } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { - } + version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); + lineWidthAvailable = ( version >= 2.0 ); - } else if ( materialDefaultAttributeValues !== undefined ) { + } - var value = materialDefaultAttributeValues[ name ]; + let currentTextureSlot = null; + let currentBoundTextures = {}; - if ( value !== undefined ) { + const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); + const viewportParam = gl.getParameter( gl.VIEWPORT ); - switch ( value.length ) { + const currentScissor = new Vector4().fromArray( scissorParam ); + const currentViewport = new Vector4().fromArray( viewportParam ); - case 2: - _gl.vertexAttrib2fv( programAttribute, value ); - break; + function createTexture( type, target, count, dimensions ) { - case 3: - _gl.vertexAttrib3fv( programAttribute, value ); - break; + const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. + const texture = gl.createTexture(); - case 4: - _gl.vertexAttrib4fv( programAttribute, value ); - break; + gl.bindTexture( type, texture ); + gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - default: - _gl.vertexAttrib1fv( programAttribute, value ); + for ( let i = 0; i < count; i ++ ) { - } + if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) { - } + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); - } + } else { + + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); } } - state.disableUnusedAttributes(); + return texture; } - // Compile + 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 ); + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); - this.compile = function ( scene, camera ) { + // init - lightsArray.length = 0; - shadowsArray.length = 0; + colorBuffer.setClear( 0, 0, 0, 1 ); + depthBuffer.setClear( 1 ); + stencilBuffer.setClear( 0 ); - scene.traverse( function ( object ) { + enable( gl.DEPTH_TEST ); + depthBuffer.setFunc( LessEqualDepth ); - if ( object.isLight ) { + setFlipSided( false ); + setCullFace( CullFaceBack ); + enable( gl.CULL_FACE ); - lightsArray.push( object ); + setBlending( NoBlending ); - if ( object.castShadow ) { + // - shadowsArray.push( object ); + function enable( id ) { - } + if ( enabledCapabilities[ id ] !== true ) { - } + gl.enable( id ); + enabledCapabilities[ id ] = true; - } ); + } - lights.setup( lightsArray, shadowsArray, camera ); + } - scene.traverse( function ( object ) { + function disable( id ) { - if ( object.material ) { + if ( enabledCapabilities[ id ] !== false ) { - if ( Array.isArray( object.material ) ) { + gl.disable( id ); + enabledCapabilities[ id ] = false; - for ( var i = 0; i < object.material.length; i ++ ) { + } - initMaterial( object.material[ i ], scene.fog, object ); + } - } + function bindFramebuffer( target, framebuffer ) { - } else { + if ( currentBoundFramebuffers[ target ] !== framebuffer ) { - initMaterial( object.material, scene.fog, object ); + gl.bindFramebuffer( target, framebuffer ); - } + currentBoundFramebuffers[ target ] = framebuffer; - } + // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER - } ); + if ( target === gl.DRAW_FRAMEBUFFER ) { - }; + currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; - // Animation Loop + } - var isAnimating = false; - var onAnimationFrame = null; + if ( target === gl.FRAMEBUFFER ) { - function start() { + currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; - if ( isAnimating ) return; + } - var device = vr.getDevice(); + return true; - if ( device && device.isPresenting ) { + } - device.requestAnimationFrame( loop ); + return false; - } else { + } - window.requestAnimationFrame( loop ); + function drawBuffers( renderTarget, framebuffer ) { - } + let drawBuffers = defaultDrawbuffers; - isAnimating = true; + let needsUpdate = false; - } + if ( renderTarget ) { - function loop( time ) { + drawBuffers = currentDrawbuffers.get( framebuffer ); - if ( onAnimationFrame !== null ) onAnimationFrame( time ); + if ( drawBuffers === undefined ) { - var device = vr.getDevice(); + drawBuffers = []; + currentDrawbuffers.set( framebuffer, drawBuffers ); - if ( device && device.isPresenting ) { + } - device.requestAnimationFrame( loop ); + const textures = renderTarget.textures; - } else { + if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { - window.requestAnimationFrame( loop ); + for ( let i = 0, il = textures.length; i < il; i ++ ) { - } + drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; - } + } - this.animate = function ( callback ) { + drawBuffers.length = textures.length; - onAnimationFrame = callback; - start(); + needsUpdate = true; - }; + } - // Rendering + } else { - this.render = function ( scene, camera, renderTarget, forceClear ) { + if ( drawBuffers[ 0 ] !== gl.BACK ) { - if ( ! ( camera && camera.isCamera ) ) { + drawBuffers[ 0 ] = gl.BACK; - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + needsUpdate = true; + + } } - if ( _isContextLost ) return; + if ( needsUpdate ) { - // reset caching for this frame + gl.drawBuffers( drawBuffers ); - _currentGeometryProgram = ''; - _currentMaterialId = - 1; - _currentCamera = null; + } - // update scene graph + } - if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); + function useProgram( program ) { - // update camera matrices and frustum + if ( currentProgram !== program ) { - if ( camera.parent === null ) camera.updateMatrixWorld(); + gl.useProgram( program ); - if ( vr.enabled ) { + currentProgram = program; - camera = vr.getCamera( camera ); + return true; } - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); + return false; - lightsArray.length = 0; - shadowsArray.length = 0; + } - spritesArray.length = 0; - flaresArray.length = 0; + const equationToGL = { + [ AddEquation ]: gl.FUNC_ADD, + [ SubtractEquation ]: gl.FUNC_SUBTRACT, + [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT + }; - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); + equationToGL[ MinEquation ] = gl.MIN; + equationToGL[ MaxEquation ] = gl.MAX; + + const factorToGL = { + [ ZeroFactor ]: gl.ZERO, + [ OneFactor ]: gl.ONE, + [ SrcColorFactor ]: gl.SRC_COLOR, + [ SrcAlphaFactor ]: gl.SRC_ALPHA, + [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, + [ DstColorFactor ]: gl.DST_COLOR, + [ DstAlphaFactor ]: gl.DST_ALPHA, + [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, + [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, + [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, + [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, + [ ConstantColorFactor ]: gl.CONSTANT_COLOR, + [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, + [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, + [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA + }; - currentRenderList = renderLists.get( scene, camera ); - currentRenderList.init(); + function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { - projectObject( scene, camera, _this.sortObjects ); + if ( blending === NoBlending ) { - if ( _this.sortObjects === true ) { + if ( currentBlendingEnabled === true ) { - currentRenderList.sort(); + disable( gl.BLEND ); + currentBlendingEnabled = false; - } + } - // + return; - textures.updateVideoTextures(); + } - // + if ( currentBlendingEnabled === false ) { + + enable( gl.BLEND ); + currentBlendingEnabled = true; - if ( _clippingEnabled ) _clipping.beginShadows(); + } - shadowMap.render( shadowsArray, scene, camera ); + if ( blending !== CustomBlending ) { - lights.setup( lightsArray, shadowsArray, camera ); + if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { - if ( _clippingEnabled ) _clipping.endShadows(); + if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { - // + gl.blendEquation( gl.FUNC_ADD ); - _infoRender.frame ++; - _infoRender.calls = 0; - _infoRender.vertices = 0; - _infoRender.faces = 0; - _infoRender.points = 0; + currentBlendEquation = AddEquation; + currentBlendEquationAlpha = AddEquation; - if ( renderTarget === undefined ) { + } - renderTarget = null; + if ( premultipliedAlpha ) { - } + switch ( blending ) { - this.setRenderTarget( renderTarget ); + case NormalBlending: + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; - // + case AdditiveBlending: + gl.blendFunc( gl.ONE, gl.ONE ); + break; - background.render( currentRenderList, scene, camera, forceClear ); + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; - // render scene + case MultiplyBlending: + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + break; - var opaqueObjects = currentRenderList.opaque; - var transparentObjects = currentRenderList.transparent; + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; - if ( scene.overrideMaterial ) { + } - var overrideMaterial = scene.overrideMaterial; + } else { - if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial ); - if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial ); + switch ( blending ) { - } else { + case NormalBlending: + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; - // opaque pass (front-to-back order) + case AdditiveBlending: + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + break; - if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera ); + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; - // transparent pass (back-to-front order) + case MultiplyBlending: + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + break; - if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera ); + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; - } + } - // custom renderers + } - spriteRenderer.render( spritesArray, scene, camera ); - flareRenderer.render( flaresArray, scene, camera, _currentViewport ); + currentBlendSrc = null; + currentBlendDst = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlendColor.set( 0, 0, 0 ); + currentBlendAlpha = 0; - // Generate mipmap if we're using any kind of mipmap filtering + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; - if ( renderTarget ) { + } - textures.updateRenderTargetMipmap( renderTarget ); + return; } - // Ensure depth buffer writing is enabled so it can be cleared on next render + // custom blending - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; - state.setPolygonOffset( false ); + if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { - if ( vr.enabled ) { + gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); - vr.submitFrame(); + currentBlendEquation = blendEquation; + currentBlendEquationAlpha = blendEquationAlpha; } - // _gl.finish(); + if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { - }; + gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); - /* - // TODO Duplicated code (Frustum) + currentBlendSrc = blendSrc; + currentBlendDst = blendDst; + currentBlendSrcAlpha = blendSrcAlpha; + currentBlendDstAlpha = blendDstAlpha; - var _sphere = new Sphere(); + } - function isObjectViewable( object ) { + if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) { - var geometry = object.geometry; + gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); + currentBlendColor.copy( blendColor ); + currentBlendAlpha = blendAlpha; - _sphere.copy( geometry.boundingSphere ). - applyMatrix4( object.matrixWorld ); + } - return isSphereViewable( _sphere ); + currentBlending = blending; + currentPremultipledAlpha = false; } - function isSpriteViewable( sprite ) { + function setMaterial( material, frontFaceCW ) { - _sphere.center.set( 0, 0, 0 ); - _sphere.radius = 0.7071067811865476; - _sphere.applyMatrix4( sprite.matrixWorld ); + material.side === DoubleSide + ? disable( gl.CULL_FACE ) + : enable( gl.CULL_FACE ); - return isSphereViewable( _sphere ); + let flipSided = ( material.side === BackSide ); + if ( frontFaceCW ) flipSided = ! flipSided; - } + setFlipSided( flipSided ); - function isSphereViewable( sphere ) { + ( material.blending === NormalBlending && material.transparent === false ) + ? setBlending( NoBlending ) + : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); - if ( ! _frustum.intersectsSphere( sphere ) ) return false; + depthBuffer.setFunc( material.depthFunc ); + depthBuffer.setTest( material.depthTest ); + depthBuffer.setMask( material.depthWrite ); + colorBuffer.setMask( material.colorWrite ); - var numPlanes = _clipping.numPlanes; + const stencilWrite = material.stencilWrite; + stencilBuffer.setTest( stencilWrite ); + if ( stencilWrite ) { - if ( numPlanes === 0 ) return true; + stencilBuffer.setMask( material.stencilWriteMask ); + stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); + stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); - var planes = _this.clippingPlanes, + } - center = sphere.center, - negRad = - sphere.radius, - i = 0; + setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - do { + material.alphaToCoverage === true + ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) + : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); - // out when deeper than radius in the negative halfspace - if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; + } - } while ( ++ i !== numPlanes ); + // - return true; + function setFlipSided( flipSided ) { - } - */ + if ( currentFlipSided !== flipSided ) { - function projectObject( object, camera, sortObjects ) { + if ( flipSided ) { - if ( object.visible === false ) return; + gl.frontFace( gl.CW ); - var visible = object.layers.test( camera.layers ); + } else { - if ( visible ) { + gl.frontFace( gl.CCW ); - if ( object.isLight ) { + } - lightsArray.push( object ); + currentFlipSided = flipSided; - if ( object.castShadow ) { + } - shadowsArray.push( object ); + } - } + function setCullFace( cullFace ) { - } else if ( object.isSprite ) { + if ( cullFace !== CullFaceNone ) { - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + enable( gl.CULL_FACE ); - spritesArray.push( object ); + if ( cullFace !== currentCullFace ) { - } + if ( cullFace === CullFaceBack ) { - } else if ( object.isLensFlare ) { + gl.cullFace( gl.BACK ); - flaresArray.push( object ); + } else if ( cullFace === CullFaceFront ) { - } else if ( object.isImmediateRenderObject ) { + gl.cullFace( gl.FRONT ); - if ( sortObjects ) { + } else { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + gl.cullFace( gl.FRONT_AND_BACK ); } - currentRenderList.push( object, null, object.material, _vector3.z, null ); + } + + } else { - } else if ( object.isMesh || object.isLine || object.isPoints ) { + disable( gl.CULL_FACE ); - if ( object.isSkinnedMesh ) { + } - object.skeleton.update(); + currentCullFace = cullFace; - } + } - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + function setLineWidth( width ) { - if ( sortObjects ) { + if ( width !== currentLineWidth ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + if ( lineWidthAvailable ) gl.lineWidth( width ); - } + currentLineWidth = width; - var geometry = objects.update( object ); - var material = object.material; + } - if ( Array.isArray( material ) ) { + } - var groups = geometry.groups; + function setPolygonOffset( polygonOffset, factor, units ) { - for ( var i = 0, l = groups.length; i < l; i ++ ) { + if ( polygonOffset ) { - var group = groups[ i ]; - var groupMaterial = material[ group.materialIndex ]; + enable( gl.POLYGON_OFFSET_FILL ); - if ( groupMaterial && groupMaterial.visible ) { + if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { - currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group ); + gl.polygonOffset( factor, units ); - } + currentPolygonOffsetFactor = factor; + currentPolygonOffsetUnits = units; - } + } - } else if ( material.visible ) { + } else { - currentRenderList.push( object, geometry, material, _vector3.z, null ); + disable( gl.POLYGON_OFFSET_FILL ); - } + } - } + } - } + function setScissorTest( scissorTest ) { - } + if ( scissorTest ) { - var children = object.children; + enable( gl.SCISSOR_TEST ); - for ( var i = 0, l = children.length; i < l; i ++ ) { + } else { - projectObject( children[ i ], camera, sortObjects ); + disable( gl.SCISSOR_TEST ); } } - function renderObjects( renderList, scene, camera, overrideMaterial ) { + // texture - for ( var i = 0, l = renderList.length; i < l; i ++ ) { + function activeTexture( webglSlot ) { - var renderItem = renderList[ i ]; + if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; - var object = renderItem.object; - var geometry = renderItem.geometry; - var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; - var group = renderItem.group; + if ( currentTextureSlot !== webglSlot ) { - if ( camera.isArrayCamera ) { + gl.activeTexture( webglSlot ); + currentTextureSlot = webglSlot; - _currentArrayCamera = camera; + } - var cameras = camera.cameras; + } - for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { + function bindTexture( webglType, webglTexture, webglSlot ) { - var camera2 = cameras[ j ]; + if ( webglSlot === undefined ) { - if ( object.layers.test( camera2.layers ) ) { + if ( currentTextureSlot === null ) { - var bounds = camera2.bounds; + webglSlot = gl.TEXTURE0 + maxTextures - 1; - var x = bounds.x * _width; - var y = bounds.y * _height; - var width = bounds.z * _width; - var height = bounds.w * _height; + } else { - state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); + webglSlot = currentTextureSlot; - renderObject( object, scene, camera2, geometry, material, group ); + } - } + } - } + let boundTexture = currentBoundTextures[ webglSlot ]; - } else { + if ( boundTexture === undefined ) { - _currentArrayCamera = null; + boundTexture = { type: undefined, texture: undefined }; + currentBoundTextures[ webglSlot ] = boundTexture; + + } + + if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { + + if ( currentTextureSlot !== webglSlot ) { - renderObject( object, scene, camera, geometry, material, group ); + gl.activeTexture( webglSlot ); + currentTextureSlot = webglSlot; } + gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); + + boundTexture.type = webglType; + boundTexture.texture = webglTexture; + } } - function renderObject( object, scene, camera, geometry, material, group ) { + function unbindTexture() { - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + const boundTexture = currentBoundTextures[ currentTextureSlot ]; - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + if ( boundTexture !== undefined && boundTexture.type !== undefined ) { - if ( object.isImmediateRenderObject ) { + gl.bindTexture( boundTexture.type, null ); - var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + boundTexture.type = undefined; + boundTexture.texture = undefined; - state.setMaterial( material, frontFaceCW ); + } + + } - var program = setProgram( camera, scene.fog, material, object ); + function compressedTexImage2D() { - _currentGeometryProgram = ''; + try { - renderObjectImmediate( object, program, material ); + gl.compressedTexImage2D.apply( gl, arguments ); - } else { + } catch ( error ) { - _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group ); + console.error( 'THREE.WebGLState:', error ); } - object.onAfterRender( _this, scene, camera, geometry, material, group ); - } - function initMaterial( material, fog, object ) { + function compressedTexImage3D() { - var materialProperties = properties.get( material ); - - var parameters = programCache.getParameters( - material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); + try { - var code = programCache.getProgramCode( material, parameters ); + gl.compressedTexImage3D.apply( gl, arguments ); - var program = materialProperties.program; - var programChange = true; + } catch ( error ) { - if ( program === undefined ) { + console.error( 'THREE.WebGLState:', error ); - // new material - material.addEventListener( 'dispose', onMaterialDispose ); + } - } else if ( program.code !== code ) { + } - // changed glsl or parameters - releaseMaterialProgramReference( material ); + function texSubImage2D() { - } else if ( parameters.shaderID !== undefined ) { + try { - // same glsl and uniform list - return; + gl.texSubImage2D.apply( gl, arguments ); - } else { + } catch ( error ) { - // only rebuild uniform list - programChange = false; + console.error( 'THREE.WebGLState:', error ); } - if ( programChange ) { + } - if ( parameters.shaderID ) { + function texSubImage3D() { - var shader = ShaderLib[ parameters.shaderID ]; + try { - materialProperties.shader = { - name: material.type, - uniforms: UniformsUtils.clone( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader - }; + gl.texSubImage3D.apply( gl, arguments ); - } else { + } catch ( error ) { - materialProperties.shader = { - name: material.type, - uniforms: material.uniforms, - vertexShader: material.vertexShader, - fragmentShader: material.fragmentShader - }; + console.error( 'THREE.WebGLState:', error ); - } + } + + } - material.onBeforeCompile( materialProperties.shader ); + function compressedTexSubImage2D() { - program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); + try { - materialProperties.program = program; - material.program = program; + gl.compressedTexSubImage2D.apply( gl, arguments ); - } + } catch ( error ) { - var programAttributes = program.getAttributes(); + console.error( 'THREE.WebGLState:', error ); - if ( material.morphTargets ) { + } - material.numSupportedMorphTargets = 0; + } - for ( var i = 0; i < _this.maxMorphTargets; i ++ ) { + function compressedTexSubImage3D() { - if ( programAttributes[ 'morphTarget' + i ] >= 0 ) { + try { - material.numSupportedMorphTargets ++; + gl.compressedTexSubImage3D.apply( gl, arguments ); - } + } catch ( error ) { - } + console.error( 'THREE.WebGLState:', error ); } - if ( material.morphNormals ) { - - material.numSupportedMorphNormals = 0; + } - for ( var i = 0; i < _this.maxMorphNormals; i ++ ) { + function texStorage2D() { - if ( programAttributes[ 'morphNormal' + i ] >= 0 ) { + try { - material.numSupportedMorphNormals ++; + gl.texStorage2D.apply( gl, arguments ); - } + } catch ( error ) { - } + console.error( 'THREE.WebGLState:', error ); } - var uniforms = materialProperties.shader.uniforms; + } - if ( ! material.isShaderMaterial && - ! material.isRawShaderMaterial || - material.clipping === true ) { + function texStorage3D() { - materialProperties.numClippingPlanes = _clipping.numPlanes; - materialProperties.numIntersection = _clipping.numIntersection; - uniforms.clippingPlanes = _clipping.uniform; + try { - } + gl.texStorage3D.apply( gl, arguments ); - materialProperties.fog = fog; + } catch ( error ) { - // store the light setup it was created for + console.error( 'THREE.WebGLState:', error ); - materialProperties.lightsHash = lights.state.hash; + } - if ( material.lights ) { + } - // wire up the material to this renderer's lighting state + function texImage2D() { - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.directionalLights.value = lights.state.directional; - uniforms.spotLights.value = lights.state.spot; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.pointLights.value = lights.state.point; - uniforms.hemisphereLights.value = lights.state.hemi; + try { - 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; - // TODO (abelnation): add area lights shadow info to uniforms + gl.texImage2D.apply( gl, arguments ); - } + } catch ( error ) { - var progUniforms = materialProperties.program.getUniforms(), - uniformsList = - WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + console.error( 'THREE.WebGLState:', error ); - materialProperties.uniformsList = uniformsList; + } } - function setProgram( camera, fog, material, object ) { + function texImage3D() { + + try { - _usedTextureUnits = 0; + gl.texImage3D.apply( gl, arguments ); - var materialProperties = properties.get( material ); + } catch ( error ) { - if ( _clippingEnabled ) { + console.error( 'THREE.WebGLState:', error ); - if ( _localClippingEnabled || camera !== _currentCamera ) { + } - var useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + } - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - _clipping.setState( - material.clippingPlanes, material.clipIntersection, material.clipShadows, - camera, materialProperties, useCache ); + // - } + function scissor( scissor ) { - } + if ( currentScissor.equals( scissor ) === false ) { - if ( material.needsUpdate === false ) { + gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); + currentScissor.copy( scissor ); - if ( materialProperties.program === undefined ) { + } - material.needsUpdate = true; + } - } else if ( material.fog && materialProperties.fog !== fog ) { + function viewport( viewport ) { - material.needsUpdate = true; + if ( currentViewport.equals( viewport ) === false ) { - } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { + gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); + currentViewport.copy( viewport ); - material.needsUpdate = true; + } - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== _clipping.numPlanes || - materialProperties.numIntersection !== _clipping.numIntersection ) ) { + } - material.needsUpdate = true; + function updateUBOMapping( uniformsGroup, program ) { - } + let mapping = uboProgramMap.get( program ); - } + if ( mapping === undefined ) { - if ( material.needsUpdate ) { + mapping = new WeakMap(); - initMaterial( material, fog, object ); - material.needsUpdate = false; + uboProgramMap.set( program, mapping ); } - var refreshProgram = false; - var refreshMaterial = false; - var refreshLights = false; + let blockIndex = mapping.get( uniformsGroup ); - var program = materialProperties.program, - p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.shader.uniforms; + if ( blockIndex === undefined ) { - if ( state.useProgram( program.program ) ) { + blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + mapping.set( uniformsGroup, blockIndex ); } - if ( material.id !== _currentMaterialId ) { + } - _currentMaterialId = material.id; + function uniformBlockBinding( uniformsGroup, program ) { - refreshMaterial = true; + const mapping = uboProgramMap.get( program ); + const blockIndex = mapping.get( uniformsGroup ); - } + if ( uboBindings.get( program ) !== blockIndex ) { - if ( refreshProgram || camera !== _currentCamera ) { + // bind shader specific block index to global block point + gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + uboBindings.set( program, blockIndex ); - if ( capabilities.logarithmicDepthBuffer ) { + } - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } - } + // - // Avoid unneeded uniform updates per ArrayCamera's sub-camera + function reset() { - if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { + // reset state - _currentCamera = ( _currentArrayCamera || camera ); + 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 ); - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ONE, gl.ZERO ); + gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); + gl.blendColor( 0, 0, 0, 0 ); - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + gl.colorMask( true, true, true, true ); + gl.clearColor( 0, 0, 0, 0 ); - } + gl.depthMask( true ); + gl.depthFunc( gl.LESS ); + gl.clearDepth( 1 ); - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + gl.stencilMask( 0xffffffff ); + gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); + gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); + gl.clearStencil( 0 ); - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + gl.cullFace( gl.BACK ); + gl.frontFace( gl.CCW ); - var uCamPos = p_uniforms.map.cameraPosition; + gl.polygonOffset( 0, 0 ); - if ( uCamPos !== undefined ) { - - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + gl.activeTexture( gl.TEXTURE0 ); - } + gl.bindFramebuffer( gl.FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); - } + gl.useProgram( null ); - if ( material.isMeshPhongMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.skinning ) { + gl.lineWidth( 1 ); - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); + gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); - } + // reset internals - } + enabledCapabilities = {}; - // skinning uniforms must be set even if material didn't change - // auto-setting of texture unit for bone texture must go before other textures - // not sure why, but otherwise weird things happen + currentTextureSlot = null; + currentBoundTextures = {}; - if ( material.skinning ) { + currentBoundFramebuffers = {}; + currentDrawbuffers = new WeakMap(); + defaultDrawbuffers = []; - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + currentProgram = null; - var skeleton = object.skeleton; + currentBlendingEnabled = false; + currentBlending = null; + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlendColor = new Color( 0, 0, 0 ); + currentBlendAlpha = 0; + currentPremultipledAlpha = false; - if ( skeleton ) { + currentFlipSided = null; + currentCullFace = null; - var bones = skeleton.bones; + currentLineWidth = null; - if ( capabilities.floatVertexTextures ) { + currentPolygonOffsetFactor = null; + currentPolygonOffsetUnits = null; - if ( skeleton.boneTexture === undefined ) { + currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); + currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); - // layout (1 matrix = 4 pixels) - // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) - // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) - // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) - // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) - // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) + colorBuffer.reset(); + depthBuffer.reset(); + stencilBuffer.reset(); + } - var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix - size = _Math.ceilPowerOfTwo( size ); - size = Math.max( size, 4 ); + return { - var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel - boneMatrices.set( skeleton.boneMatrices ); // copy current values + buffers: { + color: colorBuffer, + depth: depthBuffer, + stencil: stencilBuffer + }, - var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + enable: enable, + disable: disable, - skeleton.boneMatrices = boneMatrices; - skeleton.boneTexture = boneTexture; - skeleton.boneTextureSize = size; + bindFramebuffer: bindFramebuffer, + drawBuffers: drawBuffers, - } + useProgram: useProgram, - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + setBlending: setBlending, + setMaterial: setMaterial, - } else { + setFlipSided: setFlipSided, + setCullFace: setCullFace, - p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' ); + setLineWidth: setLineWidth, + setPolygonOffset: setPolygonOffset, - } + setScissorTest: setScissorTest, - } + activeTexture: activeTexture, + bindTexture: bindTexture, + unbindTexture: unbindTexture, + compressedTexImage2D: compressedTexImage2D, + compressedTexImage3D: compressedTexImage3D, + texImage2D: texImage2D, + texImage3D: texImage3D, - } + updateUBOMapping: updateUBOMapping, + uniformBlockBinding: uniformBlockBinding, - if ( refreshMaterial ) { + texStorage2D: texStorage2D, + texStorage3D: texStorage3D, + texSubImage2D: texSubImage2D, + texSubImage3D: texSubImage3D, + compressedTexSubImage2D: compressedTexSubImage2D, + compressedTexSubImage3D: compressedTexSubImage3D, - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); + scissor: scissor, + viewport: viewport, - if ( material.lights ) { + reset: reset - // the current material requires lighting info + }; - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + } - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); - } - // refresh uniforms common to several materials + /** + * Given the width, height, format, and type of a texture. Determines how many + * bytes must be used to represent the texture. + */ + function getByteLength( width, height, format, type ) { + + const typeByteLength = getTextureTypeByteLength( type ); + + switch ( format ) { + + // https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml + case AlphaFormat: + return width * height; + case LuminanceFormat: + return width * height; + case LuminanceAlphaFormat: + return width * height * 2; + case RedFormat: + return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength; + case RedIntegerFormat: + return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGFormat: + return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGIntegerFormat: + return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBFormat: + return ( ( width * height * 3 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBAFormat: + return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength; + case RGBAIntegerFormat: + return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_s3tc_srgb/ + case RGB_S3TC_DXT1_Format: + case RGBA_S3TC_DXT1_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; + case RGBA_S3TC_DXT3_Format: + case RGBA_S3TC_DXT5_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_pvrtc/ + case RGB_PVRTC_2BPPV1_Format: + case RGBA_PVRTC_2BPPV1_Format: + return ( Math.max( width, 16 ) * Math.max( height, 8 ) ) / 4; + case RGB_PVRTC_4BPPV1_Format: + case RGBA_PVRTC_4BPPV1_Format: + return ( Math.max( width, 8 ) * Math.max( height, 8 ) ) / 2; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_etc/ + case RGB_ETC1_Format: + case RGB_ETC2_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; + case RGBA_ETC2_EAC_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/ + case RGBA_ASTC_4x4_Format: + return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + case RGBA_ASTC_5x4_Format: + return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 3 ) / 4 ) * 16; + case RGBA_ASTC_5x5_Format: + return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_6x5_Format: + return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_6x6_Format: + return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_8x5_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_8x6_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_8x8_Format: + return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 7 ) / 8 ) * 16; + case RGBA_ASTC_10x5_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 4 ) / 5 ) * 16; + case RGBA_ASTC_10x6_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 5 ) / 6 ) * 16; + case RGBA_ASTC_10x8_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 7 ) / 8 ) * 16; + case RGBA_ASTC_10x10_Format: + return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 9 ) / 10 ) * 16; + case RGBA_ASTC_12x10_Format: + return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 9 ) / 10 ) * 16; + case RGBA_ASTC_12x12_Format: + return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 11 ) / 12 ) * 16; + + // https://registry.khronos.org/webgl/extensions/EXT_texture_compression_bptc/ + case RGBA_BPTC_Format: + case RGB_BPTC_SIGNED_Format: + case RGB_BPTC_UNSIGNED_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16; + + // https://registry.khronos.org/webgl/extensions/EXT_texture_compression_rgtc/ + case RED_RGTC1_Format: + case SIGNED_RED_RGTC1_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 8; + case RED_GREEN_RGTC2_Format: + case SIGNED_RED_GREEN_RGTC2_Format: + return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16; + + } + + throw new Error( + `Unable to determine texture byte length for ${format} format.`, + ); - if ( fog && material.fog ) { + } - refreshUniformsFog( m_uniforms, fog ); + function getTextureTypeByteLength( type ) { - } + switch ( type ) { - if ( material.isMeshBasicMaterial ) { + case UnsignedByteType: + case ByteType: + return { byteLength: 1, components: 1 }; + case UnsignedShortType: + case ShortType: + case HalfFloatType: + return { byteLength: 2, components: 1 }; + case UnsignedShort4444Type: + case UnsignedShort5551Type: + return { byteLength: 2, components: 4 }; + case UnsignedIntType: + case IntType: + case FloatType: + return { byteLength: 4, components: 1 }; + case UnsignedInt5999Type: + return { byteLength: 4, components: 3 }; - refreshUniformsCommon( m_uniforms, material ); + } - } else if ( material.isMeshLambertMaterial ) { + throw new Error( `Unknown texture type ${type}.` ); - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsLambert( m_uniforms, material ); + } - } else if ( material.isMeshPhongMaterial ) { + function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { - refreshUniformsCommon( m_uniforms, material ); + const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; + const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); - if ( material.isMeshToonMaterial ) { + const _imageDimensions = new Vector2(); + const _videoTextures = new WeakMap(); + let _canvas; - refreshUniformsToon( m_uniforms, material ); + const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source - } else { + // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, + // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! + // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). - refreshUniformsPhong( m_uniforms, material ); + let useOffscreenCanvas = false; - } + try { - } else if ( material.isMeshStandardMaterial ) { + useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' + // eslint-disable-next-line compat/compat + && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; - refreshUniformsCommon( m_uniforms, material ); + } catch ( err ) { - if ( material.isMeshPhysicalMaterial ) { + // Ignore any errors - refreshUniformsPhysical( m_uniforms, material ); + } - } else { + function createCanvas( width, height ) { - refreshUniformsStandard( m_uniforms, material ); + // Use OffscreenCanvas when available. Specially needed in web workers - } + return useOffscreenCanvas ? + // eslint-disable-next-line compat/compat + new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); - } else if ( material.isMeshDepthMaterial ) { + } - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDepth( m_uniforms, material ); + function resizeImage( image, needsNewCanvas, maxSize ) { - } else if ( material.isMeshDistanceMaterial ) { + let scale = 1; - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDistance( m_uniforms, material ); + const dimensions = getDimensions( image ); - } else if ( material.isMeshNormalMaterial ) { + // handle case if texture exceeds max size - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsNormal( m_uniforms, material ); + if ( dimensions.width > maxSize || dimensions.height > maxSize ) { - } else if ( material.isLineBasicMaterial ) { + scale = maxSize / Math.max( dimensions.width, dimensions.height ); - refreshUniformsLine( m_uniforms, material ); + } - if ( material.isLineDashedMaterial ) { + // only perform resize if necessary - refreshUniformsDash( m_uniforms, material ); + if ( scale < 1 ) { - } + // only perform resize for certain image types - } else if ( material.isPointsMaterial ) { + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) || + ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) { - refreshUniformsPoints( m_uniforms, material ); + const width = Math.floor( scale * dimensions.width ); + const height = Math.floor( scale * dimensions.height ); - } else if ( material.isShadowMaterial ) { + if ( _canvas === undefined ) _canvas = createCanvas( width, height ); - m_uniforms.color.value = material.color; - m_uniforms.opacity.value = material.opacity; + // cube textures can't reuse the same canvas - } + const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; - // RectAreaLight Texture - // TODO (mrdoob): Find a nicer implementation + canvas.width = width; + canvas.height = height; - if ( m_uniforms.ltcMat !== undefined ) m_uniforms.ltcMat.value = UniformsLib.LTC_MAT_TEXTURE; - if ( m_uniforms.ltcMag !== undefined ) m_uniforms.ltcMag.value = UniformsLib.LTC_MAG_TEXTURE; + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, width, height ); - WebGLUniforms.upload( - _gl, materialProperties.uniformsList, m_uniforms, _this ); + console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); - } + return canvas; + } else { - // common matrices + if ( 'data' in image ) { - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); - return program; + } - } + return image; - // Uniforms (refresh uniforms objects) + } - function refreshUniformsCommon( uniforms, material ) { + } - uniforms.opacity.value = material.opacity; + return image; - if ( material.color ) { + } - uniforms.diffuse.value = material.color; + function textureNeedsGenerateMipmaps( texture ) { - } + return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; - if ( material.emissive ) { + } - uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); + function generateMipmap( target ) { - } + _gl.generateMipmap( target ); - if ( material.map ) { + } - uniforms.map.value = material.map; + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { - } + if ( internalFormatName !== null ) { - if ( material.alphaMap ) { + if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; - uniforms.alphaMap.value = material.alphaMap; + console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); } - if ( material.specularMap ) { - - uniforms.specularMap.value = material.specularMap; + let internalFormat = glFormat; - } + if ( glFormat === _gl.RED ) { - if ( material.envMap ) { + if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; - uniforms.envMap.value = material.envMap; + } - // don't flip CubeTexture envMaps, flip everything else: - // WebGLRenderTargetCube will be flipped for backwards compatibility - // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture - // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future - uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + if ( glFormat === _gl.RED_INTEGER ) { - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.R8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.R16I; + if ( glType === _gl.INT ) internalFormat = _gl.R32I; } - if ( material.lightMap ) { + if ( glFormat === _gl.RG ) { - uniforms.lightMap.value = material.lightMap; - uniforms.lightMapIntensity.value = material.lightMapIntensity; + if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; } - if ( material.aoMap ) { + if ( glFormat === _gl.RG_INTEGER ) { - uniforms.aoMap.value = material.aoMap; - uniforms.aoMapIntensity.value = material.aoMapIntensity; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I; + if ( glType === _gl.INT ) internalFormat = _gl.RG32I; } - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. normal map - // 4. bump map - // 5. alpha map - // 6. emissive map + if ( glFormat === _gl.RGB ) { - var uvScaleMap; + if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; - if ( material.map ) { + } - uvScaleMap = material.map; + if ( glFormat === _gl.RGBA ) { - } else if ( material.specularMap ) { + const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace ); - uvScaleMap = material.specularMap; + if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _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; - } else if ( material.displacementMap ) { + } - uvScaleMap = material.displacementMap; + if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || + internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || + internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { - } else if ( material.normalMap ) { + extensions.get( 'EXT_color_buffer_float' ); - uvScaleMap = material.normalMap; + } - } else if ( material.bumpMap ) { + return internalFormat; - uvScaleMap = material.bumpMap; + } - } else if ( material.roughnessMap ) { + function getInternalDepthFormat( useStencil, depthType ) { - uvScaleMap = material.roughnessMap; + let glInternalFormat; + if ( useStencil ) { - } else if ( material.metalnessMap ) { + if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { - uvScaleMap = material.metalnessMap; + glInternalFormat = _gl.DEPTH24_STENCIL8; - } else if ( material.alphaMap ) { + } else if ( depthType === FloatType ) { - uvScaleMap = material.alphaMap; + glInternalFormat = _gl.DEPTH32F_STENCIL8; - } else if ( material.emissiveMap ) { + } else if ( depthType === UnsignedShortType ) { - uvScaleMap = material.emissiveMap; + glInternalFormat = _gl.DEPTH24_STENCIL8; + console.warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' ); - } + } - if ( uvScaleMap !== undefined ) { + } else { - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { + if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { - uvScaleMap = uvScaleMap.texture; + glInternalFormat = _gl.DEPTH_COMPONENT24; - } + } else if ( depthType === FloatType ) { - if ( uvScaleMap.matrixAutoUpdate === true ) { + glInternalFormat = _gl.DEPTH_COMPONENT32F; - var offset = uvScaleMap.offset; - var repeat = uvScaleMap.repeat; - var rotation = uvScaleMap.rotation; - var center = uvScaleMap.center; + } else if ( depthType === UnsignedShortType ) { - uvScaleMap.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); + glInternalFormat = _gl.DEPTH_COMPONENT16; } - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - } - } - - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; + return glInternalFormat; } - function refreshUniformsDash( uniforms, material ) { - - uniforms.dashSize.value = material.dashSize; - uniforms.totalSize.value = material.dashSize + material.gapSize; - uniforms.scale.value = material.scale; + function getMipLevels( texture, image ) { - } + if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { - function refreshUniformsPoints( uniforms, material ) { + return Math.log2( Math.max( image.width, image.height ) ) + 1; - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - uniforms.size.value = material.size * _pixelRatio; - uniforms.scale.value = _height * 0.5; + } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { - uniforms.map.value = material.map; + // user-defined mipmaps - if ( material.map !== null ) { + return texture.mipmaps.length; - if ( material.map.matrixAutoUpdate === true ) { + } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { - var offset = material.map.offset; - var repeat = material.map.repeat; - var rotation = material.map.rotation; - var center = material.map.center; + return image.mipmaps.length; - material.map.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); + } else { - } + // texture without mipmaps (only base level) - uniforms.uvTransform.value.copy( material.map.matrix ); + return 1; } } - function refreshUniformsFog( uniforms, fog ) { + // + + function onTextureDispose( event ) { - uniforms.fogColor.value = fog.color; + const texture = event.target; - if ( fog.isFog ) { + texture.removeEventListener( 'dispose', onTextureDispose ); - uniforms.fogNear.value = fog.near; - uniforms.fogFar.value = fog.far; + deallocateTexture( texture ); - } else if ( fog.isFogExp2 ) { + if ( texture.isVideoTexture ) { - uniforms.fogDensity.value = fog.density; + _videoTextures.delete( texture ); } } - function refreshUniformsLambert( uniforms, material ) { + function onRenderTargetDispose( event ) { - if ( material.emissiveMap ) { + const renderTarget = event.target; - uniforms.emissiveMap.value = material.emissiveMap; + renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); - } + deallocateRenderTarget( renderTarget ); } - function refreshUniformsPhong( uniforms, material ) { + // - uniforms.specular.value = material.specular; - uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) + function deallocateTexture( texture ) { - if ( material.emissiveMap ) { + const textureProperties = properties.get( texture ); - uniforms.emissiveMap.value = material.emissiveMap; + if ( textureProperties.__webglInit === undefined ) return; - } + // check if it's necessary to remove the WebGLTexture object - if ( material.bumpMap ) { + const source = texture.source; + const webglTextures = _sources.get( source ); - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + if ( webglTextures ) { - } + const webglTexture = webglTextures[ textureProperties.__cacheKey ]; + webglTexture.usedTimes --; - if ( material.normalMap ) { + // the WebGLTexture object is not used anymore, remove it - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + if ( webglTexture.usedTimes === 0 ) { - } + deleteTexture( texture ); - if ( material.displacementMap ) { + } - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + // remove the weak map entry if no WebGLTexture uses the source anymore + + if ( Object.keys( webglTextures ).length === 0 ) { + + _sources.delete( source ); + + } } - } + properties.remove( texture ); - function refreshUniformsToon( uniforms, material ) { + } - refreshUniformsPhong( uniforms, material ); + function deleteTexture( texture ) { - if ( material.gradientMap ) { + const textureProperties = properties.get( texture ); + _gl.deleteTexture( textureProperties.__webglTexture ); - uniforms.gradientMap.value = material.gradientMap; + const source = texture.source; + const webglTextures = _sources.get( source ); + delete webglTextures[ textureProperties.__cacheKey ]; - } + info.memory.textures --; } - function refreshUniformsStandard( uniforms, material ) { + function deallocateRenderTarget( renderTarget ) { - uniforms.roughness.value = material.roughness; - uniforms.metalness.value = material.metalness; + const renderTargetProperties = properties.get( renderTarget ); - if ( material.roughnessMap ) { + if ( renderTarget.depthTexture ) { - uniforms.roughnessMap.value = material.roughnessMap; + renderTarget.depthTexture.dispose(); } - if ( material.metalnessMap ) { + if ( renderTarget.isWebGLCubeRenderTarget ) { - uniforms.metalnessMap.value = material.metalnessMap; + for ( let i = 0; i < 6; i ++ ) { - } + if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) { - if ( material.emissiveMap ) { + for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] ); - uniforms.emissiveMap.value = material.emissiveMap; + } else { - } + _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - if ( material.bumpMap ) { + } - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); - } + } - if ( material.normalMap ) { + } else { - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) { - } + for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] ); - if ( material.displacementMap ) { + } else { - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - } + } - if ( material.envMap ) { + if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); + if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); - //uniforms.envMap.value = material.envMap; // part of uniforms common - uniforms.envMapIntensity.value = material.envMapIntensity; + if ( renderTargetProperties.__webglColorRenderbuffer ) { - } + for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { - } + if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); - function refreshUniformsPhysical( uniforms, material ) { + } - uniforms.clearCoat.value = material.clearCoat; - uniforms.clearCoatRoughness.value = material.clearCoatRoughness; + } - refreshUniformsStandard( uniforms, material ); + if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); - } + } - function refreshUniformsDepth( uniforms, material ) { + const textures = renderTarget.textures; - if ( material.displacementMap ) { + for ( let i = 0, il = textures.length; i < il; i ++ ) { - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + const attachmentProperties = properties.get( textures[ i ] ); - } + if ( attachmentProperties.__webglTexture ) { - } + _gl.deleteTexture( attachmentProperties.__webglTexture ); - function refreshUniformsDistance( uniforms, material ) { + info.memory.textures --; - if ( material.displacementMap ) { + } - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + properties.remove( textures[ i ] ); } - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; + properties.remove( renderTarget ); } - function refreshUniformsNormal( uniforms, material ) { + // - if ( material.bumpMap ) { + let textureUnits = 0; - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; + function resetTextureUnits() { - } + textureUnits = 0; - if ( material.normalMap ) { + } - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); + function allocateTextureUnit() { - } + const textureUnit = textureUnits; - if ( material.displacementMap ) { + if ( textureUnit >= capabilities.maxTextures ) { - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; + console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); } + textureUnits += 1; + + return textureUnit; + } - // If uniforms are marked as clean, they don't need to be loaded to the GPU. + function getTextureCacheKey( texture ) { - function markUniformsLightsNeedsUpdate( uniforms, value ) { + const array = []; - uniforms.ambientLightColor.needsUpdate = value; + array.push( texture.wrapS ); + array.push( texture.wrapT ); + array.push( texture.wrapR || 0 ); + array.push( texture.magFilter ); + array.push( texture.minFilter ); + array.push( texture.anisotropy ); + array.push( texture.internalFormat ); + array.push( texture.format ); + array.push( texture.type ); + array.push( texture.generateMipmaps ); + array.push( texture.premultiplyAlpha ); + array.push( texture.flipY ); + array.push( texture.unpackAlignment ); + array.push( texture.colorSpace ); - uniforms.directionalLights.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + return array.join(); } - // GL state setting + // - this.setFaceCulling = function ( cullFace, frontFaceDirection ) { + function setTexture2D( texture, slot ) { - state.setCullFace( cullFace ); - state.setFlipSided( frontFaceDirection === FrontFaceDirectionCW ); + const textureProperties = properties.get( texture ); - }; + if ( texture.isVideoTexture ) updateVideoTexture( texture ); - // Textures + if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { - function allocTextureUnit() { + const image = texture.image; - var textureUnit = _usedTextureUnits; + if ( image === null ) { - if ( textureUnit >= capabilities.maxTextures ) { + console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); - console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); + } else if ( image.complete === false ) { - } - - _usedTextureUnits += 1; - - return textureUnit; + console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); - } + } else { - this.allocTextureUnit = allocTextureUnit; + uploadTexture( textureProperties, texture, slot ); + return; - // this.setTexture2D = setTexture2D; - this.setTexture2D = ( function () { + } - var warned = false; + } - // backwards compatibility: peel texture.texture - return function setTexture2D( texture, slot ) { + state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - if ( texture && texture.isWebGLRenderTarget ) { + } - if ( ! warned ) { + function setTexture2DArray( texture, slot ) { - console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." ); - warned = true; + const textureProperties = properties.get( texture ); - } + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - texture = texture.texture; + uploadTexture( textureProperties, texture, slot ); + return; - } + } - textures.setTexture2D( texture, slot ); + state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - }; + } - }() ); + function setTexture3D( texture, slot ) { - this.setTexture = ( function () { + const textureProperties = properties.get( texture ); - var warned = false; + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - return function setTexture( texture, slot ) { + uploadTexture( textureProperties, texture, slot ); + return; - if ( ! warned ) { + } - console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." ); - warned = true; + state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } + } - textures.setTexture2D( texture, slot ); + function setTextureCube( texture, slot ) { - }; + const textureProperties = properties.get( texture ); - }() ); + if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - this.setTextureCube = ( function () { + uploadCubeTexture( textureProperties, texture, slot ); + return; - var warned = false; + } - return function setTextureCube( texture, slot ) { + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - // backwards compatibility: peel texture.texture - if ( texture && texture.isWebGLRenderTargetCube ) { + } - if ( ! warned ) { + const wrappingToGL = { + [ RepeatWrapping ]: _gl.REPEAT, + [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, + [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT + }; - console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." ); - warned = true; + const filterToGL = { + [ NearestFilter ]: _gl.NEAREST, + [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, + [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, - } + [ LinearFilter ]: _gl.LINEAR, + [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, + [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR + }; - texture = texture.texture; + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL + }; - } + function setTextureParameters( textureType, texture ) { - // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture - // TODO: unify these code paths - if ( ( texture && texture.isCubeTexture ) || - ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) { + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false && + ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || + texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) { - // CompressedTexture can have Array in image :/ + console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); - // this function alone should take care of cube textures - textures.setTextureCube( texture, slot ); + } - } else { + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); - // assumed: texture property of THREE.WebGLRenderTargetCube + if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { - textures.setTextureCubeDynamic( texture, slot ); + _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 ] ); - }() ); + if ( texture.compareFunction ) { - this.getRenderTarget = function () { + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); - return _currentRenderTarget; + } - }; + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { - this.setRenderTarget = function ( renderTarget ) { + if ( texture.magFilter === NearestFilter ) return; + if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension - _currentRenderTarget = renderTarget; + if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { - if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) { + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); + properties.get( texture ).__currentAnisotropy = texture.anisotropy; - textures.setupRenderTarget( renderTarget ); + } } - var framebuffer = null; - var isCube = false; - - if ( renderTarget ) { - - var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - - if ( renderTarget.isWebGLRenderTargetCube ) { - - framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; - isCube = true; - - } else { + } - framebuffer = __webglFramebuffer; + function initTexture( textureProperties, texture ) { - } + let forceUpload = false; - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + if ( textureProperties.__webglInit === undefined ) { - } else { + textureProperties.__webglInit = true; - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); - _currentScissorTest = _scissorTest; + texture.addEventListener( 'dispose', onTextureDispose ); } - if ( _currentFramebuffer !== framebuffer ) { + // create Source <-> WebGLTextures mapping if necessary - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _currentFramebuffer = framebuffer; + const source = texture.source; + let webglTextures = _sources.get( source ); - } + if ( webglTextures === undefined ) { - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); + webglTextures = {}; + _sources.set( source, webglTextures ); - if ( isCube ) { + } - var textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel ); + // check if there is already a WebGLTexture object for the given texture parameters - } + const textureCacheKey = getTextureCacheKey( texture ); - }; + if ( textureCacheKey !== textureProperties.__cacheKey ) { - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { + // if not, create a new instance of WebGLTexture - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + if ( webglTextures[ textureCacheKey ] === undefined ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + // create new entry - } + webglTextures[ textureCacheKey ] = { + texture: _gl.createTexture(), + usedTimes: 0 + }; - var framebuffer = properties.get( renderTarget ).__webglFramebuffer; + info.memory.textures ++; - if ( framebuffer ) { + // when a new instance of WebGLTexture was created, a texture upload is required + // even if the image contents are identical - var restore = false; + forceUpload = true; - if ( framebuffer !== _currentFramebuffer ) { + } - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + webglTextures[ textureCacheKey ].usedTimes ++; - restore = true; + // every time the texture cache key changes, it's necessary to check if an instance of + // WebGLTexture can be deleted in order to avoid a memory leak. - } + const webglTexture = webglTextures[ textureProperties.__cacheKey ]; - try { + if ( webglTexture !== undefined ) { - var texture = renderTarget.texture; - var textureFormat = texture.format; - var textureType = texture.type; + webglTextures[ textureProperties.__cacheKey ].usedTimes --; - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + if ( webglTexture.usedTimes === 0 ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + deleteTexture( texture ); } - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { + } - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + // store references to cache key and WebGLTexture object - } + textureProperties.__cacheKey = textureCacheKey; + textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; - if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) { + } - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + return forceUpload; - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + } - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); + function uploadTexture( textureProperties, texture, slot ) { - } + let textureType = _gl.TEXTURE_2D; - } else { + if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; + if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' ); + const forceUpload = initTexture( textureProperties, texture ); + const source = texture.source; - } + state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } finally { + const sourceProperties = properties.get( source ); - if ( restore ) { + if ( source.version !== sourceProperties.__version || forceUpload === true ) { - _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer ); + state.activeTexture( _gl.TEXTURE0 + slot ); - } + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); + const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - } + _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, unpackConversion ); - } + let image = resizeImage( texture.image, false, capabilities.maxTextureSize ); + image = verifyColorSpace( texture, image ); - }; + const glFormat = utils.convert( texture.format, texture.colorSpace ); - } + const glType = utils.convert( texture.type ); + let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + setTextureParameters( textureType, texture ); - function FogExp2( color, density ) { + let mipmap; + const mipmaps = texture.mipmaps; - this.name = ''; + const useTexStorage = ( texture.isVideoTexture !== true ); + const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); + const dataReady = source.dataReady; + const levels = getMipLevels( texture, image ); - this.color = new Color( color ); - this.density = ( density !== undefined ) ? density : 0.00025; + if ( texture.isDepthTexture ) { - } + glInternalFormat = getInternalDepthFormat( texture.format === DepthStencilFormat, texture.type ); - FogExp2.prototype.isFogExp2 = true; + // - FogExp2.prototype.clone = function () { + if ( allocateMemory ) { - return new FogExp2( this.color.getHex(), this.density ); + if ( useTexStorage ) { - }; + state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); - FogExp2.prototype.toJSON = function ( /* meta */ ) { + } else { - return { - type: 'FogExp2', - color: this.color.getHex(), - density: this.density - }; + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); - }; + } - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + } - function Fog( color, near, far ) { + } else if ( texture.isDataTexture ) { - this.name = ''; + // use manually created mipmaps if available + // if there are no manual mipmaps + // set 0 level mipmap and then use GL to generate other mipmap levels - this.color = new Color( color ); + if ( mipmaps.length > 0 ) { - this.near = ( near !== undefined ) ? near : 1; - this.far = ( far !== undefined ) ? far : 1000; + if ( useTexStorage && allocateMemory ) { - } + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); - Fog.prototype.isFog = true; + } - Fog.prototype.clone = function () { + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - return new Fog( this.color.getHex(), this.near, this.far ); + mipmap = mipmaps[ i ]; - }; + if ( useTexStorage ) { - Fog.prototype.toJSON = function ( /* meta */ ) { + if ( dataReady ) { - return { - type: 'Fog', - color: this.color.getHex(), - near: this.near, - far: this.far - }; + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - }; + } - /** - * @author mrdoob / http://mrdoob.com/ - */ + } else { - function Scene() { + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - Object3D.call( this ); + } - this.type = 'Scene'; + } - this.background = null; - this.fog = null; - this.overrideMaterial = null; + texture.generateMipmaps = false; - this.autoUpdate = true; // checked by the renderer + } else { - } + if ( useTexStorage ) { - Scene.prototype = Object.assign( Object.create( Object3D.prototype ), { + if ( allocateMemory ) { - constructor: Scene, + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); - copy: function ( source, recursive ) { + } - Object3D.prototype.copy.call( this, source, recursive ); + if ( dataReady ) { - if ( source.background !== null ) this.background = source.background.clone(); - if ( source.fog !== null ) this.fog = source.fog.clone(); - if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); - this.autoUpdate = source.autoUpdate; - this.matrixAutoUpdate = source.matrixAutoUpdate; + } - return this; + } else { - }, + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); - toJSON: function ( meta ) { + } - var data = Object3D.prototype.toJSON.call( this, meta ); + } - if ( this.background !== null ) data.object.background = this.background.toJSON( meta ); - if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); + } else if ( texture.isCompressedTexture ) { - return data; + if ( texture.isCompressedArrayTexture ) { - } + if ( useTexStorage && allocateMemory ) { - } ); + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + } - function LensFlare( texture, size, distance, blending, color ) { + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - Object3D.call( this ); + mipmap = mipmaps[ i ]; - this.lensFlares = []; + if ( texture.format !== RGBAFormat ) { - this.positionScreen = new Vector3(); - this.customUpdateCallback = undefined; + if ( glFormat !== null ) { - if ( texture !== undefined ) { + if ( useTexStorage ) { - this.add( texture, size, distance, blending, color ); + if ( dataReady ) { - } + if ( texture.layerUpdates.size > 0 ) { - } + const layerByteLength = getByteLength( mipmap.width, mipmap.height, texture.format, texture.type ); - LensFlare.prototype = Object.assign( Object.create( Object3D.prototype ), { + for ( const layerIndex of texture.layerUpdates ) { - constructor: LensFlare, + const layerData = mipmap.data.subarray( + layerIndex * layerByteLength / mipmap.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / mipmap.data.BYTES_PER_ELEMENT + ); + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, layerData, 0, 0 ); - isLensFlare: true, + } - copy: function ( source ) { + texture.clearLayerUpdates(); - Object3D.prototype.copy.call( this, source ); + } else { - this.positionScreen.copy( source.positionScreen ); - this.customUpdateCallback = source.customUpdateCallback; + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); - for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) { + } - this.lensFlares.push( source.lensFlares[ i ] ); + } - } + } else { - return this; + state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); - }, + } - add: function ( texture, size, distance, blending, color, opacity ) { - - if ( size === undefined ) size = - 1; - if ( distance === undefined ) distance = 0; - if ( opacity === undefined ) opacity = 1; - if ( color === undefined ) color = new Color( 0xffffff ); - if ( blending === undefined ) blending = NormalBlending; - - distance = Math.min( distance, Math.max( 0, distance ) ); - - this.lensFlares.push( { - texture: texture, // THREE.Texture - size: size, // size in pixels (-1 = use texture.width) - distance: distance, // distance (0-1) from light source (0=at light source) - x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is in front z = 1 is back - scale: 1, // scale - rotation: 0, // rotation - opacity: opacity, // opacity - color: color, // color - blending: blending // blending - } ); + } else { - }, + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - /* - * Update lens flares update positions on all flares based on the screen position - * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way. - */ + } - updateLensFlares: function () { + } else { - var f, fl = this.lensFlares.length; - var flare; - var vecX = - this.positionScreen.x * 2; - var vecY = - this.positionScreen.y * 2; + if ( useTexStorage ) { - for ( f = 0; f < fl; f ++ ) { + if ( dataReady ) { - flare = this.lensFlares[ f ]; + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); - flare.x = this.positionScreen.x + vecX * flare.distance; - flare.y = this.positionScreen.y + vecY * flare.distance; + } - flare.wantedRotation = flare.x * Math.PI * 0.25; - flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25; + } else { - } + state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); - } + } - } ); + } - /** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * uvOffset: new THREE.Vector2(), - * uvScale: new THREE.Vector2() - * } - */ + } - function SpriteMaterial( parameters ) { + } else { - Material.call( this ); + if ( useTexStorage && allocateMemory ) { - this.type = 'SpriteMaterial'; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); - this.color = new Color( 0xffffff ); - this.map = null; + } - this.rotation = 0; + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - this.fog = false; - this.lights = false; + mipmap = mipmaps[ i ]; - this.setValues( parameters ); + if ( texture.format !== RGBAFormat ) { - } + if ( glFormat !== null ) { - SpriteMaterial.prototype = Object.create( Material.prototype ); - SpriteMaterial.prototype.constructor = SpriteMaterial; - SpriteMaterial.prototype.isSpriteMaterial = true; + if ( useTexStorage ) { - SpriteMaterial.prototype.copy = function ( source ) { + if ( dataReady ) { - Material.prototype.copy.call( this, source ); + state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); - this.color.copy( source.color ); - this.map = source.map; + } - this.rotation = source.rotation; + } else { - return this; + state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - }; + } - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ + } else { - function Sprite( material ) { + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - Object3D.call( this ); + } - this.type = 'Sprite'; + } else { - this.material = ( material !== undefined ) ? material : new SpriteMaterial(); + if ( useTexStorage ) { - } + if ( dataReady ) { - Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - constructor: Sprite, + } - isSprite: true, + } else { - raycast: ( function () { + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - var intersectPoint = new Vector3(); - var worldPosition = new Vector3(); - var worldScale = new Vector3(); + } - return function raycast( raycaster, intersects ) { + } - worldPosition.setFromMatrixPosition( this.matrixWorld ); - raycaster.ray.closestPointToPoint( worldPosition, intersectPoint ); + } - worldScale.setFromMatrixScale( this.matrixWorld ); - var guessSizeSq = worldScale.x * worldScale.y / 4; + } - if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return; + } else if ( texture.isDataArrayTexture ) { - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); + if ( useTexStorage ) { - if ( distance < raycaster.near || distance > raycaster.far ) return; + if ( allocateMemory ) { - intersects.push( { + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); - distance: distance, - point: intersectPoint.clone(), - face: null, - object: this + } - } ); + if ( dataReady ) { - }; + if ( texture.layerUpdates.size > 0 ) { - }() ), + const layerByteLength = getByteLength( image.width, image.height, texture.format, texture.type ); - clone: function () { + for ( const layerIndex of texture.layerUpdates ) { - return new this.constructor( this.material ).copy( this ); + const layerData = image.data.subarray( + layerIndex * layerByteLength / image.data.BYTES_PER_ELEMENT, + ( layerIndex + 1 ) * layerByteLength / image.data.BYTES_PER_ELEMENT + ); + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, layerData ); - } + } - } ); + texture.clearLayerUpdates(); - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + } else { - function LOD() { + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); - Object3D.call( this ); + } - this.type = 'LOD'; + } - Object.defineProperties( this, { - levels: { - enumerable: true, - value: [] - } - } ); + } else { - } + state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); - LOD.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: LOD, + } else if ( texture.isData3DTexture ) { - copy: function ( source ) { + if ( useTexStorage ) { - Object3D.prototype.copy.call( this, source, false ); + if ( allocateMemory ) { - var levels = source.levels; + state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); - for ( var i = 0, l = levels.length; i < l; i ++ ) { + } - var level = levels[ i ]; + if ( dataReady ) { - this.addLevel( level.object.clone(), level.distance ); + state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); - } + } - return this; + } else { - }, + state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); - addLevel: function ( object, distance ) { + } - if ( distance === undefined ) distance = 0; + } else if ( texture.isFramebufferTexture ) { - distance = Math.abs( distance ); + if ( allocateMemory ) { - var levels = this.levels; + if ( useTexStorage ) { - for ( var l = 0; l < levels.length; l ++ ) { + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); - if ( distance < levels[ l ].distance ) { + } else { - break; + 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 ); - levels.splice( l, 0, { distance: distance, object: object } ); + width >>= 1; + height >>= 1; - this.add( object ); + } - }, + } - getObjectForDistance: function ( distance ) { + } - var levels = this.levels; + } else { - for ( var i = 1, l = levels.length; i < l; i ++ ) { + // regular Texture (image, video, canvas) - if ( distance < levels[ i ].distance ) { + // use manually created mipmaps if available + // if there are no manual mipmaps + // set 0 level mipmap and then use GL to generate other mipmap levels - break; + if ( mipmaps.length > 0 ) { - } + if ( useTexStorage && allocateMemory ) { - } + const dimensions = getDimensions( mipmaps[ 0 ] ); - return levels[ i - 1 ].object; + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); - }, + } - raycast: ( function () { + for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { - var matrixPosition = new Vector3(); + mipmap = mipmaps[ i ]; - return function raycast( raycaster, intersects ) { + if ( useTexStorage ) { - matrixPosition.setFromMatrixPosition( this.matrixWorld ); + if ( dataReady ) { - var distance = raycaster.ray.origin.distanceTo( matrixPosition ); + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); - this.getObjectForDistance( distance ).raycast( raycaster, intersects ); + } - }; + } else { + + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); - }() ), + } - update: function () { + } - var v1 = new Vector3(); - var v2 = new Vector3(); + texture.generateMipmaps = false; - return function update( camera ) { + } else { - var levels = this.levels; + if ( useTexStorage ) { - if ( levels.length > 1 ) { + if ( allocateMemory ) { - v1.setFromMatrixPosition( camera.matrixWorld ); - v2.setFromMatrixPosition( this.matrixWorld ); + const dimensions = getDimensions( image ); - var distance = v1.distanceTo( v2 ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); - levels[ 0 ].object.visible = true; + } - for ( var i = 1, l = levels.length; i < l; i ++ ) { + if ( dataReady ) { - if ( distance >= levels[ i ].distance ) { + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); - levels[ i - 1 ].object.visible = false; - levels[ i ].object.visible = true; + } } else { - break; + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); } } - for ( ; i < l; i ++ ) { + } - levels[ i ].object.visible = false; + if ( textureNeedsGenerateMipmaps( texture ) ) { - } + generateMipmap( textureType ); } - }; + sourceProperties.__version = source.version; - }(), + if ( texture.onUpdate ) texture.onUpdate( texture ); - toJSON: function ( meta ) { + } - var data = Object3D.prototype.toJSON.call( this, meta ); + textureProperties.__version = texture.version; - data.object.levels = []; + } - var levels = this.levels; + function uploadCubeTexture( textureProperties, texture, slot ) { - for ( var i = 0, l = levels.length; i < l; i ++ ) { + if ( texture.image.length !== 6 ) return; - var level = levels[ i ]; + const forceUpload = initTexture( textureProperties, texture ); + const source = texture.source; - data.object.levels.push( { - object: level.object.uuid, - distance: level.distance - } ); + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); - } + const sourceProperties = properties.get( source ); - return data; + if ( source.version !== sourceProperties.__version || forceUpload === true ) { - } + state.activeTexture( _gl.TEXTURE0 + slot ); - } ); + const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); + const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); + const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author michael guerrero / http://realitymeltdown.com - * @author ikerr / http://verold.com - */ + _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, unpackConversion ); - function Skeleton( bones, boneInverses ) { + const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); + const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); - // copy the bone array + const cubeImage = []; - bones = bones || []; + for ( let i = 0; i < 6; i ++ ) { - this.bones = bones.slice( 0 ); - this.boneMatrices = new Float32Array( this.bones.length * 16 ); + if ( ! isCompressed && ! isDataTexture ) { - // use the supplied bone inverses or calculate the inverses + cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize ); - if ( boneInverses === undefined ) { + } else { - this.calculateInverses(); + cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; - } else { + } - if ( this.bones.length === boneInverses.length ) { + cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); - this.boneInverses = boneInverses.slice( 0 ); + } - } else { + const image = cubeImage[ 0 ], + glFormat = utils.convert( texture.format, texture.colorSpace ), + glType = utils.convert( texture.type ), + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); - console.warn( 'THREE.Skeleton boneInverses is the wrong length.' ); + const useTexStorage = ( texture.isVideoTexture !== true ); + const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); + const dataReady = source.dataReady; + let levels = getMipLevels( texture, image ); - this.boneInverses = []; + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { + let mipmaps; - this.boneInverses.push( new Matrix4() ); + if ( isCompressed ) { - } + if ( useTexStorage && allocateMemory ) { - } + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); - } + } - } + for ( let i = 0; i < 6; i ++ ) { - Object.assign( Skeleton.prototype, { + mipmaps = cubeImage[ i ].mipmaps; - calculateInverses: function () { + for ( let j = 0; j < mipmaps.length; j ++ ) { - this.boneInverses = []; + const mipmap = mipmaps[ j ]; - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { + if ( texture.format !== RGBAFormat ) { - var inverse = new Matrix4(); + if ( glFormat !== null ) { - if ( this.bones[ i ] ) { + if ( useTexStorage ) { - inverse.getInverse( this.bones[ i ].matrixWorld ); + if ( dataReady ) { - } + state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); - this.boneInverses.push( inverse ); + } - } + } else { - }, + state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - pose: function () { + } - var bone, i, il; + } else { - // recover the bind-time world matrices + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); - for ( i = 0, il = this.bones.length; i < il; i ++ ) { + } - bone = this.bones[ i ]; + } else { - if ( bone ) { + if ( useTexStorage ) { - bone.matrixWorld.getInverse( this.boneInverses[ i ] ); + if ( dataReady ) { - } + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); - } - - // compute the local matrices, positions, rotations and scales - - for ( i = 0, il = this.bones.length; i < il; i ++ ) { - - bone = this.bones[ i ]; + } - if ( bone ) { + } else { - if ( bone.parent && bone.parent.isBone ) { + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - bone.matrix.getInverse( bone.parent.matrixWorld ); - bone.matrix.multiply( bone.matrixWorld ); + } - } else { + } - bone.matrix.copy( bone.matrixWorld ); + } } - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); + } else { - } + mipmaps = texture.mipmaps; - } + if ( useTexStorage && allocateMemory ) { - }, + // TODO: Uniformly handle mipmap definitions + // Normal textures and compressed cube textures define base level + mips with their mipmap array + // Uncompressed cube textures use their mipmap array only for mips (no base level) - update: ( function () { + if ( mipmaps.length > 0 ) levels ++; - var offsetMatrix = new Matrix4(); - var identityMatrix = new Matrix4(); + const dimensions = getDimensions( cubeImage[ 0 ] ); - return function update() { + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height ); - var bones = this.bones; - var boneInverses = this.boneInverses; - var boneMatrices = this.boneMatrices; - var boneTexture = this.boneTexture; + } - // flatten bone matrices to array + for ( let i = 0; i < 6; i ++ ) { - for ( var i = 0, il = bones.length; i < il; i ++ ) { + if ( isDataTexture ) { - // compute the offset between the current and the original transform + if ( useTexStorage ) { - var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix; + if ( dataReady ) { - offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); - offsetMatrix.toArray( boneMatrices, i * 16 ); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); - } + } - if ( boneTexture !== undefined ) { + } else { - boneTexture.needsUpdate = true; + 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; - clone: function () { + if ( useTexStorage ) { - return new Skeleton( this.bones, this.boneInverses ); + if ( dataReady ) { - } + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); - } ); + } - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author ikerr / http://verold.com - */ + } else { - function Bone() { + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); - Object3D.call( this ); + } - this.type = 'Bone'; + } - } + } else { - Bone.prototype = Object.assign( Object.create( Object3D.prototype ), { + if ( useTexStorage ) { - constructor: Bone, + if ( dataReady ) { - isBone: true + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); - } ); + } - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * @author ikerr / http://verold.com - */ + } else { - function SkinnedMesh( geometry, material ) { + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); - Mesh.call( this, geometry, material ); + } - this.type = 'SkinnedMesh'; + for ( let j = 0; j < mipmaps.length; j ++ ) { - this.bindMode = 'attached'; - this.bindMatrix = new Matrix4(); - this.bindMatrixInverse = new Matrix4(); + const mipmap = mipmaps[ j ]; - var bones = this.initBones(); - var skeleton = new Skeleton( bones ); + if ( useTexStorage ) { - this.bind( skeleton, this.matrixWorld ); + if ( dataReady ) { - this.normalizeSkinWeights(); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); - } + } - SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { + } else { - constructor: SkinnedMesh, + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); - isSkinnedMesh: true, + } - initBones: function () { + } - var bones = [], bone, gbone; - var i, il; + } - if ( this.geometry && this.geometry.bones !== undefined ) { + } - // first, create array of 'Bone' objects from geometry data + } - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { + if ( textureNeedsGenerateMipmaps( texture ) ) { - gbone = this.geometry.bones[ i ]; + // We assume images for cube map have the same size. + generateMipmap( _gl.TEXTURE_CUBE_MAP ); - // create new 'Bone' object + } - bone = new Bone(); - bones.push( bone ); + sourceProperties.__version = source.version; - // apply values + if ( texture.onUpdate ) texture.onUpdate( texture ); - bone.name = gbone.name; - bone.position.fromArray( gbone.pos ); - bone.quaternion.fromArray( gbone.rotq ); - if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl ); + } - } + textureProperties.__version = texture.version; - // second, create bone hierarchy + } - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { + // Render targets - gbone = this.geometry.bones[ i ]; + // Setup storage for target texture and bind it to correct framebuffer + function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) { - if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const renderTargetProperties = properties.get( renderTarget ); - // subsequent bones in the hierarchy + if ( ! renderTargetProperties.__hasExternalTextures ) { - bones[ gbone.parent ].add( bones[ i ] ); + const width = Math.max( 1, renderTarget.width >> level ); + const height = Math.max( 1, renderTarget.height >> level ); - } else { + if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { - // topmost bone, immediate child of the skinned mesh + state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null ); - this.add( bones[ i ] ); + } else { - } + state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null ); } } - // now the bones are part of the scene graph and children of the skinned mesh. - // let's update the corresponding matrices - - this.updateMatrixWorld( true ); - - return bones; - - }, - - bind: function ( skeleton, bindMatrix ) { - - this.skeleton = skeleton; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( bindMatrix === undefined ) { + if ( useMultisampledRTT( renderTarget ) ) { - this.updateMatrixWorld( true ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); - this.skeleton.calculateInverses(); + } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 - bindMatrix = this.matrixWorld; + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); } - this.bindMatrix.copy( bindMatrix ); - this.bindMatrixInverse.getInverse( bindMatrix ); - - }, - - pose: function () { + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - this.skeleton.pose(); + } - }, + // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { - normalizeSkinWeights: function () { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); - var scale, i; + if ( renderTarget.depthBuffer ) { - if ( this.geometry && this.geometry.isGeometry ) { + // retrieve the depth attachment types + const depthTexture = renderTarget.depthTexture; + const depthType = depthTexture && depthTexture.isDepthTexture ? depthTexture.type : null; + const glInternalFormat = getInternalDepthFormat( renderTarget.stencilBuffer, depthType ); + const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; - for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) { + // set up the attachment + const samples = getRenderTargetSamples( renderTarget ); + const isUseMultisampledRTT = useMultisampledRTT( renderTarget ); + if ( isUseMultisampledRTT ) { - var sw = this.geometry.skinWeights[ i ]; + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - scale = 1.0 / sw.manhattanLength(); + } else if ( isMultisample ) { - if ( scale !== Infinity ) { + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - sw.multiplyScalar( scale ); + } else { - } else { + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); - sw.set( 1, 0, 0, 0 ); // do something reasonable + } - } + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer ); - } + } else { - } else if ( this.geometry && this.geometry.isBufferGeometry ) { + const textures = renderTarget.textures; - var vec = new Vector4(); + for ( let i = 0; i < textures.length; i ++ ) { - var skinWeight = this.geometry.attributes.skinWeight; + const texture = textures[ i ]; - for ( i = 0; i < skinWeight.count; i ++ ) { + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const samples = getRenderTargetSamples( renderTarget ); - vec.x = skinWeight.getX( i ); - vec.y = skinWeight.getY( i ); - vec.z = skinWeight.getZ( i ); - vec.w = skinWeight.getW( i ); + if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { - scale = 1.0 / vec.manhattanLength(); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - if ( scale !== Infinity ) { + } else if ( useMultisampledRTT( renderTarget ) ) { - vec.multiplyScalar( scale ); + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); } else { - vec.set( 1, 0, 0, 0 ); // do something reasonable + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); } - skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w ); - } } - }, + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); + + } - updateMatrixWorld: function ( force ) { + // Setup resources for a Depth Texture for a FBO (needs an extension) + function setupDepthTexture( framebuffer, renderTarget ) { - Mesh.prototype.updateMatrixWorld.call( this, force ); + const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); + if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); - if ( this.bindMode === 'attached' ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - this.bindMatrixInverse.getInverse( this.matrixWorld ); + if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { - } else if ( this.bindMode === 'detached' ) { + throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); - this.bindMatrixInverse.getInverse( this.bindMatrix ); + } - } else { + // upload an empty depth texture with framebuffer size + if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || + renderTarget.depthTexture.image.width !== renderTarget.width || + renderTarget.depthTexture.image.height !== renderTarget.height ) { - console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); + renderTarget.depthTexture.image.width = renderTarget.width; + renderTarget.depthTexture.image.height = renderTarget.height; + renderTarget.depthTexture.needsUpdate = true; } - }, + setTexture2D( renderTarget.depthTexture, 0 ); - clone: function () { + const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; + const samples = getRenderTargetSamples( renderTarget ); - return new this.constructor( this.geometry, this.material ).copy( this ); + if ( renderTarget.depthTexture.format === DepthFormat ) { - } + if ( useMultisampledRTT( renderTarget ) ) { - } ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * linecap: "round", - * linejoin: "round" - * } - */ + } else { - function LineBasicMaterial( parameters ) { + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - Material.call( this ); + } - this.type = 'LineBasicMaterial'; + } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { - this.color = new Color( 0xffffff ); + if ( useMultisampledRTT( renderTarget ) ) { - this.linewidth = 1; - this.linecap = 'round'; - this.linejoin = 'round'; + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); - this.lights = false; + } else { - this.setValues( parameters ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - } + } - LineBasicMaterial.prototype = Object.create( Material.prototype ); - LineBasicMaterial.prototype.constructor = LineBasicMaterial; + } else { - LineBasicMaterial.prototype.isLineBasicMaterial = true; + throw new Error( 'Unknown depthTexture format' ); - LineBasicMaterial.prototype.copy = function ( source ) { + } - Material.prototype.copy.call( this, source ); + } - this.color.copy( source.color ); + // Setup GL resources for a non-texture depth buffer + function setupDepthRenderbuffer( renderTarget ) { - this.linewidth = source.linewidth; - this.linecap = source.linecap; - this.linejoin = source.linejoin; + const renderTargetProperties = properties.get( renderTarget ); + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); - return this; + if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { - }; + if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); - function Line( geometry, material, mode ) { + } else { - if ( mode === 1 ) { + if ( isCube ) { - console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' ); - return new LineSegments( geometry, material ); + renderTargetProperties.__webglDepthbuffer = []; - } + for ( let i = 0; i < 6; i ++ ) { - Object3D.call( this ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); + renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); - this.type = 'Line'; + } - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } ); + } else { - } + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); - Line.prototype = Object.assign( Object.create( Object3D.prototype ), { + } - constructor: Line, + } - isLine: true, + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - raycast: ( function () { + } - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + // rebind framebuffer with external textures + function rebindTextures( renderTarget, colorTexture, depthTexture ) { - return function raycast( raycaster, intersects ) { + const renderTargetProperties = properties.get( renderTarget ); - var precision = raycaster.linePrecision; - var precisionSq = precision * precision; + if ( colorTexture !== undefined ) { - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 ); - // Checking boundingSphere distance to ray + } - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + if ( depthTexture !== undefined ) { - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); + setupDepthRenderbuffer( renderTarget ); - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; + } - // + } - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + // Set up GL resources for the render target + function setupRenderTarget( renderTarget ) { - var vStart = new Vector3(); - var vEnd = new Vector3(); - var interSegment = new Vector3(); - var interRay = new Vector3(); - var step = ( this && this.isLineSegments ) ? 2 : 1; + const texture = renderTarget.texture; - if ( geometry.isBufferGeometry ) { + const renderTargetProperties = properties.get( renderTarget ); + const textureProperties = properties.get( texture ); - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; + renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); - if ( index !== null ) { + const textures = renderTarget.textures; - var indices = index.array; + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); + const isMultipleRenderTargets = ( textures.length > 1 ); - for ( var i = 0, l = indices.length - 1; i < l; i += step ) { + if ( ! isMultipleRenderTargets ) { - var a = indices[ i ]; - var b = indices[ i + 1 ]; + if ( textureProperties.__webglTexture === undefined ) { - vStart.fromArray( positions, a * 3 ); - vEnd.fromArray( positions, b * 3 ); + textureProperties.__webglTexture = _gl.createTexture(); - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + } - if ( distSq > precisionSq ) continue; + textureProperties.__version = texture.version; + info.memory.textures ++; - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + } - var distance = raycaster.ray.origin.distanceTo( interRay ); + // Setup framebuffer - if ( distance < raycaster.near || distance > raycaster.far ) continue; + if ( isCube ) { - intersects.push( { + renderTargetProperties.__webglFramebuffer = []; - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + for ( let i = 0; i < 6; i ++ ) { - } ); + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - } + renderTargetProperties.__webglFramebuffer[ i ] = []; - } else { + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) { + renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer(); - vStart.fromArray( positions, 3 * i ); - vEnd.fromArray( positions, 3 * i + 3 ); + } - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + } else { - if ( distSq > precisionSq ) continue; + renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + } - var distance = raycaster.ray.origin.distanceTo( interRay ); + } - if ( distance < raycaster.near || distance > raycaster.far ) continue; + } else { - intersects.push( { + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + renderTargetProperties.__webglFramebuffer = []; - } ); + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - } + renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer(); } - } else if ( geometry.isGeometry ) { - - var vertices = geometry.vertices; - var nbVertices = vertices.length; + } else { - for ( var i = 0; i < nbVertices - 1; i += step ) { + renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); - var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); + } - if ( distSq > precisionSq ) continue; + if ( isMultipleRenderTargets ) { - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation + for ( let i = 0, il = textures.length; i < il; i ++ ) { - var distance = raycaster.ray.origin.distanceTo( interRay ); + const attachmentProperties = properties.get( textures[ i ] ); - if ( distance < raycaster.near || distance > raycaster.far ) continue; + if ( attachmentProperties.__webglTexture === undefined ) { - intersects.push( { + attachmentProperties.__webglTexture = _gl.createTexture(); - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this + info.memory.textures ++; - } ); + } } } - }; - - }() ), + if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { - clone: function () { + renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); + renderTargetProperties.__webglColorRenderbuffer = []; - return new this.constructor( this.geometry, this.material ).copy( this ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); - } - - } ); + for ( let i = 0; i < textures.length; i ++ ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + const texture = textures[ i ]; + renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); - function LineSegments( geometry, material ) { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - Line.call( this, geometry, material ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); + const glType = utils.convert( texture.type ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); + const samples = getRenderTargetSamples( renderTarget ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - this.type = 'LineSegments'; + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - } + } - LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - constructor: LineSegments, + if ( renderTarget.depthBuffer ) { - isLineSegments: true + renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); - } ); + } - /** - * @author mgreter / http://github.com/mgreter - */ + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - function LineLoop( geometry, material ) { + } - Line.call( this, geometry, material ); + } - this.type = 'LineLoop'; + // Setup color buffer - } + if ( isCube ) { - LineLoop.prototype = Object.assign( Object.create( Line.prototype ), { + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); - constructor: LineLoop, + for ( let i = 0; i < 6; i ++ ) { - isLineLoop: true, + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - } ); + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * size: , - * sizeAttenuation: - * } - */ + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level ); - function PointsMaterial( parameters ) { + } - Material.call( this ); + } else { - this.type = 'PointsMaterial'; + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 ); - this.color = new Color( 0xffffff ); + } - this.map = null; + } - this.size = 1; - this.sizeAttenuation = true; + if ( textureNeedsGenerateMipmaps( texture ) ) { - this.lights = false; + generateMipmap( _gl.TEXTURE_CUBE_MAP ); - this.setValues( parameters ); + } - } + state.unbindTexture(); - PointsMaterial.prototype = Object.create( Material.prototype ); - PointsMaterial.prototype.constructor = PointsMaterial; + } else if ( isMultipleRenderTargets ) { - PointsMaterial.prototype.isPointsMaterial = true; + for ( let i = 0, il = textures.length; i < il; i ++ ) { - PointsMaterial.prototype.copy = function ( source ) { + const attachment = textures[ i ]; + const attachmentProperties = properties.get( attachment ); - Material.prototype.copy.call( this, source ); + state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_2D, attachment ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 ); - this.color.copy( source.color ); + if ( textureNeedsGenerateMipmaps( attachment ) ) { - this.map = source.map; + generateMipmap( _gl.TEXTURE_2D ); - this.size = source.size; - this.sizeAttenuation = source.sizeAttenuation; + } - return this; + } - }; + state.unbindTexture(); - /** - * @author alteredq / http://alteredqualia.com/ - */ + } else { - function Points$1( geometry, material ) { + let glTextureType = _gl.TEXTURE_2D; - Object3D.call( this ); + if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { - this.type = 'Points'; + glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } ); + } - } + state.bindTexture( glTextureType, textureProperties.__webglTexture ); + setTextureParameters( glTextureType, texture ); - Points$1.prototype = Object.assign( Object.create( Object3D.prototype ), { + if ( texture.mipmaps && texture.mipmaps.length > 0 ) { - constructor: Points$1, + for ( let level = 0; level < texture.mipmaps.length; level ++ ) { - isPoints: true, + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level ); - raycast: ( function () { + } - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + } else { - return function raycast( raycaster, intersects ) { + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 ); - var object = this; - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; - var threshold = raycaster.params.Points.threshold; + } - // Checking boundingSphere distance to ray + if ( textureNeedsGenerateMipmaps( texture ) ) { - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + generateMipmap( glTextureType ); - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - sphere.radius += threshold; + } - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; + state.unbindTexture(); - // + } - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + // Setup depth and stencil buffers - var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); - var localThresholdSq = localThreshold * localThreshold; - var position = new Vector3(); + if ( renderTarget.depthBuffer ) { - function testPoint( point, index ) { + setupDepthRenderbuffer( renderTarget ); - var rayPointDistanceSq = ray.distanceSqToPoint( point ); + } - if ( rayPointDistanceSq < localThresholdSq ) { + } - var intersectPoint = ray.closestPointToPoint( point ); - intersectPoint.applyMatrix4( matrixWorld ); + function updateRenderTargetMipmap( renderTarget ) { - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); + const textures = renderTarget.textures; - if ( distance < raycaster.near || distance > raycaster.far ) return; + for ( let i = 0, il = textures.length; i < il; i ++ ) { - intersects.push( { + const texture = textures[ i ]; - distance: distance, - distanceToRay: Math.sqrt( rayPointDistanceSq ), - point: intersectPoint.clone(), - index: index, - face: null, - object: object + if ( textureNeedsGenerateMipmaps( texture ) ) { - } ); + 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(); } - if ( geometry.isBufferGeometry ) { - - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; - - if ( index !== null ) { + } - var indices = index.array; + } - for ( var i = 0, il = indices.length; i < il; i ++ ) { + const invalidationArrayRead = []; + const invalidationArrayDraw = []; - var a = indices[ i ]; + function updateMultisampleRenderTarget( renderTarget ) { - position.fromArray( positions, a * 3 ); + if ( renderTarget.samples > 0 ) { - testPoint( position, a ); + if ( useMultisampledRTT( renderTarget ) === false ) { - } + const textures = renderTarget.textures; + const width = renderTarget.width; + const height = renderTarget.height; + let mask = _gl.COLOR_BUFFER_BIT; + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + const renderTargetProperties = properties.get( renderTarget ); + const isMultipleRenderTargets = ( textures.length > 1 ); - } else { + // If MRT we need to remove FBO attachments + if ( isMultipleRenderTargets ) { - for ( var i = 0, l = positions.length / 3; i < l; i ++ ) { + for ( let i = 0; i < textures.length; i ++ ) { - position.fromArray( positions, i * 3 ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); - testPoint( position, i ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); } } - } else { - - var vertices = geometry.vertices; - - for ( var i = 0, l = vertices.length; i < l; i ++ ) { + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - testPoint( vertices[ i ], i ); + for ( let i = 0; i < textures.length; i ++ ) { - } + if ( renderTarget.resolveDepthBuffer ) { - } + if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; - }; + // resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) - }() ), + if ( renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; - clone: function () { + } - return new this.constructor( this.geometry, this.material ).copy( this ); + if ( isMultipleRenderTargets ) { - } + _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - } ); + const webglTexture = properties.get( textures[ i ] ).__webglTexture; + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + } - function Group() { + _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); - Object3D.call( this ); + if ( supportsInvalidateFramebuffer === true ) { - this.type = 'Group'; + invalidationArrayRead.length = 0; + invalidationArrayDraw.length = 0; - } + invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i ); - Group.prototype = Object.assign( Object.create( Object3D.prototype ), { + if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false ) { - constructor: Group, + invalidationArrayRead.push( depthStyle ); + invalidationArrayDraw.push( depthStyle ); - isGroup: true + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw ); - } ); + } - /** - * @author mrdoob / http://mrdoob.com/ - */ + _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArrayRead ); - function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + } - Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + } - this.generateMipmaps = false; + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); - // Set needsUpdate when first frame is ready + // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments + if ( isMultipleRenderTargets ) { - var scope = this; + for ( let i = 0; i < textures.length; i ++ ) { - function onLoaded() { + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - video.removeEventListener( 'loadeddata', onLoaded, false ); - scope.needsUpdate = true; + 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 ); - video.addEventListener( 'loadeddata', onLoaded, false ); + } - } + } - VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), { + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); - constructor: VideoTexture, + } else { - isVideoTexture: true, + if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false && supportsInvalidateFramebuffer ) { - update: function () { + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; - var video = this.image; + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); - if ( video.readyState >= video.HAVE_CURRENT_DATA ) { + } - this.needsUpdate = true; + } } } - } ); + function getRenderTargetSamples( renderTarget ) { - /** - * @author alteredq / http://alteredqualia.com/ - */ + return Math.min( capabilities.maxSamples, renderTarget.samples ); - function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + } - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + function useMultisampledRTT( renderTarget ) { - this.image = { width: width, height: height }; - this.mipmaps = mipmaps; + const renderTargetProperties = properties.get( renderTarget ); - // no flipping for cube textures - // (also flipping doesn't work for compressed textures ) + return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; - this.flipY = false; + } - // can't generate mipmaps for compressed textures - // mips must be embedded in DDS files + function updateVideoTexture( texture ) { - this.generateMipmaps = false; + const frame = info.render.frame; - } + // Check the last frame we updated the VideoTexture - CompressedTexture.prototype = Object.create( Texture.prototype ); - CompressedTexture.prototype.constructor = CompressedTexture; + if ( _videoTextures.get( texture ) !== frame ) { - CompressedTexture.prototype.isCompressedTexture = true; + _videoTextures.set( texture, frame ); + texture.update(); - /** - * @author Matt DesLauriers / @mattdesl - * @author atix / arthursilber.de - */ + } + + } + + function verifyColorSpace( texture, image ) { + + const colorSpace = texture.colorSpace; + const format = texture.format; + const type = texture.type; + + if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image; + + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { + + // sRGB + + if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) { + + // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format - function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { + if ( format !== RGBAFormat || type !== UnsignedByteType ) { - format = format !== undefined ? format : DepthFormat; + console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); - if ( format !== DepthFormat && format !== DepthStencilFormat ) { + } + + } else { + + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); + + } + + } - throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); + return image; } - if ( type === undefined && format === DepthFormat ) type = UnsignedShortType; - if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; + function getDimensions( image ) { + + if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) { + + // if intrinsic data are not available, fallback to width/height + + _imageDimensions.width = image.naturalWidth || image.width; + _imageDimensions.height = image.naturalHeight || image.height; + + } else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) { + + _imageDimensions.width = image.displayWidth; + _imageDimensions.height = image.displayHeight; + + } else { + + _imageDimensions.width = image.width; + _imageDimensions.height = image.height; + + } + + return _imageDimensions; - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + } - this.image = { width: width, height: height }; + // - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + this.allocateTextureUnit = allocateTextureUnit; + this.resetTextureUnits = resetTextureUnits; - this.flipY = false; - this.generateMipmaps = false; + 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; } - DepthTexture.prototype = Object.create( Texture.prototype ); - DepthTexture.prototype.constructor = DepthTexture; - DepthTexture.prototype.isDepthTexture = true; + function WebGLUtils( gl, extensions ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + function convert( p, colorSpace = NoColorSpace ) { + + let extension; + + const transfer = ColorManagement.getTransfer( colorSpace ); + + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; + if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV; + + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; + if ( p === HalfFloatType ) return gl.HALF_FLOAT; - function WireframeGeometry( geometry ) { + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBFormat ) return gl.RGB; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; - BufferGeometry.call( this ); + // WebGL2 formats. - this.type = 'WireframeGeometry'; + if ( p === RedFormat ) return gl.RED; + if ( p === RedIntegerFormat ) return gl.RED_INTEGER; + if ( p === RGFormat ) return gl.RG; + if ( p === RGIntegerFormat ) return gl.RG_INTEGER; + if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; - // buffer + // S3TC - var vertices = []; + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - // helper variables + if ( transfer === SRGBTransfer ) { - var i, j, l, o, ol; - var edge = [ 0, 0 ], edges = {}, e, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; - var vertex; + extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); - // different logic for Geometry and BufferGeometry + if ( extension !== null ) { - if ( geometry && geometry.isGeometry ) { + 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; - // create a data structure that contains all edges without duplicates + } else { - var faces = geometry.faces; + return null; - for ( i = 0, l = faces.length; i < l; i ++ ) { + } - var face = faces[ i ]; + } else { - for ( j = 0; j < 3; j ++ ) { + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); + if ( extension !== null ) { - key = edge[ 0 ] + ',' + edge[ 1 ]; + 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; - if ( edges[ key ] === undefined ) { + } else { - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; + return null; } @@ -25275,8628 +25677,7807 @@ var ROS3D = (function (exports, ROSLIB) { } - // generate vertices + // PVRTC - for ( key in edges ) { + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { - e = edges[ key ]; + extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - vertex = geometry.vertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( extension !== null ) { - vertex = geometry.vertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + 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 { - } else if ( geometry && geometry.isBufferGeometry ) { + return null; - var position, indices, groups; - var group, start, count; - var index1, index2; + } - vertex = new Vector3(); + } - if ( geometry.index !== null ) { + // ETC - // indexed BufferGeometry + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { - position = geometry.attributes.position; - indices = geometry.index; - groups = geometry.groups; + extension = extensions.get( 'WEBGL_compressed_texture_etc' ); - if ( groups.length === 0 ) { + if ( extension !== null ) { - groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; - } + } else { - // create a data structure that contains all eges without duplicates + return null; - for ( o = 0, ol = groups.length; o < ol; ++ o ) { + } - group = groups[ o ]; + } - start = group.start; - count = group.count; + // ASTC - for ( i = start, l = ( start + count ); i < l; i += 3 ) { + 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 ) { - for ( j = 0; j < 3; j ++ ) { + extension = extensions.get( 'WEBGL_compressed_texture_astc' ); - edge1 = indices.getX( i + j ); - edge2 = indices.getX( i + ( j + 1 ) % 3 ); - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); + if ( extension !== null ) { - key = edge[ 0 ] + ',' + edge[ 1 ]; + if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; - if ( edges[ key ] === undefined ) { + } else { - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; + return null; - } + } - } + } - } + // BPTC - } + if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) { - // generate vertices + extension = extensions.get( 'EXT_texture_compression_bptc' ); - for ( key in edges ) { + if ( extension !== null ) { - e = edges[ key ]; + if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT; + if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT; - vertex.fromBufferAttribute( position, e.index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } else { - vertex.fromBufferAttribute( position, e.index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + return null; } - } else { - - // non-indexed BufferGeometry + } - position = geometry.attributes.position; + // RGTC - for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) { + if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { - for ( j = 0; j < 3; j ++ ) { + extension = extensions.get( 'EXT_texture_compression_rgtc' ); - // three edges per triangle, an edge is represented as (index1, index2) - // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) + if ( extension !== null ) { - index1 = 3 * i + j; - vertex.fromBufferAttribute( position, index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; + if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; + if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; + if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; - index2 = 3 * i + ( ( j + 1 ) % 3 ); - vertex.fromBufferAttribute( position, index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } else { - } + return null; } } - } + // - // build geometry + if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8; - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) - } + return ( gl[ p ] !== undefined ) ? gl[ p ] : null; - WireframeGeometry.prototype = Object.create( BufferGeometry.prototype ); - WireframeGeometry.prototype.constructor = WireframeGeometry; + } - /** - * @author zz85 / https://github.com/zz85 - * @author Mugen87 / https://github.com/Mugen87 - * - * Parametric Surfaces Geometry - * based on the brilliant article by @prideout http://prideout.net/blog/?p=44 - */ + return { convert: convert }; - // ParametricGeometry + } - function ParametricGeometry( func, slices, stacks ) { + class ArrayCamera extends PerspectiveCamera { - Geometry.call( this ); + constructor( array = [] ) { - this.type = 'ParametricGeometry'; + super(); - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + this.isArrayCamera = true; - this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) ); - this.mergeVertices(); + this.cameras = array; + + } } - ParametricGeometry.prototype = Object.create( Geometry.prototype ); - ParametricGeometry.prototype.constructor = ParametricGeometry; + class Group extends Object3D { - // ParametricBufferGeometry + constructor() { - function ParametricBufferGeometry( func, slices, stacks ) { + super(); - BufferGeometry.call( this ); + this.isGroup = true; - this.type = 'ParametricBufferGeometry'; + this.type = 'Group'; - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + } + + } + + const _moveEvent = { type: 'move' }; + + class WebXRController { - // buffers + constructor() { - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + this._targetRay = null; + this._grip = null; + this._hand = null; - var EPS = 0.00001; + } - var normal = new Vector3(); + getHandSpace() { - var p0 = new Vector3(), p1 = new Vector3(); - var pu = new Vector3(), pv = new Vector3(); + if ( this._hand === null ) { - var i, j; + this._hand = new Group(); + this._hand.matrixAutoUpdate = false; + this._hand.visible = false; - // generate vertices, normals and uvs + this._hand.joints = {}; + this._hand.inputState = { pinching: false }; - var sliceCount = slices + 1; + } - for ( i = 0; i <= stacks; i ++ ) { + return this._hand; - var v = i / stacks; + } - for ( j = 0; j <= slices; j ++ ) { + getTargetRaySpace() { - var u = j / slices; + if ( this._targetRay === null ) { - // vertex + 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(); - p0 = func( u, v, p0 ); - vertices.push( p0.x, p0.y, p0.z ); + } - // normal + return this._targetRay; - // approximate tangent vectors via finite differences + } - if ( u - EPS >= 0 ) { + getGripSpace() { - p1 = func( u - EPS, v, p1 ); - pu.subVectors( p0, p1 ); + if ( this._grip === null ) { - } else { + 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(); - p1 = func( u + EPS, v, p1 ); - pu.subVectors( p1, p0 ); + } - } + return this._grip; - if ( v - EPS >= 0 ) { + } - p1 = func( u, v - EPS, p1 ); - pv.subVectors( p0, p1 ); + dispatchEvent( event ) { - } else { + if ( this._targetRay !== null ) { - p1 = func( u, v + EPS, p1 ); - pv.subVectors( p1, p0 ); + this._targetRay.dispatchEvent( event ); - } + } - // cross product of tangent vectors returns surface normal + if ( this._grip !== null ) { - normal.crossVectors( pu, pv ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + this._grip.dispatchEvent( event ); - // uv + } + + if ( this._hand !== null ) { - uvs.push( u, v ); + this._hand.dispatchEvent( event ); } + return this; + } - // generate indices + connect( inputSource ) { - for ( i = 0; i < stacks; i ++ ) { + if ( inputSource && inputSource.hand ) { - for ( j = 0; j < slices; j ++ ) { + const hand = this._hand; - var a = i * sliceCount + j; - var b = i * sliceCount + j + 1; - var c = ( i + 1 ) * sliceCount + j + 1; - var d = ( i + 1 ) * sliceCount + j; + if ( hand ) { - // faces one and two + for ( const inputjoint of inputSource.hand.values() ) { - indices.push( a, b, d ); - indices.push( b, c, d ); + // Initialize hand with joints when connected + this._getHandJoint( hand, inputjoint ); + + } + + } } + this.dispatchEvent( { type: 'connected', data: inputSource } ); + + return this; + } - // build geometry + disconnect( inputSource ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + this.dispatchEvent( { type: 'disconnected', data: inputSource } ); - } + if ( this._targetRay !== null ) { - ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry; + this._targetRay.visible = false; - /** - * @author clockworkgeek / https://github.com/clockworkgeek - * @author timothypratley / https://github.com/timothypratley - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ + } - // PolyhedronGeometry + if ( this._grip !== null ) { - function PolyhedronGeometry( vertices, indices, radius, detail ) { + this._grip.visible = false; - Geometry.call( this ); + } - this.type = 'PolyhedronGeometry'; + if ( this._hand !== null ) { - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; + this._hand.visible = false; - this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) ); - this.mergeVertices(); + } - } + return this; - PolyhedronGeometry.prototype = Object.create( Geometry.prototype ); - PolyhedronGeometry.prototype.constructor = PolyhedronGeometry; + } - // PolyhedronBufferGeometry + update( inputSource, frame, referenceSpace ) { - function PolyhedronBufferGeometry( vertices, indices, radius, detail ) { + let inputPose = null; + let gripPose = null; + let handPose = null; - BufferGeometry.call( this ); + const targetRay = this._targetRay; + const grip = this._grip; + const hand = this._hand; - this.type = 'PolyhedronBufferGeometry'; + if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; + if ( hand && inputSource.hand ) { - radius = radius || 1; - detail = detail || 0; + handPose = true; - // default buffer data + for ( const inputjoint of inputSource.hand.values() ) { - var vertexBuffer = []; - var uvBuffer = []; + // Update the joints groups with the XRJoint poses + const jointPose = frame.getJointPose( inputjoint, referenceSpace ); - // the subdivision creates the vertex buffer data + // The transform of this joint will be updated with the joint pose on each frame + const joint = this._getHandJoint( hand, inputjoint ); - subdivide( detail ); + if ( jointPose !== null ) { - // all vertices should lie on a conceptual sphere with a given radius + joint.matrix.fromArray( jointPose.transform.matrix ); + joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; + joint.jointRadius = jointPose.radius; - appplyRadius( radius ); + } - // finally, create the uv data + joint.visible = jointPose !== null; - generateUVs(); + } - // build non-indexed geometry + // Custom events - this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); + // Check pinchz + const indexTip = hand.joints[ 'index-finger-tip' ]; + const thumbTip = hand.joints[ 'thumb-tip' ]; + const distance = indexTip.position.distanceTo( thumbTip.position ); - if ( detail === 0 ) { + const distanceToPinch = 0.02; + const threshold = 0.005; - this.computeVertexNormals(); // flat normals + if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { - } else { + hand.inputState.pinching = false; + this.dispatchEvent( { + type: 'pinchend', + handedness: inputSource.handedness, + target: this + } ); - this.normalizeNormals(); // smooth normals + } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { - } + hand.inputState.pinching = true; + this.dispatchEvent( { + type: 'pinchstart', + handedness: inputSource.handedness, + target: this + } ); - // helper functions + } - function subdivide( detail ) { + } else { - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); + if ( grip !== null && inputSource.gripSpace ) { - // iterate over all faces and apply a subdivison with the given detail value + gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); - for ( var i = 0; i < indices.length; i += 3 ) { + if ( gripPose !== null ) { - // get the vertices of the face + grip.matrix.fromArray( gripPose.transform.matrix ); + grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; - getVertexByIndex( indices[ i + 0 ], a ); - getVertexByIndex( indices[ i + 1 ], b ); - getVertexByIndex( indices[ i + 2 ], c ); + if ( gripPose.linearVelocity ) { - // perform subdivision + grip.hasLinearVelocity = true; + grip.linearVelocity.copy( gripPose.linearVelocity ); - subdivideFace( a, b, c, detail ); + } else { - } + grip.hasLinearVelocity = false; - } + } - function subdivideFace( a, b, c, detail ) { + if ( gripPose.angularVelocity ) { - var cols = Math.pow( 2, detail ); + grip.hasAngularVelocity = true; + grip.angularVelocity.copy( gripPose.angularVelocity ); - // we use this multidimensional array as a data structure for creating the subdivision + } else { - var v = []; + grip.hasAngularVelocity = false; - var i, j; + } - // construct all of the vertices for this subdivision + } - for ( i = 0; i <= cols; i ++ ) { + } - v[ i ] = []; + } - var aj = a.clone().lerp( c, i / cols ); - var bj = b.clone().lerp( c, i / cols ); + if ( targetRay !== null ) { - var rows = cols - i; + inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); - for ( j = 0; j <= rows; j ++ ) { + // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it + if ( inputPose === null && gripPose !== null ) { - if ( j === 0 && i === cols ) { + inputPose = gripPose; - v[ i ][ j ] = aj; + } - } else { + if ( inputPose !== null ) { - v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); + targetRay.matrix.fromArray( inputPose.transform.matrix ); + targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; - } + if ( inputPose.linearVelocity ) { - } + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy( inputPose.linearVelocity ); - } + } else { - // construct all of the faces + targetRay.hasLinearVelocity = false; - for ( i = 0; i < cols; i ++ ) { + } - for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { + if ( inputPose.angularVelocity ) { - var k = Math.floor( j / 2 ); + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy( inputPose.angularVelocity ); - if ( j % 2 === 0 ) { + } else { - pushVertex( v[ i ][ k + 1 ] ); - pushVertex( v[ i + 1 ][ k ] ); - pushVertex( v[ i ][ k ] ); + targetRay.hasAngularVelocity = false; - } else { + } - pushVertex( v[ i ][ k + 1 ] ); - pushVertex( v[ i + 1 ][ k + 1 ] ); - pushVertex( v[ i + 1 ][ k ] ); + this.dispatchEvent( _moveEvent ); } } + } - } + if ( targetRay !== null ) { - function appplyRadius( radius ) { + targetRay.visible = ( inputPose !== null ); - var vertex = new Vector3(); + } - // iterate over the entire buffer and apply the radius to each vertex + if ( grip !== null ) { - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { + grip.visible = ( gripPose !== null ); - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; + } - vertex.normalize().multiplyScalar( radius ); + if ( hand !== null ) { - vertexBuffer[ i + 0 ] = vertex.x; - vertexBuffer[ i + 1 ] = vertex.y; - vertexBuffer[ i + 2 ] = vertex.z; + hand.visible = ( handPose !== null ); } + return this; + } - function generateUVs() { + // private method - var vertex = new Vector3(); + _getHandJoint( hand, inputjoint ) { - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { + if ( hand.joints[ inputjoint.jointName ] === undefined ) { - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; + const joint = new Group(); + joint.matrixAutoUpdate = false; + joint.visible = false; + hand.joints[ inputjoint.jointName ] = joint; - var u = azimuth( vertex ) / 2 / Math.PI + 0.5; - var v = inclination( vertex ) / Math.PI + 0.5; - uvBuffer.push( u, 1 - v ); + hand.add( joint ); } - correctUVs(); - - correctSeam(); + return hand.joints[ inputjoint.jointName ]; } - function correctSeam() { - - // handle case when face straddles the seam, see #3269 + } - for ( var i = 0; i < uvBuffer.length; i += 6 ) { + const _occlusion_vertex = ` +void main() { - // uv data of a single face + gl_Position = vec4( position, 1.0 ); - var x0 = uvBuffer[ i + 0 ]; - var x1 = uvBuffer[ i + 2 ]; - var x2 = uvBuffer[ i + 4 ]; +}`; - var max = Math.max( x0, x1, x2 ); - var min = Math.min( x0, x1, x2 ); + const _occlusion_fragment = ` +uniform sampler2DArray depthColor; +uniform float depthWidth; +uniform float depthHeight; - // 0.9 is somewhat arbitrary +void main() { - if ( max > 0.9 && min < 0.1 ) { + vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); - if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; - if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; - if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; + if ( coord.x >= 1.0 ) { - } + gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; - } + } else { - } + gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; - function pushVertex( vertex ) { + } - vertexBuffer.push( vertex.x, vertex.y, vertex.z ); +}`; - } + class WebXRDepthSensing { - function getVertexByIndex( index, vertex ) { + constructor() { - var stride = index * 3; + this.texture = null; + this.mesh = null; - vertex.x = vertices[ stride + 0 ]; - vertex.y = vertices[ stride + 1 ]; - vertex.z = vertices[ stride + 2 ]; + this.depthNear = 0; + this.depthFar = 0; } - function correctUVs() { - - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); + init( renderer, depthData, renderState ) { - var centroid = new Vector3(); + if ( this.texture === null ) { - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + const texture = new Texture(); - for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { + const texProps = renderer.properties.get( texture ); + texProps.__webglTexture = depthData.texture; - a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); - b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); - c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); + if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) { - uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); - uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); - uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); + this.depthNear = depthData.depthNear; + this.depthFar = depthData.depthFar; - centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); - - var azi = azimuth( centroid ); + } - correctUV( uvA, j + 0, a, azi ); - correctUV( uvB, j + 2, b, azi ); - correctUV( uvC, j + 4, c, azi ); + this.texture = texture; } } - function correctUV( uv, stride, vector, azimuth ) { + getMesh( cameraXR ) { - if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { + if ( this.texture !== null ) { - uvBuffer[ stride ] = uv.x - 1; + if ( this.mesh === null ) { - } + const viewport = cameraXR.cameras[ 0 ].viewport; + const material = new ShaderMaterial( { + vertexShader: _occlusion_vertex, + fragmentShader: _occlusion_fragment, + uniforms: { + depthColor: { value: this.texture }, + depthWidth: { value: viewport.z }, + depthHeight: { value: viewport.w } + } + } ); - if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { + this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material ); - uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; + } } - } + return this.mesh; - // Angle around the Y axis, counter-clockwise when looking from above. + } - function azimuth( vector ) { + reset() { - return Math.atan2( vector.z, - vector.x ); + this.texture = null; + this.mesh = null; } + getDepthTexture() { - // Angle above the XZ plane. - - function inclination( vector ) { - - return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); + return this.texture; } } - PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry; + class WebXRManager extends EventDispatcher { - /** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + constructor( renderer, gl ) { - // TetrahedronGeometry + super(); - function TetrahedronGeometry( radius, detail ) { + const scope = this; - Geometry.call( this ); + let session = null; - this.type = 'TetrahedronGeometry'; + let framebufferScaleFactor = 1.0; - this.parameters = { - radius: radius, - detail: detail - }; + let referenceSpace = null; + let referenceSpaceType = 'local-floor'; + // Set default foveation to maximum. + let foveation = 1.0; + let customReferenceSpace = null; - this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + let pose = null; + let glBinding = null; + let glProjLayer = null; + let glBaseLayer = null; + let xrFrame = null; - } + const depthSensing = new WebXRDepthSensing(); + const attributes = gl.getContextAttributes(); - TetrahedronGeometry.prototype = Object.create( Geometry.prototype ); - TetrahedronGeometry.prototype.constructor = TetrahedronGeometry; + let initialRenderTarget = null; + let newRenderTarget = null; - // TetrahedronBufferGeometry + const controllers = []; + const controllerInputSources = []; - function TetrahedronBufferGeometry( radius, detail ) { + const currentSize = new Vector2(); + let currentPixelRatio = null; - var vertices = [ - 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 - ]; + // - var indices = [ - 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 - ]; + const cameraL = new PerspectiveCamera(); + cameraL.layers.enable( 1 ); + cameraL.viewport = new Vector4(); - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + const cameraR = new PerspectiveCamera(); + cameraR.layers.enable( 2 ); + cameraR.viewport = new Vector4(); - this.type = 'TetrahedronBufferGeometry'; + const cameras = [ cameraL, cameraR ]; - this.parameters = { - radius: radius, - detail: detail - }; + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); - } + let _currentDepthNear = null; + let _currentDepthFar = null; - TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry; + // - /** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + this.cameraAutoUpdate = true; + this.enabled = false; - // OctahedronGeometry + this.isPresenting = false; - function OctahedronGeometry( radius, detail ) { + this.getController = function ( index ) { - Geometry.call( this ); + let controller = controllers[ index ]; - this.type = 'OctahedronGeometry'; + if ( controller === undefined ) { - this.parameters = { - radius: radius, - detail: detail - }; + controller = new WebXRController(); + controllers[ index ] = controller; - this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + } - } + return controller.getTargetRaySpace(); - OctahedronGeometry.prototype = Object.create( Geometry.prototype ); - OctahedronGeometry.prototype.constructor = OctahedronGeometry; + }; - // OctahedronBufferGeometry + this.getControllerGrip = function ( index ) { - function OctahedronBufferGeometry( radius, detail ) { + let controller = controllers[ index ]; - var vertices = [ - 1, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, - 1, 0, 0, 0, 1, 0, 0, - 1 - ]; + if ( controller === undefined ) { - var 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 - ]; + controller = new WebXRController(); + controllers[ index ] = controller; - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + } - this.type = 'OctahedronBufferGeometry'; + return controller.getGripSpace(); - this.parameters = { - radius: radius, - detail: detail - }; + }; - } + this.getHand = function ( index ) { - OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry; + let controller = controllers[ index ]; - /** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ + if ( controller === undefined ) { - // IcosahedronGeometry + controller = new WebXRController(); + controllers[ index ] = controller; - function IcosahedronGeometry( radius, detail ) { + } - Geometry.call( this ); + return controller.getHandSpace(); - this.type = 'IcosahedronGeometry'; + }; - this.parameters = { - radius: radius, - detail: detail - }; + // - this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + function onSessionEvent( event ) { - } + const controllerIndex = controllerInputSources.indexOf( event.inputSource ); - IcosahedronGeometry.prototype = Object.create( Geometry.prototype ); - IcosahedronGeometry.prototype.constructor = IcosahedronGeometry; + if ( controllerIndex === - 1 ) { - // IcosahedronBufferGeometry + return; - function IcosahedronBufferGeometry( radius, detail ) { + } - var t = ( 1 + Math.sqrt( 5 ) ) / 2; + const controller = controllers[ controllerIndex ]; - var 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 - ]; + if ( controller !== undefined ) { - var 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 - ]; + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); + controller.dispatchEvent( { type: event.type, data: event.inputSource } ); - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + } - this.type = 'IcosahedronBufferGeometry'; + } - this.parameters = { - radius: radius, - detail: detail - }; + 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 ); - IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry; + for ( let i = 0; i < controllers.length; i ++ ) { - /** - * @author Abe Pazos / https://hamoid.com - * @author Mugen87 / https://github.com/Mugen87 - */ + const inputSource = controllerInputSources[ i ]; - // DodecahedronGeometry + if ( inputSource === null ) continue; - function DodecahedronGeometry( radius, detail ) { + controllerInputSources[ i ] = null; - Geometry.call( this ); + controllers[ i ].disconnect( inputSource ); - this.type = 'DodecahedronGeometry'; + } - this.parameters = { - radius: radius, - detail: detail - }; + _currentDepthNear = null; + _currentDepthFar = null; - this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); + depthSensing.reset(); - } + // restore framebuffer/rendering state - DodecahedronGeometry.prototype = Object.create( Geometry.prototype ); - DodecahedronGeometry.prototype.constructor = DodecahedronGeometry; + renderer.setRenderTarget( initialRenderTarget ); - // DodecahedronBufferGeometry + glBaseLayer = null; + glProjLayer = null; + glBinding = null; + session = null; + newRenderTarget = null; - function DodecahedronBufferGeometry( radius, detail ) { - - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - var r = 1 / t; - - var 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, 1, 1, 1, + animation.stop(); - // (0, ±1/φ, ±φ) - 0, - r, - t, 0, - r, t, - 0, r, - t, 0, r, t, + scope.isPresenting = false; - // (±1/φ, ±φ, 0) - - r, - t, 0, - r, t, 0, - r, - t, 0, r, t, 0, + renderer.setPixelRatio( currentPixelRatio ); + renderer.setSize( currentSize.width, currentSize.height, false ); - // (±φ, 0, ±1/φ) - - t, 0, - r, t, 0, - r, - - t, 0, r, t, 0, r - ]; + scope.dispatchEvent( { type: 'sessionend' } ); - var 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 - ]; + } - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); + this.setFramebufferScaleFactor = function ( value ) { - this.type = 'DodecahedronBufferGeometry'; + framebufferScaleFactor = value; - this.parameters = { - radius: radius, - detail: detail - }; + if ( scope.isPresenting === true ) { - } + console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); - DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry; + } - /** - * @author oosmoxiecode / https://github.com/oosmoxiecode - * @author WestLangley / https://github.com/WestLangley - * @author zz85 / https://github.com/zz85 - * @author miningold / https://github.com/miningold - * @author jonobr1 / https://github.com/jonobr1 - * @author Mugen87 / https://github.com/Mugen87 - * - */ + }; - // TubeGeometry + this.setReferenceSpaceType = function ( value ) { - function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) { + referenceSpaceType = value; - Geometry.call( this ); + if ( scope.isPresenting === true ) { - this.type = 'TubeGeometry'; + console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; + } - if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' ); + }; - var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ); + this.getReferenceSpace = function () { - // expose internals + return customReferenceSpace || referenceSpace; - this.tangents = bufferGeometry.tangents; - this.normals = bufferGeometry.normals; - this.binormals = bufferGeometry.binormals; + }; - // create geometry + this.setReferenceSpace = function ( space ) { - this.fromBufferGeometry( bufferGeometry ); - this.mergeVertices(); + customReferenceSpace = space; - } + }; - TubeGeometry.prototype = Object.create( Geometry.prototype ); - TubeGeometry.prototype.constructor = TubeGeometry; + this.getBaseLayer = function () { - // TubeBufferGeometry + return glProjLayer !== null ? glProjLayer : glBaseLayer; - function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) { + }; - BufferGeometry.call( this ); + this.getBinding = function () { - this.type = 'TubeBufferGeometry'; + return glBinding; - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; + }; - tubularSegments = tubularSegments || 64; - radius = radius || 1; - radialSegments = radialSegments || 8; - closed = closed || false; + this.getFrame = function () { - var frames = path.computeFrenetFrames( tubularSegments, closed ); + return xrFrame; - // expose internals + }; - this.tangents = frames.tangents; - this.normals = frames.normals; - this.binormals = frames.binormals; + this.getSession = function () { - // helper variables + return session; - var vertex = new Vector3(); - var normal = new Vector3(); - var uv = new Vector2(); - var P = new Vector3(); + }; - var i, j; + this.setSession = async function ( value ) { - // buffer + session = value; - var vertices = []; - var normals = []; - var uvs = []; - var indices = []; + if ( session !== null ) { - // create buffer data + initialRenderTarget = renderer.getRenderTarget(); - generateBufferData(); + 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 ); - // build geometry + if ( attributes.xrCompatible !== true ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + await gl.makeXRCompatible(); - // functions + } - function generateBufferData() { + currentPixelRatio = renderer.getPixelRatio(); + renderer.getSize( currentSize ); - for ( i = 0; i < tubularSegments; i ++ ) { + if ( session.renderState.layers === undefined ) { - generateSegment( i ); + const layerInit = { + antialias: attributes.antialias, + alpha: true, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor: framebufferScaleFactor + }; - } + glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); - // if the geometry is not closed, generate the last row of vertices and normals - // at the regular position on the given path - // - // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) + session.updateRenderState( { baseLayer: glBaseLayer } ); - generateSegment( ( closed === false ) ? tubularSegments : 0 ); + renderer.setPixelRatio( 1 ); + renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); - // uvs are generated in a separate function. - // this makes it easy compute correct values for closed geometries + newRenderTarget = new WebGLRenderTarget( + glBaseLayer.framebufferWidth, + glBaseLayer.framebufferHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + colorSpace: renderer.outputColorSpace, + stencilBuffer: attributes.stencil + } + ); - generateUVs(); + } else { - // finally create faces + let depthFormat = null; + let depthType = null; + let glDepthFormat = null; - generateIndices(); + if ( attributes.depth ) { - } + glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; + depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; + depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; - function generateSegment( i ) { + } - // we use getPointAt to sample evenly distributed points from the given path + const projectionlayerInit = { + colorFormat: gl.RGBA8, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; - P = path.getPointAt( i / tubularSegments, P ); + glBinding = new XRWebGLBinding( session, gl ); - // retrieve corresponding normal and binormal + glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); - var N = frames.normals[ i ]; - var B = frames.binormals[ i ]; + session.updateRenderState( { layers: [ glProjLayer ] } ); - // generate normals and vertices for the current segment + renderer.setPixelRatio( 1 ); + renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false ); - for ( j = 0; j <= radialSegments; j ++ ) { + newRenderTarget = new WebGLRenderTarget( + glProjLayer.textureWidth, + glProjLayer.textureHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), + stencilBuffer: attributes.stencil, + colorSpace: renderer.outputColorSpace, + samples: attributes.antialias ? 4 : 0, + resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false ) + } ); - var v = j / radialSegments * Math.PI * 2; + } - var sin = Math.sin( v ); - var cos = - Math.cos( v ); + newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 - // normal + this.setFoveation( foveation ); - 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(); + customReferenceSpace = null; + referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); - normals.push( normal.x, normal.y, normal.z ); + animation.setContext( session ); + animation.start(); - // vertex + scope.isPresenting = true; - vertex.x = P.x + radius * normal.x; - vertex.y = P.y + radius * normal.y; - vertex.z = P.z + radius * normal.z; + scope.dispatchEvent( { type: 'sessionstart' } ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - } + }; - } + this.getEnvironmentBlendMode = function () { - function generateIndices() { + if ( session !== null ) { - for ( j = 1; j <= tubularSegments; j ++ ) { + return session.environmentBlendMode; - for ( i = 1; i <= radialSegments; i ++ ) { + } - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; + }; - // faces + this.getDepthTexture = function () { - indices.push( a, b, d ); - indices.push( b, c, d ); + return depthSensing.getDepthTexture(); - } + }; - } + function onInputSourcesChange( event ) { - } + // Notify disconnected - function generateUVs() { + for ( let i = 0; i < event.removed.length; i ++ ) { - for ( i = 0; i <= tubularSegments; i ++ ) { + const inputSource = event.removed[ i ]; + const index = controllerInputSources.indexOf( inputSource ); - for ( j = 0; j <= radialSegments; j ++ ) { + if ( index >= 0 ) { - uv.x = i / tubularSegments; - uv.y = j / radialSegments; + controllerInputSources[ index ] = null; + controllers[ index ].disconnect( inputSource ); - uvs.push( uv.x, uv.y ); + } } - } - - } - - } + // Notify connected - TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - TubeBufferGeometry.prototype.constructor = TubeBufferGeometry; + for ( let i = 0; i < event.added.length; i ++ ) { - /** - * @author oosmoxiecode - * @author Mugen87 / https://github.com/Mugen87 - * - * based on http://www.blackpawn.com/texts/pqtorus/ - */ + const inputSource = event.added[ i ]; - // TorusKnotGeometry + let controllerIndex = controllerInputSources.indexOf( inputSource ); - function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) { + if ( controllerIndex === - 1 ) { - Geometry.call( this ); + // Assign input source a controller that currently has no input source - this.type = 'TorusKnotGeometry'; + for ( let i = 0; i < controllers.length; i ++ ) { - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q - }; + if ( i >= controllerInputSources.length ) { - if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); + controllerInputSources.push( inputSource ); + controllerIndex = i; + break; - this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) ); - this.mergeVertices(); + } else if ( controllerInputSources[ i ] === null ) { - } + controllerInputSources[ i ] = inputSource; + controllerIndex = i; + break; - TorusKnotGeometry.prototype = Object.create( Geometry.prototype ); - TorusKnotGeometry.prototype.constructor = TorusKnotGeometry; + } - // TorusKnotBufferGeometry + } - function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) { + // If all controllers do currently receive input we ignore new ones - BufferGeometry.call( this ); + if ( controllerIndex === - 1 ) break; - this.type = 'TorusKnotBufferGeometry'; + } - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q - }; + const controller = controllers[ controllerIndex ]; - radius = radius || 1; - tube = tube || 0.4; - tubularSegments = Math.floor( tubularSegments ) || 64; - radialSegments = Math.floor( radialSegments ) || 8; - p = p || 2; - q = q || 3; + if ( controller ) { - // buffers + controller.connect( inputSource ); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // helper variables + } - var i, j; + } - var vertex = new Vector3(); - var normal = new Vector3(); + // - var P1 = new Vector3(); - var P2 = new Vector3(); + const cameraLPos = new Vector3(); + const cameraRPos = new Vector3(); - var B = new Vector3(); - var T = new Vector3(); - var N = new Vector3(); + /** + * Assumes 2 cameras that are parallel and share an X-axis, and that + * the cameras' projection and world matrices have already been set. + * And that near and far planes are identical for both cameras. + * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 + */ + function setProjectionFromUnion( camera, cameraL, cameraR ) { - // generate vertices, normals and uvs + cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); + cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); - for ( i = 0; i <= tubularSegments; ++ i ) { + const ipd = cameraLPos.distanceTo( cameraRPos ); - // the radian "u" is used to calculate the position on the torus curve of the current tubular segement + const projL = cameraL.projectionMatrix.elements; + const projR = cameraR.projectionMatrix.elements; - var u = i / tubularSegments * p * Math.PI * 2; + // VR systems will have identical far and near planes, and + // most likely identical top and bottom frustum extents. + // Use the left camera for these values. + 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 ]; - // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. - // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions + const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; + const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; + const left = near * leftFov; + const right = near * rightFov; - calculatePositionOnCurve( u, p, q, radius, P1 ); - calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); + // Calculate the new camera's position offset from the + // left camera. xOffset should be roughly half `ipd`. + const zOffset = ipd / ( - leftFov + rightFov ); + const xOffset = zOffset * - leftFov; - // calculate orthonormal basis + // TODO: Better way to apply this offset? + cameraL.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(); - T.subVectors( P2, P1 ); - N.addVectors( P2, P1 ); - B.crossVectors( T, N ); - N.crossVectors( B, T ); + // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // although must now be relative to the new union camera. + 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; - // normalize B, N. T can be ignored, we don't use it + camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); - B.normalize(); - N.normalize(); + } - for ( j = 0; j <= radialSegments; ++ j ) { + function updateCamera( camera, parent ) { - // now calculate the vertices. they are nothing more than an extrusion of the torus curve. - // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. + if ( parent === null ) { - var v = j / radialSegments * Math.PI * 2; - var cx = - tube * Math.cos( v ); - var cy = tube * Math.sin( v ); + camera.matrixWorld.copy( camera.matrix ); - // now calculate the final vertex position. - // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve + } else { - vertex.x = P1.x + ( cx * N.x + cy * B.x ); - vertex.y = P1.y + ( cx * N.y + cy * B.y ); - vertex.z = P1.z + ( cx * N.z + cy * B.z ); + camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); - vertices.push( vertex.x, vertex.y, vertex.z ); + } - // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); - normal.subVectors( vertex, P1 ).normalize(); + } - normals.push( normal.x, normal.y, normal.z ); + this.updateCamera = function ( camera ) { - // uv + if ( session === null ) return; - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); + if ( depthSensing.texture !== null ) { - } + camera.near = depthSensing.depthNear; + camera.far = depthSensing.depthFar; - } + } - // generate indices + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; - for ( j = 1; j <= tubularSegments; j ++ ) { + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { - for ( i = 1; i <= radialSegments; i ++ ) { + // Note that the new renderState won't apply until the next frame. See #18320 - // indices + session.updateRenderState( { + depthNear: cameraXR.near, + depthFar: cameraXR.far + } ); - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; - // faces + cameraL.near = _currentDepthNear; + cameraL.far = _currentDepthFar; + cameraR.near = _currentDepthNear; + cameraR.far = _currentDepthFar; - indices.push( a, b, d ); - indices.push( b, c, d ); + cameraL.updateProjectionMatrix(); + cameraR.updateProjectionMatrix(); + camera.updateProjectionMatrix(); - } + } - } + const parent = camera.parent; + const cameras = cameraXR.cameras; - // build geometry + updateCamera( cameraXR, parent ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + for ( let i = 0; i < cameras.length; i ++ ) { - // this function calculates the current position on the torus curve + updateCamera( cameras[ i ], parent ); - function calculatePositionOnCurve( u, p, q, radius, position ) { + } - var cu = Math.cos( u ); - var su = Math.sin( u ); - var quOverP = q / p * u; - var cs = Math.cos( quOverP ); + // update projection matrix for proper view frustum culling - position.x = radius * ( 2 + cs ) * 0.5 * cu; - position.y = radius * ( 2 + cs ) * su * 0.5; - position.z = radius * Math.sin( quOverP ) * 0.5; + if ( cameras.length === 2 ) { - } + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - } + } else { - TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry; + // assume single camera setup (AR) - /** - * @author oosmoxiecode - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); - // TorusGeometry + } - function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) { + // update user camera and its children - Geometry.call( this ); + updateUserCamera( camera, cameraXR, parent ); - this.type = 'TorusGeometry'; + }; - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; + function updateUserCamera( camera, cameraXR, parent ) { - this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) ); - this.mergeVertices(); + if ( parent === null ) { - } + camera.matrix.copy( cameraXR.matrixWorld ); - TorusGeometry.prototype = Object.create( Geometry.prototype ); - TorusGeometry.prototype.constructor = TorusGeometry; + } else { - // TorusBufferGeometry + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); - function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) { + } - BufferGeometry.call( this ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); - this.type = 'TorusBufferGeometry'; + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; + if ( camera.isPerspectiveCamera ) { - radius = radius || 1; - tube = tube || 0.4; - radialSegments = Math.floor( radialSegments ) || 8; - tubularSegments = Math.floor( tubularSegments ) || 6; - arc = arc || Math.PI * 2; + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - // buffers + } - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // helper variables + this.getCamera = function () { - var center = new Vector3(); - var vertex = new Vector3(); - var normal = new Vector3(); + return cameraXR; - var j, i; + }; - // generate vertices, normals and uvs + this.getFoveation = function () { - for ( j = 0; j <= radialSegments; j ++ ) { + if ( glProjLayer === null && glBaseLayer === null ) { - for ( i = 0; i <= tubularSegments; i ++ ) { + return undefined; - var u = i / tubularSegments * arc; - var v = j / radialSegments * Math.PI * 2; + } - // vertex + return foveation; - vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); - vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); - vertex.z = tube * Math.sin( v ); + }; - vertices.push( vertex.x, vertex.y, vertex.z ); + this.setFoveation = function ( value ) { - // normal + // 0 = no foveation = full resolution + // 1 = maximum foveation = the edges render at lower resolution - center.x = radius * Math.cos( u ); - center.y = radius * Math.sin( u ); - normal.subVectors( vertex, center ).normalize(); + foveation = value; - normals.push( normal.x, normal.y, normal.z ); + if ( glProjLayer !== null ) { - // uv + glProjLayer.fixedFoveation = value; - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); + } - } + if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { - } + glBaseLayer.fixedFoveation = value; - // generate indices + } - for ( j = 1; j <= radialSegments; j ++ ) { + }; - for ( i = 1; i <= tubularSegments; i ++ ) { + this.hasDepthSensing = function () { - // indices + return depthSensing.texture !== null; - var a = ( tubularSegments + 1 ) * j + i - 1; - var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; - var c = ( tubularSegments + 1 ) * ( j - 1 ) + i; - var d = ( tubularSegments + 1 ) * j + i; + }; - // faces + this.getDepthSensingMesh = function () { - indices.push( a, b, d ); - indices.push( b, c, d ); + return depthSensing.getMesh( cameraXR ); - } + }; - } + // Animation Loop - // build geometry + let onAnimationFrameCallback = null; - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + function onAnimationFrame( time, frame ) { - } + pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); + xrFrame = frame; - TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - TorusBufferGeometry.prototype.constructor = TorusBufferGeometry; + if ( pose !== null ) { - /** - * @author Mugen87 / https://github.com/Mugen87 - * Port from https://github.com/mapbox/earcut (v2.1.2) - */ + const views = pose.views; - var Earcut = { + if ( glBaseLayer !== null ) { - triangulate: function ( data, holeIndices, dim ) { + renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); + renderer.setRenderTarget( newRenderTarget ); - dim = dim || 2; + } - var hasHoles = holeIndices && holeIndices.length, - outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length, - outerNode = linkedList( data, 0, outerLen, dim, true ), - triangles = []; + let cameraXRNeedsUpdate = false; - if ( ! outerNode ) return triangles; + // check if it's necessary to rebuild cameraXR's camera list - var minX, minY, maxX, maxY, x, y, invSize; + if ( views.length !== cameraXR.cameras.length ) { - if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; - // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + } - if ( data.length > 80 * dim ) { + for ( let i = 0; i < views.length; i ++ ) { - minX = maxX = data[ 0 ]; - minY = maxY = data[ 1 ]; + const view = views[ i ]; - for ( var i = dim; i < outerLen; i += dim ) { + let viewport = null; - x = data[ i ]; - y = data[ i + 1 ]; - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; + if ( glBaseLayer !== null ) { - } + viewport = glBaseLayer.getViewport( view ); - // minX, minY and invSize are later used to transform coords into integers for z-order calculation + } else { - invSize = Math.max( maxX - minX, maxY - minY ); - invSize = invSize !== 0 ? 1 / invSize : 0; + const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); + viewport = glSubImage.viewport; - } + // For side-by-side projection, we only produce a single texture for both eyes. + if ( i === 0 ) { - earcutLinked( outerNode, triangles, dim, minX, minY, invSize ); + renderer.setRenderTargetTextures( + newRenderTarget, + glSubImage.colorTexture, + glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); - return triangles; + renderer.setRenderTarget( newRenderTarget ); - } + } - }; + } - // create a circular doubly linked list from polygon points in the specified winding order + let camera = cameras[ i ]; - function linkedList( data, start, end, dim, clockwise ) { + if ( camera === undefined ) { - var i, last; + camera = new PerspectiveCamera(); + camera.layers.enable( i ); + camera.viewport = new Vector4(); + cameras[ i ] = camera; - if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { + } - for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); + camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); + camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); - } else { + if ( i === 0 ) { - for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); - } + } - if ( last && equals( last, last.next ) ) { + if ( cameraXRNeedsUpdate === true ) { - removeNode( last ); - last = last.next; + cameraXR.cameras.push( camera ); - } + } - return last; + } - } + // - // eliminate colinear or duplicate points + const enabledFeatures = session.enabledFeatures; - function filterPoints( start, end ) { + if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { - if ( ! start ) return start; - if ( ! end ) end = start; + const depthData = glBinding.getDepthInformation( views[ 0 ] ); - var p = start, again; + if ( depthData && depthData.isValid && depthData.texture ) { - do { + depthSensing.init( renderer, depthData, session.renderState ); - 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; + for ( let i = 0; i < controllers.length; i ++ ) { - } + const inputSource = controllerInputSources[ i ]; + const controller = controllers[ i ]; - } while ( again || p !== end ); + if ( inputSource !== null && controller !== undefined ) { - return end; + controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); - } + } - // main ear slicing loop which triangulates a polygon (given as a linked list) + } - function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); - if ( ! ear ) return; + if ( frame.detectedPlanes ) { - // interlink polygon nodes in z-order + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); - if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); + } - var stop = ear, prev, next; + xrFrame = null; - // iterate through ears, slicing them one by one + } - while ( ear.prev !== ear.next ) { + const animation = new WebGLAnimation(); - prev = ear.prev; - next = ear.next; + animation.setAnimationLoop( onAnimationFrame ); - if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { + this.setAnimationLoop = function ( callback ) { - // cut off the triangle - triangles.push( prev.i / dim ); - triangles.push( ear.i / dim ); - triangles.push( next.i / dim ); + onAnimationFrameCallback = callback; - removeNode( ear ); + }; - // skipping the next vertice leads to less sliver triangles - ear = next.next; - stop = next.next; + this.dispose = function () {}; - continue; + } - } + } - ear = next; + const _e1 = /*@__PURE__*/ new Euler(); + const _m1 = /*@__PURE__*/ new Matrix4(); - // if we looped through the whole remaining polygon and can't find any more ears + function WebGLMaterials( renderer, properties ) { - if ( ear === stop ) { + function refreshTransformUniform( map, uniform ) { - // try filtering points and slicing again + if ( map.matrixAutoUpdate === true ) { - if ( ! pass ) { + map.updateMatrix(); - earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); + } - // if this didn't work, try curing all small self-intersections locally + uniform.value.copy( map.matrix ); - } else if ( pass === 1 ) { + } - ear = cureLocalIntersections( ear, triangles, dim ); - earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); + function refreshFogUniforms( uniforms, fog ) { - // as a last resort, try splitting the remaining polygon into two + fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); - } else if ( pass === 2 ) { + if ( fog.isFog ) { - splitEarcut( ear, triangles, dim, minX, minY, invSize ); + uniforms.fogNear.value = fog.near; + uniforms.fogFar.value = fog.far; - } + } else if ( fog.isFogExp2 ) { - break; + uniforms.fogDensity.value = fog.density; } } - } - - // check whether a polygon node forms a valid ear with adjacent nodes - - function isEar( ear ) { + function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { - var a = ear.prev, - b = ear, - c = ear.next; + if ( material.isMeshBasicMaterial ) { - if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear + refreshUniformsCommon( uniforms, material ); - // now make sure we don't have other points inside the potential ear - var p = ear.next.next; + } else if ( material.isMeshLambertMaterial ) { - while ( p !== ear.prev ) { + refreshUniformsCommon( uniforms, material ); - if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) { + } else if ( material.isMeshToonMaterial ) { - return false; - - } + refreshUniformsCommon( uniforms, material ); + refreshUniformsToon( uniforms, material ); - p = p.next; + } else if ( material.isMeshPhongMaterial ) { - } + refreshUniformsCommon( uniforms, material ); + refreshUniformsPhong( uniforms, material ); - return true; + } else if ( material.isMeshStandardMaterial ) { - } + refreshUniformsCommon( uniforms, material ); + refreshUniformsStandard( uniforms, material ); - function isEarHashed( ear, minX, minY, invSize ) { + if ( material.isMeshPhysicalMaterial ) { - var a = ear.prev, - b = ear, - c = ear.next; + refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); - if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear + } - // triangle bbox; min & max are calculated like this for speed + } else if ( material.isMeshMatcapMaterial ) { - var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ), - minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ), - maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ), - maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y ); + refreshUniformsCommon( uniforms, material ); + refreshUniformsMatcap( uniforms, material ); - // z-order range for the current triangle bbox; + } else if ( material.isMeshDepthMaterial ) { - var minZ = zOrder( minTX, minTY, minX, minY, invSize ), - maxZ = zOrder( maxTX, maxTY, minX, minY, invSize ); + refreshUniformsCommon( uniforms, material ); - // first look for points inside the triangle in increasing z-order + } else if ( material.isMeshDistanceMaterial ) { - var p = ear.nextZ; + refreshUniformsCommon( uniforms, material ); + refreshUniformsDistance( uniforms, material ); - while ( p && p.z <= maxZ ) { + } else if ( material.isMeshNormalMaterial ) { - if ( p !== ear.prev && p !== ear.next && - pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && - area( p.prev, p, p.next ) >= 0 ) return false; - p = p.nextZ; + refreshUniformsCommon( uniforms, material ); - } + } else if ( material.isLineBasicMaterial ) { - // then look for points in decreasing z-order + refreshUniformsLine( uniforms, material ); - p = ear.prevZ; + if ( material.isLineDashedMaterial ) { - while ( p && p.z >= minZ ) { + refreshUniformsDash( uniforms, material ); - if ( p !== ear.prev && p !== ear.next && - pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && - area( p.prev, p, p.next ) >= 0 ) return false; + } - p = p.prevZ; + } else if ( material.isPointsMaterial ) { - } + refreshUniformsPoints( uniforms, material, pixelRatio, height ); - return true; + } else if ( material.isSpriteMaterial ) { - } + refreshUniformsSprites( uniforms, material ); - // go through all polygon nodes and cure small local self-intersections + } else if ( material.isShadowMaterial ) { - function cureLocalIntersections( start, triangles, dim ) { + uniforms.color.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - var p = start; + } else if ( material.isShaderMaterial ) { - do { + material.uniformsNeedUpdate = false; // #15581 - var a = p.prev, b = p.next.next; + } - if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { + } - triangles.push( a.i / dim ); - triangles.push( p.i / dim ); - triangles.push( b.i / dim ); + function refreshUniformsCommon( uniforms, material ) { - // remove two nodes involved + uniforms.opacity.value = material.opacity; - removeNode( p ); - removeNode( p.next ); + if ( material.color ) { - p = start = b; + uniforms.diffuse.value.copy( material.color ); } - p = p.next; - - } while ( p !== start ); + if ( material.emissive ) { - return p; + uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); - } + } - // try splitting polygon into two and triangulate them independently + if ( material.map ) { - function splitEarcut( start, triangles, dim, minX, minY, invSize ) { + uniforms.map.value = material.map; - // look for a valid diagonal that divides the polygon into two + refreshTransformUniform( material.map, uniforms.mapTransform ); - var a = start; + } - do { + if ( material.alphaMap ) { - var b = a.next.next; + uniforms.alphaMap.value = material.alphaMap; - while ( b !== a.prev ) { + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - if ( a.i !== b.i && isValidDiagonal( a, b ) ) { + } - // split the polygon in two by the diagonal + if ( material.bumpMap ) { - var c = splitPolygon( a, b ); + uniforms.bumpMap.value = material.bumpMap; - // filter colinear points around the cuts + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); - a = filterPoints( a, a.next ); - c = filterPoints( c, c.next ); + uniforms.bumpScale.value = material.bumpScale; - // run earcut on each half + if ( material.side === BackSide ) { - earcutLinked( a, triangles, dim, minX, minY, invSize ); - earcutLinked( c, triangles, dim, minX, minY, invSize ); - return; + uniforms.bumpScale.value *= - 1; } - b = b.next; - } - a = a.next; - - } while ( a !== start ); + if ( material.normalMap ) { - } + uniforms.normalMap.value = material.normalMap; - // link every hole into the outer loop, producing a single-ring polygon without holes + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); - function eliminateHoles( data, holeIndices, outerNode, dim ) { + uniforms.normalScale.value.copy( material.normalScale ); - var queue = [], i, len, start, end, list; + if ( material.side === BackSide ) { - for ( i = 0, len = holeIndices.length; i < len; i ++ ) { + uniforms.normalScale.value.negate(); - start = holeIndices[ i ] * dim; - end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; - list = linkedList( data, start, end, dim, false ); - if ( list === list.next ) list.steiner = true; - queue.push( getLeftmost( list ) ); + } - } + } - queue.sort( compareX ); + if ( material.displacementMap ) { - // process holes from left to right + uniforms.displacementMap.value = material.displacementMap; - for ( i = 0; i < queue.length; i ++ ) { + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); - eliminateHole( queue[ i ], outerNode ); - outerNode = filterPoints( outerNode, outerNode.next ); + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; - } + } - return outerNode; + if ( material.emissiveMap ) { - } + uniforms.emissiveMap.value = material.emissiveMap; - function compareX( a, b ) { + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); - return a.x - b.x; + } - } + if ( material.specularMap ) { - // find a bridge between vertices that connects hole with an outer ring and and link it + uniforms.specularMap.value = material.specularMap; - function eliminateHole( hole, outerNode ) { + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); - outerNode = findHoleBridge( hole, outerNode ); + } - if ( outerNode ) { + if ( material.alphaTest > 0 ) { - var b = splitPolygon( outerNode, hole ); + uniforms.alphaTest.value = material.alphaTest; - filterPoints( b, b.next ); + } - } + const materialProperties = properties.get( material ); - } + const envMap = materialProperties.envMap; + const envMapRotation = materialProperties.envMapRotation; - // David Eberly's algorithm for finding a bridge between hole and outer polygon + if ( envMap ) { - function findHoleBridge( hole, outerNode ) { + uniforms.envMap.value = envMap; - var p = outerNode, - hx = hole.x, - hy = hole.y, - qx = - Infinity, - m; + _e1.copy( envMapRotation ); - // find a segment intersected by a ray from the hole's leftmost point to the left; - // segment's endpoint with lesser x will be potential connection point + // accommodate left-handed frame + _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1; - do { + if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) { - if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { + // environment maps which are not cube render targets or PMREMs follow a different convention + _e1.y *= - 1; + _e1.z *= - 1; - var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); + } - if ( x <= hx && x > qx ) { + uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) ); - qx = x; + uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - if ( x === hx ) { + uniforms.reflectivity.value = material.reflectivity; + uniforms.ior.value = material.ior; + uniforms.refractionRatio.value = material.refractionRatio; - if ( hy === p.y ) return p; - if ( hy === p.next.y ) return p.next; + } - } + if ( material.lightMap ) { - m = p.x < p.next.x ? p : p.next; + uniforms.lightMap.value = material.lightMap; + uniforms.lightMapIntensity.value = material.lightMapIntensity; - } + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); } - p = p.next; - - } while ( p !== outerNode ); + if ( material.aoMap ) { - if ( ! m ) return null; + uniforms.aoMap.value = material.aoMap; + uniforms.aoMapIntensity.value = material.aoMapIntensity; - if ( hx === qx ) return m.prev; // hole touches outer segment; pick lower endpoint + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); - // look for points inside the triangle of hole point, segment intersection and endpoint; - // if there are no points found, we have a valid connection; - // otherwise choose the point of the minimum angle with the ray as connection point + } - var stop = m, - mx = m.x, - my = m.y, - tanMin = Infinity, - tan; + } - p = m.next; + function refreshUniformsLine( uniforms, material ) { - while ( p !== stop ) { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - 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 ) ) { + if ( material.map ) { - tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential + uniforms.map.value = material.map; - if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) { + refreshTransformUniform( material.map, uniforms.mapTransform ); - m = p; - tanMin = tan; + } - } + } - } + function refreshUniformsDash( uniforms, material ) { - p = p.next; + uniforms.dashSize.value = material.dashSize; + uniforms.totalSize.value = material.dashSize + material.gapSize; + uniforms.scale.value = material.scale; } - return m; + 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; - // interlink polygon nodes in z-order + if ( material.map ) { - function indexCurve( start, minX, minY, invSize ) { + uniforms.map.value = material.map; - var p = start; + refreshTransformUniform( material.map, uniforms.uvTransform ); - 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; + if ( material.alphaMap ) { - } while ( p !== start ); + uniforms.alphaMap.value = material.alphaMap; - p.prevZ.nextZ = null; - p.prevZ = null; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - sortLinked( p ); + } - } - - // Simon Tatham's linked list merge sort algorithm - // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html + if ( material.alphaTest > 0 ) { - function sortLinked( list ) { + uniforms.alphaTest.value = material.alphaTest; - var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; - - do { + } - p = list; - list = null; - tail = null; - numMerges = 0; + } - while ( p ) { + function refreshUniformsSprites( uniforms, material ) { - numMerges ++; - q = p; - pSize = 0; + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; + uniforms.rotation.value = material.rotation; - for ( i = 0; i < inSize; i ++ ) { + if ( material.map ) { - pSize ++; - q = q.nextZ; - if ( ! q ) break; + uniforms.map.value = material.map; - } + refreshTransformUniform( material.map, uniforms.mapTransform ); - qSize = inSize; + } - while ( pSize > 0 || ( qSize > 0 && q ) ) { + if ( material.alphaMap ) { - if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { + uniforms.alphaMap.value = material.alphaMap; - e = p; - p = p.nextZ; - pSize --; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); - } else { + } - e = q; - q = q.nextZ; - qSize --; + if ( material.alphaTest > 0 ) { - } + uniforms.alphaTest.value = material.alphaTest; - if ( tail ) tail.nextZ = e; - else list = e; + } - e.prevZ = tail; - tail = e; + } - } + function refreshUniformsPhong( uniforms, material ) { - p = q; + uniforms.specular.value.copy( material.specular ); + uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) - } + } - tail.nextZ = null; - inSize *= 2; + function refreshUniformsToon( uniforms, material ) { - } while ( numMerges > 1 ); + if ( material.gradientMap ) { - return list; + uniforms.gradientMap.value = material.gradientMap; - } + } - // z-order of a point given coords and inverse of the longer side of data bbox + } - function zOrder( x, y, minX, minY, invSize ) { + function refreshUniformsStandard( uniforms, material ) { - // coords are transformed into non-negative 15-bit integer range + uniforms.metalness.value = material.metalness; - x = 32767 * ( x - minX ) * invSize; - y = 32767 * ( y - minY ) * invSize; + if ( material.metalnessMap ) { - x = ( x | ( x << 8 ) ) & 0x00FF00FF; - x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; - x = ( x | ( x << 2 ) ) & 0x33333333; - x = ( x | ( x << 1 ) ) & 0x55555555; + uniforms.metalnessMap.value = material.metalnessMap; - y = ( y | ( y << 8 ) ) & 0x00FF00FF; - y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; - y = ( y | ( y << 2 ) ) & 0x33333333; - y = ( y | ( y << 1 ) ) & 0x55555555; + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); - return x | ( y << 1 ); + } - } + uniforms.roughness.value = material.roughness; - // find the leftmost node of a polygon ring + if ( material.roughnessMap ) { - function getLeftmost( start ) { + uniforms.roughnessMap.value = material.roughnessMap; - var p = start, leftmost = start; + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); - do { + } - if ( p.x < leftmost.x ) leftmost = p; - p = p.next; + if ( material.envMap ) { - } while ( p !== start ); + //uniforms.envMap.value = material.envMap; // part of uniforms common - return leftmost; + uniforms.envMapIntensity.value = material.envMapIntensity; - } + } - // check if a point lies within a convex triangle + } - function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { + function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { - return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 && - ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 && - ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0; + uniforms.ior.value = material.ior; // also part of uniforms common - } + if ( material.sheen > 0 ) { - // check if a diagonal between two polygon nodes is valid (lies in polygon interior) + uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); - function isValidDiagonal( a, b ) { + uniforms.sheenRoughness.value = material.sheenRoughness; - return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && - locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ); + if ( material.sheenColorMap ) { - } + uniforms.sheenColorMap.value = material.sheenColorMap; - // signed area of a triangle + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); - function area( p, q, r ) { + } - return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); + if ( material.sheenRoughnessMap ) { - } + uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; - // check if two points are equal + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); - function equals( p1, p2 ) { + } - return p1.x === p2.x && p1.y === p2.y; + } - } + if ( material.clearcoat > 0 ) { - // check if two segments intersect + uniforms.clearcoat.value = material.clearcoat; + uniforms.clearcoatRoughness.value = material.clearcoatRoughness; - function intersects( p1, q1, p2, q2 ) { + if ( material.clearcoatMap ) { - if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) || - ( equals( p1, q2 ) && equals( p2, q1 ) ) ) return true; + uniforms.clearcoatMap.value = material.clearcoatMap; - return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 && - area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0; + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); - } + } - // check if a polygon diagonal intersects any polygon segments + if ( material.clearcoatRoughnessMap ) { - function intersectsPolygon( a, b ) { + uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; - var p = a; + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); - do { + } - if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && - intersects( p, p.next, a, b ) ) { + if ( material.clearcoatNormalMap ) { - return true; + uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; - } + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); - p = p.next; + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); - } while ( p !== a ); + if ( material.side === BackSide ) { - return false; + uniforms.clearcoatNormalScale.value.negate(); - } + } - // check if a polygon diagonal is locally inside the polygon + } - function locallyInside( a, b ) { + } - return area( a.prev, a, a.next ) < 0 ? - area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : - area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; + if ( material.dispersion > 0 ) { - } + uniforms.dispersion.value = material.dispersion; - // check if the middle point of a polygon diagonal is inside the polygon + } - function middleInside( a, b ) { + if ( material.iridescence > 0 ) { - var p = a, - inside = false, - px = ( a.x + b.x ) / 2, - py = ( a.y + b.y ) / 2; + uniforms.iridescence.value = material.iridescence; + uniforms.iridescenceIOR.value = material.iridescenceIOR; + uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ]; + uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ]; - do { + if ( material.iridescenceMap ) { - if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && - ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) { + uniforms.iridescenceMap.value = material.iridescenceMap; - inside = ! inside; + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); - } + } - p = p.next; + if ( material.iridescenceThicknessMap ) { - } while ( p !== a ); + uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; - return inside; + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); - } + } - // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; - // if one belongs to the outer ring and another to a hole, it merges it into a single ring + } - function splitPolygon( a, b ) { + if ( material.transmission > 0 ) { - var a2 = new Node( a.i, a.x, a.y ), - b2 = new Node( b.i, b.x, b.y ), - an = a.next, - bp = b.prev; + uniforms.transmission.value = material.transmission; + uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; + uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); - a.next = b; - b.prev = a; + if ( material.transmissionMap ) { - a2.next = an; - an.prev = a2; + uniforms.transmissionMap.value = material.transmissionMap; - b2.next = a2; - a2.prev = b2; + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); - bp.next = b2; - b2.prev = bp; + } - return b2; + uniforms.thickness.value = material.thickness; - } + if ( material.thicknessMap ) { - // create a node and optionally link it with previous one (in a circular doubly linked list) + uniforms.thicknessMap.value = material.thicknessMap; - function insertNode( i, x, y, last ) { + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); - var p = new Node( i, x, y ); + } - if ( ! last ) { + uniforms.attenuationDistance.value = material.attenuationDistance; + uniforms.attenuationColor.value.copy( material.attenuationColor ); - p.prev = p; - p.next = p; + } - } else { + if ( material.anisotropy > 0 ) { - p.next = last.next; - p.prev = last; - last.next.prev = p; - last.next = p; + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - } + if ( material.anisotropyMap ) { - return p; + uniforms.anisotropyMap.value = material.anisotropyMap; - } + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); - 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; + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); - } + if ( material.specularColorMap ) { - function Node( i, x, y ) { + uniforms.specularColorMap.value = material.specularColorMap; - // vertice index in coordinates array - this.i = i; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); - // vertex coordinates - this.x = x; - this.y = y; + } - // previous and next vertice nodes in a polygon ring - this.prev = null; - this.next = null; + if ( material.specularIntensityMap ) { - // z-order curve value - this.z = null; + uniforms.specularIntensityMap.value = material.specularIntensityMap; - // previous and next nodes in z-order - this.prevZ = null; - this.nextZ = null; + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); - // indicates whether this is a steiner point - this.steiner = false; + } - } + } - function signedArea( data, start, end, dim ) { + function refreshUniformsMatcap( uniforms, material ) { - var sum = 0; + if ( material.matcap ) { - for ( var i = start, j = end - dim; i < end; i += dim ) { + uniforms.matcap.value = material.matcap; - sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); - j = i; + } } - return sum; + function refreshUniformsDistance( uniforms, material ) { - } + const light = properties.get( material ).light; - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - */ + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; - var ShapeUtils = { + } - // calculate area of the contour polygon + return { + refreshFogUniforms: refreshFogUniforms, + refreshMaterialUniforms: refreshMaterialUniforms + }; - area: function ( contour ) { + } - var n = contour.length; - var a = 0.0; + function WebGLUniformsGroups( gl, info, capabilities, state ) { - for ( var p = n - 1, q = 0; q < n; p = q ++ ) { + let buffers = {}; + let updateList = {}; + let allocatedBindingPoints = []; - a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; + const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program - } + function bind( uniformsGroup, program ) { - return a * 0.5; + const webglProgram = program.program; + state.uniformBlockBinding( uniformsGroup, webglProgram ); - }, + } - isClockWise: function ( pts ) { + function update( uniformsGroup, program ) { - return ShapeUtils.area( pts ) < 0; + let buffer = buffers[ uniformsGroup.id ]; - }, + if ( buffer === undefined ) { - triangulateShape: function ( contour, holes ) { + prepareUniformsGroup( uniformsGroup ); - function removeDupEndPts( points ) { + buffer = createBuffer( uniformsGroup ); + buffers[ uniformsGroup.id ] = buffer; - var l = points.length; + uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); - if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { + } - points.pop(); + // ensure to update the binding points/block indices mapping for this program - } + const webglProgram = program.program; + state.updateUBOMapping( uniformsGroup, webglProgram ); - } + // update UBO once per frame - function addContour( vertices, contour ) { + const frame = info.render.frame; - for ( var i = 0; i < contour.length; i ++ ) { + if ( updateList[ uniformsGroup.id ] !== frame ) { - vertices.push( contour[ i ].x ); - vertices.push( contour[ i ].y ); + updateBufferData( uniformsGroup ); - } + updateList[ uniformsGroup.id ] = frame; } - var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] - var holeIndices = []; // array of hole indices - var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] + } - removeDupEndPts( contour ); - addContour( vertices, contour ); + function createBuffer( uniformsGroup ) { - // + // the setup of an UBO is independent of a particular shader program but global - var holeIndex = contour.length; - holes.forEach( removeDupEndPts ); + const bindingPointIndex = allocateBindingPointIndex(); + uniformsGroup.__bindingPointIndex = bindingPointIndex; - for ( i = 0; i < holes.length; i ++ ) { + const buffer = gl.createBuffer(); + const size = uniformsGroup.__size; + const usage = uniformsGroup.usage; - holeIndices.push( holeIndex ); - holeIndex += holes[ i ].length; - addContour( vertices, holes[ i ] ); + 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; - // + } - var triangles = Earcut.triangulate( vertices, holeIndices ); + function allocateBindingPointIndex() { - // + for ( let i = 0; i < maxBindingPoints; i ++ ) { - for ( var i = 0; i < triangles.length; i += 3 ) { + if ( allocatedBindingPoints.indexOf( i ) === - 1 ) { - faces.push( triangles.slice( i, i + 3 ) ); + allocatedBindingPoints.push( i ); + return i; + + } } - return faces; + console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); + + return 0; } - }; + function updateBufferData( uniformsGroup ) { - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Creates extruded geometry from a path shape. - * - * parameters = { - * - * curveSegments: , // number of points on the curves - * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too - * amount: , // Depth to extrude the shape - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into the original shape bevel goes - * bevelSize: , // how far from shape outline is bevel - * bevelSegments: , // number of bevel layers - * - * extrudePath: // curve to extrude shape along - * frames: // containing arrays of tangents, normals, binormals - * - * UVGenerator: // object that provides UV generator functions - * - * } - */ + const buffer = buffers[ uniformsGroup.id ]; + const uniforms = uniformsGroup.uniforms; + const cache = uniformsGroup.__cache; - // ExtrudeGeometry + gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); - function ExtrudeGeometry( shapes, options ) { + for ( let i = 0, il = uniforms.length; i < il; i ++ ) { - Geometry.call( this ); + const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; - this.type = 'ExtrudeGeometry'; + for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { - this.parameters = { - shapes: shapes, - options: options - }; + const uniform = uniformArray[ j ]; - this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) ); - this.mergeVertices(); + if ( hasUniformChanged( uniform, i, j, cache ) === true ) { - } + const offset = uniform.__offset; - ExtrudeGeometry.prototype = Object.create( Geometry.prototype ); - ExtrudeGeometry.prototype.constructor = ExtrudeGeometry; + const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; - // ExtrudeBufferGeometry + let arrayOffset = 0; - function ExtrudeBufferGeometry( shapes, options ) { + for ( let k = 0; k < values.length; k ++ ) { - if ( typeof ( shapes ) === "undefined" ) { + const value = values[ k ]; - return; + const info = getUniformSize( value ); - } + // TODO add integer and struct support + if ( typeof value === 'number' || typeof value === 'boolean' ) { + + uniform.__data[ 0 ] = value; + gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); - BufferGeometry.call( this ); + } else if ( value.isMatrix3 ) { - this.type = 'ExtrudeBufferGeometry'; + // manually converting 3x3 to 3x4 - shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; + uniform.__data[ 0 ] = value.elements[ 0 ]; + uniform.__data[ 1 ] = value.elements[ 1 ]; + uniform.__data[ 2 ] = value.elements[ 2 ]; + uniform.__data[ 3 ] = 0; + uniform.__data[ 4 ] = value.elements[ 3 ]; + uniform.__data[ 5 ] = value.elements[ 4 ]; + uniform.__data[ 6 ] = value.elements[ 5 ]; + uniform.__data[ 7 ] = 0; + uniform.__data[ 8 ] = value.elements[ 6 ]; + uniform.__data[ 9 ] = value.elements[ 7 ]; + uniform.__data[ 10 ] = value.elements[ 8 ]; + uniform.__data[ 11 ] = 0; - this.addShapeList( shapes, options ); + } else { - this.computeVertexNormals(); + value.toArray( uniform.__data, arrayOffset ); - // can't really use automatic vertex normals - // as then front and back sides get smoothed too - // should do separate smoothing just for sides + arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; - //this.computeVertexNormals(); + } - //console.log( "took", ( Date.now() - startTime ) ); + } - } + gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); - ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry; + } - ExtrudeBufferGeometry.prototype.getArrays = function () { + } - var positionAttribute = this.getAttribute( "position" ); - var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : []; + } - var uvAttribute = this.getAttribute( "uv" ); - var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : []; + gl.bindBuffer( gl.UNIFORM_BUFFER, null ); - var IndexAttribute = this.index; - var indicesArray = IndexAttribute ? Array.prototype.slice.call( IndexAttribute.array ) : []; + } - return { - position: verticesArray, - uv: uvArray, - index: indicesArray - }; + function hasUniformChanged( uniform, index, indexArray, cache ) { - }; + const value = uniform.value; + const indexString = index + '_' + indexArray; - ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) { + if ( cache[ indexString ] === undefined ) { - var sl = shapes.length; - options.arrays = this.getArrays(); + // cache entry does not exist so far - for ( var s = 0; s < sl; s ++ ) { + if ( typeof value === 'number' || typeof value === 'boolean' ) { - var shape = shapes[ s ]; - this.addShape( shape, options ); + cache[ indexString ] = value; - } + } else { - this.setIndex( options.arrays.index ); - this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) ); + cache[ indexString ] = value.clone(); - }; + } - ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) { + return true; - var arrays = options.arrays ? options.arrays : this.getArrays(); - var verticesArray = arrays.position; - var indicesArray = arrays.index; - var uvArray = arrays.uv; + } else { - var placeholder = []; + const cachedObject = cache[ indexString ]; + // compare current value with cached entry - var amount = options.amount !== undefined ? options.amount : 100; + if ( typeof value === 'number' || typeof value === 'boolean' ) { - var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10 - var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8 - var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; + if ( cachedObject !== value ) { - var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false + cache[ indexString ] = value; + return true; - var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; + } - var steps = options.steps !== undefined ? options.steps : 1; + } else { - var extrudePath = options.extrudePath; - var extrudePts, extrudeByPath = false; + if ( cachedObject.equals( value ) === false ) { - // Use default WorldUVGenerator if no UV generators are specified. - var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator; + cachedObject.copy( value ); + return true; - var splineTube, binormal, normal, position2; - if ( extrudePath ) { + } - extrudePts = extrudePath.getSpacedPoints( steps ); + } - extrudeByPath = true; - bevelEnabled = false; // bevels not supported for path extrusion + } - // SETUP TNB variables + return false; - // TODO1 - have a .isClosed in spline? + } - splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false ); + function prepareUniformsGroup( uniformsGroup ) { - // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); + // determine total buffer size according to the STD140 layout + // Hint: STD140 is the only supported layout in WebGL 2 - binormal = new Vector3(); - normal = new Vector3(); - position2 = new Vector3(); + const uniforms = uniformsGroup.uniforms; - } + let offset = 0; // global buffer offset in bytes + const chunkSize = 16; // size of a chunk in bytes - // Safeguards if bevels are not enabled + for ( let i = 0, l = uniforms.length; i < l; i ++ ) { - if ( ! bevelEnabled ) { + const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; - bevelSegments = 0; - bevelThickness = 0; - bevelSize = 0; + for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { - } + const uniform = uniformArray[ j ]; - // Variables initialization + const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; - var ahole, h, hl; // looping of holes - var scope = this; + for ( let k = 0, kl = values.length; k < kl; k ++ ) { - var shapePoints = shape.extractPoints( curveSegments ); + const value = values[ k ]; - var vertices = shapePoints.shape; - var holes = shapePoints.holes; + const info = getUniformSize( value ); - var reverse = ! ShapeUtils.isClockWise( vertices ); + const chunkOffset = offset % chunkSize; // offset in the current chunk + const chunkPadding = chunkOffset % info.boundary; // required padding to match boundary + const chunkStart = chunkOffset + chunkPadding; // the start position in the current chunk for the data - if ( reverse ) { + offset += chunkPadding; - vertices = vertices.reverse(); + // Check for chunk overflow + if ( chunkStart !== 0 && ( chunkSize - chunkStart ) < info.storage ) { - // Maybe we should also check if holes are in the opposite direction, just to be safe ... + // Add padding and adjust offset + offset += ( chunkSize - chunkStart ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + } - ahole = holes[ h ]; + // the following two properties will be used for partial buffer updates + uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT ); + uniform.__offset = offset; - if ( ShapeUtils.isClockWise( ahole ) ) { + // Update the global offset + offset += info.storage; - holes[ h ] = ahole.reverse(); + } } } - } - + // ensure correct final padding - var faces = ShapeUtils.triangulateShape( vertices, holes ); + const chunkOffset = offset % chunkSize; - /* Vertices */ + if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); - var contour = vertices; // vertices has all points but contour has only points of circumference - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + // - ahole = holes[ h ]; + uniformsGroup.__size = offset; + uniformsGroup.__cache = {}; - vertices = vertices.concat( ahole ); + return this; } + function getUniformSize( value ) { - function scalePt2( pt, vec, size ) { + const info = { + boundary: 0, // bytes + storage: 0 // bytes + }; - if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" ); + // determine sizes according to STD140 - return vec.clone().multiplyScalar( size ).add( pt ); + if ( typeof value === 'number' || typeof value === 'boolean' ) { - } + // float/int/bool - var b, bs, t, z, - vert, vlen = vertices.length, - face, flen = faces.length; + info.boundary = 4; + info.storage = 4; + } else if ( value.isVector2 ) { - // Find directions for point movement + // vec2 + info.boundary = 8; + info.storage = 8; - function getBevelVec( inPt, inPrev, inNext ) { + } else if ( value.isVector3 || value.isColor ) { - // computes for inPt the corresponding point inPt' on a new contour - // shifted by 1 unit (length of normalized vector) to the left - // if we walk along contour clockwise, this new contour is outside the old one - // - // inPt' is the intersection of the two lines parallel to the two - // adjacent edges of inPt at a distance of 1 unit on the left side. + // vec3 - var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt + info.boundary = 16; + info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes - // good reading for geometry algorithms (here: line-line intersection) - // http://geomalgorithms.com/a05-_intersect-1.html + } else if ( value.isVector4 ) { - var v_prev_x = inPt.x - inPrev.x, - v_prev_y = inPt.y - inPrev.y; - var v_next_x = inNext.x - inPt.x, - v_next_y = inNext.y - inPt.y; + // vec4 - var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); + info.boundary = 16; + info.storage = 16; - // check for collinear edges - var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); + } else if ( value.isMatrix3 ) { - if ( Math.abs( collinear0 ) > Number.EPSILON ) { + // mat3 (in STD140 a 3x3 matrix is represented as 3x4) - // not collinear + info.boundary = 48; + info.storage = 48; - // length of vectors for normalizing + } else if ( value.isMatrix4 ) { - var v_prev_len = Math.sqrt( v_prev_lensq ); - var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); + // mat4 - // shift adjacent points by unit vectors to the left + info.boundary = 64; + info.storage = 64; - var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); - var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); + } else if ( value.isTexture ) { - var ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); - var ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); + console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); - // scaling factor for v_prev to intersection point + } else { - var 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 ); + console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); - // vector from inPt to intersection point + } - v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); - v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); + return info; - // Don't normalize!, otherwise sharp corners become ugly - // but prevent crazy spikes - var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); - if ( v_trans_lensq <= 2 ) { + } - return new Vector2( v_trans_x, v_trans_y ); + function onUniformsGroupsDispose( event ) { - } else { + const uniformsGroup = event.target; - shrink_by = Math.sqrt( v_trans_lensq / 2 ); + uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); - } + const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); + allocatedBindingPoints.splice( index, 1 ); - } else { + gl.deleteBuffer( buffers[ uniformsGroup.id ] ); - // handle special case of collinear edges + delete buffers[ uniformsGroup.id ]; + delete updateList[ uniformsGroup.id ]; - var direction_eq = false; // assumes: opposite - if ( v_prev_x > Number.EPSILON ) { + } - if ( v_next_x > Number.EPSILON ) { + function dispose() { - direction_eq = true; + for ( const id in buffers ) { - } + gl.deleteBuffer( buffers[ id ] ); - } else { + } - if ( v_prev_x < - Number.EPSILON ) { + allocatedBindingPoints = []; + buffers = {}; + updateList = {}; - if ( v_next_x < - Number.EPSILON ) { + } - direction_eq = true; + return { - } + bind: bind, + update: update, - } else { + dispose: dispose - if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { + }; - direction_eq = true; + } - } + class WebGLRenderer { - } + constructor( parameters = {} ) { - } + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = false, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; - if ( direction_eq ) { + this.isWebGLRenderer = true; - // console.log("Warning: lines are a straight sequence"); - v_trans_x = - v_prev_y; - v_trans_y = v_prev_x; - shrink_by = Math.sqrt( v_prev_lensq ); + let _alpha; - } else { + if ( context !== null ) { - // console.log("Warning: lines are a straight spike"); - v_trans_x = v_prev_x; - v_trans_y = v_prev_y; - shrink_by = Math.sqrt( v_prev_lensq / 2 ); + if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) { + + throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' ); } - } + _alpha = context.getContextAttributes().alpha; - return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); + } else { - } + _alpha = alpha; + } - var contourMovements = []; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + let currentRenderList = null; + let currentRenderState = null; - if ( j === il ) j = 0; - if ( k === il ) k = 0; + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - // (j)---(i)---(k) - // console.log('i,j,k', i, j , k) + const renderListStack = []; + const renderStateStack = []; - contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); + // public properties - } + this.domElement = canvas; - var holesMovements = [], - oneHoleMovements, verticesMovements = contourMovements.concat(); + // Debug configuration container + this.debug = { - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - ahole = holes[ h ]; + // clearing - oneHoleMovements = []; + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; - for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + // scene graph - if ( j === il ) j = 0; - if ( k === il ) k = 0; + this.sortObjects = true; - // (j)---(i)---(k) - oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); + // user-defined clipping - } + this.clippingPlanes = []; + this.localClippingEnabled = false; - holesMovements.push( oneHoleMovements ); - verticesMovements = verticesMovements.concat( oneHoleMovements ); + // physically based shading - } + this._outputColorSpace = SRGBColorSpace; + // tone mapping - // Loop bevelSegments, 1 for the front, 1 for the back + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - for ( b = 0; b < bevelSegments; b ++ ) { + // internal properties - //for ( b = bevelSegments; b > 0; b -- ) { + const _this = this; - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); + let _isContextLost = false; - // contract shape + // internal state cache - for ( i = 0, il = contour.length; i < il; i ++ ) { + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); + let _currentCamera = null; - v( vert.x, vert.y, - z ); + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - } + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - // expand holes + // - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + let _width = canvas.width; + let _height = canvas.height; - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - for ( i = 0, il = ahole.length; i < il; i ++ ) { + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + // frustum - v( vert.x, vert.y, - z ); + const _frustum = new Frustum(); - } + // clipping - } + let _clippingEnabled = false; + let _localClippingEnabled = false; - } + // camera matrices cache - bs = bevelSize; + const _projScreenMatrix = new Matrix4(); - // Back facing vertices + const _vector3 = new Vector3(); - for ( i = 0; i < vlen; i ++ ) { + const _vector4 = new Vector4(); - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - if ( ! extrudeByPath ) { + let _renderBackground = false; - v( vert.x, vert.y, 0 ); + function getTargetPixelRatio() { - } else { + return _currentRenderTarget === null ? _pixelRatio : 1; + + } - // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); + // initialize - normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); + let _gl = context; - position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); + function getContext( contextName, contextAttributes ) { - v( position2.x, position2.y, position2.z ); + return canvas.getContext( contextName, contextAttributes ); } - } + try { + + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - // Add stepped vertices... - // Including front facing vertices + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - var s; + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - for ( s = 1; s <= steps; s ++ ) { + if ( _gl === null ) { - for ( i = 0; i < vlen; i ++ ) { + const contextName = 'webgl2'; - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; + _gl = getContext( contextName, contextAttributes ); - if ( ! extrudeByPath ) { + if ( _gl === null ) { - v( vert.x, vert.y, amount / steps * s ); + if ( getContext( contextName ) ) { - } else { + throw new Error( 'Error creating WebGL context with your selected attributes.' ); - // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); + } else { - normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); + throw new Error( 'Error creating WebGL context.' ); - position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); + } - v( position2.x, position2.y, position2.z ); + } } - } + } catch ( error ) { - } + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; + } - // Add bevel segments planes + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; - //for ( b = 1; b <= bevelSegments; b ++ ) { - for ( b = bevelSegments - 1; b >= 0; b -- ) { + let background, morphtargets, bufferRenderer, indexedBufferRenderer; - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); + let utils, bindingStates, uniformsGroups; - // contract shape + function initGLContext() { - for ( i = 0, il = contour.length; i < il; i ++ ) { + extensions = new WebGLExtensions( _gl ); + extensions.init(); - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); - v( vert.x, vert.y, amount + z ); + utils = new WebGLUtils( _gl, extensions ); - } + capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils ); - // expand holes + state = new WebGLState( _gl ); - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + info = new WebGLInfo( _gl ); + 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 ); + bindingStates = new WebGLBindingStates( _gl, attributes ); + 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 ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info ); - for ( i = 0, il = ahole.length; i < il; i ++ ) { + info.programs = programCache.programs; - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; - if ( ! extrudeByPath ) { + } - v( vert.x, vert.y, amount + z ); + initGLContext(); - } else { + // xr - v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); + const xr = new WebXRManager( _this, _gl ); - } + this.xr = xr; - } + // API - } + this.getContext = function () { - } + return _gl; - /* Faces */ + }; - // Top and bottom faces + this.getContextAttributes = function () { - buildLidFaces(); + return _gl.getContextAttributes(); - // Sides faces + }; - buildSideFaces(); + this.forceContextLoss = function () { + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); - ///// Internal functions + }; - function buildLidFaces() { + this.forceContextRestore = function () { - var start = verticesArray.length / 3; + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); - if ( bevelEnabled ) { + }; - var layer = 0; // steps + 1 - var offset = vlen * layer; + this.getPixelRatio = function () { - // Bottom faces + return _pixelRatio; - for ( i = 0; i < flen; i ++ ) { + }; - face = faces[ i ]; - f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); + this.setPixelRatio = function ( value ) { - } + if ( value === undefined ) return; - layer = steps + bevelSegments * 2; - offset = vlen * layer; + _pixelRatio = value; - // Top faces + this.setSize( _width, _height, false ); - for ( i = 0; i < flen; i ++ ) { + }; - face = faces[ i ]; - f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); + this.getSize = function ( target ) { - } + return target.set( _width, _height ); - } else { + }; - // Bottom faces + this.setSize = function ( width, height, updateStyle = true ) { - for ( i = 0; i < flen; i ++ ) { + if ( xr.isPresenting ) { - face = faces[ i ]; - f3( face[ 2 ], face[ 1 ], face[ 0 ] ); + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; } - // Top faces + _width = width; + _height = height; - for ( i = 0; i < flen; i ++ ) { + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); - face = faces[ i ]; - f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); + if ( updateStyle === true ) { + + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; } - } + this.setViewport( 0, 0, width, height ); - scope.addGroup( start, verticesArray.length / 3 - start, options.material !== undefined ? options.material : 0 ); + }; - } + this.getDrawingBufferSize = function ( target ) { - // Create faces for the z-sides of the shape + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); - function buildSideFaces() { + }; - var start = verticesArray.length / 3; - var layeroffset = 0; - sidewalls( contour, layeroffset ); - layeroffset += contour.length; + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + _width = width; + _height = height; - ahole = holes[ h ]; - sidewalls( ahole, layeroffset ); + _pixelRatio = pixelRatio; - //, true - layeroffset += ahole.length; + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); - } + this.setViewport( 0, 0, width, height ); + }; - scope.addGroup( start, verticesArray.length / 3 - start, options.extrudeMaterial !== undefined ? options.extrudeMaterial : 1 ); + this.getCurrentViewport = function ( target ) { + return target.copy( _currentViewport ); - } + }; - function sidewalls( contour, layeroffset ) { + this.getViewport = function ( target ) { - var j, k; - i = contour.length; + return target.copy( _viewport ); - while ( -- i >= 0 ) { + }; - j = i; - k = i - 1; - if ( k < 0 ) k = contour.length - 1; + this.setViewport = function ( x, y, width, height ) { - //console.log('b', i,j, i-1, k,vertices.length); + if ( x.isVector4 ) { - var s = 0, - sl = steps + bevelSegments * 2; + _viewport.set( x.x, x.y, x.z, x.w ); - for ( s = 0; s < sl; s ++ ) { + } else { - var slen1 = vlen * s; - var slen2 = vlen * ( s + 1 ); + _viewport.set( x, y, width, height ); - var a = layeroffset + j + slen1, - b = layeroffset + k + slen1, - c = layeroffset + k + slen2, - d = layeroffset + j + slen2; + } - f4( a, b, c, d ); + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() ); - } + }; - } + this.getScissor = function ( target ) { - } + return target.copy( _scissor ); - function v( x, y, z ) { + }; - placeholder.push( x ); - placeholder.push( y ); - placeholder.push( z ); + this.setScissor = function ( x, y, width, height ) { - } + if ( x.isVector4 ) { + _scissor.set( x.x, x.y, x.z, x.w ); - function f3( a, b, c ) { + } else { - addVertex( a ); - addVertex( b ); - addVertex( c ); + _scissor.set( x, y, width, height ); - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + } - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() ); - } + }; - function f4( a, b, c, d ) { + this.getScissorTest = function () { - addVertex( a ); - addVertex( b ); - addVertex( d ); + return _scissorTest; - addVertex( b ); - addVertex( c ); - addVertex( d ); + }; + this.setScissorTest = function ( boolean ) { - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + state.setScissorTest( _scissorTest = boolean ); - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 3 ] ); + }; - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); - addUV( uvs[ 3 ] ); + this.setOpaqueSort = function ( method ) { - } + _opaqueSort = method; - function addVertex( index ) { + }; - indicesArray.push( verticesArray.length / 3 ); - verticesArray.push( placeholder[ index * 3 + 0 ] ); - verticesArray.push( placeholder[ index * 3 + 1 ] ); - verticesArray.push( placeholder[ index * 3 + 2 ] ); + this.setTransparentSort = function ( method ) { - } + _transparentSort = method; + }; - function addUV( vector2 ) { + // Clearing - uvArray.push( vector2.x ); - uvArray.push( vector2.y ); + this.getClearColor = function ( target ) { - } + return target.copy( background.getClearColor() ); - if ( ! options.arrays ) { + }; - this.setIndex( indicesArray ); - this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); + this.setClearColor = function () { - } + background.setClearColor.apply( background, arguments ); - }; + }; - ExtrudeGeometry.WorldUVGenerator = { + this.getClearAlpha = function () { - generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { + return background.getClearAlpha(); - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; + }; - return [ - new Vector2( a_x, a_y ), - new Vector2( b_x, b_y ), - new Vector2( c_x, c_y ) - ]; + this.setClearAlpha = function () { - }, + background.setClearAlpha.apply( background, arguments ); - generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { - - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var a_z = vertices[ indexA * 3 + 2 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var b_z = vertices[ indexB * 3 + 2 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; - var c_z = vertices[ indexC * 3 + 2 ]; - var d_x = vertices[ indexD * 3 ]; - var d_y = vertices[ indexD * 3 + 1 ]; - var d_z = vertices[ indexD * 3 + 2 ]; - - if ( Math.abs( a_y - b_y ) < 0.01 ) { - - return [ - new Vector2( a_x, 1 - a_z ), - new Vector2( b_x, 1 - b_z ), - new Vector2( c_x, 1 - c_z ), - new Vector2( d_x, 1 - d_z ) - ]; + }; - } else { + this.clear = function ( color = true, depth = true, stencil = true ) { - return [ - new Vector2( a_y, 1 - a_z ), - new Vector2( b_y, 1 - b_z ), - new Vector2( c_y, 1 - c_z ), - new Vector2( d_y, 1 - d_z ) - ]; + let bits = 0; - } + if ( color ) { - } - }; + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author alteredq / http://alteredqualia.com/ - * - * Text = 3D Text - * - * parameters = { - * font: , // font - * - * size: , // size of the text - * height: , // thickness to extrude text - * curveSegments: , // number of points on the curves - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into text bevel goes - * bevelSize: // how far from text outline is bevel - * } - */ + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - // TextGeometry + } - function TextGeometry( text, parameters ) { + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - Geometry.call( this ); + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - this.type = 'TextGeometry'; + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - this.parameters = { - text: text, - parameters: parameters - }; + if ( isUnsignedType ) { - this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) ); - this.mergeVertices(); + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor ); - } + } else { - TextGeometry.prototype = Object.create( Geometry.prototype ); - TextGeometry.prototype.constructor = TextGeometry; + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, 0, intClearColor ); - // TextBufferGeometry + } - function TextBufferGeometry( text, parameters ) { + } else { - parameters = parameters || {}; + bits |= _gl.COLOR_BUFFER_BIT; - var font = parameters.font; + } - if ( ! ( font && font.isFont ) ) { + } - console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); - return new Geometry(); + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) { - } + bits |= _gl.STENCIL_BUFFER_BIT; + this.state.buffers.stencil.setMask( 0xffffffff ); - var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments ); + } - // translate parameters to ExtrudeGeometry API + _gl.clear( bits ); - parameters.amount = parameters.height !== undefined ? parameters.height : 50; + }; - // defaults + this.clearColor = function () { - if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10; - if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8; - if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false; + this.clear( true, false, false ); - ExtrudeBufferGeometry.call( this, shapes, parameters ); + }; - this.type = 'TextBufferGeometry'; + this.clearDepth = function () { - } + this.clear( false, true, false ); - TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype ); - TextBufferGeometry.prototype.constructor = TextBufferGeometry; + }; - /** - * @author mrdoob / http://mrdoob.com/ - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - */ + this.clearStencil = function () { - // SphereGeometry + this.clear( false, false, true ); - function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { + }; - Geometry.call( this ); + // - this.type = 'SphereGeometry'; + this.dispose = function () { - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) ); - this.mergeVertices(); + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - } + xr.dispose(); - SphereGeometry.prototype = Object.create( Geometry.prototype ); - SphereGeometry.prototype.constructor = SphereGeometry; + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - // SphereBufferGeometry + animation.stop(); - function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { + }; - BufferGeometry.call( this ); + // Events - this.type = 'SphereBufferGeometry'; + function onContextLost( event ) { - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + event.preventDefault(); - radius = radius || 1; + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 ); - heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 ); + _isContextLost = true; - phiStart = phiStart !== undefined ? phiStart : 0; - phiLength = phiLength !== undefined ? phiLength : Math.PI * 2; + } - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI; + function onContextRestore( /* event */ ) { - var thetaEnd = thetaStart + thetaLength; + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - var ix, iy; + _isContextLost = false; - var index = 0; - var grid = []; + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - var vertex = new Vector3(); - var normal = new Vector3(); + initGLContext(); - // buffers + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // generate vertices, normals and uvs + function onContextCreationError( event ) { - for ( iy = 0; iy <= heightSegments; iy ++ ) { + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); - var verticesRow = []; + } - var v = iy / heightSegments; + function onMaterialDispose( event ) { - for ( ix = 0; ix <= widthSegments; ix ++ ) { + const material = event.target; - var u = ix / widthSegments; + material.removeEventListener( 'dispose', onMaterialDispose ); - // vertex + deallocateMaterial( material ); - vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); - vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); + } - vertices.push( vertex.x, vertex.y, vertex.z ); + // Buffer deallocation - // normal + function deallocateMaterial( material ) { - normal.set( vertex.x, vertex.y, vertex.z ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + releaseMaterialProgramReferences( material ); - // uv + properties.remove( material ); - uvs.push( u, 1 - v ); + } - verticesRow.push( index ++ ); - } + function releaseMaterialProgramReferences( material ) { - grid.push( verticesRow ); + const programs = properties.get( material ).programs; - } + if ( programs !== undefined ) { - // indices + programs.forEach( function ( program ) { - for ( iy = 0; iy < heightSegments; iy ++ ) { + programCache.releaseProgram( program ); - for ( ix = 0; ix < widthSegments; ix ++ ) { + } ); - var a = grid[ iy ][ ix + 1 ]; - var b = grid[ iy ][ ix ]; - var c = grid[ iy + 1 ][ ix ]; - var d = grid[ iy + 1 ][ ix + 1 ]; + if ( material.isShaderMaterial ) { - if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); - if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); + programCache.releaseShaderCache( material ); - } + } - } + } - // build geometry + } - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + // Buffer rendering - } + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - SphereBufferGeometry.prototype.constructor = SphereBufferGeometry; + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - /** - * @author Kaleb Murphy - * @author Mugen87 / https://github.com/Mugen87 - */ + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - // RingGeometry + const program = setProgram( camera, scene, geometry, material, object ); - function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { + state.setMaterial( material, frontFaceCW ); - Geometry.call( this ); + // - this.type = 'RingGeometry'; + let index = geometry.index; + let rangeFactor = 1; - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + if ( material.wireframe === true ) { - this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) ); - this.mergeVertices(); + index = geometries.getWireframeAttribute( geometry ); - } + if ( index === undefined ) return; - RingGeometry.prototype = Object.create( Geometry.prototype ); - RingGeometry.prototype.constructor = RingGeometry; + rangeFactor = 2; - // RingBufferGeometry + } - function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { + // - BufferGeometry.call( this ); + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - this.type = 'RingBufferGeometry'; + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + if ( group !== null ) { - innerRadius = innerRadius || 0.5; - outerRadius = outerRadius || 1; + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + } - thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8; - phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1; + if ( index !== null ) { - // buffers + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } else if ( position !== undefined && position !== null ) { - // some helper variables + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); - var segment; - var radius = innerRadius; - var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); - var vertex = new Vector3(); - var uv = new Vector2(); - var j, i; + } - // generate vertices, normals and uvs + const drawCount = drawEnd - drawStart; - for ( j = 0; j <= phiSegments; j ++ ) { + if ( drawCount < 0 || drawCount === Infinity ) return; - for ( i = 0; i <= thetaSegments; i ++ ) { + // - // values are generate from the inside of the ring to the outside + bindingStates.setup( object, material, program, geometry, index ); - segment = thetaStart + i / thetaSegments * thetaLength; + let attribute; + let renderer = bufferRenderer; - // vertex + if ( index !== null ) { - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); + attribute = attributes.get( index ); - vertices.push( vertex.x, vertex.y, vertex.z ); + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - // normal + } - normals.push( 0, 0, 1 ); + // - // uv + if ( object.isMesh ) { - uv.x = ( vertex.x / outerRadius + 1 ) / 2; - uv.y = ( vertex.y / outerRadius + 1 ) / 2; + if ( material.wireframe === true ) { - uvs.push( uv.x, uv.y ); + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - } + } else { - // increase the radius for next row of vertices + renderer.setMode( _gl.TRIANGLES ); - radius += radiusStep; + } - } + } else if ( object.isLine ) { - // indices + let lineWidth = material.linewidth; - for ( j = 0; j < phiSegments; j ++ ) { + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - var thetaSegmentLevel = j * ( thetaSegments + 1 ); + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - for ( i = 0; i < thetaSegments; i ++ ) { + if ( object.isLineSegments ) { - segment = i + thetaSegmentLevel; + renderer.setMode( _gl.LINES ); - var a = segment; - var b = segment + thetaSegments + 1; - var c = segment + thetaSegments + 2; - var d = segment + 1; + } else if ( object.isLineLoop ) { - // faces + renderer.setMode( _gl.LINE_LOOP ); - indices.push( a, b, d ); - indices.push( b, c, d ); + } else { - } + renderer.setMode( _gl.LINE_STRIP ); - } + } - // build geometry + } else if ( object.isPoints ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + renderer.setMode( _gl.POINTS ); - } + } else if ( object.isSprite ) { - RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - RingBufferGeometry.prototype.constructor = RingBufferGeometry; + renderer.setMode( _gl.TRIANGLES ); - /** - * @author astrodud / http://astrodud.isgreat.org/ - * @author zz85 / https://github.com/zz85 - * @author bhouston / http://clara.io - * @author Mugen87 / https://github.com/Mugen87 - */ + } - // LatheGeometry + if ( object.isBatchedMesh ) { - function LatheGeometry( points, segments, phiStart, phiLength ) { + if ( object._multiDrawInstances !== null ) { - Geometry.call( this ); + renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); - this.type = 'LatheGeometry'; + } else { - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; + if ( ! extensions.get( 'WEBGL_multi_draw' ) ) { - this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) ); - this.mergeVertices(); + const starts = object._multiDrawStarts; + const counts = object._multiDrawCounts; + const drawCount = object._multiDrawCount; + const bytesPerElement = index ? attributes.get( index ).bytesPerElement : 1; + const uniforms = properties.get( material ).currentProgram.getUniforms(); + for ( let i = 0; i < drawCount; i ++ ) { - } + uniforms.setValue( _gl, '_gl_DrawID', i ); + renderer.render( starts[ i ] / bytesPerElement, counts[ i ] ); - LatheGeometry.prototype = Object.create( Geometry.prototype ); - LatheGeometry.prototype.constructor = LatheGeometry; + } - // LatheBufferGeometry + } else { - function LatheBufferGeometry( points, segments, phiStart, phiLength ) { + renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); - BufferGeometry.call( this ); + } - this.type = 'LatheBufferGeometry'; + } - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; + } else if ( object.isInstancedMesh ) { - segments = Math.floor( segments ) || 12; - phiStart = phiStart || 0; - phiLength = phiLength || Math.PI * 2; + renderer.renderInstances( drawStart, drawCount, object.count ); - // clamp phiLength so it's in range of [ 0, 2PI ] + } else if ( geometry.isInstancedBufferGeometry ) { - phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 ); + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); + renderer.renderInstances( drawStart, drawCount, instanceCount ); - // buffers + } else { - var indices = []; - var vertices = []; - var uvs = []; + renderer.render( drawStart, drawCount ); - // helper variables + } - var base; - var inverseSegments = 1.0 / segments; - var vertex = new Vector3(); - var uv = new Vector2(); - var i, j; + }; - // generate vertices and uvs + // Compile - for ( i = 0; i <= segments; i ++ ) { + function prepareMaterial( material, scene, object ) { - var phi = phiStart + i * inverseSegments * phiLength; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - var sin = Math.sin( phi ); - var cos = Math.cos( phi ); + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - for ( j = 0; j <= ( points.length - 1 ); j ++ ) { + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - // vertex + material.side = DoubleSide; - vertex.x = points[ j ].x * sin; - vertex.y = points[ j ].y; - vertex.z = points[ j ].x * cos; + } else { - vertices.push( vertex.x, vertex.y, vertex.z ); + getProgram( material, scene, object ); - // uv + } - uv.x = i / segments; - uv.y = j / ( points.length - 1 ); + } - uvs.push( uv.x, uv.y ); + this.compile = function ( scene, camera, targetScene = null ) { + if ( targetScene === null ) targetScene = scene; - } + currentRenderState = renderStates.get( targetScene ); + currentRenderState.init( camera ); - } + renderStateStack.push( currentRenderState ); - // indices + // gather lights from both the target scene and the new object that will be added to the scene. - for ( i = 0; i < segments; i ++ ) { + targetScene.traverseVisible( function ( object ) { - for ( j = 0; j < ( points.length - 1 ); j ++ ) { + if ( object.isLight && object.layers.test( camera.layers ) ) { - base = j + i * points.length; + currentRenderState.pushLight( object ); - var a = base; - var b = base + points.length; - var c = base + points.length + 1; - var d = base + 1; + if ( object.castShadow ) { - // faces + currentRenderState.pushShadow( object ); - indices.push( a, b, d ); - indices.push( b, c, d ); + } - } + } - } + } ); - // build geometry + if ( scene !== targetScene ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + scene.traverseVisible( function ( object ) { - // generate normals + if ( object.isLight && object.layers.test( camera.layers ) ) { - this.computeVertexNormals(); + currentRenderState.pushLight( object ); - // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). + if ( object.castShadow ) { - if ( phiLength === Math.PI * 2 ) { + currentRenderState.pushShadow( object ); - var normals = this.attributes.normal.array; - var n1 = new Vector3(); - var n2 = new Vector3(); - var n = new Vector3(); + } - // this is the buffer offset for the last line of vertices + } - base = segments * points.length * 3; + } ); - for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) { + } - // select the normal of the vertex in the first line + currentRenderState.setupLights(); - n1.x = normals[ j + 0 ]; - n1.y = normals[ j + 1 ]; - n1.z = normals[ j + 2 ]; + // Only initialize materials in the new scene, not the targetScene. - // select the normal of the vertex in the last line + const materials = new Set(); - n2.x = normals[ base + j + 0 ]; - n2.y = normals[ base + j + 1 ]; - n2.z = normals[ base + j + 2 ]; + scene.traverse( function ( object ) { - // average normals + const material = object.material; - n.addVectors( n1, n2 ).normalize(); + if ( material ) { - // assign the new values to both normals + if ( Array.isArray( material ) ) { - normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; - normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; - normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; + for ( let i = 0; i < material.length; i ++ ) { - } + const material2 = material[ i ]; - } + prepareMaterial( material2, targetScene, object ); + materials.add( material2 ); - } + } - LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - LatheBufferGeometry.prototype.constructor = LatheBufferGeometry; + } else { - /** - * @author jonobr1 / http://jonobr1.com - * @author Mugen87 / https://github.com/Mugen87 - */ + prepareMaterial( material, targetScene, object ); + materials.add( material ); - // ShapeGeometry + } - function ShapeGeometry( shapes, curveSegments ) { + } - Geometry.call( this ); + } ); - this.type = 'ShapeGeometry'; + renderStateStack.pop(); + currentRenderState = null; - if ( typeof curveSegments === 'object' ) { + return materials; - console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' ); + }; - curveSegments = curveSegments.curveSegments; + // compileAsync - } + this.compileAsync = function ( scene, camera, targetScene = null ) { - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; + const materials = this.compile( scene, camera, targetScene ); - this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) ); - this.mergeVertices(); + // Wait for all the materials in the new object to indicate that they're + // ready to be used before resolving the promise. - } + return new Promise( ( resolve ) => { - ShapeGeometry.prototype = Object.create( Geometry.prototype ); - ShapeGeometry.prototype.constructor = ShapeGeometry; + function checkMaterialsReady() { - ShapeGeometry.prototype.toJSON = function () { + materials.forEach( function ( material ) { - var data = Geometry.prototype.toJSON.call( this ); + const materialProperties = properties.get( material ); + const program = materialProperties.currentProgram; - var shapes = this.parameters.shapes; + if ( program.isReady() ) { - return toJSON( shapes, data ); + // remove any programs that report they're ready to use from the list + materials.delete( material ); - }; + } - // ShapeBufferGeometry + } ); - function ShapeBufferGeometry( shapes, curveSegments ) { + // once the list of compiling materials is empty, call the callback - BufferGeometry.call( this ); + if ( materials.size === 0 ) { - this.type = 'ShapeBufferGeometry'; + resolve( scene ); + return; - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; + } - curveSegments = curveSegments || 12; + // if some materials are still not ready, wait a bit and check again - // buffers + setTimeout( checkMaterialsReady, 10 ); - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // helper variables + if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) { - var groupStart = 0; - var groupCount = 0; + // If we can check the compilation status of the materials without + // blocking then do so right away. - // allow single and array values for "shapes" parameter + checkMaterialsReady(); - if ( Array.isArray( shapes ) === false ) { + } else { - addShape( shapes ); + // Otherwise start by waiting a bit to give the materials we just + // initialized a chance to finish. - } else { + setTimeout( checkMaterialsReady, 10 ); - for ( var i = 0; i < shapes.length; i ++ ) { + } - addShape( shapes[ i ] ); + } ); - this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support + }; - groupStart += groupCount; - groupCount = 0; + // Animation Loop - } + let onAnimationFrameCallback = null; - } + function onAnimationFrame( time ) { - // build geometry + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + } + function onXRSessionStart() { - // helper functions + animation.stop(); - function addShape( shape ) { + } - var i, l, shapeHole; + function onXRSessionEnd() { - var indexOffset = vertices.length / 3; - var points = shape.extractPoints( curveSegments ); + animation.start(); - var shapeVertices = points.shape; - var shapeHoles = points.holes; + } - // check direction of vertices + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); - if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { + if ( typeof self !== 'undefined' ) animation.setContext( self ); - shapeVertices = shapeVertices.reverse(); + this.setAnimationLoop = function ( callback ) { - // also check if holes are in the opposite direction + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { + ( callback === null ) ? animation.stop() : animation.start(); - shapeHole = shapeHoles[ i ]; + }; - if ( ShapeUtils.isClockWise( shapeHole ) === true ) { + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - shapeHoles[ i ] = shapeHole.reverse(); + // Rendering - } + this.render = function ( scene, camera ) { - } + if ( camera !== undefined && camera.isCamera !== true ) { - } + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; - var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); + } - // join vertices of inner and outer paths to a single array + if ( _isContextLost === true ) return; - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { + // update scene graph - shapeHole = shapeHoles[ i ]; - shapeVertices = shapeVertices.concat( shapeHole ); + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - } + // update camera matrices and frustum - // vertices, normals, uvs + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - for ( i = 0, l = shapeVertices.length; i < l; i ++ ) { + if ( xr.enabled === true && xr.isPresenting === true ) { - var vertex = shapeVertices[ i ]; + if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); - vertices.push( vertex.x, vertex.y, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( vertex.x, vertex.y ); // world uvs + camera = xr.getCamera(); // use XR camera for rendering - } + } - // incides + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - for ( i = 0, l = faces.length; i < l; i ++ ) { + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init( camera ); - var face = faces[ i ]; + renderStateStack.push( currentRenderState ); - var a = face[ 0 ] + indexOffset; - var b = face[ 1 ] + indexOffset; - var c = face[ 2 ] + indexOffset; + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - indices.push( a, b, c ); - groupCount += 3; + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - } + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - } + renderListStack.push( currentRenderList ); - } + if ( xr.enabled === true && xr.isPresenting === true ) { - ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry; + const depthSensingMesh = _this.xr.getDepthSensingMesh(); - ShapeBufferGeometry.prototype.toJSON = function () { + if ( depthSensingMesh !== null ) { - var data = BufferGeometry.prototype.toJSON.call( this ); + projectObject( depthSensingMesh, camera, - Infinity, _this.sortObjects ); - var shapes = this.parameters.shapes; + } - return toJSON( shapes, data ); + } - }; + projectObject( scene, camera, 0, _this.sortObjects ); - // + currentRenderList.finish(); - function toJSON( shapes, data ) { + if ( _this.sortObjects === true ) { - data.shapes = []; + currentRenderList.sort( _opaqueSort, _transparentSort ); - if ( Array.isArray( shapes ) ) { + } - for ( var i = 0, l = shapes.length; i < l; i ++ ) { + _renderBackground = xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false; + if ( _renderBackground ) { - var shape = shapes[ i ]; + background.addToRenderList( currentRenderList, scene ); - data.shapes.push( shape.uuid ); + } - } + // - } else { + this.info.render.frame ++; - data.shapes.push( shapes.uuid ); + if ( _clippingEnabled === true ) clipping.beginShadows(); - } + const shadowsArray = currentRenderState.state.shadowsArray; - return data; + shadowMap.render( shadowsArray, scene, camera ); - } + if ( _clippingEnabled === true ) clipping.endShadows(); - /** - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ + // - function EdgesGeometry( geometry, thresholdAngle ) { + if ( this.info.autoReset === true ) this.info.reset(); - BufferGeometry.call( this ); + // render scene - this.type = 'EdgesGeometry'; + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; - this.parameters = { - thresholdAngle: thresholdAngle - }; + currentRenderState.setupLights(); - thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1; + if ( camera.isArrayCamera ) { - // buffer + const cameras = camera.cameras; - var vertices = []; + if ( transmissiveObjects.length > 0 ) { - // helper variables + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle ); - var edge = [ 0, 0 ], edges = {}, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; + const camera2 = cameras[ i ]; - // prepare source geometry + renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 ); - var geometry2; + } - if ( geometry.isBufferGeometry ) { + } - geometry2 = new Geometry(); - geometry2.fromBufferGeometry( geometry ); + if ( _renderBackground ) background.render( scene ); - } else { + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - geometry2 = geometry.clone(); + const camera2 = cameras[ i ]; - } + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - geometry2.mergeVertices(); - geometry2.computeFaceNormals(); + } - var sourceVertices = geometry2.vertices; - var faces = geometry2.faces; + } else { - // now create a data structure where each entry represents an edge with its adjoining faces + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - for ( var i = 0, l = faces.length; i < l; i ++ ) { + if ( _renderBackground ) background.render( scene ); - var face = faces[ i ]; + renderScene( currentRenderList, scene, camera ); - for ( var j = 0; j < 3; j ++ ) { + } - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); - edge[ 1 ] = Math.max( edge1, edge2 ); + // - key = edge[ 0 ] + ',' + edge[ 1 ]; + if ( _currentRenderTarget !== null ) { - if ( edges[ key ] === undefined ) { + // resolve multisample renderbuffers to a single-sample texture if necessary - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined }; + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - } else { + // Generate mipmap if we're using any kind of mipmap filtering - edges[ key ].face2 = i; + textures.updateRenderTargetMipmap( _currentRenderTarget ); } - } - - } + // - // generate vertices + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - for ( key in edges ) { + // _gl.finish(); - var e = edges[ key ]; + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree. + renderStateStack.pop(); - if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) { + if ( renderStateStack.length > 0 ) { - var vertex = sourceVertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - vertex = sourceVertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, currentRenderState.state.camera ); - } + } else { - } + currentRenderState = null; - // build geometry + } - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + renderListStack.pop(); - } + if ( renderListStack.length > 0 ) { - EdgesGeometry.prototype = Object.create( BufferGeometry.prototype ); - EdgesGeometry.prototype.constructor = EdgesGeometry; + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + } else { - // CylinderGeometry + currentRenderList = null; - function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + } - Geometry.call( this ); + }; - this.type = 'CylinderGeometry'; + function projectObject( object, camera, groupOrder, sortObjects ) { - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + if ( object.visible === false ) return; - this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) ); - this.mergeVertices(); + const visible = object.layers.test( camera.layers ); - } + if ( visible ) { - CylinderGeometry.prototype = Object.create( Geometry.prototype ); - CylinderGeometry.prototype.constructor = CylinderGeometry; + if ( object.isGroup ) { - // CylinderBufferGeometry + groupOrder = object.renderOrder; - function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + } else if ( object.isLOD ) { - BufferGeometry.call( this ); + if ( object.autoUpdate === true ) object.update( camera ); - this.type = 'CylinderBufferGeometry'; + } else if ( object.isLight ) { - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + currentRenderState.pushLight( object ); - var scope = this; + if ( object.castShadow ) { - radiusTop = radiusTop !== undefined ? radiusTop : 1; - radiusBottom = radiusBottom !== undefined ? radiusBottom : 1; - height = height || 1; + currentRenderState.pushShadow( object ); - radialSegments = Math.floor( radialSegments ) || 8; - heightSegments = Math.floor( heightSegments ) || 1; + } - openEnded = openEnded !== undefined ? openEnded : false; - thetaStart = thetaStart !== undefined ? thetaStart : 0.0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + } else if ( object.isSprite ) { - // buffers + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + if ( sortObjects ) { - // helper variables + _vector4.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - var index = 0; - var indexArray = []; - var halfHeight = height / 2; - var groupStart = 0; + } - // generate geometry + const geometry = objects.update( object ); + const material = object.material; - generateTorso(); + if ( material.visible ) { - if ( openEnded === false ) { + currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null ); - if ( radiusTop > 0 ) generateCap( true ); - if ( radiusBottom > 0 ) generateCap( false ); + } - } + } - // build geometry + } else if ( object.isMesh || object.isLine || object.isPoints ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - function generateTorso() { + const geometry = objects.update( object ); + const material = object.material; - var x, y; - var normal = new Vector3(); - var vertex = new Vector3(); + if ( sortObjects ) { - var groupCount = 0; + if ( object.boundingSphere !== undefined ) { - // this will be used to calculate the normal - var slope = ( radiusBottom - radiusTop ) / height; + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector4.copy( object.boundingSphere.center ); - // generate vertices, normals and uvs + } else { - for ( y = 0; y <= heightSegments; y ++ ) { + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector4.copy( geometry.boundingSphere.center ); - var indexRow = []; + } - var v = y / heightSegments; + _vector4 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - // calculate the radius of the current row + } - var radius = v * ( radiusBottom - radiusTop ) + radiusTop; + if ( Array.isArray( material ) ) { - for ( x = 0; x <= radialSegments; x ++ ) { + const groups = geometry.groups; - var u = x / radialSegments; + for ( let i = 0, l = groups.length; i < l; i ++ ) { - var theta = u * thetaLength + thetaStart; + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - var sinTheta = Math.sin( theta ); - var cosTheta = Math.cos( theta ); + if ( groupMaterial && groupMaterial.visible ) { - // vertex + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group ); - vertex.x = radius * sinTheta; - vertex.y = - v * height + halfHeight; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); + } - // normal + } - normal.set( sinTheta, slope, cosTheta ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + } else if ( material.visible ) { - // uv + currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null ); - uvs.push( u, 1 - v ); + } - // save index of vertex in respective row + } - indexRow.push( index ++ ); + } } - // now save vertices of the row in our index array + const children = object.children; - indexArray.push( indexRow ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - } + projectObject( children[ i ], camera, groupOrder, sortObjects ); - // generate indices + } - for ( x = 0; x < radialSegments; x ++ ) { + } - for ( y = 0; y < heightSegments; y ++ ) { + function renderScene( currentRenderList, scene, camera, viewport ) { - // we use the index array to access the correct indices + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - var a = indexArray[ y ][ x ]; - var b = indexArray[ y + 1 ][ x ]; - var c = indexArray[ y + 1 ][ x + 1 ]; - var d = indexArray[ y ][ x + 1 ]; + currentRenderState.setupLightsView( camera ); - // faces + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - indices.push( a, b, d ); - indices.push( b, c, d ); + if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); - // update group counter + if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); + if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); + if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); - groupCount += 6; + // Ensure depth buffer writing is enabled so it can be cleared on next render - } + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); + + state.setPolygonOffset( false ); } - // add a group to the geometry. this will ensure multi material support + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - scope.addGroup( groupStart, groupCount, 0 ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - // calculate new start value for groups + if ( overrideMaterial !== null ) { - groupStart += groupCount; + return; - } + } - function generateCap( top ) { + if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) { - var x, centerIndexStart, centerIndexEnd; + currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: 4, + stencilBuffer: stencil, + resolveDepthBuffer: false, + resolveStencilBuffer: false, + colorSpace: ColorManagement.workingColorSpace, + } ); - var uv = new Vector2(); - var vertex = new Vector3(); + // debug - var groupCount = 0; + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - var radius = ( top === true ) ? radiusTop : radiusBottom; - var sign = ( top === true ) ? 1 : - 1; + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - // save the index of the first center vertex - centerIndexStart = index; + } - // first we generate the center vertex data of the cap. - // because the geometry needs one set of uvs per face, - // we must generate a center vertex per face/segment + const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget[ camera.id ]; - for ( x = 1; x <= radialSegments; x ++ ) { + const activeViewport = camera.viewport || _currentViewport; + transmissionRenderTarget.setSize( activeViewport.z, activeViewport.w ); - // vertex + // - vertices.push( 0, halfHeight * sign, 0 ); + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( transmissionRenderTarget ); - // normal + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - normals.push( 0, sign, 0 ); + _this.clear(); - // uv + if ( _renderBackground ) background.render( scene ); - uvs.push( 0.5, 0.5 ); + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - // increase index + // Remove viewport from camera to avoid nested render calls resetting viewport to it (e.g Reflector). + // Transmission render pass requires viewport to match the transmissionRenderTarget. + const currentCameraViewport = camera.viewport; + if ( camera.viewport !== undefined ) camera.viewport = undefined; - index ++; + currentRenderState.setupLightsView( camera ); - } + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - // save the index of the last center vertex + renderObjects( opaqueObjects, scene, camera ); - centerIndexEnd = index; + textures.updateMultisampleRenderTarget( transmissionRenderTarget ); + textures.updateRenderTargetMipmap( transmissionRenderTarget ); - // now we generate the surrounding vertices, normals and uvs + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === false ) { // see #28131 - for ( x = 0; x <= radialSegments; x ++ ) { + let renderTargetNeedsUpdate = false; - var u = x / radialSegments; - var theta = u * thetaLength + thetaStart; + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - var cosTheta = Math.cos( theta ); - var sinTheta = Math.sin( theta ); + const renderItem = transmissiveObjects[ i ]; - // vertex + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - vertex.x = radius * sinTheta; - vertex.y = halfHeight * sign; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - // normal + const currentSide = material.side; - normals.push( 0, sign, 0 ); + material.side = BackSide; + material.needsUpdate = true; - // uv + renderObject( object, scene, camera, geometry, material, group ); - uv.x = ( cosTheta * 0.5 ) + 0.5; - uv.y = ( sinTheta * 0.5 * sign ) + 0.5; - uvs.push( uv.x, uv.y ); + material.side = currentSide; + material.needsUpdate = true; - // increase index + renderTargetNeedsUpdate = true; - index ++; + } - } + } - // generate indices + if ( renderTargetNeedsUpdate === true ) { - for ( x = 0; x < radialSegments; x ++ ) { + textures.updateMultisampleRenderTarget( transmissionRenderTarget ); + textures.updateRenderTargetMipmap( transmissionRenderTarget ); - var c = centerIndexStart + x; - var i = centerIndexEnd + x; + } - if ( top === true ) { + } - // face top + _this.setRenderTarget( currentRenderTarget ); - indices.push( i, i + 1, c ); + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - } else { + if ( currentCameraViewport !== undefined ) camera.viewport = currentCameraViewport; - // face bottom + _this.toneMapping = currentToneMapping; - indices.push( i + 1, i, c ); + } - } + function renderObjects( renderList, scene, camera ) { - groupCount += 3; + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - } + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - // add a group to the geometry. this will ensure multi material support + const renderItem = renderList[ i ]; - scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; - // calculate new start value for groups + if ( object.layers.test( camera.layers ) ) { - groupStart += groupCount; + renderObject( object, scene, camera, geometry, material, group ); - } + } - } + } - CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry; + } - /** - * @author abelnation / http://github.com/abelnation - */ + function renderObject( object, scene, camera, geometry, material, group ) { - // ConeGeometry + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - this.type = 'ConeGeometry'; + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - } + material.side = DoubleSide; - ConeGeometry.prototype = Object.create( CylinderGeometry.prototype ); - ConeGeometry.prototype.constructor = ConeGeometry; + } else { - // ConeBufferGeometry + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { + } - CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + object.onAfterRender( _this, scene, camera, geometry, material, group ); - this.type = 'ConeBufferGeometry'; + } - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + function getProgram( material, scene, object ) { - } + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype ); - ConeBufferGeometry.prototype.constructor = ConeBufferGeometry; + const materialProperties = properties.get( material ); - /** - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - * @author hughes - */ + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - // CircleGeometry + const lightsStateVersion = lights.state.version; - function CircleGeometry( radius, segments, thetaStart, thetaLength ) { + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - Geometry.call( this ); + let programs = materialProperties.programs; - this.type = 'CircleGeometry'; + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; - this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) ); - this.mergeVertices(); + if ( programs === undefined ) { - } + // new material - CircleGeometry.prototype = Object.create( Geometry.prototype ); - CircleGeometry.prototype.constructor = CircleGeometry; + material.addEventListener( 'dispose', onMaterialDispose ); - // CircleBufferGeometry + programs = new Map(); + materialProperties.programs = programs; - function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) { + } - BufferGeometry.call( this ); + let program = programs.get( programCacheKey ); - this.type = 'CircleBufferGeometry'; + if ( program !== undefined ) { - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; + // early out if program and light state is identical - radius = radius || 1; - segments = segments !== undefined ? Math.max( 3, segments ) : 8; + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; + updateCommonMaterialProperties( material, parameters ); - // buffers + return program; - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + } - // helper variables + } else { - var i, s; - var vertex = new Vector3(); - var uv = new Vector2(); + parameters.uniforms = programCache.getUniforms( material ); - // center point + material.onBeforeCompile( parameters, _this ); - vertices.push( 0, 0, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( 0.5, 0.5 ); + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) { + materialProperties.uniforms = parameters.uniforms; - var segment = thetaStart + s / segments * thetaLength; + } - // vertex + const uniforms = materialProperties.uniforms; - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - vertices.push( vertex.x, vertex.y, vertex.z ); + uniforms.clippingPlanes = clipping.uniform; - // normal + } - normals.push( 0, 0, 1 ); + updateCommonMaterialProperties( material, parameters ); - // uvs + // store the light setup it was created for - uv.x = ( vertices[ i ] / radius + 1 ) / 2; - uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - uvs.push( uv.x, uv.y ); + if ( materialProperties.needsLights ) { - } + // wire up the material to this renderer's lighting state - // indices + 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; - for ( i = 1; i <= segments; i ++ ) { + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms - indices.push( i, i + 1, 0 ); + } - } + materialProperties.currentProgram = program; + materialProperties.uniformsList = null; - // build geometry + return program; - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + } - } + function getUniformList( materialProperties ) { - CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - CircleBufferGeometry.prototype.constructor = CircleBufferGeometry; + if ( materialProperties.uniformsList === null ) { + const progUniforms = materialProperties.currentProgram.getUniforms(); + materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms ); + } - var Geometries = Object.freeze({ - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry - }); + return materialProperties.uniformsList; - /** - * @author mrdoob / http://mrdoob.com/ - * - * parameters = { - * color: , - * opacity: - * } - */ + } - function ShadowMaterial( parameters ) { + function updateCommonMaterialProperties( material, parameters ) { - Material.call( this ); + const materialProperties = properties.get( material ); - this.type = 'ShadowMaterial'; + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.batching = parameters.batching; + materialProperties.batchingColor = parameters.batchingColor; + materialProperties.instancing = parameters.instancing; + materialProperties.instancingColor = parameters.instancingColor; + materialProperties.instancingMorph = parameters.instancingMorph; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; - this.color = new Color( 0x000000 ); - this.opacity = 1.0; + } - this.lights = true; - this.transparent = true; + function setProgram( camera, scene, geometry, material, object ) { - this.setValues( parameters ); + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - } + textures.resetTextureUnits(); - ShadowMaterial.prototype = Object.create( Material.prototype ); - ShadowMaterial.prototype.constructor = ShadowMaterial; + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + 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 = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; - ShadowMaterial.prototype.isShadowMaterial = true; + let toneMapping = NoToneMapping; - /** - * @author mrdoob / http://mrdoob.com/ - */ + if ( material.toneMapped ) { - function RawShaderMaterial( parameters ) { + if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) { - ShaderMaterial.call( this, parameters ); + toneMapping = _this.toneMapping; - this.type = 'RawShaderMaterial'; + } - } + } - RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype ); - RawShaderMaterial.prototype.constructor = RawShaderMaterial; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - RawShaderMaterial.prototype.isRawShaderMaterial = true; + const materialProperties = properties.get( material ); + const lights = currentRenderState.state.lights; - /** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * color: , - * roughness: , - * metalness: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * roughnessMap: new THREE.Texture( ), - * - * metalnessMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), - * envMapIntensity: - * - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + if ( _clippingEnabled === true ) { - function MeshStandardMaterial( parameters ) { + if ( _localClippingEnabled === true || camera !== _currentCamera ) { - Material.call( this ); + const useCache = + camera === _currentCamera && + material.id === _currentMaterialId; - this.defines = { 'STANDARD': '' }; + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); - this.type = 'MeshStandardMaterial'; + } - this.color = new Color( 0xffffff ); // diffuse - this.roughness = 0.5; - this.metalness = 0.5; + } - this.map = null; + // - this.lightMap = null; - this.lightMapIntensity = 1.0; + let needsProgramChange = false; - this.aoMap = null; - this.aoMapIntensity = 1.0; + if ( material.version === materialProperties.__version ) { - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - this.bumpMap = null; - this.bumpScale = 1; + needsProgramChange = true; - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + needsProgramChange = true; - this.roughnessMap = null; + } else if ( object.isBatchedMesh && materialProperties.batching === false ) { - this.metalnessMap = null; + needsProgramChange = true; - this.alphaMap = null; + } else if ( ! object.isBatchedMesh && materialProperties.batching === true ) { - this.envMap = null; - this.envMapIntensity = 1.0; + needsProgramChange = true; - this.refractionRatio = 0.98; + } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + needsProgramChange = true; - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { - this.setValues( parameters ); + needsProgramChange = true; - } + } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { - MeshStandardMaterial.prototype = Object.create( Material.prototype ); - MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; + needsProgramChange = true; - MeshStandardMaterial.prototype.isMeshStandardMaterial = true; + } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { - MeshStandardMaterial.prototype.copy = function ( source ) { + needsProgramChange = true; - Material.prototype.copy.call( this, source ); + } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { - this.defines = { 'STANDARD': '' }; + needsProgramChange = true; - this.color.copy( source.color ); - this.roughness = source.roughness; - this.metalness = source.metalness; + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - this.map = source.map; + needsProgramChange = true; - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + } else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) { - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + needsProgramChange = true; - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + } else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) { - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + needsProgramChange = true; - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + } else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) { - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + needsProgramChange = true; - this.roughnessMap = source.roughnessMap; + } else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) { - this.metalnessMap = source.metalnessMap; + needsProgramChange = true; - this.alphaMap = source.alphaMap; + } else if ( materialProperties.envMap !== envMap ) { - this.envMap = source.envMap; - this.envMapIntensity = source.envMapIntensity; + needsProgramChange = true; - this.refractionRatio = source.refractionRatio; + } else if ( material.fog === true && materialProperties.fog !== fog ) { - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + needsProgramChange = true; - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - return this; + needsProgramChange = true; - }; + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - /** - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * reflectivity: - * } - */ + needsProgramChange = true; - function MeshPhysicalMaterial( parameters ) { + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - MeshStandardMaterial.call( this ); + needsProgramChange = true; - this.defines = { 'PHYSICAL': '' }; + } else if ( materialProperties.morphTargets !== morphTargets ) { - this.type = 'MeshPhysicalMaterial'; + needsProgramChange = true; - this.reflectivity = 0.5; // maps to F0 = 0.04 + } else if ( materialProperties.morphNormals !== morphNormals ) { - this.clearCoat = 0.0; - this.clearCoatRoughness = 0.0; + needsProgramChange = true; - this.setValues( parameters ); + } else if ( materialProperties.morphColors !== morphColors ) { - } + needsProgramChange = true; - MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); - MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; + } else if ( materialProperties.toneMapping !== toneMapping ) { - MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; + needsProgramChange = true; - MeshPhysicalMaterial.prototype.copy = function ( source ) { + } else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) { - MeshStandardMaterial.prototype.copy.call( this, source ); + needsProgramChange = true; - this.defines = { 'PHYSICAL': '' }; + } - this.reflectivity = source.reflectivity; + } else { - this.clearCoat = source.clearCoat; - this.clearCoatRoughness = source.clearCoatRoughness; + needsProgramChange = true; + materialProperties.__version = material.version; - return this; + } - }; + // - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * specular: , - * shininess: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + let program = materialProperties.currentProgram; - function MeshPhongMaterial( parameters ) { + if ( needsProgramChange === true ) { - Material.call( this ); + program = getProgram( material, scene, object ); - this.type = 'MeshPhongMaterial'; + } - this.color = new Color( 0xffffff ); // diffuse - this.specular = new Color( 0x111111 ); - this.shininess = 30; + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - this.map = null; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - this.lightMap = null; - this.lightMapIntensity = 1.0; + if ( state.useProgram( program.program ) ) { - this.aoMap = null; - this.aoMapIntensity = 1.0; + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; + } - this.bumpMap = null; - this.bumpScale = 1; + if ( material.id !== _currentMaterialId ) { - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + _currentMaterialId = material.id; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + refreshMaterial = true; - this.specularMap = null; + } - this.alphaMap = null; + if ( refreshProgram || _currentCamera !== camera ) { - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + // common camera uniforms - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + const uCamPos = p_uniforms.map.cameraPosition; - this.setValues( parameters ); + if ( uCamPos !== undefined ) { - } + uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) ); - MeshPhongMaterial.prototype = Object.create( Material.prototype ); - MeshPhongMaterial.prototype.constructor = MeshPhongMaterial; + } - MeshPhongMaterial.prototype.isMeshPhongMaterial = true; + if ( capabilities.logarithmicDepthBuffer ) { - MeshPhongMaterial.prototype.copy = function ( source ) { + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); - Material.prototype.copy.call( this, source ); + } - this.color.copy( source.color ); - this.specular.copy( source.specular ); - this.shininess = source.shininess; + // consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067 - this.map = source.map; + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + } - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + if ( _currentCamera !== camera ) { - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + _currentCamera = camera; - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - this.specularMap = source.specularMap; + } - this.alphaMap = source.alphaMap; + } - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + if ( object.isSkinnedMesh ) { - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - return this; + const skeleton = object.skeleton; - }; + if ( skeleton ) { - /** - * @author takahirox / http://github.com/takahirox - * - * parameters = { - * gradientMap: new THREE.Texture( ) - * } - */ + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - function MeshToonMaterial( parameters ) { + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - MeshPhongMaterial.call( this ); + } - this.defines = { 'TOON': '' }; + } - this.type = 'MeshToonMaterial'; + if ( object.isBatchedMesh ) { - this.gradientMap = null; + p_uniforms.setOptional( _gl, object, 'batchingTexture' ); + p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); - this.setValues( parameters ); + p_uniforms.setOptional( _gl, object, 'batchingIdTexture' ); + p_uniforms.setValue( _gl, 'batchingIdTexture', object._indirectTexture, textures ); - } + p_uniforms.setOptional( _gl, object, 'batchingColorTexture' ); + if ( object._colorsTexture !== null ) { - MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype ); - MeshToonMaterial.prototype.constructor = MeshToonMaterial; + p_uniforms.setValue( _gl, 'batchingColorTexture', object._colorsTexture, textures ); - MeshToonMaterial.prototype.isMeshToonMaterial = true; + } - MeshToonMaterial.prototype.copy = function ( source ) { + } - MeshPhongMaterial.prototype.copy.call( this, source ); + const morphAttributes = geometry.morphAttributes; - this.gradientMap = source.gradientMap; + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) { - return this; + morphtargets.update( object, geometry, program ); - }; + } - /** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - * - * parameters = { - * opacity: , - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * wireframe: , - * wireframeLinewidth: - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { - function MeshNormalMaterial( parameters ) { + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); - Material.call( this ); + } - this.type = 'MeshNormalMaterial'; + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - this.bumpMap = null; - this.bumpScale = 1; + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); + m_uniforms.envMap.value = envMap; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - this.wireframe = false; - this.wireframeLinewidth = 1; + } - this.fog = false; - this.lights = false; + if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) { - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + m_uniforms.envMapIntensity.value = scene.environmentIntensity; - this.setValues( parameters ); + } - } + if ( refreshMaterial ) { - MeshNormalMaterial.prototype = Object.create( Material.prototype ); - MeshNormalMaterial.prototype.constructor = MeshNormalMaterial; + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - MeshNormalMaterial.prototype.isMeshNormalMaterial = true; + if ( materialProperties.needsLights ) { - MeshNormalMaterial.prototype.copy = function ( source ) { + // the current material requires lighting info - Material.prototype.copy.call( this, source ); + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); + } - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + // refresh uniforms common to several materials - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; + if ( fog && material.fog === true ) { - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + materials.refreshFogUniforms( m_uniforms, fog ); - return this; + } - }; + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget[ camera.id ] ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ + WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); - function MeshLambertMaterial( parameters ) { + } - Material.call( this ); + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - this.type = 'MeshLambertMaterial'; + WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); + material.uniformsNeedUpdate = false; - this.color = new Color( 0xffffff ); // diffuse + } - this.map = null; + if ( material.isSpriteMaterial ) { - this.lightMap = null; - this.lightMapIntensity = 1.0; + p_uniforms.setValue( _gl, 'center', object.center ); - this.aoMap = null; - this.aoMapIntensity = 1.0; + } - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; + // common matrices - this.specularMap = null; + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - this.alphaMap = null; + // UBOs - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + const groups = material.uniformsGroups; - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + for ( let i = 0, l = groups.length; i < l; i ++ ) { - this.setValues( parameters ); + const group = groups[ i ]; - } + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - MeshLambertMaterial.prototype = Object.create( Material.prototype ); - MeshLambertMaterial.prototype.constructor = MeshLambertMaterial; + } - MeshLambertMaterial.prototype.isMeshLambertMaterial = true; + } - MeshLambertMaterial.prototype.copy = function ( source ) { + return program; - Material.prototype.copy.call( this, source ); + } - this.color.copy( source.color ); + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - this.map = source.map; + function markUniformsLightsNeedsUpdate( uniforms, value ) { - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + 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; - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + } - this.specularMap = source.specularMap; + function materialNeedsLights( material ) { - this.alphaMap = source.alphaMap; + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - 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.getActiveCubeFace = function () { - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + return _currentActiveCubeFace; - return this; + }; - }; + this.getActiveMipmapLevel = function () { - /** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * - * scale: , - * dashSize: , - * gapSize: - * } - */ + return _currentActiveMipmapLevel; - function LineDashedMaterial( parameters ) { + }; - LineBasicMaterial.call( this ); + this.getRenderTarget = function () { - this.type = 'LineDashedMaterial'; + return _currentRenderTarget; - this.scale = 1; - this.dashSize = 3; - this.gapSize = 1; + }; - this.setValues( parameters ); + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - } + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); - LineDashedMaterial.prototype.constructor = LineDashedMaterial; + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - LineDashedMaterial.prototype.isLineDashedMaterial = true; + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - LineDashedMaterial.prototype.copy = function ( source ) { + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { - LineBasicMaterial.prototype.copy.call( this, source ); + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - this.scale = source.scale; - this.dashSize = source.dashSize; - this.gapSize = source.gapSize; + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - return this; + } - }; + } + }; + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - var Materials = Object.freeze({ - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material - }); + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - /** - * @author mrdoob / http://mrdoob.com/ - */ + }; - var Cache = { + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - enabled: false, + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - files: {}, + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - add: function ( key, file ) { + if ( renderTarget ) { - if ( this.enabled === false ) return; + const renderTargetProperties = properties.get( renderTarget ); - // console.log( 'THREE.Cache', 'Adding key:', key ); + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - this.files[ key ] = file; + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - }, + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - get: function ( key ) { + textures.setupRenderTarget( renderTarget ); - if ( this.enabled === false ) return; + } else if ( renderTargetProperties.__hasExternalTextures ) { - // console.log( 'THREE.Cache', 'Checking key:', key ); + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); - return this.files[ key ]; + } - }, + const texture = renderTarget.texture; - remove: function ( key ) { + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - delete this.files[ key ]; + isRenderTarget3D = true; - }, + } - clear: function () { + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - this.files = {}; + if ( renderTarget.isWebGLCubeRenderTarget ) { - } + if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) { - }; + framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ]; - /** - * @author mrdoob / http://mrdoob.com/ - */ + } else { - function LoadingManager( onLoad, onProgress, onError ) { + framebuffer = __webglFramebuffer[ activeCubeFace ]; - var scope = this; + } - var isLoading = false; - var itemsLoaded = 0; - var itemsTotal = 0; - var urlModifier = undefined; + isCube = true; - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; + } else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - this.itemStart = function ( url ) { + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - itemsTotal ++; + } else { - if ( isLoading === false ) { + if ( Array.isArray( __webglFramebuffer ) ) { - if ( scope.onStart !== undefined ) { + framebuffer = __webglFramebuffer[ activeMipmapLevel ]; - scope.onStart( url, itemsLoaded, itemsTotal ); + } else { - } + framebuffer = __webglFramebuffer; - } + } - isLoading = true; + } - }; + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; - this.itemEnd = function ( url ) { + } else { - itemsLoaded ++; + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; - if ( scope.onProgress !== undefined ) { + } - scope.onProgress( url, itemsLoaded, itemsTotal ); + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - } + if ( framebufferBound && useDefaultFramebuffer ) { - if ( itemsLoaded === itemsTotal ) { + state.drawBuffers( renderTarget, framebuffer ); - isLoading = false; + } - if ( scope.onLoad !== undefined ) { + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - scope.onLoad(); + 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 ); - this.itemError = function ( url ) { + } - if ( scope.onError !== undefined ) { + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - scope.onError( url ); + }; - } + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - }; + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - this.resolveURL = function ( url ) { + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - if ( urlModifier ) { + } - return urlModifier( url ); + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - } + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - return url; + framebuffer = framebuffer[ activeCubeFaceIndex ]; - }; + } - this.setURLModifier = function ( transform ) { + if ( framebuffer ) { - urlModifier = transform; - return this; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - }; + try { - } + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - var DefaultLoadingManager = new LoadingManager(); + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - var loading = {}; + } - function FileLoader( manager ) { + if ( ! capabilities.textureTypeReadable( textureType ) ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - } + } - Object.assign( FileLoader.prototype, { + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - load: function ( url, onLoad, onProgress, onError ) { + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - if ( url === undefined ) url = ''; + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - if ( this.path !== undefined ) url = this.path + url; + } - url = this.manager.resolveURL( url ); + } finally { - var scope = this; + // restore framebuffer of current render target if necessary - var cached = Cache.get( url ); + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( cached !== undefined ) { + } - scope.manager.itemStart( url ); + } - setTimeout( function () { + }; - if ( onLoad ) onLoad( cached ); + this.readRenderTargetPixelsAsync = async function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - scope.manager.itemEnd( url ); + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - }, 0 ); + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return cached; + } - } + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - // Check if request is duplicate + framebuffer = framebuffer[ activeCubeFaceIndex ]; - if ( loading[ url ] !== undefined ) { + } - loading[ url ].push( { + if ( framebuffer ) { - onLoad: onLoad, - onProgress: onProgress, - onError: onError + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - } ); + try { - return; + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - } + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - // Check for data: URI - var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/; - var dataUriRegexResult = url.match( dataUriRegex ); + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); - // Safari can not handle Data URIs through XMLHttpRequest so process manually - if ( dataUriRegexResult ) { + } - var mimeType = dataUriRegexResult[ 1 ]; - var isBase64 = !! dataUriRegexResult[ 2 ]; - var data = dataUriRegexResult[ 3 ]; + if ( ! capabilities.textureTypeReadable( textureType ) ) { - data = window.decodeURIComponent( data ); + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); - if ( isBase64 ) data = window.atob( data ); + } - try { + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - var response; - var responseType = ( this.responseType || '' ).toLowerCase(); + const glBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); + _gl.flush(); - switch ( responseType ) { + // check if the commands have finished every 8 ms + const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); + await probeAsync( _gl, sync, 4 ); - case 'arraybuffer': - case 'blob': + try { - var view = new Uint8Array( data.length ); + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); - for ( var i = 0; i < data.length; i ++ ) { + } finally { - view[ i ] = data.charCodeAt( i ); + _gl.deleteBuffer( glBuffer ); + _gl.deleteSync( sync ); } - if ( responseType === 'blob' ) { - - response = new Blob( [ view.buffer ], { type: mimeType } ); - - } else { + return buffer; - response = view.buffer; + } - } + } finally { - break; + // restore framebuffer of current render target if necessary - case 'document': + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - var parser = new DOMParser(); - response = parser.parseFromString( data, mimeType ); + } - break; + } - case 'json': + }; - response = JSON.parse( data ); + this.copyFramebufferToTexture = function ( texture, position = null, level = 0 ) { - break; + // support previous signature with position first + if ( texture.isTexture !== true ) { - default: // 'text' or other + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyFramebufferToTexture function signature has changed.' ); - response = data; + position = arguments[ 0 ] || null; + texture = arguments[ 1 ]; - break; + } - } + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { + const x = position !== null ? position.x : 0; + const y = position !== null ? position.y : 0; - if ( onLoad ) onLoad( response ); + textures.setTexture2D( texture, 0 ); - scope.manager.itemEnd( url ); + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, x, y, width, height ); - }, 0 ); + state.unbindTexture(); - } catch ( error ) { + }; - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { + this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { - if ( onError ) onError( error ); + // support previous signature with dstPosition first + if ( srcTexture.isTexture !== true ) { - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyTextureToTexture function signature has changed.' ); - }, 0 ); + dstPosition = arguments[ 0 ] || null; + srcTexture = arguments[ 1 ]; + dstTexture = arguments[ 2 ]; + level = arguments[ 3 ] || 0; + srcRegion = null; } - } else { - - // Initialise array for duplicate requests + let width, height, minX, minY; + let dstX, dstY; + if ( srcRegion !== null ) { - loading[ url ] = []; + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + minX = srcRegion.min.x; + minY = srcRegion.min.y; - loading[ url ].push( { + } else { - onLoad: onLoad, - onProgress: onProgress, - onError: onError + width = srcTexture.image.width; + height = srcTexture.image.height; + minX = 0; + minY = 0; - } ); + } - var request = new XMLHttpRequest(); + if ( dstPosition !== null ) { - request.open( 'GET', url, true ); + dstX = dstPosition.x; + dstY = dstPosition.y; - request.addEventListener( 'load', function ( event ) { + } else { - var response = this.response; + dstX = 0; + dstY = 0; - Cache.add( url, response ); + } - var callbacks = loading[ url ]; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - delete loading[ url ]; + textures.setTexture2D( dstTexture, 0 ); - if ( this.status === 200 ) { + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _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 ); - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - var callback = callbacks[ i ]; - if ( callback.onLoad ) callback.onLoad( response ); + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; - } + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); - scope.manager.itemEnd( url ); + if ( srcTexture.isDataTexture ) { - } else if ( this.status === 0 ) { + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); - // Some browsers return HTTP Status 0 when using non-http protocol - // e.g. 'file://' or 'data://'. Handle as success. + } else { - console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); + if ( srcTexture.isCompressedTexture ) { - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); - var callback = callbacks[ i ]; - if ( callback.onLoad ) callback.onLoad( response ); + } else { - } + _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image ); - scope.manager.itemEnd( url ); + } - } else { + } - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); - var callback = callbacks[ i ]; - if ( callback.onError ) callback.onError( event ); + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - } + state.unbindTexture(); - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + }; - } + this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { - }, false ); + // support previous signature with source box first + if ( srcTexture.isTexture !== true ) { - request.addEventListener( 'progress', function ( event ) { + // @deprecated, r165 + warnOnce( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' ); - var callbacks = loading[ url ]; + srcRegion = arguments[ 0 ] || null; + dstPosition = arguments[ 1 ] || null; + srcTexture = arguments[ 2 ]; + dstTexture = arguments[ 3 ]; + level = arguments[ 4 ] || 0; - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + } - var callback = callbacks[ i ]; - if ( callback.onProgress ) callback.onProgress( event ); + let width, height, depth, minX, minY, minZ; + let dstX, dstY, dstZ; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; + if ( srcRegion !== null ) { - } + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + depth = srcRegion.max.z - srcRegion.min.z; + minX = srcRegion.min.x; + minY = srcRegion.min.y; + minZ = srcRegion.min.z; - }, false ); + } else { - request.addEventListener( 'error', function ( event ) { + width = image.width; + height = image.height; + depth = image.depth; + minX = 0; + minY = 0; + minZ = 0; - var callbacks = loading[ url ]; + } - delete loading[ url ]; + if ( dstPosition !== null ) { - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { + dstX = dstPosition.x; + dstY = dstPosition.y; + dstZ = dstPosition.z; - var callback = callbacks[ i ]; - if ( callback.onError ) callback.onError( event ); + } else { - } + dstX = 0; + dstY = 0; + dstZ = 0; - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + } - }, false ); + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - if ( this.responseType !== undefined ) request.responseType = this.responseType; - if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials; + if ( dstTexture.isData3DTexture ) { - if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - for ( var header in this.requestHeader ) { + } else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) { - request.setRequestHeader( header, this.requestHeader[ header ] ); + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; - } + } else { - request.send( null ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; - } + } - scope.manager.itemStart( url ); + _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 ); - return request; + const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - }, + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ ); - setPath: function ( value ) { + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - this.path = value; - return this; + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data ); - }, + } else { - setResponseType: function ( value ) { + if ( dstTexture.isCompressedArrayTexture ) { - this.responseType = value; - return this; + _gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data ); - }, + } else { - setWithCredentials: function ( value ) { + _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image ); - this.withCredentials = value; - return this; + } - }, + } - setMimeType: function ( value ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); - this.mimeType = value; - return this; + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - }, + state.unbindTexture(); - setRequestHeader: function ( value ) { + }; - this.requestHeader = value; - return this; + this.initRenderTarget = function ( target ) { - } + if ( properties.get( target ).__webglFramebuffer === undefined ) { - } ); + textures.setupRenderTarget( target ); - /** - * @author mrdoob / http://mrdoob.com/ - * - * Abstract Base class to block based textures loader (dds, pvr, ...) - */ + } - function CompressedTextureLoader( manager ) { + }; - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + this.initTexture = function ( texture ) { - // override in sub classes - this._parser = null; + if ( texture.isCubeTexture ) { - } + textures.setTextureCube( texture, 0 ); - Object.assign( CompressedTextureLoader.prototype, { + } else if ( texture.isData3DTexture ) { - load: function ( url, onLoad, onProgress, onError ) { + textures.setTexture3D( texture, 0 ); - var scope = this; + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - var images = []; + textures.setTexture2DArray( texture, 0 ); - var texture = new CompressedTexture(); - texture.image = images; + } else { - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); + textures.setTexture2D( texture, 0 ); - function loadTexture( i ) { + } - loader.load( url[ i ], function ( buffer ) { + state.unbindTexture(); - var texDatas = scope._parser( buffer, true ); + }; - images[ i ] = { - width: texDatas.width, - height: texDatas.height, - format: texDatas.format, - mipmaps: texDatas.mipmaps - }; + this.resetState = function () { - loaded += 1; + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - if ( loaded === 6 ) { + state.reset(); + bindingStates.reset(); - if ( texDatas.mipmapCount === 1 ) - texture.minFilter = LinearFilter; + }; - texture.format = texDatas.format; - texture.needsUpdate = true; + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - if ( onLoad ) onLoad( texture ); + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); - } + } - }, onProgress, onError ); + } - } + get coordinateSystem() { - if ( Array.isArray( url ) ) { + return WebGLCoordinateSystem; - var loaded = 0; + } - for ( var i = 0, il = url.length; i < il; ++ i ) { + get outputColorSpace() { - loadTexture( i ); + return this._outputColorSpace; - } + } - } else { + set outputColorSpace( colorSpace ) { - // compressed cubemap texture stored in a single DDS file + this._outputColorSpace = colorSpace; - loader.load( url, function ( buffer ) { + const gl = this.getContext(); + gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb'; + gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb'; - var texDatas = scope._parser( buffer, true ); + } - if ( texDatas.isCubemap ) { + } - var faces = texDatas.mipmaps.length / texDatas.mipmapCount; + class Scene extends Object3D { - for ( var f = 0; f < faces; f ++ ) { + constructor() { - images[ f ] = { mipmaps: [] }; + super(); - for ( var i = 0; i < texDatas.mipmapCount; i ++ ) { + this.isScene = true; - 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; + this.type = 'Scene'; - } + this.background = null; + this.environment = null; + this.fog = null; - } + this.backgroundBlurriness = 0; + this.backgroundIntensity = 1; + this.backgroundRotation = new Euler(); - } else { + this.environmentIntensity = 1; + this.environmentRotation = new Euler(); - texture.image.width = texDatas.width; - texture.image.height = texDatas.height; - texture.mipmaps = texDatas.mipmaps; + this.overrideMaterial = null; - } + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - if ( texDatas.mipmapCount === 1 ) { + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); - texture.minFilter = LinearFilter; + } - } + } - texture.format = texDatas.format; - texture.needsUpdate = true; + copy( source, recursive ) { - if ( onLoad ) onLoad( texture ); + super.copy( source, recursive ); - }, onProgress, onError ); + 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(); - } + this.backgroundBlurriness = source.backgroundBlurriness; + this.backgroundIntensity = source.backgroundIntensity; + this.backgroundRotation.copy( source.backgroundRotation ); - return texture; + this.environmentIntensity = source.environmentIntensity; + this.environmentRotation.copy( source.environmentRotation ); - }, + if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); - setPath: function ( value ) { + this.matrixAutoUpdate = source.matrixAutoUpdate; - this.path = value; return this; } - } ); + toJSON( meta ) { - /** - * @author Nikos M. / https://github.com/foo123/ - * - * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) - */ + const data = super.toJSON( meta ); - function DataTextureLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - // override in sub classes - this._parser = null; + if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); - } + if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; + if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; + data.object.backgroundRotation = this.backgroundRotation.toArray(); - Object.assign( DataTextureLoader.prototype, { + if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity; + data.object.environmentRotation = this.environmentRotation.toArray(); - load: function ( url, onLoad, onProgress, onError ) { + return data; - var scope = this; + } - var texture = new DataTexture(); + } - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); + class InterleavedBuffer { - loader.load( url, function ( buffer ) { + constructor( array, stride ) { - var texData = scope._parser( buffer ); + this.isInterleavedBuffer = true; - if ( ! texData ) return; + this.array = array; + this.stride = stride; + this.count = array !== undefined ? array.length / stride : 0; - if ( undefined !== texData.image ) { + this.usage = StaticDrawUsage; + this._updateRange = { offset: 0, count: - 1 }; + this.updateRanges = []; - texture.image = texData.image; + this.version = 0; - } else if ( undefined !== texData.data ) { + this.uuid = generateUUID(); - texture.image.width = texData.width; - texture.image.height = texData.height; - texture.image.data = texData.data; + } - } + onUploadCallback() {} - texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping; - texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping; + set needsUpdate( value ) { - texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter; - texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter; + if ( value === true ) this.version ++; - texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1; + } - if ( undefined !== texData.format ) { + get updateRange() { - texture.format = texData.format; + warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 + return this._updateRange; - } - if ( undefined !== texData.type ) { + } - texture.type = texData.type; + setUsage( value ) { - } + this.usage = value; - if ( undefined !== texData.mipmaps ) { + return this; - texture.mipmaps = texData.mipmaps; + } - } + addUpdateRange( start, count ) { - if ( 1 === texData.mipmapCount ) { + this.updateRanges.push( { start, count } ); - texture.minFilter = LinearFilter; + } - } + clearUpdateRanges() { - texture.needsUpdate = true; + this.updateRanges.length = 0; - if ( onLoad ) onLoad( texture, texData ); + } - }, onProgress, onError ); + copy( source ) { + this.array = new source.array.constructor( source.array ); + this.count = source.count; + this.stride = source.stride; + this.usage = source.usage; - return texture; + return this; } - } ); + copyAt( index1, attribute, index2 ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + index1 *= this.stride; + index2 *= attribute.stride; - function ImageLoader( manager ) { + for ( let i = 0, l = this.stride; i < l; i ++ ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + this.array[ index1 + i ] = attribute.array[ index2 + i ]; - } + } - Object.assign( ImageLoader.prototype, { + return this; - crossOrigin: 'Anonymous', + } - load: function ( url, onLoad, onProgress, onError ) { + set( value, offset = 0 ) { - if ( url === undefined ) url = ''; + this.array.set( value, offset ); - if ( this.path !== undefined ) url = this.path + url; + return this; - url = this.manager.resolveURL( url ); + } - var scope = this; + clone( data ) { - var cached = Cache.get( url ); + if ( data.arrayBuffers === undefined ) { - if ( cached !== undefined ) { + data.arrayBuffers = {}; - scope.manager.itemStart( url ); + } - setTimeout( function () { + if ( this.array.buffer._uuid === undefined ) { - if ( onLoad ) onLoad( cached ); + this.array.buffer._uuid = generateUUID(); - scope.manager.itemEnd( url ); + } - }, 0 ); + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { - return cached; + data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; } - var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' ); + const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); - image.addEventListener( 'load', function () { + const ib = new this.constructor( array, this.stride ); + ib.setUsage( this.usage ); - Cache.add( url, this ); + return ib; - if ( onLoad ) onLoad( this ); + } - scope.manager.itemEnd( url ); + onUpload( callback ) { - }, false ); + this.onUploadCallback = callback; - /* - image.addEventListener( 'progress', function ( event ) { + return this; - if ( onProgress ) onProgress( event ); + } - }, false ); - */ + toJSON( data ) { - image.addEventListener( 'error', function ( event ) { + if ( data.arrayBuffers === undefined ) { - if ( onError ) onError( event ); + data.arrayBuffers = {}; - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + } - }, false ); + // generate UUID for array buffer if necessary - if ( url.substr( 0, 5 ) !== 'data:' ) { + if ( this.array.buffer._uuid === undefined ) { - if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; + this.array.buffer._uuid = generateUUID(); } - scope.manager.itemStart( url ); - - image.src = url; + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { - return image; + data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); - }, + } - setCrossOrigin: function ( value ) { + // - this.crossOrigin = value; - return this; + return { + uuid: this.uuid, + buffer: this.array.buffer._uuid, + type: this.array.constructor.name, + stride: this.stride + }; - }, + } - setPath: function ( value ) { + } - this.path = value; - return this; + const _vector$6 = /*@__PURE__*/ new Vector3(); - } + class InterleavedBufferAttribute { - } ); + constructor( interleavedBuffer, itemSize, offset, normalized = false ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + this.isInterleavedBufferAttribute = true; - function CubeTextureLoader( manager ) { + this.name = ''; - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; - } + this.normalized = normalized; - Object.assign( CubeTextureLoader.prototype, { + } - crossOrigin: 'Anonymous', + get count() { - load: function ( urls, onLoad, onProgress, onError ) { + return this.data.count; - var texture = new CubeTexture(); + } - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); + get array() { - var loaded = 0; + return this.data.array; - function loadTexture( i ) { + } - loader.load( urls[ i ], function ( image ) { + set needsUpdate( value ) { - texture.images[ i ] = image; + this.data.needsUpdate = value; - loaded ++; + } - if ( loaded === 6 ) { + applyMatrix4( m ) { - texture.needsUpdate = true; + for ( let i = 0, l = this.data.count; i < l; i ++ ) { - if ( onLoad ) onLoad( texture ); + _vector$6.fromBufferAttribute( this, i ); - } + _vector$6.applyMatrix4( m ); - }, undefined, onError ); + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); } - for ( var i = 0; i < urls.length; ++ i ) { - - loadTexture( i ); + return this; - } + } - return texture; + applyNormalMatrix( m ) { - }, + for ( let i = 0, l = this.count; i < l; i ++ ) { - setCrossOrigin: function ( value ) { + _vector$6.fromBufferAttribute( this, i ); - this.crossOrigin = value; - return this; + _vector$6.applyNormalMatrix( m ); - }, + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); - setPath: function ( value ) { + } - this.path = value; return this; } - } ); + transformDirection( m ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + for ( let i = 0, l = this.count; i < l; i ++ ) { - function TextureLoader( manager ) { + _vector$6.fromBufferAttribute( this, i ); - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + _vector$6.transformDirection( m ); - } + this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); - Object.assign( TextureLoader.prototype, { + } - crossOrigin: 'Anonymous', + return this; - load: function ( url, onLoad, onProgress, onError ) { + } - var texture = new Texture(); + getComponent( index, component ) { - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); + let value = this.array[ index * this.data.stride + this.offset + component ]; - loader.load( url, function ( image ) { + if ( this.normalized ) value = denormalize( value, this.array ); - texture.image = image; + return value; - // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB. - var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0; + } - texture.format = isJPEG ? RGBFormat : RGBAFormat; - texture.needsUpdate = true; + setComponent( index, component, value ) { - if ( onLoad !== undefined ) { + if ( this.normalized ) value = normalize( value, this.array ); - onLoad( texture ); + this.data.array[ index * this.data.stride + this.offset + component ] = value; - } + return this; - }, onProgress, onError ); + } - return texture; + setX( index, x ) { - }, + if ( this.normalized ) x = normalize( x, this.array ); - setCrossOrigin: function ( value ) { + this.data.array[ index * this.data.stride + this.offset ] = x; - this.crossOrigin = value; return this; - }, + } - setPath: function ( value ) { + setY( index, y ) { + + if ( this.normalized ) y = normalize( y, this.array ); + + this.data.array[ index * this.data.stride + this.offset + 1 ] = y; - this.path = value; return this; } - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Extensible curve object - * - * Some common of curve methods: - * .getPoint( t, optionalTarget ), .getTangent( t ) - * .getPointAt( u, optionalTarget ), .getTangentAt( u ) - * .getPoints(), .getSpacedPoints() - * .getLength() - * .updateArcLengths() - * - * This following curves inherit from THREE.Curve: - * - * -- 2D curves -- - * THREE.ArcCurve - * THREE.CubicBezierCurve - * THREE.EllipseCurve - * THREE.LineCurve - * THREE.QuadraticBezierCurve - * THREE.SplineCurve - * - * -- 3D curves -- - * THREE.CatmullRomCurve3 - * THREE.CubicBezierCurve3 - * THREE.LineCurve3 - * THREE.QuadraticBezierCurve3 - * - * A series of curves can be represented as a THREE.CurvePath. - * - **/ + setZ( index, z ) { - /************************************************************** - * Abstract Curve base class - **************************************************************/ + if ( this.normalized ) z = normalize( z, this.array ); - function Curve() { + this.data.array[ index * this.data.stride + this.offset + 2 ] = z; - this.type = 'Curve'; + return this; - this.arcLengthDivisions = 200; + } - } + setW( index, w ) { - Object.assign( Curve.prototype, { + if ( this.normalized ) w = normalize( w, this.array ); - // Virtual base class method to overwrite and implement in subclasses - // - t [0 .. 1] + this.data.array[ index * this.data.stride + this.offset + 3 ] = w; - getPoint: function ( /* t, optionalTarget */ ) { + return this; - console.warn( 'THREE.Curve: .getPoint() not implemented.' ); - return null; + } - }, + getX( index ) { - // Get point at relative position in curve according to arc length - // - u [0 .. 1] + let x = this.data.array[ index * this.data.stride + this.offset ]; - getPointAt: function ( u, optionalTarget ) { + if ( this.normalized ) x = denormalize( x, this.array ); - var t = this.getUtoTmapping( u ); - return this.getPoint( t, optionalTarget ); + return x; - }, + } - // Get sequence of points using getPoint( t ) + getY( index ) { - getPoints: function ( divisions ) { + let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; - if ( divisions === undefined ) divisions = 5; + if ( this.normalized ) y = denormalize( y, this.array ); - var points = []; + return y; - for ( var d = 0; d <= divisions; d ++ ) { + } - points.push( this.getPoint( d / divisions ) ); + getZ( index ) { - } + let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; - return points; + if ( this.normalized ) z = denormalize( z, this.array ); - }, + return z; - // Get sequence of points using getPointAt( u ) + } - getSpacedPoints: function ( divisions ) { + getW( index ) { - if ( divisions === undefined ) divisions = 5; + let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; - var points = []; + if ( this.normalized ) w = denormalize( w, this.array ); - for ( var d = 0; d <= divisions; d ++ ) { + return w; - points.push( this.getPointAt( d / divisions ) ); + } - } + setXY( index, x, y ) { - return points; + index = index * this.data.stride + this.offset; - }, + if ( this.normalized ) { - // Get total curve arc length + x = normalize( x, this.array ); + y = normalize( y, this.array ); - getLength: function () { + } - var lengths = this.getLengths(); - return lengths[ lengths.length - 1 ]; + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; - }, + return this; - // Get list of cumulative segment lengths + } - getLengths: function ( divisions ) { + setXYZ( index, x, y, z ) { - if ( divisions === undefined ) divisions = this.arcLengthDivisions; + index = index * this.data.stride + this.offset; - if ( this.cacheArcLengths && - ( this.cacheArcLengths.length === divisions + 1 ) && - ! this.needsUpdate ) { + if ( this.normalized ) { - return this.cacheArcLengths; + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); } - this.needsUpdate = false; + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; + + return this; + + } - var cache = []; - var current, last = this.getPoint( 0 ); - var p, sum = 0; + setXYZW( index, x, y, z, w ) { - cache.push( 0 ); + index = index * this.data.stride + this.offset; - for ( p = 1; p <= divisions; p ++ ) { + if ( this.normalized ) { - current = this.getPoint( p / divisions ); - sum += current.distanceTo( last ); - cache.push( sum ); - last = current; + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); } - this.cacheArcLengths = cache; + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; + this.data.array[ index + 3 ] = w; - return cache; // { sums: cache, sum: sum }; Sum is in the last element. + return this; - }, + } - updateArcLengths: function () { + clone( data ) { - this.needsUpdate = true; - this.getLengths(); + if ( data === undefined ) { - }, + console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); - // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant + const array = []; - getUtoTmapping: function ( u, distance ) { + for ( let i = 0; i < this.count; i ++ ) { - var arcLengths = this.getLengths(); + const index = i * this.data.stride + this.offset; - var i = 0, il = arcLengths.length; + for ( let j = 0; j < this.itemSize; j ++ ) { - var targetArcLength; // The targeted u distance value to get + array.push( this.data.array[ index + j ] ); - if ( distance ) { + } + + } - targetArcLength = distance; + return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); } else { - targetArcLength = u * arcLengths[ il - 1 ]; + if ( data.interleavedBuffers === undefined ) { - } + data.interleavedBuffers = {}; - // binary search for the index with largest value smaller than target u distance + } - var low = 0, high = il - 1, comparison; + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { - while ( low <= high ) { + data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); - i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats + } - comparison = arcLengths[ i ] - targetArcLength; + return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); - if ( comparison < 0 ) { + } - low = i + 1; + } - } else if ( comparison > 0 ) { + toJSON( data ) { - high = i - 1; + if ( data === undefined ) { - } else { + console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); - high = i; - break; + const array = []; - // DONE + for ( let i = 0; i < this.count; i ++ ) { - } + const index = i * this.data.stride + this.offset; - } + for ( let j = 0; j < this.itemSize; j ++ ) { - i = high; + array.push( this.data.array[ index + j ] ); - if ( arcLengths[ i ] === targetArcLength ) { + } - return i / ( il - 1 ); + } - } + // de-interleave data and save it as an ordinary buffer attribute for now - // we could get finer grain at lengths, or use simple interpolation between two points + return { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: array, + normalized: this.normalized + }; - var lengthBefore = arcLengths[ i ]; - var lengthAfter = arcLengths[ i + 1 ]; + } else { - var segmentLength = lengthAfter - lengthBefore; + // save as true interleaved attribute - // determine where we are between the 'before' and 'after' points + if ( data.interleavedBuffers === undefined ) { - var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; + data.interleavedBuffers = {}; - // add that fractional amount to t + } - var t = ( i + segmentFraction ) / ( il - 1 ); + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { - return t; + data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); - }, + } - // Returns a unit vector tangent at t - // In case any sub curve does not implement its tangent derivation, - // 2 points a small delta apart will be used to find its gradient - // which seems to give a reasonable approximation + return { + isInterleavedBufferAttribute: true, + itemSize: this.itemSize, + data: this.data.uuid, + offset: this.offset, + normalized: this.normalized + }; - getTangent: function ( t ) { + } - var delta = 0.0001; - var t1 = t - delta; - var t2 = t + delta; + } - // Capping in case of danger + } - if ( t1 < 0 ) t1 = 0; - if ( t2 > 1 ) t2 = 1; + class SpriteMaterial extends Material { - var pt1 = this.getPoint( t1 ); - var pt2 = this.getPoint( t2 ); + constructor( parameters ) { - var vec = pt2.clone().sub( pt1 ); - return vec.normalize(); + super(); - }, + this.isSpriteMaterial = true; - getTangentAt: function ( u ) { + this.type = 'SpriteMaterial'; - var t = this.getUtoTmapping( u ); - return this.getTangent( t ); + this.color = new Color( 0xffffff ); - }, + this.map = null; - computeFrenetFrames: function ( segments, closed ) { + this.alphaMap = null; - // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf + this.rotation = 0; - var normal = new Vector3(); + this.sizeAttenuation = true; - var tangents = []; - var normals = []; - var binormals = []; + this.transparent = true; - var vec = new Vector3(); - var mat = new Matrix4(); + this.fog = true; - var i, u, theta; + this.setValues( parameters ); - // compute the tangent vectors for each segment on the curve + } - for ( i = 0; i <= segments; i ++ ) { + copy( source ) { - u = i / segments; + super.copy( source ); - tangents[ i ] = this.getTangentAt( u ); - tangents[ i ].normalize(); + this.color.copy( source.color ); - } + this.map = source.map; - // select an initial normal vector perpendicular to the first tangent vector, - // and in the direction of the minimum tangent xyz component + this.alphaMap = source.alphaMap; - normals[ 0 ] = new Vector3(); - binormals[ 0 ] = new Vector3(); - var min = Number.MAX_VALUE; - var tx = Math.abs( tangents[ 0 ].x ); - var ty = Math.abs( tangents[ 0 ].y ); - var tz = Math.abs( tangents[ 0 ].z ); + this.rotation = source.rotation; - if ( tx <= min ) { + this.sizeAttenuation = source.sizeAttenuation; - min = tx; - normal.set( 1, 0, 0 ); + this.fog = source.fog; - } + return this; - if ( ty <= min ) { + } - min = ty; - normal.set( 0, 1, 0 ); + } - } + let _geometry; - if ( tz <= min ) { + const _intersectPoint = /*@__PURE__*/ new Vector3(); + const _worldScale = /*@__PURE__*/ new Vector3(); + const _mvPosition = /*@__PURE__*/ new Vector3(); - normal.set( 0, 0, 1 ); + const _alignedPosition = /*@__PURE__*/ new Vector2(); + const _rotatedPosition = /*@__PURE__*/ new Vector2(); + const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); - } + const _vA$2 = /*@__PURE__*/ new Vector3(); + const _vB$2 = /*@__PURE__*/ new Vector3(); + const _vC$2 = /*@__PURE__*/ new Vector3(); - vec.crossVectors( tangents[ 0 ], normal ).normalize(); + const _uvA = /*@__PURE__*/ new Vector2(); + const _uvB = /*@__PURE__*/ new Vector2(); + const _uvC = /*@__PURE__*/ new Vector2(); - normals[ 0 ].crossVectors( tangents[ 0 ], vec ); - binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); + class Sprite extends Object3D { + constructor( material = new SpriteMaterial() ) { - // compute the slowly-varying normal and binormal vectors for each segment on the curve + super(); - for ( i = 1; i <= segments; i ++ ) { + this.isSprite = true; - normals[ i ] = normals[ i - 1 ].clone(); + this.type = 'Sprite'; - binormals[ i ] = binormals[ i - 1 ].clone(); + if ( _geometry === undefined ) { - vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); + _geometry = new BufferGeometry(); - if ( vec.length() > Number.EPSILON ) { + 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 + ] ); - vec.normalize(); + const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); - theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors + _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 ) ); - normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); + } - } + this.geometry = _geometry; + this.material = material; - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + this.center = new Vector2( 0.5, 0.5 ); - } + } - // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same + raycast( raycaster, intersects ) { - if ( closed === true ) { + if ( raycaster.camera === null ) { - theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); - theta /= segments; + console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); - if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { + } - theta = - theta; + _worldScale.setFromMatrixScale( this.matrixWorld ); - } + _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); + this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); - for ( i = 1; i <= segments; i ++ ) { + _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); - // twist a little... - normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { - } + _worldScale.multiplyScalar( - _mvPosition.z ); } - return { - tangents: tangents, - normals: normals, - binormals: binormals - }; + const rotation = this.material.rotation; + let sin, cos; - }, + if ( rotation !== 0 ) { - clone: function () { + cos = Math.cos( rotation ); + sin = Math.sin( rotation ); - return new this.constructor().copy( this ); + } - }, + const center = this.center; - copy: function ( source ) { + transformVertex( _vA$2.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vB$2.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vC$2.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); - this.arcLengthDivisions = source.arcLengthDivisions; + _uvA.set( 0, 0 ); + _uvB.set( 1, 0 ); + _uvC.set( 1, 1 ); - return this; + // check first triangle + let intersect = raycaster.ray.intersectTriangle( _vA$2, _vB$2, _vC$2, false, _intersectPoint ); - }, + if ( intersect === null ) { - toJSON: function () { + // check second triangle + transformVertex( _vB$2.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + _uvB.set( 0, 1 ); + + intersect = raycaster.ray.intersectTriangle( _vA$2, _vC$2, _vB$2, false, _intersectPoint ); + if ( intersect === null ) { + + return; - var data = { - metadata: { - version: 4.5, - type: 'Curve', - generator: 'Curve.toJSON' } - }; - data.arcLengthDivisions = this.arcLengthDivisions; - data.type = this.type; + } - return data; + const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); - }, + if ( distance < raycaster.near || distance > raycaster.far ) return; - fromJSON: function ( json ) { + intersects.push( { - this.arcLengthDivisions = json.arcLengthDivisions; + distance: distance, + point: _intersectPoint.clone(), + uv: Triangle.getInterpolation( _intersectPoint, _vA$2, _vB$2, _vC$2, _uvA, _uvB, _uvC, new Vector2() ), + face: null, + object: this - return this; + } ); } - } ); + copy( source, recursive ) { - function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + super.copy( source, recursive ); - Curve.call( this ); + if ( source.center !== undefined ) this.center.copy( source.center ); - this.type = 'EllipseCurve'; + this.material = source.material; - this.aX = aX || 0; - this.aY = aY || 0; + return this; - this.xRadius = xRadius || 1; - this.yRadius = yRadius || 1; + } - this.aStartAngle = aStartAngle || 0; - this.aEndAngle = aEndAngle || 2 * Math.PI; + } - this.aClockwise = aClockwise || false; + function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { - this.aRotation = aRotation || 0; + // compute position in camera space + _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); - } + // to check if rotation is not zero + if ( sin !== undefined ) { - EllipseCurve.prototype = Object.create( Curve.prototype ); - EllipseCurve.prototype.constructor = EllipseCurve; + _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); + _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); - EllipseCurve.prototype.isEllipseCurve = true; + } else { - EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) { + _rotatedPosition.copy( _alignedPosition ); - var point = optionalTarget || new Vector2(); + } - var twoPi = Math.PI * 2; - var deltaAngle = this.aEndAngle - this.aStartAngle; - var samePoints = Math.abs( deltaAngle ) < Number.EPSILON; - // ensures that deltaAngle is 0 .. 2 PI - while ( deltaAngle < 0 ) deltaAngle += twoPi; - while ( deltaAngle > twoPi ) deltaAngle -= twoPi; + vertexPosition.copy( mvPosition ); + vertexPosition.x += _rotatedPosition.x; + vertexPosition.y += _rotatedPosition.y; - if ( deltaAngle < Number.EPSILON ) { + // transform to world space + vertexPosition.applyMatrix4( _viewWorldMatrix ); - if ( samePoints ) { + } - deltaAngle = 0; + const _basePosition = /*@__PURE__*/ new Vector3(); - } else { + const _skinIndex = /*@__PURE__*/ new Vector4(); + const _skinWeight = /*@__PURE__*/ new Vector4(); - deltaAngle = twoPi; + const _vector3 = /*@__PURE__*/ new Vector3(); + const _matrix4 = /*@__PURE__*/ new Matrix4(); + const _vertex = /*@__PURE__*/ new Vector3(); - } + const _sphere$4 = /*@__PURE__*/ new Sphere(); + const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); + const _ray$2 = /*@__PURE__*/ new Ray(); - } + class SkinnedMesh extends Mesh { - if ( this.aClockwise === true && ! samePoints ) { + constructor( geometry, material ) { - if ( deltaAngle === twoPi ) { + super( geometry, material ); - deltaAngle = - twoPi; + this.isSkinnedMesh = true; - } else { + this.type = 'SkinnedMesh'; - deltaAngle = deltaAngle - twoPi; + this.bindMode = AttachedBindMode; + this.bindMatrix = new Matrix4(); + this.bindMatrixInverse = new Matrix4(); - } + this.boundingBox = null; + this.boundingSphere = null; } - var angle = this.aStartAngle + t * deltaAngle; - var x = this.aX + this.xRadius * Math.cos( angle ); - var y = this.aY + this.yRadius * Math.sin( angle ); + computeBoundingBox() { - if ( this.aRotation !== 0 ) { + const geometry = this.geometry; - var cos = Math.cos( this.aRotation ); - var sin = Math.sin( this.aRotation ); - - var tx = x - this.aX; - var ty = y - this.aY; + if ( this.boundingBox === null ) { - // Rotate the point about the center of the ellipse. - x = tx * cos - ty * sin + this.aX; - y = tx * sin + ty * cos + this.aY; + this.boundingBox = new Box3(); - } + } - return point.set( x, y ); + this.boundingBox.makeEmpty(); - }; + const positionAttribute = geometry.getAttribute( 'position' ); - EllipseCurve.prototype.copy = function ( source ) { + for ( let i = 0; i < positionAttribute.count; i ++ ) { - Curve.prototype.copy.call( this, source ); + this.getVertexPosition( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); - this.aX = source.aX; - this.aY = source.aY; + } - this.xRadius = source.xRadius; - this.yRadius = source.yRadius; + } - this.aStartAngle = source.aStartAngle; - this.aEndAngle = source.aEndAngle; + computeBoundingSphere() { - this.aClockwise = source.aClockwise; + const geometry = this.geometry; - this.aRotation = source.aRotation; + if ( this.boundingSphere === null ) { - return this; + this.boundingSphere = new Sphere(); - }; + } + this.boundingSphere.makeEmpty(); - EllipseCurve.prototype.toJSON = function () { + const positionAttribute = geometry.getAttribute( 'position' ); - var data = Curve.prototype.toJSON.call( this ); + for ( let i = 0; i < positionAttribute.count; i ++ ) { - data.aX = this.aX; - data.aY = this.aY; + this.getVertexPosition( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); - data.xRadius = this.xRadius; - data.yRadius = this.yRadius; + } - data.aStartAngle = this.aStartAngle; - data.aEndAngle = this.aEndAngle; + } - data.aClockwise = this.aClockwise; + copy( source, recursive ) { - data.aRotation = this.aRotation; + super.copy( source, recursive ); - return data; + this.bindMode = source.bindMode; + this.bindMatrix.copy( source.bindMatrix ); + this.bindMatrixInverse.copy( source.bindMatrixInverse ); - }; + this.skeleton = source.skeleton; - EllipseCurve.prototype.fromJSON = function ( json ) { + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); - Curve.prototype.fromJSON.call( this, json ); + return this; - this.aX = json.aX; - this.aY = json.aY; + } - this.xRadius = json.xRadius; - this.yRadius = json.yRadius; + raycast( raycaster, intersects ) { - this.aStartAngle = json.aStartAngle; - this.aEndAngle = json.aEndAngle; + const material = this.material; + const matrixWorld = this.matrixWorld; - this.aClockwise = json.aClockwise; + if ( material === undefined ) return; - this.aRotation = json.aRotation; + // test with bounding sphere in world space - return this; + if ( this.boundingSphere === null ) this.computeBoundingSphere(); - }; + _sphere$4.copy( this.boundingSphere ); + _sphere$4.applyMatrix4( matrixWorld ); - function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; - EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + // convert ray to local space of skinned mesh - this.type = 'ArcCurve'; + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); - } + // test with bounding box in local space - ArcCurve.prototype = Object.create( EllipseCurve.prototype ); - ArcCurve.prototype.constructor = ArcCurve; + if ( this.boundingBox !== null ) { - ArcCurve.prototype.isArcCurve = true; + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; - /** - * @author zz85 https://github.com/zz85 - * - * Centripetal CatmullRom Curve - which is useful for avoiding - * cusps and self-intersections in non-uniform catmull rom curves. - * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf - * - * curve.type accepts centripetal(default), chordal and catmullrom - * curve.tension is used for catmullrom which defaults to 0.5 - */ + } + // test for intersections with geometry - /* - Based on an optimized c++ solution in - - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ - - http://ideone.com/NoEbVM + this._computeIntersections( raycaster, intersects, _ray$2 ); - This CubicPoly class could be used for reusing some variables and calculations, - but for three.js curve use, it could be possible inlined and flatten into a single function call - which can be placed in CurveUtils. - */ + } - function CubicPoly() { + getVertexPosition( index, target ) { - var c0 = 0, c1 = 0, c2 = 0, c3 = 0; + super.getVertexPosition( index, target ); - /* - * Compute coefficients for a cubic polynomial - * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 - * such that - * p(0) = x0, p(1) = x1 - * and - * p'(0) = t0, p'(1) = t1. - */ - function init( x0, x1, t0, t1 ) { + this.applyBoneTransform( index, target ); - c0 = x0; - c1 = t0; - c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; - c3 = 2 * x0 - 2 * x1 + t0 + t1; + return target; } - return { - - initCatmullRom: function ( x0, x1, x2, x3, tension ) { - - init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); + bind( skeleton, bindMatrix ) { - }, + this.skeleton = skeleton; - initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { + if ( bindMatrix === undefined ) { - // compute tangents when parameterized in [t1,t2] - var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; - var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; + this.updateMatrixWorld( true ); - // rescale tangents for parametrization in [0,1] - t1 *= dt1; - t2 *= dt1; + this.skeleton.calculateInverses(); - init( x1, x2, t1, t2 ); + bindMatrix = this.matrixWorld; - }, + } - calc: function ( t ) { + this.bindMatrix.copy( bindMatrix ); + this.bindMatrixInverse.copy( bindMatrix ).invert(); - var t2 = t * t; - var t3 = t2 * t; - return c0 + c1 * t + c2 * t2 + c3 * t3; + } - } + pose() { - }; + this.skeleton.pose(); - } + } - // + normalizeSkinWeights() { - var tmp = new Vector3(); - var px = new CubicPoly(); - var py = new CubicPoly(); - var pz = new CubicPoly(); + const vector = new Vector4(); - function CatmullRomCurve3( points, closed, curveType, tension ) { + const skinWeight = this.geometry.attributes.skinWeight; - Curve.call( this ); + for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { - this.type = 'CatmullRomCurve3'; + vector.fromBufferAttribute( skinWeight, i ); - this.points = points || []; - this.closed = closed || false; - this.curveType = curveType || 'centripetal'; - this.tension = tension || 0.5; + const scale = 1.0 / vector.manhattanLength(); - } + if ( scale !== Infinity ) { - CatmullRomCurve3.prototype = Object.create( Curve.prototype ); - CatmullRomCurve3.prototype.constructor = CatmullRomCurve3; + vector.multiplyScalar( scale ); - CatmullRomCurve3.prototype.isCatmullRomCurve3 = true; + } else { - CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) { + vector.set( 1, 0, 0, 0 ); // do something reasonable - var point = optionalTarget || new Vector3(); + } - var points = this.points; - var l = points.length; + skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); - var p = ( l - ( this.closed ? 0 : 1 ) ) * t; - var intPoint = Math.floor( p ); - var weight = p - intPoint; + } - if ( this.closed ) { + } - intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length; + updateMatrixWorld( force ) { - } else if ( weight === 0 && intPoint === l - 1 ) { + super.updateMatrixWorld( force ); - intPoint = l - 2; - weight = 1; + if ( this.bindMode === AttachedBindMode ) { - } + this.bindMatrixInverse.copy( this.matrixWorld ).invert(); - var p0, p1, p2, p3; // 4 points + } else if ( this.bindMode === DetachedBindMode ) { - if ( this.closed || intPoint > 0 ) { + this.bindMatrixInverse.copy( this.bindMatrix ).invert(); - p0 = points[ ( intPoint - 1 ) % l ]; + } else { - } else { + console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); - // extrapolate first point - tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); - p0 = tmp; + } } - p1 = points[ intPoint % l ]; - p2 = points[ ( intPoint + 1 ) % l ]; + applyBoneTransform( index, vector ) { - if ( this.closed || intPoint + 2 < l ) { + const skeleton = this.skeleton; + const geometry = this.geometry; - p3 = points[ ( intPoint + 2 ) % l ]; - - } else { + _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); + _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - // extrapolate last point - tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); - p3 = tmp; + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); - } + vector.set( 0, 0, 0 ); - if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { + for ( let i = 0; i < 4; i ++ ) { - // init Centripetal / Chordal Catmull-Rom - var pow = this.curveType === 'chordal' ? 0.5 : 0.25; - var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); - var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); - var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); + const weight = _skinWeight.getComponent( i ); - // safety check for repeated points - if ( dt1 < 1e-4 ) dt1 = 1.0; - if ( dt0 < 1e-4 ) dt0 = dt1; - if ( dt2 < 1e-4 ) dt2 = dt1; + if ( weight !== 0 ) { - 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 ); + const boneIndex = _skinIndex.getComponent( i ); - } else if ( this.curveType === 'catmullrom' ) { + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - 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 ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); - } + } - point.set( - px.calc( weight ), - py.calc( weight ), - pz.calc( weight ) - ); + } - return point; + return vector.applyMatrix4( this.bindMatrixInverse ); - }; + } - CatmullRomCurve3.prototype.copy = function ( source ) { + } - Curve.prototype.copy.call( this, source ); + class Bone extends Object3D { - this.points = []; + constructor() { - for ( var i = 0, l = source.points.length; i < l; i ++ ) { + super(); - var point = source.points[ i ]; + this.isBone = true; - this.points.push( point.clone() ); + this.type = 'Bone'; } - this.closed = source.closed; - this.curveType = source.curveType; - this.tension = source.tension; - - return this; + } - }; + class DataTexture extends Texture { - CatmullRomCurve3.prototype.toJSON = function () { + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { - var data = Curve.prototype.toJSON.call( this ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); - data.points = []; + this.isDataTexture = true; - for ( var i = 0, l = this.points.length; i < l; i ++ ) { + this.image = { data: data, width: width, height: height }; - var point = this.points[ i ]; - data.points.push( point.toArray() ); + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; } - data.closed = this.closed; - data.curveType = this.curveType; - data.tension = this.tension; + } - return data; + const _offsetMatrix = /*@__PURE__*/ new Matrix4(); + const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); - }; + class Skeleton { - CatmullRomCurve3.prototype.fromJSON = function ( json ) { + constructor( bones = [], boneInverses = [] ) { - Curve.prototype.fromJSON.call( this, json ); + this.uuid = generateUUID(); - this.points = []; + this.bones = bones.slice( 0 ); + this.boneInverses = boneInverses; + this.boneMatrices = null; - for ( var i = 0, l = json.points.length; i < l; i ++ ) { + this.boneTexture = null; - var point = json.points[ i ]; - this.points.push( new Vector3().fromArray( point ) ); + this.init(); } - this.closed = json.closed; - this.curveType = json.curveType; - this.tension = json.tension; + init() { - return this; + const bones = this.bones; + const boneInverses = this.boneInverses; - }; + this.boneMatrices = new Float32Array( bones.length * 16 ); - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve - */ + // calculate inverse bone matrices if necessary - function CatmullRom( t, p0, p1, p2, p3 ) { + if ( boneInverses.length === 0 ) { - var v0 = ( p2 - p0 ) * 0.5; - var v1 = ( p3 - p1 ) * 0.5; - var t2 = t * t; - var t3 = t * t2; - return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; + this.calculateInverses(); - } + } else { - // + // handle special case - function QuadraticBezierP0( t, p ) { + if ( bones.length !== boneInverses.length ) { - var k = 1 - t; - return k * k * p; + console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); - } + this.boneInverses = []; - function QuadraticBezierP1( t, p ) { + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - return 2 * ( 1 - t ) * t * p; + this.boneInverses.push( new Matrix4() ); - } + } - function QuadraticBezierP2( t, p ) { + } - return t * t * p; + } - } + } - function QuadraticBezier( t, p0, p1, p2 ) { + calculateInverses() { - return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + - QuadraticBezierP2( t, p2 ); + this.boneInverses.length = 0; - } + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - // + const inverse = new Matrix4(); - function CubicBezierP0( t, p ) { + if ( this.bones[ i ] ) { - var k = 1 - t; - return k * k * k * p; + inverse.copy( this.bones[ i ].matrixWorld ).invert(); - } + } - function CubicBezierP1( t, p ) { + this.boneInverses.push( inverse ); - var k = 1 - t; - return 3 * k * k * t * p; + } - } + } - function CubicBezierP2( t, p ) { + pose() { - return 3 * ( 1 - t ) * t * t * p; + // recover the bind-time world matrices - } + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - function CubicBezierP3( t, p ) { + const bone = this.bones[ i ]; - return t * t * t * p; + if ( bone ) { - } + bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); - function CubicBezier( t, p0, p1, p2, p3 ) { + } - return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + - CubicBezierP3( t, p3 ); + } - } + // compute the local matrices, positions, rotations and scales - function CubicBezierCurve( v0, v1, v2, v3 ) { + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - Curve.call( this ); + const bone = this.bones[ i ]; - this.type = 'CubicBezierCurve'; + if ( bone ) { - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); - this.v3 = v3 || new Vector2(); + if ( bone.parent && bone.parent.isBone ) { - } + bone.matrix.copy( bone.parent.matrixWorld ).invert(); + bone.matrix.multiply( bone.matrixWorld ); - CubicBezierCurve.prototype = Object.create( Curve.prototype ); - CubicBezierCurve.prototype.constructor = CubicBezierCurve; + } else { - CubicBezierCurve.prototype.isCubicBezierCurve = true; + bone.matrix.copy( bone.matrixWorld ); - CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new Vector2(); + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); - var 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; + } - }; + update() { - CubicBezierCurve.prototype.copy = function ( source ) { + const bones = this.bones; + const boneInverses = this.boneInverses; + const boneMatrices = this.boneMatrices; + const boneTexture = this.boneTexture; - Curve.prototype.copy.call( this, source ); + // flatten bone matrices to array - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); + for ( let i = 0, il = bones.length; i < il; i ++ ) { - return this; + // compute the offset between the current and the original transform - }; + const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; - CubicBezierCurve.prototype.toJSON = function () { + _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); + _offsetMatrix.toArray( boneMatrices, i * 16 ); - var data = Curve.prototype.toJSON.call( this ); + } - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); - data.v3 = this.v3.toArray(); + if ( boneTexture !== null ) { - return data; + boneTexture.needsUpdate = true; - }; + } - CubicBezierCurve.prototype.fromJSON = function ( json ) { + } - Curve.prototype.fromJSON.call( this, json ); + clone() { - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); - this.v3.fromArray( json.v3 ); + return new Skeleton( this.bones, this.boneInverses ); - return this; + } - }; + computeBoneTexture() { - function CubicBezierCurve3( v0, v1, v2, v3 ) { + // layout (1 matrix = 4 pixels) + // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) + // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) + // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) + // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) + // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) - Curve.call( this ); + let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix + size = Math.ceil( size / 4 ) * 4; + size = Math.max( size, 4 ); - this.type = 'CubicBezierCurve3'; + const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel + boneMatrices.set( this.boneMatrices ); // copy current values - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); - this.v3 = v3 || new Vector3(); + const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + boneTexture.needsUpdate = true; - } + this.boneMatrices = boneMatrices; + this.boneTexture = boneTexture; - CubicBezierCurve3.prototype = Object.create( Curve.prototype ); - CubicBezierCurve3.prototype.constructor = CubicBezierCurve3; + return this; - CubicBezierCurve3.prototype.isCubicBezierCurve3 = true; + } - CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { + getBoneByName( name ) { - var point = optionalTarget || new Vector3(); + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + const bone = this.bones[ i ]; - 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 ) - ); + if ( bone.name === name ) { - return point; + return bone; - }; + } - CubicBezierCurve3.prototype.copy = function ( source ) { + } - Curve.prototype.copy.call( this, source ); + return undefined; - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); + } - return this; + dispose( ) { - }; + if ( this.boneTexture !== null ) { - CubicBezierCurve3.prototype.toJSON = function () { + this.boneTexture.dispose(); - var data = Curve.prototype.toJSON.call( this ); + this.boneTexture = null; - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); - data.v3 = this.v3.toArray(); + } - return data; + } - }; + fromJSON( json, bones ) { - CubicBezierCurve3.prototype.fromJSON = function ( json ) { + this.uuid = json.uuid; - Curve.prototype.fromJSON.call( this, json ); + for ( let i = 0, l = json.bones.length; i < l; i ++ ) { - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); - this.v3.fromArray( json.v3 ); + const uuid = json.bones[ i ]; + let bone = bones[ uuid ]; - return this; + if ( bone === undefined ) { - }; + console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); + bone = new Bone(); - function LineCurve( v1, v2 ) { + } - Curve.call( this ); + this.bones.push( bone ); + this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); - this.type = 'LineCurve'; + } - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); + this.init(); - } + return this; - LineCurve.prototype = Object.create( Curve.prototype ); - LineCurve.prototype.constructor = LineCurve; + } - LineCurve.prototype.isLineCurve = true; + toJSON() { - LineCurve.prototype.getPoint = function ( t, optionalTarget ) { + const data = { + metadata: { + version: 4.6, + type: 'Skeleton', + generator: 'Skeleton.toJSON' + }, + bones: [], + boneInverses: [] + }; - var point = optionalTarget || new Vector2(); + data.uuid = this.uuid; - if ( t === 1 ) { + const bones = this.bones; + const boneInverses = this.boneInverses; - point.copy( this.v2 ); + for ( let i = 0, l = bones.length; i < l; i ++ ) { - } else { + const bone = bones[ i ]; + data.bones.push( bone.uuid ); - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); + const boneInverse = boneInverses[ i ]; + data.boneInverses.push( boneInverse.toArray() ); - } + } - return point; + return data; - }; + } - // Line curve is linear, so we can overwrite default getPointAt + } - LineCurve.prototype.getPointAt = function ( u, optionalTarget ) { + class LineBasicMaterial extends Material { - return this.getPoint( u, optionalTarget ); + constructor( parameters ) { - }; + super(); - LineCurve.prototype.getTangent = function ( /* t */ ) { + this.isLineBasicMaterial = true; - var tangent = this.v2.clone().sub( this.v1 ); + this.type = 'LineBasicMaterial'; - return tangent.normalize(); + this.color = new Color( 0xffffff ); - }; + this.map = null; - LineCurve.prototype.copy = function ( source ) { + this.linewidth = 1; + this.linecap = 'round'; + this.linejoin = 'round'; - Curve.prototype.copy.call( this, source ); + this.fog = true; - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + this.setValues( parameters ); - return this; + } - }; - LineCurve.prototype.toJSON = function () { + copy( source ) { - var data = Curve.prototype.toJSON.call( this ); + super.copy( source ); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + this.color.copy( source.color ); - return data; + this.map = source.map; - }; + this.linewidth = source.linewidth; + this.linecap = source.linecap; + this.linejoin = source.linejoin; - LineCurve.prototype.fromJSON = function ( json ) { + this.fog = source.fog; - Curve.prototype.fromJSON.call( this, json ); + return this; - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + } - return this; + } - }; + const _vStart = /*@__PURE__*/ new Vector3(); + const _vEnd = /*@__PURE__*/ new Vector3(); - function LineCurve3( v1, v2 ) { + const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); + const _ray$1 = /*@__PURE__*/ new Ray(); + const _sphere$1 = /*@__PURE__*/ new Sphere(); - Curve.call( this ); + const _intersectPointOnRay = /*@__PURE__*/ new Vector3(); + const _intersectPointOnSegment = /*@__PURE__*/ new Vector3(); - this.type = 'LineCurve3'; + class Line extends Object3D { - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); + constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { - } + super(); + + this.isLine = true; - LineCurve3.prototype = Object.create( Curve.prototype ); - LineCurve3.prototype.constructor = LineCurve3; + this.type = 'Line'; - LineCurve3.prototype.isLineCurve3 = true; + this.geometry = geometry; + this.material = material; - LineCurve3.prototype.getPoint = function ( t, optionalTarget ) { + this.updateMorphTargets(); - var point = optionalTarget || new Vector3(); + } - if ( t === 1 ) { + copy( source, recursive ) { - point.copy( this.v2 ); + super.copy( source, recursive ); - } else { + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); + return this; } - return point; + computeLineDistances() { - }; + const geometry = this.geometry; - // Line curve is linear, so we can overwrite default getPointAt + // we assume non-indexed geometry - LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) { + if ( geometry.index === null ) { - return this.getPoint( u, optionalTarget ); + const positionAttribute = geometry.attributes.position; + const lineDistances = [ 0 ]; - }; + for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { - LineCurve3.prototype.copy = function ( source ) { + _vStart.fromBufferAttribute( positionAttribute, i - 1 ); + _vEnd.fromBufferAttribute( positionAttribute, i ); - Curve.prototype.copy.call( this, source ); + lineDistances[ i ] = lineDistances[ i - 1 ]; + lineDistances[ i ] += _vStart.distanceTo( _vEnd ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + } - return this; + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); - }; + } else { - LineCurve3.prototype.toJSON = function () { + console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); - var data = Curve.prototype.toJSON.call( this ); + } - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + return this; - return data; + } - }; + raycast( raycaster, intersects ) { - LineCurve3.prototype.fromJSON = function ( json ) { + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Line.threshold; + const drawRange = geometry.drawRange; - Curve.prototype.fromJSON.call( this, json ); + // Checking boundingSphere distance to ray - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - return this; + _sphere$1.copy( geometry.boundingSphere ); + _sphere$1.applyMatrix4( matrixWorld ); + _sphere$1.radius += threshold; - }; + if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; - function QuadraticBezierCurve( v0, v1, v2 ) { + // - Curve.call( this ); + _inverseMatrix$1.copy( matrixWorld ).invert(); + _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); - this.type = 'QuadraticBezierCurve'; + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); + const step = this.isLineSegments ? 2 : 1; - } + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; - QuadraticBezierCurve.prototype = Object.create( Curve.prototype ); - QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve; + if ( index !== null ) { - QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true; + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); - QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { + for ( let i = start, l = end - 1; i < l; i += step ) { - var point = optionalTarget || new Vector2(); + const a = index.getX( i ); + const b = index.getX( i + 1 ); - var v0 = this.v0, v1 = this.v1, v2 = this.v2; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); - point.set( - QuadraticBezier( t, v0.x, v1.x, v2.x ), - QuadraticBezier( t, v0.y, v1.y, v2.y ) - ); + if ( intersect ) { - return point; + intersects.push( intersect ); - }; + } - QuadraticBezierCurve.prototype.copy = function ( source ) { + } - Curve.prototype.copy.call( this, source ); + if ( this.isLineLoop ) { - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + const a = index.getX( end - 1 ); + const b = index.getX( start ); - return this; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); - }; + if ( intersect ) { - QuadraticBezierCurve.prototype.toJSON = function () { + intersects.push( intersect ); - var data = Curve.prototype.toJSON.call( this ); + } - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + } - return data; + } else { - }; + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); - QuadraticBezierCurve.prototype.fromJSON = function ( json ) { + for ( let i = start, l = end - 1; i < l; i += step ) { - Curve.prototype.fromJSON.call( this, json ); + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1 ); - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + if ( intersect ) { - return this; + intersects.push( intersect ); - }; + } - function QuadraticBezierCurve3( v0, v1, v2 ) { + } - Curve.call( this ); + if ( this.isLineLoop ) { - this.type = 'QuadraticBezierCurve3'; + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start ); - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); + if ( intersect ) { - } + intersects.push( intersect ); - QuadraticBezierCurve3.prototype = Object.create( Curve.prototype ); - QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3; + } - QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true; + } - QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new Vector3(); + } - var v0 = this.v0, v1 = this.v1, v2 = this.v2; + updateMorphTargets() { - 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 ) - ); + const geometry = this.geometry; - return point; + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); - }; + if ( keys.length > 0 ) { - QuadraticBezierCurve3.prototype.copy = function ( source ) { + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - Curve.prototype.copy.call( this, source ); + if ( morphAttribute !== undefined ) { - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - return this; + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - }; + const name = morphAttribute[ m ].name || String( m ); - QuadraticBezierCurve3.prototype.toJSON = function () { + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - var data = Curve.prototype.toJSON.call( this ); + } - data.v0 = this.v0.toArray(); - data.v1 = this.v1.toArray(); - data.v2 = this.v2.toArray(); + } - return data; + } - }; + } - QuadraticBezierCurve3.prototype.fromJSON = function ( json ) { + } - Curve.prototype.fromJSON.call( this, json ); + function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { - this.v0.fromArray( json.v0 ); - this.v1.fromArray( json.v1 ); - this.v2.fromArray( json.v2 ); + const positionAttribute = object.geometry.attributes.position; - return this; + _vStart.fromBufferAttribute( positionAttribute, a ); + _vEnd.fromBufferAttribute( positionAttribute, b ); - }; + const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment ); - function SplineCurve( points /* array of Vector2 */ ) { + if ( distSq > thresholdSq ) return; - Curve.call( this ); + _intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation - this.type = 'SplineCurve'; + const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay ); - this.points = points || []; + if ( distance < raycaster.near || distance > raycaster.far ) return; - } + return { - SplineCurve.prototype = Object.create( Curve.prototype ); - SplineCurve.prototype.constructor = SplineCurve; + distance: distance, + // What do we want? intersection point on the ray or on the segment?? + // point: raycaster.ray.at( distance ), + point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ), + index: a, + face: null, + faceIndex: null, + object: object - SplineCurve.prototype.isSplineCurve = true; + }; - SplineCurve.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new Vector2(); + const _start = /*@__PURE__*/ new Vector3(); + const _end = /*@__PURE__*/ new Vector3(); - var points = this.points; - var p = ( points.length - 1 ) * t; + class LineSegments extends Line { - var intPoint = Math.floor( p ); - var weight = p - intPoint; + constructor( geometry, material ) { - var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; - var p1 = points[ intPoint ]; - var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; - var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; + super( geometry, material ); - point.set( - CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), - CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) - ); + this.isLineSegments = true; - return point; + this.type = 'LineSegments'; - }; + } - SplineCurve.prototype.copy = function ( source ) { + computeLineDistances() { - Curve.prototype.copy.call( this, source ); + const geometry = this.geometry; - this.points = []; + // we assume non-indexed geometry - for ( var i = 0, l = source.points.length; i < l; i ++ ) { + if ( geometry.index === null ) { - var point = source.points[ i ]; + const positionAttribute = geometry.attributes.position; + const lineDistances = []; - this.points.push( point.clone() ); + for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) { - } + _start.fromBufferAttribute( positionAttribute, i ); + _end.fromBufferAttribute( positionAttribute, i + 1 ); - return this; + lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; + lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); - }; + } - SplineCurve.prototype.toJSON = function () { + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); - var data = Curve.prototype.toJSON.call( this ); + } else { - data.points = []; + console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); - for ( var i = 0, l = this.points.length; i < l; i ++ ) { + } - var point = this.points[ i ]; - data.points.push( point.toArray() ); + return this; } - return data; + } - }; + class PointsMaterial extends Material { - SplineCurve.prototype.fromJSON = function ( json ) { + constructor( parameters ) { - Curve.prototype.fromJSON.call( this, json ); + super(); - this.points = []; + this.isPointsMaterial = true; - for ( var i = 0, l = json.points.length; i < l; i ++ ) { + this.type = 'PointsMaterial'; - var point = json.points[ i ]; - this.points.push( new Vector2().fromArray( point ) ); + this.color = new Color( 0xffffff ); - } + this.map = null; - return this; + this.alphaMap = null; - }; + this.size = 1; + this.sizeAttenuation = true; + this.fog = true; + this.setValues( parameters ); - var Curves = Object.freeze({ - ArcCurve: ArcCurve, - CatmullRomCurve3: CatmullRomCurve3, - CubicBezierCurve: CubicBezierCurve, - CubicBezierCurve3: CubicBezierCurve3, - EllipseCurve: EllipseCurve, - LineCurve: LineCurve, - LineCurve3: LineCurve3, - QuadraticBezierCurve: QuadraticBezierCurve, - QuadraticBezierCurve3: QuadraticBezierCurve3, - SplineCurve: SplineCurve - }); + } - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - **/ + copy( source ) { - /************************************************************** - * Curved Path - a curve path is simply a array of connected - * curves, but retains the api of a curve - **************************************************************/ + super.copy( source ); - function CurvePath() { + this.color.copy( source.color ); - Curve.call( this ); + this.map = source.map; - this.type = 'CurvePath'; + this.alphaMap = source.alphaMap; - this.curves = []; - this.autoClose = false; // Automatically closes the path + this.size = source.size; + this.sizeAttenuation = source.sizeAttenuation; - } + this.fog = source.fog; - CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), { + return this; - constructor: CurvePath, + } - add: function ( curve ) { + } - this.curves.push( curve ); + const _inverseMatrix = /*@__PURE__*/ new Matrix4(); + const _ray = /*@__PURE__*/ new Ray(); + const _sphere = /*@__PURE__*/ new Sphere(); + const _position$2 = /*@__PURE__*/ new Vector3(); - }, + class Points$1 extends Object3D { - closePath: function () { + constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { - // Add a line curve if start and end of lines are not connected - var startPoint = this.curves[ 0 ].getPoint( 0 ); - var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); + super(); - if ( ! startPoint.equals( endPoint ) ) { + this.isPoints = true; - this.curves.push( new LineCurve( endPoint, startPoint ) ); + this.type = 'Points'; - } + this.geometry = geometry; + this.material = material; - }, + this.updateMorphTargets(); - // To get accurate point with reference to - // entire path distance at time t, - // following has to be done: + } - // 1. Length of each sub path have to be known - // 2. Locate and identify type of curve - // 3. Get t for the curve - // 4. Return curve.getPointAt(t') + copy( source, recursive ) { - getPoint: function ( t ) { + super.copy( source, recursive ); - var d = t * this.getLength(); - var curveLengths = this.getCurveLengths(); - var i = 0; + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; - // To think about boundaries points. + return this; - while ( i < curveLengths.length ) { + } - if ( curveLengths[ i ] >= d ) { + raycast( raycaster, intersects ) { - var diff = curveLengths[ i ] - d; - var curve = this.curves[ i ]; + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Points.threshold; + const drawRange = geometry.drawRange; - var segmentLength = curve.getLength(); - var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; + // Checking boundingSphere distance to ray - return curve.getPointAt( u ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - } + _sphere.copy( geometry.boundingSphere ); + _sphere.applyMatrix4( matrixWorld ); + _sphere.radius += threshold; - i ++; + if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; - } + // - return null; + _inverseMatrix.copy( matrixWorld ).invert(); + _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); - // loop where sum != 0, sum > d , sum+1 0 ) { - this.cacheLengths = lengths; + const morphAttribute = morphAttributes[ keys[ 0 ] ]; - return lengths; + if ( morphAttribute !== undefined ) { - }, + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - getSpacedPoints: function ( divisions ) { + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - if ( divisions === undefined ) divisions = 40; + const name = morphAttribute[ m ].name || String( m ); - var points = []; + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - for ( var i = 0; i <= divisions; i ++ ) { + } - points.push( this.getPoint( i / divisions ) ); + } } - if ( this.autoClose ) { + } + + } - points.push( points[ 0 ] ); + function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { - } + const rayPointDistanceSq = _ray.distanceSqToPoint( point ); - return points; + if ( rayPointDistanceSq < localThresholdSq ) { - }, + const intersectPoint = new Vector3(); - getPoints: function ( divisions ) { + _ray.closestPointToPoint( point, intersectPoint ); + intersectPoint.applyMatrix4( matrixWorld ); - divisions = divisions || 12; + const distance = raycaster.ray.origin.distanceTo( intersectPoint ); - var points = [], last; + if ( distance < raycaster.near || distance > raycaster.far ) return; - for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) { + intersects.push( { - var curve = curves[ i ]; - var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2 - : ( curve && curve.isLineCurve ) ? 1 - : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length - : divisions; + distance: distance, + distanceToRay: Math.sqrt( rayPointDistanceSq ), + point: intersectPoint, + index: index, + face: null, + object: object - var pts = curve.getPoints( resolution ); + } ); - for ( var j = 0; j < pts.length; j ++ ) { + } - var point = pts[ j ]; + } - if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates + class CylinderGeometry extends BufferGeometry { - points.push( point ); - last = point; + constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { - } + super(); - } + this.type = 'CylinderGeometry'; - if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { + this.parameters = { + radiusTop: radiusTop, + radiusBottom: radiusBottom, + height: height, + radialSegments: radialSegments, + heightSegments: heightSegments, + openEnded: openEnded, + thetaStart: thetaStart, + thetaLength: thetaLength + }; - points.push( points[ 0 ] ); + const scope = this; - } + radialSegments = Math.floor( radialSegments ); + heightSegments = Math.floor( heightSegments ); - return points; + // buffers - }, + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - copy: function ( source ) { + // helper variables - Curve.prototype.copy.call( this, source ); + let index = 0; + const indexArray = []; + const halfHeight = height / 2; + let groupStart = 0; - this.curves = []; + // generate geometry - for ( var i = 0, l = source.curves.length; i < l; i ++ ) { + generateTorso(); - var curve = source.curves[ i ]; + if ( openEnded === false ) { - this.curves.push( curve.clone() ); + if ( radiusTop > 0 ) generateCap( true ); + if ( radiusBottom > 0 ) generateCap( false ); } - this.autoClose = source.autoClose; + // build geometry - return this; + 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 generateTorso() { - toJSON: function () { + const normal = new Vector3(); + const vertex = new Vector3(); - var data = Curve.prototype.toJSON.call( this ); + let groupCount = 0; - data.autoClose = this.autoClose; - data.curves = []; + // this will be used to calculate the normal + const slope = ( radiusBottom - radiusTop ) / height; - for ( var i = 0, l = this.curves.length; i < l; i ++ ) { + // generate vertices, normals and uvs - var curve = this.curves[ i ]; - data.curves.push( curve.toJSON() ); + for ( let y = 0; y <= heightSegments; y ++ ) { - } + const indexRow = []; - return data; + const v = y / heightSegments; - }, + // calculate the radius of the current row - fromJSON: function ( json ) { + const radius = v * ( radiusBottom - radiusTop ) + radiusTop; - Curve.prototype.fromJSON.call( this, json ); + for ( let x = 0; x <= radialSegments; x ++ ) { - this.autoClose = json.autoClose; - this.curves = []; + const u = x / radialSegments; - for ( var i = 0, l = json.curves.length; i < l; i ++ ) { + const theta = u * thetaLength + thetaStart; - var curve = json.curves[ i ]; - this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); + const sinTheta = Math.sin( theta ); + const cosTheta = Math.cos( theta ); - } + // vertex - return this; + vertex.x = radius * sinTheta; + vertex.y = - v * height + halfHeight; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); - } + // normal - } ); + normal.set( sinTheta, slope, cosTheta ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Creates free form 2d path using series of points, lines or curves. - **/ + // uv - function Path$1( points ) { + uvs.push( u, 1 - v ); - CurvePath.call( this ); + // save index of vertex in respective row - this.type = 'Path'; + indexRow.push( index ++ ); - this.currentPoint = new Vector2(); + } - if ( points ) { + // now save vertices of the row in our index array - this.setFromPoints( points ); + indexArray.push( indexRow ); - } + } - } + // generate indices - Path$1.prototype = Object.assign( Object.create( CurvePath.prototype ), { + for ( let x = 0; x < radialSegments; x ++ ) { - constructor: Path$1, + for ( let y = 0; y < heightSegments; y ++ ) { - setFromPoints: function ( points ) { + // we use the index array to access the correct indices - this.moveTo( points[ 0 ].x, points[ 0 ].y ); + const a = indexArray[ y ][ x ]; + const b = indexArray[ y + 1 ][ x ]; + const c = indexArray[ y + 1 ][ x + 1 ]; + const d = indexArray[ y ][ x + 1 ]; - for ( var i = 1, l = points.length; i < l; i ++ ) { + // faces - this.lineTo( points[ i ].x, points[ i ].y ); + indices.push( a, b, d ); + indices.push( b, c, d ); - } + // update group counter - }, + groupCount += 6; - moveTo: function ( x, y ) { + } - this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? + } - }, + // add a group to the geometry. this will ensure multi material support - lineTo: function ( x, y ) { + scope.addGroup( groupStart, groupCount, 0 ); - var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); - this.curves.push( curve ); + // calculate new start value for groups - this.currentPoint.set( x, y ); + groupStart += groupCount; - }, + } - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { + function generateCap( top ) { - var curve = new QuadraticBezierCurve( - this.currentPoint.clone(), - new Vector2( aCPx, aCPy ), - new Vector2( aX, aY ) - ); + // save the index of the first center vertex + const centerIndexStart = index; - this.curves.push( curve ); + const uv = new Vector2(); + const vertex = new Vector3(); - this.currentPoint.set( aX, aY ); + let groupCount = 0; - }, + const radius = ( top === true ) ? radiusTop : radiusBottom; + const sign = ( top === true ) ? 1 : - 1; - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + // first we generate the center vertex data of the cap. + // because the geometry needs one set of uvs per face, + // we must generate a center vertex per face/segment - var curve = new CubicBezierCurve( - this.currentPoint.clone(), - new Vector2( aCP1x, aCP1y ), - new Vector2( aCP2x, aCP2y ), - new Vector2( aX, aY ) - ); + for ( let x = 1; x <= radialSegments; x ++ ) { - this.curves.push( curve ); + // vertex - this.currentPoint.set( aX, aY ); + vertices.push( 0, halfHeight * sign, 0 ); - }, + // normal - splineThru: function ( pts /*Array of Vector*/ ) { + normals.push( 0, sign, 0 ); - var npts = [ this.currentPoint.clone() ].concat( pts ); + // uv - var curve = new SplineCurve( npts ); - this.curves.push( curve ); + uvs.push( 0.5, 0.5 ); - this.currentPoint.copy( pts[ pts.length - 1 ] ); + // increase index - }, + index ++; - arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + } - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; + // save the index of the last center vertex + const centerIndexEnd = index; - this.absarc( aX + x0, aY + y0, aRadius, - aStartAngle, aEndAngle, aClockwise ); + // now we generate the surrounding vertices, normals and uvs - }, + for ( let x = 0; x <= radialSegments; x ++ ) { - absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + const u = x / radialSegments; + const theta = u * thetaLength + thetaStart; - this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + const cosTheta = Math.cos( theta ); + const sinTheta = Math.sin( theta ); - }, + // vertex - ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + vertex.x = radius * sinTheta; + vertex.y = halfHeight * sign; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; + // normal - this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + normals.push( 0, sign, 0 ); - }, + // uv - absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + uv.x = ( cosTheta * 0.5 ) + 0.5; + uv.y = ( sinTheta * 0.5 * sign ) + 0.5; + uvs.push( uv.x, uv.y ); - var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + // increase index - if ( this.curves.length > 0 ) { + index ++; - // if a previous curve is present, attempt to join - var firstPoint = curve.getPoint( 0 ); + } - if ( ! firstPoint.equals( this.currentPoint ) ) { + // generate indices - this.lineTo( firstPoint.x, firstPoint.y ); + for ( let x = 0; x < radialSegments; x ++ ) { - } + const c = centerIndexStart + x; + const i = centerIndexEnd + x; - } + if ( top === true ) { - this.curves.push( curve ); + // face top - var lastPoint = curve.getPoint( 1 ); - this.currentPoint.copy( lastPoint ); + indices.push( i, i + 1, c ); - }, + } else { - copy: function ( source ) { + // face bottom - CurvePath.prototype.copy.call( this, source ); + indices.push( i + 1, i, c ); - this.currentPoint.copy( source.currentPoint ); + } - return this; + groupCount += 3; - }, + } - toJSON: function () { + // add a group to the geometry. this will ensure multi material support - var data = CurvePath.prototype.toJSON.call( this ); + scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); - data.currentPoint = this.currentPoint.toArray(); + // calculate new start value for groups - return data; + groupStart += groupCount; - }, + } - fromJSON: function ( json ) { + } - CurvePath.prototype.fromJSON.call( this, json ); + copy( source ) { - this.currentPoint.fromArray( json.currentPoint ); + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); return this; } - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Defines a 2d shape plane using paths. - **/ - - // STEP 1 Create a path. - // STEP 2 Turn path into shape. - // STEP 3 ExtrudeGeometry takes in Shape/Shapes - // STEP 3a - Extract points from each shape, turn to vertices - // STEP 3b - Triangulate each shape, add faces. + static fromJSON( data ) { - function Shape( points ) { + return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); - Path$1.call( this, points ); - - this.uuid = _Math.generateUUID(); - - this.type = 'Shape'; - - this.holes = []; + } } - Shape.prototype = Object.assign( Object.create( Path$1.prototype ), { + class SphereGeometry extends BufferGeometry { - constructor: Shape, + constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { - getPointsHoles: function ( divisions ) { + super(); - var holesPts = []; + this.type = 'SphereGeometry'; - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { - - holesPts[ i ] = this.holes[ i ].getPoints( divisions ); - - } - - return holesPts; + this.parameters = { + radius: radius, + widthSegments: widthSegments, + heightSegments: heightSegments, + phiStart: phiStart, + phiLength: phiLength, + thetaStart: thetaStart, + thetaLength: thetaLength + }; - }, + widthSegments = Math.max( 3, Math.floor( widthSegments ) ); + heightSegments = Math.max( 2, Math.floor( heightSegments ) ); - // get points of shape and holes (keypoints based on segments parameter) + const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); - extractPoints: function ( divisions ) { + let index = 0; + const grid = []; - return { + const vertex = new Vector3(); + const normal = new Vector3(); - shape: this.getPoints( divisions ), - holes: this.getPointsHoles( divisions ) + // buffers - }; + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - }, + // generate vertices, normals and uvs - copy: function ( source ) { + for ( let iy = 0; iy <= heightSegments; iy ++ ) { - Path$1.prototype.copy.call( this, source ); + const verticesRow = []; - this.holes = []; + const v = iy / heightSegments; - for ( var i = 0, l = source.holes.length; i < l; i ++ ) { + // special case for the poles - var hole = source.holes[ i ]; + let uOffset = 0; - this.holes.push( hole.clone() ); + if ( iy === 0 && thetaStart === 0 ) { - } + uOffset = 0.5 / widthSegments; - return this; + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { - }, + uOffset = - 0.5 / widthSegments; - toJSON: function () { + } - var data = Path$1.prototype.toJSON.call( this ); + for ( let ix = 0; ix <= widthSegments; ix ++ ) { - data.uuid = this.uuid; - data.holes = []; + const u = ix / widthSegments; - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { + // vertex - var hole = this.holes[ i ]; - data.holes.push( hole.toJSON() ); + vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); + vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); + vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - } + vertices.push( vertex.x, vertex.y, vertex.z ); - return data; + // normal - }, + normal.copy( vertex ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - fromJSON: function ( json ) { + // uv - Path$1.prototype.fromJSON.call( this, json ); + uvs.push( u + uOffset, 1 - v ); - this.uuid = json.uuid; - this.holes = []; + verticesRow.push( index ++ ); - for ( var i = 0, l = json.holes.length; i < l; i ++ ) { + } - var hole = json.holes[ i ]; - this.holes.push( new Path$1().fromJSON( hole ) ); + grid.push( verticesRow ); } - return this; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + // indices - function Light( color, intensity ) { + for ( let iy = 0; iy < heightSegments; iy ++ ) { - Object3D.call( this ); + for ( let ix = 0; ix < widthSegments; ix ++ ) { - this.type = 'Light'; + const a = grid[ iy ][ ix + 1 ]; + const b = grid[ iy ][ ix ]; + const c = grid[ iy + 1 ][ ix ]; + const d = grid[ iy + 1 ][ ix + 1 ]; - this.color = new Color( color ); - this.intensity = intensity !== undefined ? intensity : 1; + if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); + if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); - this.receiveShadow = undefined; + } - } + } - Light.prototype = Object.assign( Object.create( Object3D.prototype ), { + // build geometry - constructor: Light, + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - isLight: true, + } - copy: function ( source ) { + copy( source ) { - Object3D.prototype.copy.call( this, source ); + super.copy( source ); - this.color.copy( source.color ); - this.intensity = source.intensity; + this.parameters = Object.assign( {}, source.parameters ); return this; - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, meta ); - - data.object.color = this.color.getHex(); - data.object.intensity = this.intensity; - - if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); - - if ( this.distance !== undefined ) data.object.distance = this.distance; - if ( this.angle !== undefined ) data.object.angle = this.angle; - if ( this.decay !== undefined ) data.object.decay = this.decay; - if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - - if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); - - return data; - } - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function HemisphereLight( skyColor, groundColor, intensity ) { - - Light.call( this, skyColor, intensity ); - - this.type = 'HemisphereLight'; - - this.castShadow = undefined; - - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); - - this.groundColor = new Color( groundColor ); - - } - - HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: HemisphereLight, - - isHemisphereLight: true, + static fromJSON( data ) { - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); - - this.groundColor.copy( source.groundColor ); - - return this; + return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function LightShadow( camera ) { + } - this.camera = camera; + class MeshPhongMaterial extends Material { - this.bias = 0; - this.radius = 1; + constructor( parameters ) { - this.mapSize = new Vector2( 512, 512 ); + super(); - this.map = null; - this.matrix = new Matrix4(); + this.isMeshPhongMaterial = true; - } + this.type = 'MeshPhongMaterial'; - Object.assign( LightShadow.prototype, { + this.color = new Color( 0xffffff ); // diffuse + this.specular = new Color( 0x111111 ); + this.shininess = 30; - copy: function ( source ) { + this.map = null; - this.camera = source.camera.clone(); + this.lightMap = null; + this.lightMapIntensity = 1.0; - this.bias = source.bias; - this.radius = source.radius; + this.aoMap = null; + this.aoMapIntensity = 1.0; - this.mapSize.copy( source.mapSize ); + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - return this; + this.bumpMap = null; + this.bumpScale = 1; - }, + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); - clone: function () { + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - return new this.constructor().copy( this ); + this.specularMap = null; - }, + this.alphaMap = null; - toJSON: function () { + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - var object = {}; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - if ( this.bias !== 0 ) object.bias = this.bias; - if ( this.radius !== 1 ) object.radius = this.radius; - if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); + this.flatShading = false; - object.camera = this.camera.toJSON( false ).object; - delete object.camera.matrix; + this.fog = true; - return object; + this.setValues( parameters ); } - } ); + copy( source ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + super.copy( source ); - function SpotLightShadow() { + this.color.copy( source.color ); + this.specular.copy( source.specular ); + this.shininess = source.shininess; - LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) ); + this.map = source.map; - } + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - constructor: SpotLightShadow, + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; - isSpotLightShadow: true, + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - update: function ( light ) { + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); - var camera = this.camera; + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - var fov = _Math.RAD2DEG * 2 * light.angle; - var aspect = this.mapSize.width / this.mapSize.height; - var far = light.distance || camera.far; + this.specularMap = source.specularMap; - if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { + this.alphaMap = source.alphaMap; - camera.fov = fov; - camera.aspect = aspect; - camera.far = far; - camera.updateProjectionMatrix(); + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + 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; - /** - * @author alteredq / http://alteredqualia.com/ - */ + return this; - function SpotLight( color, intensity, distance, angle, penumbra, decay ) { + } - Light.call( this, color, intensity ); + } - this.type = 'SpotLight'; + class MeshLambertMaterial extends Material { - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + constructor( parameters ) { - this.target = new Object3D(); + super(); - Object.defineProperty( this, 'power', { - get: function () { + this.isMeshLambertMaterial = true; - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * Math.PI; + this.type = 'MeshLambertMaterial'; - }, - set: function ( power ) { + this.color = new Color( 0xffffff ); // diffuse - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / Math.PI; + this.map = null; - } - } ); + this.lightMap = null; + this.lightMapIntensity = 1.0; - this.distance = ( distance !== undefined ) ? distance : 0; - this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; - this.penumbra = ( penumbra !== undefined ) ? penumbra : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. + this.aoMap = null; + this.aoMapIntensity = 1.0; - this.shadow = new SpotLightShadow(); + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - } + this.bumpMap = null; + this.bumpScale = 1; - SpotLight.prototype = Object.assign( Object.create( Light.prototype ), { + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); - constructor: SpotLight, + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - isSpotLight: true, + this.specularMap = null; - copy: function ( source ) { + this.alphaMap = null; - Light.prototype.copy.call( this, source ); + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - this.distance = source.distance; - this.angle = source.angle; - this.penumbra = source.penumbra; - this.decay = source.decay; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - this.target = source.target.clone(); + this.flatShading = false; - this.shadow = source.shadow.clone(); + this.fog = true; - return this; + this.setValues( parameters ); } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - - function PointLight( color, intensity, distance, decay ) { + copy( source ) { - Light.call( this, color, intensity ); + super.copy( source ); - this.type = 'PointLight'; - - Object.defineProperty( this, 'power', { - get: function () { - - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * 4 * Math.PI; + this.color.copy( source.color ); - }, - set: function ( power ) { + this.map = source.map; - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / ( 4 * Math.PI ); + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - } - } ); + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - this.distance = ( distance !== undefined ) ? distance : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; - this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - } + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); - PointLight.prototype = Object.assign( Object.create( Light.prototype ), { + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - constructor: PointLight, + this.specularMap = source.specularMap; - isPointLight: true, + this.alphaMap = source.alphaMap; - copy: function ( source ) { + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; - Light.prototype.copy.call( this, source ); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - this.distance = source.distance; - this.decay = source.decay; + this.flatShading = source.flatShading; - this.shadow = source.shadow.clone(); + this.fog = source.fog; return this; } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function DirectionalLightShadow( ) { - - LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); - } - DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { - - constructor: DirectionalLightShadow - - } ); + // converts an array to a specific type + function convertArray( array, type, forceClone ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - - function DirectionalLight( color, intensity ) { - - Light.call( this, color, intensity ); + if ( ! array || // let 'undefined' and 'null' pass + ! forceClone && array.constructor === type ) return array; - this.type = 'DirectionalLight'; + if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); + return new type( array ); // create typed array - this.target = new Object3D(); + } - this.shadow = new DirectionalLightShadow(); + return Array.prototype.slice.call( array ); // create Array } - DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: DirectionalLight, + function isTypedArray( object ) { - isDirectionalLight: true, + return ArrayBuffer.isView( object ) && + ! ( object instanceof DataView ); - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); + } - this.target = source.target.clone(); + // returns an array by which times and values can be sorted + function getKeyframeOrder( times ) { - this.shadow = source.shadow.clone(); + function compareTime( i, j ) { - return this; + return times[ i ] - times[ j ]; } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function AmbientLight( color, intensity ) { - - Light.call( this, color, intensity ); + const n = times.length; + const result = new Array( n ); + for ( let i = 0; i !== n; ++ i ) result[ i ] = i; - this.type = 'AmbientLight'; + result.sort( compareTime ); - this.castShadow = undefined; + return result; } - AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), { + // uses the array previously returned by 'getKeyframeOrder' to sort data + function sortedArray( values, stride, order ) { - constructor: AmbientLight, + const nValues = values.length; + const result = new values.constructor( nValues ); - isAmbientLight: true + for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { - } ); + const srcOffset = order[ i ] * stride; - /** - * @author abelnation / http://github.com/abelnation - */ - - function RectAreaLight( color, intensity, width, height ) { - - Light.call( this, color, intensity ); + for ( let j = 0; j !== stride; ++ j ) { - this.type = 'RectAreaLight'; + result[ dstOffset ++ ] = values[ srcOffset + j ]; - this.position.set( 0, 1, 0 ); - this.updateMatrix(); - - this.width = ( width !== undefined ) ? width : 10; - this.height = ( height !== undefined ) ? height : 10; - - // TODO (abelnation): distance/decay + } - // TODO (abelnation): update method for RectAreaLight to update transform to lookat target + } - // TODO (abelnation): shadows + return result; } - // TODO (abelnation): RectAreaLight update when light shape is changed - RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), { + // function for parsing AOS keyframe formats + function flattenJSON( jsonKeys, times, values, valuePropertyName ) { - constructor: RectAreaLight, + let i = 1, key = jsonKeys[ 0 ]; - isRectAreaLight: true, + while ( key !== undefined && key[ valuePropertyName ] === undefined ) { - copy: function ( source ) { + key = jsonKeys[ i ++ ]; - Light.prototype.copy.call( this, source ); - - this.width = source.width; - this.height = source.height; + } - return this; + if ( key === undefined ) return; // no data - }, + let value = key[ valuePropertyName ]; + if ( value === undefined ) return; // no data - toJSON: function ( meta ) { + if ( Array.isArray( value ) ) { - var data = Light.prototype.toJSON.call( this, meta ); + do { - data.object.width = this.width; - data.object.height = this.height; + value = key[ valuePropertyName ]; - return data; + if ( value !== undefined ) { - } + times.push( key.time ); + values.push.apply( values, value ); // push all elements - } ); + } - /** - * - * A Track that interpolates Strings - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + key = jsonKeys[ i ++ ]; - function StringKeyframeTrack( name, times, values, interpolation ) { + } while ( key !== undefined ); - KeyframeTrack.call( this, name, times, values, interpolation ); + } else if ( value.toArray !== undefined ) { - } + // ...assume THREE.Math-ish - StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + do { - constructor: StringKeyframeTrack, + value = key[ valuePropertyName ]; - ValueTypeName: 'string', - ValueBufferType: Array, + if ( value !== undefined ) { - DefaultInterpolation: InterpolateDiscrete, + times.push( key.time ); + value.toArray( values, values.length ); - InterpolantFactoryMethodLinear: undefined, + } - InterpolantFactoryMethodSmooth: undefined + key = jsonKeys[ i ++ ]; - } ); + } while ( key !== undefined ); - /** - * - * A Track of Boolean keyframe values. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + } else { - function BooleanKeyframeTrack( name, times, values ) { + // otherwise push as-is - KeyframeTrack.call( this, name, times, values ); + do { - } + value = key[ valuePropertyName ]; - BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { + if ( value !== undefined ) { - constructor: BooleanKeyframeTrack, + times.push( key.time ); + values.push( value ); - ValueTypeName: 'bool', - ValueBufferType: Array, + } - DefaultInterpolation: InterpolateDiscrete, + key = jsonKeys[ i ++ ]; - InterpolantFactoryMethodLinear: undefined, - InterpolantFactoryMethodSmooth: undefined + } while ( key !== undefined ); - // Note: Actually this track could have a optimized / compressed - // representation of a single value and a custom interpolant that - // computes "firstValue ^ isOdd( index )". + } - } ); + } /** * Abstract base class of interpolants over parametric samples. @@ -33917,28 +33498,29 @@ var ROS3D = (function (exports, ROSLIB) { * * http://www.oodesign.com/template-method-pattern.html * - * @author tschw */ - function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + class Interpolant { - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - this.resultBuffer = resultBuffer !== undefined ? - resultBuffer : new sampleValues.constructor( sampleSize ); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; - } + this.resultBuffer = resultBuffer !== undefined ? + resultBuffer : new sampleValues.constructor( sampleSize ); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; - Object.assign( Interpolant.prototype, { + this.settings = null; + this.DefaultSettings_ = {}; - evaluate: function ( t ) { + } - var pp = this.parameterPositions, - i1 = this._cachedIndex, + evaluate( t ) { + const pp = this.parameterPositions; + let i1 = this._cachedIndex, t1 = pp[ i1 ], t0 = pp[ i1 - 1 ]; @@ -33946,7 +33528,7 @@ var ROS3D = (function (exports, ROSLIB) { seek: { - var right; + let right; linear_scan: { @@ -33956,7 +33538,7 @@ var ROS3D = (function (exports, ROSLIB) { //- if ( t >= t1 || t1 === undefined ) { forward_scan: if ( ! ( t < t1 ) ) { - for ( var giveUpAt = i1 + 2; ; ) { + for ( let giveUpAt = i1 + 2; ; ) { if ( t1 === undefined ) { @@ -33966,7 +33548,7 @@ var ROS3D = (function (exports, ROSLIB) { i1 = pp.length; this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t, t0 ); + return this.copySampleValue_( i1 - 1 ); } @@ -33996,7 +33578,7 @@ var ROS3D = (function (exports, ROSLIB) { // looping? - var t1global = pp[ 1 ]; + const t1global = pp[ 1 ]; if ( t < t1global ) { @@ -34007,14 +33589,14 @@ var ROS3D = (function (exports, ROSLIB) { // linear reverse scan - for ( var giveUpAt = i1 - 2; ; ) { + for ( let giveUpAt = i1 - 2; ; ) { if ( t0 === undefined ) { // before start this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); + return this.copySampleValue_( 0 ); } @@ -34049,7 +33631,7 @@ var ROS3D = (function (exports, ROSLIB) { while ( i1 < right ) { - var mid = ( i1 + right ) >>> 1; + const mid = ( i1 + right ) >>> 1; if ( t < pp[ mid ] ) { @@ -34071,7 +33653,7 @@ var ROS3D = (function (exports, ROSLIB) { if ( t0 === undefined ) { this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); + return this.copySampleValue_( 0 ); } @@ -34079,7 +33661,7 @@ var ROS3D = (function (exports, ROSLIB) { i1 = pp.length; this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t0, t ); + return this.copySampleValue_( i1 - 1 ); } @@ -34093,31 +33675,24 @@ var ROS3D = (function (exports, ROSLIB) { return this.interpolate_( i1, t0, t, t1 ); - }, - - settings: null, // optional, subclass-specific settings structure - // Note: The indirection allows central control of many interpolants. - - // --- Protected interface - - DefaultSettings_: {}, + } - getSettings_: function () { + getSettings_() { return this.settings || this.DefaultSettings_; - }, + } - copySampleValue_: function ( index ) { + copySampleValue_( index ) { // copies a sample value to the result buffer - var result = this.resultBuffer, + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset = index * stride; - for ( var i = 0; i !== stride; ++ i ) { + for ( let i = 0; i !== stride; ++ i ) { result[ i ] = values[ offset + i ]; @@ -34125,211 +33700,65 @@ var ROS3D = (function (exports, ROSLIB) { return result; - }, + } // Template methods for derived classes: - interpolate_: function ( /* i1, t0, t, t1 */ ) { + interpolate_( /* i1, t0, t, t1 */ ) { throw new Error( 'call to abstract method' ); // implementations shall return this.resultBuffer - }, + } - intervalChanged_: function ( /* i1, t0, t1 */ ) { + intervalChanged_( /* i1, t0, t1 */ ) { // empty } - } ); - - //!\ DECLARE ALIAS AFTER assign prototype ! - Object.assign( Interpolant.prototype, { - - //( 0, t, t0 ), returns this.resultBuffer - beforeStart_: Interpolant.prototype.copySampleValue_, - - //( N-1, tN-1, t ), returns this.resultBuffer - afterEnd_: Interpolant.prototype.copySampleValue_, - - } ); + } /** - * Spherical linear unit quaternion interpolant. + * Fast and simple cubic spline interpolant. * - * @author tschw + * It was derived from a Hermitian construction setting the first derivative + * at each sample position to the linear slope between neighboring positions + * over their parameter interval. */ - function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + class CubicInterpolant extends Interpolant { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - } + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + this._weightPrev = - 0; + this._offsetPrev = - 0; + this._weightNext = - 0; + this._offsetNext = - 0; - constructor: QuaternionLinearInterpolant, + this.DefaultSettings_ = { - interpolate_: function ( i1, t0, t, t1 ) { + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + }; - offset = i1 * stride, + } - alpha = ( t - t0 ) / ( t1 - t0 ); + intervalChanged_( i1, t0, t1 ) { - for ( var end = offset + stride; offset !== end; offset += 4 ) { + const pp = this.parameterPositions; + let iPrev = i1 - 2, + iNext = i1 + 1, - Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); + tPrev = pp[ iPrev ], + tNext = pp[ iNext ]; - } + if ( tPrev === undefined ) { - return result; - - } - - } ); - - /** - * - * A Track of quaternion keyframe values. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function QuaternionKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrack.call( this, name, times, values, interpolation ); - - } - - QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { - - constructor: QuaternionKeyframeTrack, - - ValueTypeName: 'quaternion', - - // ValueBufferType is inherited - - DefaultInterpolation: InterpolateLinear, - - InterpolantFactoryMethodLinear: function ( result ) { - - return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); - - }, - - InterpolantFactoryMethodSmooth: undefined // not yet implemented - - } ); - - /** - * - * A Track of keyframe values that represent color. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function ColorKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrack.call( this, name, times, values, interpolation ); - - } - - ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { - - constructor: ColorKeyframeTrack, - - ValueTypeName: 'color' - - // ValueBufferType is inherited - - // DefaultInterpolation is inherited - - // Note: Very basic implementation and nothing special yet. - // However, this is the place for color space parameterization. - - } ); - - /** - * - * A Track of numeric keyframe values. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function NumberKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrack.call( this, name, times, values, interpolation ); - - } - - NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { - - constructor: NumberKeyframeTrack, - - ValueTypeName: 'number' - - // ValueBufferType is inherited - - // DefaultInterpolation is inherited - - } ); - - /** - * Fast and simple cubic spline interpolant. - * - * It was derived from a Hermitian construction setting the first derivative - * at each sample position to the linear slope between neighboring positions - * over their parameter interval. - * - * @author tschw - */ - - function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - - this._weightPrev = - 0; - this._offsetPrev = - 0; - this._weightNext = - 0; - this._offsetNext = - 0; - - } - - CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { - - constructor: CubicInterpolant, - - DefaultSettings_: { - - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - - }, - - intervalChanged_: function ( i1, t0, t1 ) { - - var pp = this.parameterPositions, - iPrev = i1 - 2, - iNext = i1 + 1, - - tPrev = pp[ iPrev ], - tNext = pp[ iNext ]; - - if ( tPrev === undefined ) { - - switch ( this.getSettings_().endingStart ) { + switch ( this.getSettings_().endingStart ) { case ZeroSlopeEnding: @@ -34387,7 +33816,7 @@ var ROS3D = (function (exports, ROSLIB) { } - var halfDt = ( t1 - t0 ) * 0.5, + const halfDt = ( t1 - t0 ) * 0.5, stride = this.valueSize; this._weightPrev = halfDt / ( t0 - tPrev ); @@ -34395,11 +33824,11 @@ var ROS3D = (function (exports, ROSLIB) { this._offsetPrev = iPrev * stride; this._offsetNext = iNext * stride; - }, + } - interpolate_: function ( i1, t0, t, t1 ) { + interpolate_( i1, t0, t, t1 ) { - var result = this.resultBuffer, + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, @@ -34413,14 +33842,14 @@ var ROS3D = (function (exports, ROSLIB) { // evaluate polynomials - var sP = - wP * ppp + 2 * wP * pp - wP * p; - var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; - var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; - var sN = wN * ppp - wN * pp; + 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; // combine data linearly - for ( var i = 0; i !== stride; ++ i ) { + for ( let i = 0; i !== stride; ++ i ) { result[ i ] = sP * values[ oP + i ] + @@ -34434,25 +33863,19 @@ var ROS3D = (function (exports, ROSLIB) { } - } ); - - /** - * @author tschw - */ - - function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + } - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + class LinearInterpolant extends Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - constructor: LinearInterpolant, + } - interpolate_: function ( i1, t0, t, t1 ) { + interpolate_( i1, t0, t, t1 ) { - var result = this.resultBuffer, + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, @@ -34462,7 +33885,7 @@ var ROS3D = (function (exports, ROSLIB) { weight1 = ( t - t0 ) / ( t1 - t0 ), weight0 = 1 - weight1; - for ( var i = 0; i !== stride; ++ i ) { + for ( let i = 0; i !== stride; ++ i ) { result[ i ] = values[ offset0 + i ] * weight0 + @@ -34474,869 +33897,713 @@ var ROS3D = (function (exports, ROSLIB) { } - } ); + } /** * - * Interpolant that evaluates to the sample value at the position preceeding + * Interpolant that evaluates to the sample value at the position preceding * the parameter. - * - * @author tschw */ - function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + class DiscreteInterpolant extends Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - constructor: DiscreteInterpolant, + } - interpolate_: function ( i1 /*, t0, t, t1 */ ) { + interpolate_( i1 /*, t0, t, t1 */ ) { return this.copySampleValue_( i1 - 1 ); } - } ); + } - /** - * @author tschw - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ + class KeyframeTrack { - var AnimationUtils = { + constructor( name, times, values, interpolation ) { - // same as Array.prototype.slice, but also works on typed arrays - arraySlice: function ( array, from, to ) { + if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); + if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); - if ( AnimationUtils.isTypedArray( array ) ) { + this.name = name; - // in ios9 array.subarray(from, undefined) will return empty array - // but array.subarray(from) or array.subarray(from, len) is correct - return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) ); + this.times = convertArray( times, this.TimeBufferType ); + this.values = convertArray( values, this.ValueBufferType ); - } + this.setInterpolation( interpolation || this.DefaultInterpolation ); - return array.slice( from, to ); + } - }, + // Serialization (in static context, because of constructor invocation + // and automatic invocation of .toJSON): - // converts an array to a specific type - convertArray: function ( array, type, forceClone ) { + static toJSON( track ) { - if ( ! array || // let 'undefined' and 'null' pass - ! forceClone && array.constructor === type ) return array; + const trackType = track.constructor; - if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { + let json; - return new type( array ); // create typed array + // derived classes can define a static toJSON method + if ( trackType.toJSON !== this.toJSON ) { - } + json = trackType.toJSON( track ); - return Array.prototype.slice.call( array ); // create Array + } else { - }, + // by default, we assume the data can be serialized as-is + json = { - isTypedArray: function ( object ) { + 'name': track.name, + 'times': convertArray( track.times, Array ), + 'values': convertArray( track.values, Array ) - return ArrayBuffer.isView( object ) && - ! ( object instanceof DataView ); + }; - }, + const interpolation = track.getInterpolation(); - // returns an array by which times and values can be sorted - getKeyframeOrder: function ( times ) { + if ( interpolation !== track.DefaultInterpolation ) { - function compareTime( i, j ) { + json.interpolation = interpolation; - return times[ i ] - times[ j ]; + } } - var n = times.length; - var result = new Array( n ); - for ( var i = 0; i !== n; ++ i ) result[ i ] = i; + json.type = track.ValueTypeName; // mandatory - result.sort( compareTime ); + return json; - return result; + } - }, + InterpolantFactoryMethodDiscrete( result ) { - // uses the array previously returned by 'getKeyframeOrder' to sort data - sortedArray: function ( values, stride, order ) { + return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); - var nValues = values.length; - var result = new values.constructor( nValues ); + } - for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { + InterpolantFactoryMethodLinear( result ) { - var srcOffset = order[ i ] * stride; + return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); - for ( var j = 0; j !== stride; ++ j ) { + } - result[ dstOffset ++ ] = values[ srcOffset + j ]; + InterpolantFactoryMethodSmooth( result ) { - } + return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); - } + } - return result; + setInterpolation( interpolation ) { - }, + let factoryMethod; - // function for parsing AOS keyframe formats - flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) { + switch ( interpolation ) { - var i = 1, key = jsonKeys[ 0 ]; + case InterpolateDiscrete: - while ( key !== undefined && key[ valuePropertyName ] === undefined ) { + factoryMethod = this.InterpolantFactoryMethodDiscrete; - key = jsonKeys[ i ++ ]; + break; - } + case InterpolateLinear: - if ( key === undefined ) return; // no data + factoryMethod = this.InterpolantFactoryMethodLinear; - var value = key[ valuePropertyName ]; - if ( value === undefined ) return; // no data + break; - if ( Array.isArray( value ) ) { + case InterpolateSmooth: - do { + factoryMethod = this.InterpolantFactoryMethodSmooth; - value = key[ valuePropertyName ]; + break; - if ( value !== undefined ) { + } - times.push( key.time ); - values.push.apply( values, value ); // push all elements + if ( factoryMethod === undefined ) { - } + const message = 'unsupported interpolation for ' + + this.ValueTypeName + ' keyframe track named ' + this.name; - key = jsonKeys[ i ++ ]; + if ( this.createInterpolant === undefined ) { - } while ( key !== undefined ); + // fall back to default, unless the default itself is messed up + if ( interpolation !== this.DefaultInterpolation ) { - } else if ( value.toArray !== undefined ) { + this.setInterpolation( this.DefaultInterpolation ); - // ...assume THREE.Math-ish + } else { - do { + throw new Error( message ); // fatal, in this case - value = key[ valuePropertyName ]; + } - if ( value !== undefined ) { + } - times.push( key.time ); - value.toArray( values, values.length ); + console.warn( 'THREE.KeyframeTrack:', message ); + return this; - } + } - key = jsonKeys[ i ++ ]; + this.createInterpolant = factoryMethod; - } while ( key !== undefined ); + return this; - } else { + } - // otherwise push as-is + getInterpolation() { - do { + switch ( this.createInterpolant ) { - value = key[ valuePropertyName ]; + case this.InterpolantFactoryMethodDiscrete: - if ( value !== undefined ) { + return InterpolateDiscrete; - times.push( key.time ); - values.push( value ); + case this.InterpolantFactoryMethodLinear: - } + return InterpolateLinear; - key = jsonKeys[ i ++ ]; + case this.InterpolantFactoryMethodSmooth: - } while ( key !== undefined ); + return InterpolateSmooth; } } - }; + getValueSize() { - /** - * - * A timed sequence of keyframes for a specific property. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ + return this.values.length / this.times.length; - function KeyframeTrack( name, times, values, interpolation ) { + } - if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); - if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); + // move all keyframes either forwards or backwards in time + shift( timeOffset ) { - this.name = name; + if ( timeOffset !== 0.0 ) { - this.times = AnimationUtils.convertArray( times, this.TimeBufferType ); - this.values = AnimationUtils.convertArray( values, this.ValueBufferType ); + const times = this.times; - this.setInterpolation( interpolation || this.DefaultInterpolation ); + for ( let i = 0, n = times.length; i !== n; ++ i ) { - this.validate(); - this.optimize(); + times[ i ] += timeOffset; - } + } - // Static methods: + } - Object.assign( KeyframeTrack, { + return this; - // Serialization (in static context, because of constructor invocation - // and automatic invocation of .toJSON): + } - parse: function ( json ) { + // scale all keyframe times by a factor (useful for frame <-> seconds conversions) + scale( timeScale ) { - if ( json.type === undefined ) { + if ( timeScale !== 1.0 ) { - throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); + const times = this.times; - } + for ( let i = 0, n = times.length; i !== n; ++ i ) { - var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type ); + times[ i ] *= timeScale; - if ( json.times === undefined ) { + } - var times = [], values = []; + } - AnimationUtils.flattenJSON( json.keys, times, values, 'value' ); + return this; - json.times = times; - json.values = values; + } - } + // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. + // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values + trim( startTime, endTime ) { - // derived classes can define a static parse method - if ( trackType.parse !== undefined ) { + const times = this.times, + nKeys = times.length; - return trackType.parse( json ); + let from = 0, + to = nKeys - 1; - } else { + while ( from !== nKeys && times[ from ] < startTime ) { - // by default, we assume a constructor compatible with the base - return new trackType( json.name, json.times, json.values, json.interpolation ); + ++ from; } - }, + while ( to !== - 1 && times[ to ] > endTime ) { - toJSON: function ( track ) { + -- to; - var trackType = track.constructor; + } - var json; + ++ to; // inclusive -> exclusive bound - // derived classes can define a static toJSON method - if ( trackType.toJSON !== undefined ) { + if ( from !== 0 || to !== nKeys ) { - json = trackType.toJSON( track ); + // empty tracks are forbidden, so keep at least one keyframe + if ( from >= to ) { - } else { + to = Math.max( to, 1 ); + from = to - 1; - // by default, we assume the data can be serialized as-is - json = { + } - 'name': track.name, - 'times': AnimationUtils.convertArray( track.times, Array ), - 'values': AnimationUtils.convertArray( track.values, Array ) + const stride = this.getValueSize(); + this.times = times.slice( from, to ); + this.values = this.values.slice( from * stride, to * stride ); - }; + } - var interpolation = track.getInterpolation(); + return this; - if ( interpolation !== track.DefaultInterpolation ) { + } - json.interpolation = interpolation; + // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable + validate() { - } + let valid = true; - } + const valueSize = this.getValueSize(); + if ( valueSize - Math.floor( valueSize ) !== 0 ) { - json.type = track.ValueTypeName; // mandatory + console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); + valid = false; - return json; + } - }, + const times = this.times, + values = this.values, - _getTrackTypeForValueTypeName: function ( typeName ) { + nKeys = times.length; - switch ( typeName.toLowerCase() ) { + if ( nKeys === 0 ) { - case 'scalar': - case 'double': - case 'float': - case 'number': - case 'integer': + console.error( 'THREE.KeyframeTrack: Track is empty.', this ); + valid = false; - return NumberKeyframeTrack; + } - case 'vector': - case 'vector2': - case 'vector3': - case 'vector4': + let prevTime = null; - return VectorKeyframeTrack; + for ( let i = 0; i !== nKeys; i ++ ) { - case 'color': + const currTime = times[ i ]; - return ColorKeyframeTrack; + if ( typeof currTime === 'number' && isNaN( currTime ) ) { - case 'quaternion': + console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); + valid = false; + break; - return QuaternionKeyframeTrack; + } - case 'bool': - case 'boolean': + if ( prevTime !== null && prevTime > currTime ) { - return BooleanKeyframeTrack; + console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); + valid = false; + break; - case 'string': + } - return StringKeyframeTrack; + prevTime = currTime; } - throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); - - } - - } ); - - Object.assign( KeyframeTrack.prototype, { - - constructor: KeyframeTrack, + if ( values !== undefined ) { - TimeBufferType: Float32Array, + if ( isTypedArray( values ) ) { - ValueBufferType: Float32Array, + for ( let i = 0, n = values.length; i !== n; ++ i ) { - DefaultInterpolation: InterpolateLinear, + const value = values[ i ]; - InterpolantFactoryMethodDiscrete: function ( result ) { + if ( isNaN( value ) ) { - return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); + console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); + valid = false; + break; - }, + } - InterpolantFactoryMethodLinear: function ( result ) { + } - return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); + } - }, + } - InterpolantFactoryMethodSmooth: function ( result ) { + return valid; - return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); + } - }, + // removes equivalent sequential keys as common in morph target sequences + // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) + optimize() { - setInterpolation: function ( interpolation ) { + // times or values may be shared with other tracks, so overwriting is unsafe + const times = this.times.slice(), + values = this.values.slice(), + stride = this.getValueSize(), - var factoryMethod; + smoothInterpolation = this.getInterpolation() === InterpolateSmooth, - switch ( interpolation ) { + lastIndex = times.length - 1; - case InterpolateDiscrete: + let writeIndex = 1; - factoryMethod = this.InterpolantFactoryMethodDiscrete; + for ( let i = 1; i < lastIndex; ++ i ) { - break; + let keep = false; - case InterpolateLinear: + const time = times[ i ]; + const timeNext = times[ i + 1 ]; - factoryMethod = this.InterpolantFactoryMethodLinear; + // remove adjacent keyframes scheduled at the same time - break; + if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { - case InterpolateSmooth: + if ( ! smoothInterpolation ) { - factoryMethod = this.InterpolantFactoryMethodSmooth; + // remove unnecessary keyframes same as their neighbors - break; + const offset = i * stride, + offsetP = offset - stride, + offsetN = offset + stride; - } + for ( let j = 0; j !== stride; ++ j ) { - if ( factoryMethod === undefined ) { + const value = values[ offset + j ]; - var message = "unsupported interpolation for " + - this.ValueTypeName + " keyframe track named " + this.name; + if ( value !== values[ offsetP + j ] || + value !== values[ offsetN + j ] ) { - if ( this.createInterpolant === undefined ) { + keep = true; + break; - // fall back to default, unless the default itself is messed up - if ( interpolation !== this.DefaultInterpolation ) { + } - this.setInterpolation( this.DefaultInterpolation ); + } } else { - throw new Error( message ); // fatal, in this case + keep = true; } } - console.warn( 'THREE.KeyframeTrack:', message ); - return; - - } + // in-place compaction - this.createInterpolant = factoryMethod; + if ( keep ) { - }, + if ( i !== writeIndex ) { - getInterpolation: function () { + times[ writeIndex ] = times[ i ]; - switch ( this.createInterpolant ) { + const readOffset = i * stride, + writeOffset = writeIndex * stride; - case this.InterpolantFactoryMethodDiscrete: + for ( let j = 0; j !== stride; ++ j ) { - return InterpolateDiscrete; + values[ writeOffset + j ] = values[ readOffset + j ]; - case this.InterpolantFactoryMethodLinear: + } - return InterpolateLinear; + } - case this.InterpolantFactoryMethodSmooth: + ++ writeIndex; - return InterpolateSmooth; + } } - }, + // flush last keyframe (compaction looks ahead) - getValueSize: function () { + if ( lastIndex > 0 ) { - return this.values.length / this.times.length; + times[ writeIndex ] = times[ lastIndex ]; - }, + for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { - // move all keyframes either forwards or backwards in time - shift: function ( timeOffset ) { + values[ writeOffset + j ] = values[ readOffset + j ]; - if ( timeOffset !== 0.0 ) { + } - var times = this.times; + ++ writeIndex; - for ( var i = 0, n = times.length; i !== n; ++ i ) { + } - times[ i ] += timeOffset; + if ( writeIndex !== times.length ) { - } + this.times = times.slice( 0, writeIndex ); + this.values = values.slice( 0, writeIndex * stride ); + + } else { + + this.times = times; + this.values = values; } return this; - }, - - // scale all keyframe times by a factor (useful for frame <-> seconds conversions) - scale: function ( timeScale ) { + } - if ( timeScale !== 1.0 ) { + clone() { - var times = this.times; + const times = this.times.slice(); + const values = this.values.slice(); - for ( var i = 0, n = times.length; i !== n; ++ i ) { + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack( this.name, times, values ); - times[ i ] *= timeScale; + // Interpolant argument to constructor is not saved, so copy the factory method directly. + track.createInterpolant = this.createInterpolant; - } + return track; - } + } - return this; + } - }, + KeyframeTrack.prototype.TimeBufferType = Float32Array; + KeyframeTrack.prototype.ValueBufferType = Float32Array; + KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; - // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. - // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values - trim: function ( startTime, endTime ) { + /** + * A Track of Boolean keyframe values. + */ + class BooleanKeyframeTrack extends KeyframeTrack { - var times = this.times, - nKeys = times.length, - from = 0, - to = nKeys - 1; + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { - while ( from !== nKeys && times[ from ] < startTime ) { + super( name, times, values ); - ++ from; + } - } + } - while ( to !== - 1 && times[ to ] > endTime ) { + BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; + BooleanKeyframeTrack.prototype.ValueBufferType = Array; + BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; + BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; + BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - -- to; + /** + * A Track of keyframe values that represent color. + */ + class ColorKeyframeTrack extends KeyframeTrack {} - } + ColorKeyframeTrack.prototype.ValueTypeName = 'color'; - ++ to; // inclusive -> exclusive bound + /** + * A Track of numeric keyframe values. + */ + class NumberKeyframeTrack extends KeyframeTrack {} - if ( from !== 0 || to !== nKeys ) { + NumberKeyframeTrack.prototype.ValueTypeName = 'number'; - // empty tracks are forbidden, so keep at least one keyframe - if ( from >= to ) to = Math.max( to, 1 ), from = to - 1; + /** + * Spherical linear unit quaternion interpolant. + */ - var stride = this.getValueSize(); - this.times = AnimationUtils.arraySlice( times, from, to ); - this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride ); + class QuaternionLinearInterpolant extends Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - return this; + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - }, + } - // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable - validate: function () { + interpolate_( i1, t0, t, t1 ) { - var valid = true; + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, - var valueSize = this.getValueSize(); - if ( valueSize - Math.floor( valueSize ) !== 0 ) { + alpha = ( t - t0 ) / ( t1 - t0 ); - console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); - valid = false; + let offset = i1 * stride; - } + for ( let end = offset + stride; offset !== end; offset += 4 ) { - var times = this.times, - values = this.values, + Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); - nKeys = times.length; + } - if ( nKeys === 0 ) { + return result; - console.error( 'THREE.KeyframeTrack: Track is empty.', this ); - valid = false; + } - } + } - var prevTime = null; + /** + * A Track of quaternion keyframe values. + */ + class QuaternionKeyframeTrack extends KeyframeTrack { - for ( var i = 0; i !== nKeys; i ++ ) { + InterpolantFactoryMethodLinear( result ) { - var currTime = times[ i ]; + return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); - if ( typeof currTime === 'number' && isNaN( currTime ) ) { + } - console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); - valid = false; - break; + } - } + QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; + // ValueBufferType is inherited + // DefaultInterpolation is inherited; + QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - if ( prevTime !== null && prevTime > currTime ) { + /** + * A Track that interpolates Strings + */ + class StringKeyframeTrack extends KeyframeTrack { - console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); - valid = false; - break; + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { - } + super( name, times, values ); - prevTime = currTime; + } - } + } - if ( values !== undefined ) { + StringKeyframeTrack.prototype.ValueTypeName = 'string'; + StringKeyframeTrack.prototype.ValueBufferType = Array; + StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; + StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; + StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - if ( AnimationUtils.isTypedArray( values ) ) { + /** + * A Track of vectored keyframe values. + */ + class VectorKeyframeTrack extends KeyframeTrack {} - for ( var i = 0, n = values.length; i !== n; ++ i ) { + VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; - var value = values[ i ]; + class AnimationClip { - if ( isNaN( value ) ) { + constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { - console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); - valid = false; - break; + this.name = name; + this.tracks = tracks; + this.duration = duration; + this.blendMode = blendMode; - } + this.uuid = generateUUID(); - } + // this means it should figure out its duration by scanning the tracks + if ( this.duration < 0 ) { - } + this.resetDuration(); } - return valid; + } - }, - // removes equivalent sequential keys as common in morph target sequences - // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) - optimize: function () { + static parse( json ) { - var times = this.times, - values = this.values, - stride = this.getValueSize(), + const tracks = [], + jsonTracks = json.tracks, + frameTime = 1.0 / ( json.fps || 1.0 ); - smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { - writeIndex = 1, - lastIndex = times.length - 1; + tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); - for ( var i = 1; i < lastIndex; ++ i ) { + } - var keep = false; + const clip = new this( json.name, json.duration, tracks, json.blendMode ); + clip.uuid = json.uuid; - var time = times[ i ]; - var timeNext = times[ i + 1 ]; + return clip; - // remove adjacent keyframes scheduled at the same time + } - if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) { + static toJSON( clip ) { - if ( ! smoothInterpolation ) { + const tracks = [], + clipTracks = clip.tracks; - // remove unnecessary keyframes same as their neighbors + const json = { - var offset = i * stride, - offsetP = offset - stride, - offsetN = offset + stride; + 'name': clip.name, + 'duration': clip.duration, + 'tracks': tracks, + 'uuid': clip.uuid, + 'blendMode': clip.blendMode - for ( var j = 0; j !== stride; ++ j ) { + }; - var value = values[ offset + j ]; + for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { - if ( value !== values[ offsetP + j ] || - value !== values[ offsetN + j ] ) { + tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); - keep = true; - break; + } - } + return json; - } + } - } else { + static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { - keep = true; + const numMorphTargets = morphTargetSequence.length; + const tracks = []; - } + for ( let i = 0; i < numMorphTargets; i ++ ) { - } + let times = []; + let values = []; - // in-place compaction + times.push( + ( i + numMorphTargets - 1 ) % numMorphTargets, + i, + ( i + 1 ) % numMorphTargets ); - if ( keep ) { + values.push( 0, 1, 0 ); - if ( i !== writeIndex ) { + const order = getKeyframeOrder( times ); + times = sortedArray( times, 1, order ); + values = sortedArray( values, 1, order ); - times[ writeIndex ] = times[ i ]; + // if there is a key at the first frame, duplicate it as the + // last frame as well for perfect loop. + if ( ! noLoop && times[ 0 ] === 0 ) { - var readOffset = i * stride, - writeOffset = writeIndex * stride; + times.push( numMorphTargets ); + values.push( values[ 0 ] ); - for ( var j = 0; j !== stride; ++ j ) { + } - values[ writeOffset + j ] = values[ readOffset + j ]; + tracks.push( + new NumberKeyframeTrack( + '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', + times, values + ).scale( 1.0 / fps ) ); - } + } - } - - ++ writeIndex; - - } - - } - - // flush last keyframe (compaction looks ahead) - - if ( lastIndex > 0 ) { - - times[ writeIndex ] = times[ lastIndex ]; - - for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { - - values[ writeOffset + j ] = values[ readOffset + j ]; - - } - - ++ writeIndex; - - } - - if ( writeIndex !== times.length ) { - - this.times = AnimationUtils.arraySlice( times, 0, writeIndex ); - this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride ); - - } - - return this; - - } - - } ); - - /** - * - * A Track of vectored keyframe values. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function VectorKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrack.call( this, name, times, values, interpolation ); - - } - - VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { - - constructor: VectorKeyframeTrack, - - ValueTypeName: 'vector' - - // ValueBufferType is inherited - - // DefaultInterpolation is inherited - - } ); - - /** - * - * Reusable set of Tracks that represent an animation. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ - - function AnimationClip( name, duration, tracks ) { - - this.name = name; - this.tracks = tracks; - this.duration = ( duration !== undefined ) ? duration : - 1; - - this.uuid = _Math.generateUUID(); - - // this means it should figure out its duration by scanning the tracks - if ( this.duration < 0 ) { - - this.resetDuration(); + return new this( name, - 1, tracks ); } - this.optimize(); - - } - - Object.assign( AnimationClip, { - - parse: function ( json ) { - - var tracks = [], - jsonTracks = json.tracks, - frameTime = 1.0 / ( json.fps || 1.0 ); - - for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) { - - tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) ); - - } - - return new AnimationClip( json.name, json.duration, tracks ); - - }, - - toJSON: function ( clip ) { - - var tracks = [], - clipTracks = clip.tracks; - - var json = { - - 'name': clip.name, - 'duration': clip.duration, - 'tracks': tracks - - }; - - for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) { - - tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); - - } - - return json; - - }, - - CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) { - - var numMorphTargets = morphTargetSequence.length; - var tracks = []; - - for ( var i = 0; i < numMorphTargets; i ++ ) { - - var times = []; - var values = []; - - times.push( - ( i + numMorphTargets - 1 ) % numMorphTargets, - i, - ( i + 1 ) % numMorphTargets ); - - values.push( 0, 1, 0 ); - - var order = AnimationUtils.getKeyframeOrder( times ); - times = AnimationUtils.sortedArray( times, 1, order ); - values = AnimationUtils.sortedArray( values, 1, order ); - - // if there is a key at the first frame, duplicate it as the - // last frame as well for perfect loop. - if ( ! noLoop && times[ 0 ] === 0 ) { - - times.push( numMorphTargets ); - values.push( values[ 0 ] ); - - } + static findByName( objectOrClipArray, name ) { - tracks.push( - new NumberKeyframeTrack( - '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', - times, values - ).scale( 1.0 / fps ) ); - - } - - return new AnimationClip( name, - 1, tracks ); - - }, - - findByName: function ( objectOrClipArray, name ) { - - var clipArray = objectOrClipArray; + let clipArray = objectOrClipArray; if ( ! Array.isArray( objectOrClipArray ) ) { - var o = objectOrClipArray; + const o = objectOrClipArray; clipArray = o.geometry && o.geometry.animations || o.animations; } - for ( var i = 0; i < clipArray.length; i ++ ) { + for ( let i = 0; i < clipArray.length; i ++ ) { if ( clipArray[ i ].name === name ) { @@ -35348,28 +34615,29 @@ var ROS3D = (function (exports, ROSLIB) { return null; - }, + } - CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) { + static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { - var animationToMorphTargets = {}; + const animationToMorphTargets = {}; // tested with https://regex101.com/ on trick sequences // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 - var pattern = /^([\w-]*?)([\d]+)$/; + const pattern = /^([\w-]*?)([\d]+)$/; // sort morph target names into animation groups based // patterns like Walk_001, Walk_002, Run_001, Run_002 - for ( var i = 0, il = morphTargets.length; i < il; i ++ ) { + for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { - var morphTarget = morphTargets[ i ]; - var parts = morphTarget.name.match( pattern ); + const morphTarget = morphTargets[ i ]; + const parts = morphTarget.name.match( pattern ); if ( parts && parts.length > 1 ) { - var name = parts[ 1 ]; + const name = parts[ 1 ]; + + let animationMorphTargets = animationToMorphTargets[ name ]; - var animationMorphTargets = animationToMorphTargets[ name ]; if ( ! animationMorphTargets ) { animationToMorphTargets[ name ] = animationMorphTargets = []; @@ -35382,20 +34650,20 @@ var ROS3D = (function (exports, ROSLIB) { } - var clips = []; + const clips = []; - for ( var name in animationToMorphTargets ) { + for ( const name in animationToMorphTargets ) { - clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); + clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); } return clips; - }, + } // parse the animation.hierarchy format - parseAnimation: function ( animation, bones ) { + static parseAnimation( animation, bones ) { if ( ! animation ) { @@ -35404,15 +34672,15 @@ var ROS3D = (function (exports, ROSLIB) { } - var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { + const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { // only return track if there are actually keys. if ( animationKeys.length !== 0 ) { - var times = []; - var values = []; + const times = []; + const values = []; - AnimationUtils.flattenJSON( animationKeys, times, values, propertyName ); + flattenJSON( animationKeys, times, values, propertyName ); // empty keys are filtered out, so check again if ( times.length !== 0 ) { @@ -35425,18 +34693,20 @@ var ROS3D = (function (exports, ROSLIB) { }; - var tracks = []; + const tracks = []; + + const clipName = animation.name || 'default'; + const fps = animation.fps || 30; + const blendMode = animation.blendMode; - var clipName = animation.name || 'default'; // automatic length determination in AnimationClip. - var duration = animation.length || - 1; - var fps = animation.fps || 30; + let duration = animation.length || - 1; - var hierarchyTracks = animation.hierarchy || []; + const hierarchyTracks = animation.hierarchy || []; - for ( var h = 0; h < hierarchyTracks.length; h ++ ) { + for ( let h = 0; h < hierarchyTracks.length; h ++ ) { - var animationKeys = hierarchyTracks[ h ].keys; + const animationKeys = hierarchyTracks[ h ].keys; // skip empty tracks if ( ! animationKeys || animationKeys.length === 0 ) continue; @@ -35445,13 +34715,15 @@ var ROS3D = (function (exports, ROSLIB) { if ( animationKeys[ 0 ].morphTargets ) { // figure out all morph targets used in this track - var morphTargetNames = {}; + const morphTargetNames = {}; - for ( var k = 0; k < animationKeys.length; k ++ ) { + let k; + + for ( k = 0; k < animationKeys.length; k ++ ) { if ( animationKeys[ k ].morphTargets ) { - for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { + for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; @@ -35464,14 +34736,14 @@ var ROS3D = (function (exports, ROSLIB) { // create a track for each morph target with all zero // morphTargetInfluences except for the keys in which // the morphTarget is named. - for ( var morphTargetName in morphTargetNames ) { + for ( const morphTargetName in morphTargetNames ) { - var times = []; - var values = []; + const times = []; + const values = []; - for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { + for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { - var animationKey = animationKeys[ k ]; + const animationKey = animationKeys[ k ]; times.push( animationKey.time ); values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); @@ -35482,13 +34754,13 @@ var ROS3D = (function (exports, ROSLIB) { } - duration = morphTargetNames.length * ( fps || 1.0 ); + duration = morphTargetNames.length * fps; } else { // ...assume skeletal animation - var boneName = '.bones[' + bones[ h ].name + ']'; + const boneName = '.bones[' + bones[ h ].name + ']'; addNonemptyTrack( VectorKeyframeTrack, boneName + '.position', @@ -35512,23 +34784,20 @@ var ROS3D = (function (exports, ROSLIB) { } - var clip = new AnimationClip( clipName, duration, tracks ); + const clip = new this( clipName, duration, tracks, blendMode ); return clip; } - } ); - - Object.assign( AnimationClip.prototype, { + resetDuration() { - resetDuration: function () { + const tracks = this.tracks; + let duration = 0; - var tracks = this.tracks, duration = 0; + for ( let i = 0, n = tracks.length; i !== n; ++ i ) { - for ( var i = 0, n = tracks.length; i !== n; ++ i ) { - - var track = this.tracks[ i ]; + const track = this.tracks[ i ]; duration = Math.max( duration, track.times[ track.times.length - 1 ] ); @@ -35536,11 +34805,13 @@ var ROS3D = (function (exports, ROSLIB) { this.duration = duration; - }, + return this; + + } - trim: function () { + trim() { - for ( var i = 0; i < this.tracks.length; i ++ ) { + for ( let i = 0; i < this.tracks.length; i ++ ) { this.tracks[ i ].trim( 0, this.duration ); @@ -35548,16347 +34819,7364 @@ var ROS3D = (function (exports, ROSLIB) { return this; - }, + } - optimize: function () { + validate() { - for ( var i = 0; i < this.tracks.length; i ++ ) { + let valid = true; - this.tracks[ i ].optimize(); + for ( let i = 0; i < this.tracks.length; i ++ ) { + + valid = valid && this.tracks[ i ].validate(); } - return this; + return valid; } - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function MaterialLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.textures = {}; + optimize() { - } - - Object.assign( MaterialLoader.prototype, { + for ( let i = 0; i < this.tracks.length; i ++ ) { - load: function ( url, onLoad, onProgress, onError ) { + this.tracks[ i ].optimize(); - var scope = this; + } - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + return this; - onLoad( scope.parse( JSON.parse( text ) ) ); + } - }, onProgress, onError ); + clone() { - }, + const tracks = []; - setTextures: function ( value ) { + for ( let i = 0; i < this.tracks.length; i ++ ) { - this.textures = value; + tracks.push( this.tracks[ i ].clone() ); - }, + } - parse: function ( json ) { + return new this.constructor( this.name, this.duration, tracks, this.blendMode ); - var textures = this.textures; + } - function getTexture( name ) { + toJSON() { - if ( textures[ name ] === undefined ) { + return this.constructor.toJSON( this ); - console.warn( 'THREE.MaterialLoader: Undefined texture', name ); + } - } + } - return textures[ name ]; + function getTrackTypeForValueTypeName( typeName ) { - } + switch ( typeName.toLowerCase() ) { - var material = new Materials[ json.type ](); + case 'scalar': + case 'double': + case 'float': + case 'number': + case 'integer': - if ( json.uuid !== undefined ) material.uuid = json.uuid; - if ( json.name !== undefined ) material.name = json.name; - if ( json.color !== undefined ) material.color.setHex( json.color ); - if ( json.roughness !== undefined ) material.roughness = json.roughness; - if ( json.metalness !== undefined ) material.metalness = json.metalness; - if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive ); - if ( json.specular !== undefined ) material.specular.setHex( json.specular ); - if ( json.shininess !== undefined ) material.shininess = json.shininess; - if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat; - if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness; - if ( json.uniforms !== undefined ) material.uniforms = json.uniforms; - if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; - if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; - if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors; - if ( json.fog !== undefined ) material.fog = json.fog; - if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; - if ( json.blending !== undefined ) material.blending = json.blending; - if ( json.side !== undefined ) material.side = json.side; - if ( json.opacity !== undefined ) material.opacity = json.opacity; - if ( json.transparent !== undefined ) material.transparent = json.transparent; - if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; - if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; - if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; - if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; - if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; - if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; - if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; - if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; + return NumberKeyframeTrack; - if ( json.rotation !== undefined ) material.rotation = json.rotation; + case 'vector': + case 'vector2': + case 'vector3': + case 'vector4': - if ( json.linewidth !== 1 ) material.linewidth = json.linewidth; - if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; - if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; - if ( json.scale !== undefined ) material.scale = json.scale; + return VectorKeyframeTrack; - if ( json.skinning !== undefined ) material.skinning = json.skinning; - if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets; - if ( json.dithering !== undefined ) material.dithering = json.dithering; + case 'color': - if ( json.visible !== undefined ) material.visible = json.visible; - if ( json.userData !== undefined ) material.userData = json.userData; + return ColorKeyframeTrack; - // Deprecated + case 'quaternion': - if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading + return QuaternionKeyframeTrack; - // for PointsMaterial + case 'bool': + case 'boolean': - if ( json.size !== undefined ) material.size = json.size; - if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; + return BooleanKeyframeTrack; - // maps + case 'string': - if ( json.map !== undefined ) material.map = getTexture( json.map ); + return StringKeyframeTrack; - if ( json.alphaMap !== undefined ) { + } - material.alphaMap = getTexture( json.alphaMap ); - material.transparent = true; + throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); - } + } - if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); - if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; + function parseKeyframeTrack( json ) { - if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); - if ( json.normalScale !== undefined ) { + if ( json.type === undefined ) { - var normalScale = json.normalScale; + throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); - if ( Array.isArray( normalScale ) === false ) { + } - // Blender exporter used to export a scalar. See #7459 + const trackType = getTrackTypeForValueTypeName( json.type ); - normalScale = [ normalScale, normalScale ]; + if ( json.times === undefined ) { - } + const times = [], values = []; - material.normalScale = new Vector2().fromArray( normalScale ); + flattenJSON( json.keys, times, values, 'value' ); - } + json.times = times; + json.values = values; - if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); - if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; - if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; + } - if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); - if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); + // derived classes can define a static parse method + if ( trackType.parse !== undefined ) { - if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); - if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; + return trackType.parse( json ); - if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); + } else { - if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); + // by default, we assume a constructor compatible with the base + return new trackType( json.name, json.times, json.values, json.interpolation ); - if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; + } - if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); - if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; + } - if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); - if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; + const Cache = { - if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); + enabled: false, - return material; + files: {}, - } + add: function ( key, file ) { - } ); + if ( this.enabled === false ) return; - /** - * @author mrdoob / http://mrdoob.com/ - */ + // console.log( 'THREE.Cache', 'Adding key:', key ); - function BufferGeometryLoader( manager ) { + this.files[ key ] = file; - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + }, - } + get: function ( key ) { - Object.assign( BufferGeometryLoader.prototype, { + if ( this.enabled === false ) return; - load: function ( url, onLoad, onProgress, onError ) { + // console.log( 'THREE.Cache', 'Checking key:', key ); - var scope = this; + return this.files[ key ]; - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + }, - onLoad( scope.parse( JSON.parse( text ) ) ); + remove: function ( key ) { - }, onProgress, onError ); + delete this.files[ key ]; }, - parse: function ( json ) { + clear: function () { - var geometry = new BufferGeometry(); + this.files = {}; - var index = json.data.index; + } - if ( index !== undefined ) { + }; - var typedArray = new TYPED_ARRAYS[ index.type ]( index.array ); - geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); + class LoadingManager { - } + constructor( onLoad, onProgress, onError ) { - var attributes = json.data.attributes; + const scope = this; - for ( var key in attributes ) { + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; - var attribute = attributes[ key ]; - var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); + // Refer to #5689 for the reason why we don't set .onStart + // in the constructor - geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) ); + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; - } + this.itemStart = function ( url ) { - var groups = json.data.groups || json.data.drawcalls || json.data.offsets; + itemsTotal ++; - if ( groups !== undefined ) { + if ( isLoading === false ) { - for ( var i = 0, n = groups.length; i !== n; ++ i ) { + if ( scope.onStart !== undefined ) { - var group = groups[ i ]; + scope.onStart( url, itemsLoaded, itemsTotal ); - geometry.addGroup( group.start, group.count, group.materialIndex ); + } } - } + isLoading = true; - var boundingSphere = json.data.boundingSphere; + }; - if ( boundingSphere !== undefined ) { + this.itemEnd = function ( url ) { - var center = new Vector3(); + itemsLoaded ++; - if ( boundingSphere.center !== undefined ) { + if ( scope.onProgress !== undefined ) { - center.fromArray( boundingSphere.center ); + scope.onProgress( url, itemsLoaded, itemsTotal ); } - geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); - - } + if ( itemsLoaded === itemsTotal ) { - return geometry; + isLoading = false; - } + if ( scope.onLoad !== undefined ) { - } ); + scope.onLoad(); - var TYPED_ARRAYS = { - Int8Array: Int8Array, - Uint8Array: Uint8Array, - // Workaround for IE11 pre KB2929437. See #11440 - Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, - Int16Array: Int16Array, - Uint16Array: Uint16Array, - Int32Array: Int32Array, - Uint32Array: Uint32Array, - Float32Array: Float32Array, - Float64Array: Float64Array - }; + } - /** - * @author alteredq / http://alteredqualia.com/ - */ + } - function Loader() { + }; - this.onLoadStart = function () {}; - this.onLoadProgress = function () {}; - this.onLoadComplete = function () {}; + this.itemError = function ( url ) { - } + if ( scope.onError !== undefined ) { - Loader.Handlers = { + scope.onError( url ); - handlers: [], + } - add: function ( regex, loader ) { + }; - this.handlers.push( regex, loader ); + this.resolveURL = function ( url ) { - }, + if ( urlModifier ) { - get: function ( file ) { + return urlModifier( url ); - var handlers = this.handlers; + } - for ( var i = 0, l = handlers.length; i < l; i += 2 ) { + return url; - var regex = handlers[ i ]; - var loader = handlers[ i + 1 ]; + }; - if ( regex.test( file ) ) { + this.setURLModifier = function ( transform ) { - return loader; + urlModifier = transform; - } + return this; - } + }; - return null; + this.addHandler = function ( regex, loader ) { - } + handlers.push( regex, loader ); - }; + return this; - Object.assign( Loader.prototype, { + }; - crossOrigin: undefined, + this.removeHandler = function ( regex ) { - initMaterials: function ( materials, texturePath, crossOrigin ) { + const index = handlers.indexOf( regex ); - var array = []; + if ( index !== - 1 ) { - for ( var i = 0; i < materials.length; ++ i ) { + handlers.splice( index, 2 ); - array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin ); + } - } + return this; - return array; + }; - }, + this.getHandler = function ( file ) { - createMaterial: ( function () { + for ( let i = 0, l = handlers.length; i < l; i += 2 ) { - var BlendingMode = { - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending - }; + const regex = handlers[ i ]; + const loader = handlers[ i + 1 ]; - var color = new Color(); - var textureLoader = new TextureLoader(); - var materialLoader = new MaterialLoader(); + if ( regex.global ) regex.lastIndex = 0; // see #17920 - return function createMaterial( m, texturePath, crossOrigin ) { + if ( regex.test( file ) ) { - // convert from old material format + return loader; - var textures = {}; + } - function loadTexture( path, repeat, offset, wrap, anisotropy ) { + } - var fullPath = texturePath + path; - var loader = Loader.Handlers.get( fullPath ); + return null; - var texture; + }; - if ( loader !== null ) { + } - texture = loader.load( fullPath ); + } - } else { + const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); - textureLoader.setCrossOrigin( crossOrigin ); - texture = textureLoader.load( fullPath ); + class Loader { - } + constructor( manager ) { - if ( repeat !== undefined ) { + this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - texture.repeat.fromArray( repeat ); + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; - if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping; - if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping; + } - } + load( /* url, onLoad, onProgress, onError */ ) {} - if ( offset !== undefined ) { + loadAsync( url, onProgress ) { - texture.offset.fromArray( offset ); + const scope = this; - } + return new Promise( function ( resolve, reject ) { - if ( wrap !== undefined ) { + scope.load( url, resolve, onProgress, reject ); - if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping; - if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping; + } ); - if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping; - if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping; + } - } + parse( /* data */ ) {} - if ( anisotropy !== undefined ) { + setCrossOrigin( crossOrigin ) { - texture.anisotropy = anisotropy; + this.crossOrigin = crossOrigin; + return this; - } + } - var uuid = _Math.generateUUID(); + setWithCredentials( value ) { - textures[ uuid ] = texture; - - return uuid; - - } - - // - - var json = { - uuid: _Math.generateUUID(), - type: 'MeshLambertMaterial' - }; - - for ( var name in m ) { + this.withCredentials = value; + return this; - var value = m[ name ]; + } - switch ( name ) { + setPath( path ) { - case 'DbgColor': - case 'DbgIndex': - case 'opticalDensity': - case 'illumination': - break; - case 'DbgName': - json.name = value; - break; - case 'blending': - json.blending = BlendingMode[ value ]; - break; - case 'colorAmbient': - case 'mapAmbient': - console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' ); - break; - case 'colorDiffuse': - json.color = color.fromArray( value ).getHex(); - break; - case 'colorSpecular': - json.specular = color.fromArray( value ).getHex(); - break; - case 'colorEmissive': - json.emissive = color.fromArray( value ).getHex(); - break; - case 'specularCoef': - json.shininess = value; - break; - case 'shading': - if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial'; - if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial'; - if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial'; - break; - case 'mapDiffuse': - json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy ); - break; - case 'mapDiffuseRepeat': - case 'mapDiffuseOffset': - case 'mapDiffuseWrap': - case 'mapDiffuseAnisotropy': - break; - case 'mapEmissive': - json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy ); - break; - case 'mapEmissiveRepeat': - case 'mapEmissiveOffset': - case 'mapEmissiveWrap': - case 'mapEmissiveAnisotropy': - break; - case 'mapLight': - json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy ); - break; - case 'mapLightRepeat': - case 'mapLightOffset': - case 'mapLightWrap': - case 'mapLightAnisotropy': - break; - case 'mapAO': - json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy ); - break; - case 'mapAORepeat': - case 'mapAOOffset': - case 'mapAOWrap': - case 'mapAOAnisotropy': - break; - case 'mapBump': - json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy ); - break; - case 'mapBumpScale': - json.bumpScale = value; - break; - case 'mapBumpRepeat': - case 'mapBumpOffset': - case 'mapBumpWrap': - case 'mapBumpAnisotropy': - break; - case 'mapNormal': - json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy ); - break; - case 'mapNormalFactor': - json.normalScale = [ value, value ]; - break; - case 'mapNormalRepeat': - case 'mapNormalOffset': - case 'mapNormalWrap': - case 'mapNormalAnisotropy': - break; - case 'mapSpecular': - json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy ); - break; - case 'mapSpecularRepeat': - case 'mapSpecularOffset': - case 'mapSpecularWrap': - case 'mapSpecularAnisotropy': - break; - case 'mapMetalness': - json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy ); - break; - case 'mapMetalnessRepeat': - case 'mapMetalnessOffset': - case 'mapMetalnessWrap': - case 'mapMetalnessAnisotropy': - break; - case 'mapRoughness': - json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy ); - break; - case 'mapRoughnessRepeat': - case 'mapRoughnessOffset': - case 'mapRoughnessWrap': - case 'mapRoughnessAnisotropy': - break; - case 'mapAlpha': - json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy ); - break; - case 'mapAlphaRepeat': - case 'mapAlphaOffset': - case 'mapAlphaWrap': - case 'mapAlphaAnisotropy': - break; - case 'flipSided': - json.side = BackSide; - break; - case 'doubleSided': - json.side = DoubleSide; - break; - case 'transparency': - console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' ); - json.opacity = value; - break; - case 'depthTest': - case 'depthWrite': - case 'colorWrite': - case 'opacity': - case 'reflectivity': - case 'transparent': - case 'visible': - case 'wireframe': - json[ name ] = value; - break; - case 'vertexColors': - if ( value === true ) json.vertexColors = VertexColors; - if ( value === 'face' ) json.vertexColors = FaceColors; - break; - default: - console.error( 'THREE.Loader.createMaterial: Unsupported', name, value ); - break; + this.path = path; + return this; - } + } - } + setResourcePath( resourcePath ) { - if ( json.type === 'MeshBasicMaterial' ) delete json.emissive; - if ( json.type !== 'MeshPhongMaterial' ) delete json.specular; + this.resourcePath = resourcePath; + return this; - if ( json.opacity < 1 ) json.transparent = true; + } - materialLoader.setTextures( textures ); + setRequestHeader( requestHeader ) { - return materialLoader.parse( json ); + this.requestHeader = requestHeader; + return this; - }; + } - } )() + } - } ); + Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; - /** - * @author Don McCurdy / https://www.donmccurdy.com - */ + const loading = {}; - var LoaderUtils = { + class HttpError extends Error { - decodeText: function ( array ) { + constructor( message, response ) { - if ( typeof TextDecoder !== 'undefined' ) { + super( message ); + this.response = response; - return new TextDecoder().decode( array ); + } - } + } - // Avoid the String.fromCharCode.apply(null, array) shortcut, which - // throws a "maximum call stack size exceeded" error for large arrays. + class FileLoader extends Loader { - var s = ''; + constructor( manager ) { - for ( var i = 0, il = array.length; i < il; i ++ ) { + super( manager ); - // Implicitly assumes little-endian. - s += String.fromCharCode( array[ i ] ); + } - } + load( url, onLoad, onProgress, onError ) { - return s; + if ( url === undefined ) url = ''; - }, + if ( this.path !== undefined ) url = this.path + url; - extractUrlBase: function ( url ) { + url = this.manager.resolveURL( url ); - var parts = url.split( '/' ); + const cached = Cache.get( url ); - if ( parts.length === 1 ) return './'; + if ( cached !== undefined ) { - parts.pop(); + this.manager.itemStart( url ); - return parts.join( '/' ) + '/'; + setTimeout( () => { - } + if ( onLoad ) onLoad( cached ); - }; + this.manager.itemEnd( url ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + }, 0 ); - function JSONLoader( manager ) { + return cached; - if ( typeof manager === 'boolean' ) { + } - console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' ); - manager = undefined; + // Check if request is duplicate - } + if ( loading[ url ] !== undefined ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + loading[ url ].push( { - this.withCredentials = false; + onLoad: onLoad, + onProgress: onProgress, + onError: onError - } + } ); - Object.assign( JSONLoader.prototype, { + return; - load: function ( url, onLoad, onProgress, onError ) { + } - var scope = this; + // Initialise array for duplicate requests + loading[ url ] = []; - var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url ); + loading[ url ].push( { + onLoad: onLoad, + onProgress: onProgress, + onError: onError, + } ); - var loader = new FileLoader( this.manager ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { + // create request + const req = new Request( url, { + headers: new Headers( this.requestHeader ), + credentials: this.withCredentials ? 'include' : 'same-origin', + // An abort controller could be added within a future PR + } ); - var json = JSON.parse( text ); - var metadata = json.metadata; + // record states ( avoid data race ) + const mimeType = this.mimeType; + const responseType = this.responseType; - if ( metadata !== undefined ) { + // start the fetch + fetch( req ) + .then( response => { - var type = metadata.type; + if ( response.status === 200 || response.status === 0 ) { - if ( type !== undefined ) { + // Some browsers return HTTP Status 0 when using non-http protocol + // e.g. 'file://' or 'data://'. Handle as success. - if ( type.toLowerCase() === 'object' ) { + if ( response.status === 0 ) { - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); - return; + console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); } - if ( type.toLowerCase() === 'scene' ) { + // Workaround: Checking if response.body === undefined for Alipay browser #23548 - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' ); - return; + if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { + + return response; } - } + const callbacks = loading[ url ]; + const reader = response.body.getReader(); - } + // Nginx needs X-File-Size check + // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content + const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); + const total = contentLength ? parseInt( contentLength ) : 0; + const lengthComputable = total !== 0; + let loaded = 0; - var object = scope.parse( json, texturePath ); - onLoad( object.geometry, object.materials ); + // periodically read data into the new stream tracking while download progress + const stream = new ReadableStream( { + start( controller ) { - }, onProgress, onError ); + readData(); - }, + function readData() { - setTexturePath: function ( value ) { + reader.read().then( ( { done, value } ) => { - this.texturePath = value; + if ( done ) { - }, + controller.close(); - parse: ( function () { + } else { - function parseModel( json, geometry ) { + loaded += value.byteLength; - function isBitSet( value, position ) { + const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - return value & ( 1 << position ); + const callback = callbacks[ i ]; + if ( callback.onProgress ) callback.onProgress( event ); - } + } - var i, j, fi, + controller.enqueue( value ); + readData(); - offset, zLength, + } - colorIndex, normalIndex, uvIndex, materialIndex, + }, ( e ) => { - type, - isQuad, - hasMaterial, - hasFaceVertexUv, - hasFaceNormal, hasFaceVertexNormal, - hasFaceColor, hasFaceVertexColor, + controller.error( e ); - vertex, face, faceA, faceB, hex, normal, + } ); - uvLayer, uv, u, v, + } - faces = json.faces, - vertices = json.vertices, - normals = json.normals, - colors = json.colors, + } - scale = json.scale, + } ); - nUvLayers = 0; + return new Response( stream ); + } else { - if ( json.uvs !== undefined ) { + throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); - // disregard empty arrays + } - for ( i = 0; i < json.uvs.length; i ++ ) { + } ) + .then( response => { - if ( json.uvs[ i ].length ) nUvLayers ++; + switch ( responseType ) { - } + case 'arraybuffer': - for ( i = 0; i < nUvLayers; i ++ ) { + return response.arrayBuffer(); - geometry.faceVertexUvs[ i ] = []; + case 'blob': - } + return response.blob(); - } + case 'document': - offset = 0; - zLength = vertices.length; + return response.text() + .then( text => { - while ( offset < zLength ) { + const parser = new DOMParser(); + return parser.parseFromString( text, mimeType ); - vertex = new Vector3(); + } ); - vertex.x = vertices[ offset ++ ] * scale; - vertex.y = vertices[ offset ++ ] * scale; - vertex.z = vertices[ offset ++ ] * scale; + case 'json': - geometry.vertices.push( vertex ); + return response.json(); - } + default: - offset = 0; - zLength = faces.length; + if ( mimeType === undefined ) { - while ( offset < zLength ) { + return response.text(); - type = faces[ offset ++ ]; + } else { - isQuad = isBitSet( type, 0 ); - hasMaterial = isBitSet( type, 1 ); - hasFaceVertexUv = isBitSet( type, 3 ); - hasFaceNormal = isBitSet( type, 4 ); - hasFaceVertexNormal = isBitSet( type, 5 ); - hasFaceColor = isBitSet( type, 6 ); - hasFaceVertexColor = isBitSet( type, 7 ); + // sniff encoding + const re = /charset="?([^;"\s]*)"?/i; + const exec = re.exec( mimeType ); + const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; + const decoder = new TextDecoder( label ); + return response.arrayBuffer().then( ab => decoder.decode( ab ) ); - // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); + } - if ( isQuad ) { + } - faceA = new Face3(); - faceA.a = faces[ offset ]; - faceA.b = faces[ offset + 1 ]; - faceA.c = faces[ offset + 3 ]; + } ) + .then( data => { - faceB = new Face3(); - faceB.a = faces[ offset + 1 ]; - faceB.b = faces[ offset + 2 ]; - faceB.c = faces[ offset + 3 ]; + // Add to cache only on HTTP success, so that we do not cache + // error response bodies as proper responses to requests. + Cache.add( url, data ); - offset += 4; + const callbacks = loading[ url ]; + delete loading[ url ]; - if ( hasMaterial ) { + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - materialIndex = faces[ offset ++ ]; - faceA.materialIndex = materialIndex; - faceB.materialIndex = materialIndex; + const callback = callbacks[ i ]; + if ( callback.onLoad ) callback.onLoad( data ); - } + } - // to get face <=> uv index correspondence + } ) + .catch( err => { - fi = geometry.faces.length; + // Abort errors and other errors are handled the same - if ( hasFaceVertexUv ) { + const callbacks = loading[ url ]; - for ( i = 0; i < nUvLayers; i ++ ) { + if ( callbacks === undefined ) { - uvLayer = json.uvs[ i ]; + // When onLoad was called and url was deleted in `loading` + this.manager.itemError( url ); + throw err; - geometry.faceVertexUvs[ i ][ fi ] = []; - geometry.faceVertexUvs[ i ][ fi + 1 ] = []; + } - for ( j = 0; j < 4; j ++ ) { + delete loading[ url ]; - uvIndex = faces[ offset ++ ]; + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; + const callback = callbacks[ i ]; + if ( callback.onError ) callback.onError( err ); - uv = new Vector2( u, v ); + } - if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv ); - if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv ); + this.manager.itemError( url ); - } + } ) + .finally( () => { - } + this.manager.itemEnd( url ); - } + } ); - if ( hasFaceNormal ) { + this.manager.itemStart( url ); - normalIndex = faces[ offset ++ ] * 3; + } - faceA.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + setResponseType( value ) { - faceB.normal.copy( faceA.normal ); + this.responseType = value; + return this; - } + } - if ( hasFaceVertexNormal ) { + setMimeType( value ) { - for ( i = 0; i < 4; i ++ ) { + this.mimeType = value; + return this; - normalIndex = faces[ offset ++ ] * 3; + } - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + } + class ImageLoader extends Loader { - if ( i !== 2 ) faceA.vertexNormals.push( normal ); - if ( i !== 0 ) faceB.vertexNormals.push( normal ); + constructor( manager ) { - } + super( manager ); - } + } + load( url, onLoad, onProgress, onError ) { - if ( hasFaceColor ) { + if ( this.path !== undefined ) url = this.path + url; - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; + url = this.manager.resolveURL( url ); - faceA.color.setHex( hex ); - faceB.color.setHex( hex ); + const scope = this; - } + const cached = Cache.get( url ); + if ( cached !== undefined ) { - if ( hasFaceVertexColor ) { + scope.manager.itemStart( url ); - for ( i = 0; i < 4; i ++ ) { + setTimeout( function () { - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; + if ( onLoad ) onLoad( cached ); - if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) ); - if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) ); + scope.manager.itemEnd( url ); - } + }, 0 ); - } + return cached; - geometry.faces.push( faceA ); - geometry.faces.push( faceB ); + } - } else { + const image = createElementNS( 'img' ); - face = new Face3(); - face.a = faces[ offset ++ ]; - face.b = faces[ offset ++ ]; - face.c = faces[ offset ++ ]; + function onImageLoad() { - if ( hasMaterial ) { + removeEventListeners(); - materialIndex = faces[ offset ++ ]; - face.materialIndex = materialIndex; + Cache.add( url, this ); - } + if ( onLoad ) onLoad( this ); - // to get face <=> uv index correspondence + scope.manager.itemEnd( url ); - fi = geometry.faces.length; + } - if ( hasFaceVertexUv ) { + function onImageError( event ) { - for ( i = 0; i < nUvLayers; i ++ ) { + removeEventListeners(); - uvLayer = json.uvs[ i ]; + if ( onError ) onError( event ); - geometry.faceVertexUvs[ i ][ fi ] = []; + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - for ( j = 0; j < 3; j ++ ) { + } - uvIndex = faces[ offset ++ ]; + function removeEventListeners() { - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; + image.removeEventListener( 'load', onImageLoad, false ); + image.removeEventListener( 'error', onImageError, false ); - uv = new Vector2( u, v ); + } - geometry.faceVertexUvs[ i ][ fi ].push( uv ); + image.addEventListener( 'load', onImageLoad, false ); + image.addEventListener( 'error', onImageError, false ); - } + if ( url.slice( 0, 5 ) !== 'data:' ) { - } + if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; - } + } - if ( hasFaceNormal ) { + scope.manager.itemStart( url ); - normalIndex = faces[ offset ++ ] * 3; + image.src = url; - face.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + return image; - } + } - if ( hasFaceVertexNormal ) { + } - for ( i = 0; i < 3; i ++ ) { + /** + * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) + * + * Sub classes have to implement the parse() method which will be used in load(). + */ - normalIndex = faces[ offset ++ ] * 3; + class DataTextureLoader extends Loader { - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); + constructor( manager ) { - face.vertexNormals.push( normal ); + super( manager ); - } + } - } + load( url, onLoad, onProgress, onError ) { + const scope = this; - if ( hasFaceColor ) { + const texture = new DataTexture(); - colorIndex = faces[ offset ++ ]; - face.color.setHex( colors[ colorIndex ] ); + 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 ) { - } + let texData; + try { - if ( hasFaceVertexColor ) { + texData = scope.parse( buffer ); - for ( i = 0; i < 3; i ++ ) { + } catch ( error ) { - colorIndex = faces[ offset ++ ]; - face.vertexColors.push( new Color( colors[ colorIndex ] ) ); + if ( onError !== undefined ) { - } + onError( error ); - } + } else { - geometry.faces.push( face ); + console.error( error ); + return; } } - } + if ( texData.image !== undefined ) { + + texture.image = texData.image; - function parseSkin( json, geometry ) { + } else if ( texData.data !== undefined ) { - var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2; + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; - if ( json.skinWeights ) { + } - for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) { + texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; + texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; - var x = json.skinWeights[ i ]; - var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0; - var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0; - var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0; + texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; + texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; - geometry.skinWeights.push( new Vector4( x, y, z, w ) ); + texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - } + if ( texData.colorSpace !== undefined ) { + + texture.colorSpace = texData.colorSpace; } - if ( json.skinIndices ) { + if ( texData.flipY !== undefined ) { - for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) { + texture.flipY = texData.flipY; - var a = json.skinIndices[ i ]; - var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0; - var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0; - var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0; + } - geometry.skinIndices.push( new Vector4( a, b, c, d ) ); + if ( texData.format !== undefined ) { - } + texture.format = texData.format; } - geometry.bones = json.bones; + if ( texData.type !== undefined ) { - if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { - - console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + - geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); + texture.type = texData.type; } - } + if ( texData.mipmaps !== undefined ) { + + texture.mipmaps = texData.mipmaps; + texture.minFilter = LinearMipmapLinearFilter; // presumably... - function parseMorphing( json, geometry ) { + } - var scale = json.scale; + if ( texData.mipmapCount === 1 ) { - if ( json.morphTargets !== undefined ) { + texture.minFilter = LinearFilter; - for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) { + } - geometry.morphTargets[ i ] = {}; - geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; - geometry.morphTargets[ i ].vertices = []; + if ( texData.generateMipmaps !== undefined ) { - var dstVertices = geometry.morphTargets[ i ].vertices; - var srcVertices = json.morphTargets[ i ].vertices; + texture.generateMipmaps = texData.generateMipmaps; - for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) { + } - var vertex = new Vector3(); - vertex.x = srcVertices[ v ] * scale; - vertex.y = srcVertices[ v + 1 ] * scale; - vertex.z = srcVertices[ v + 2 ] * scale; + texture.needsUpdate = true; - dstVertices.push( vertex ); + if ( onLoad ) onLoad( texture, texData ); - } + }, onProgress, onError ); - } - } + return texture; - if ( json.morphColors !== undefined && json.morphColors.length > 0 ) { + } - console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' ); + } - var faces = geometry.faces; - var morphColors = json.morphColors[ 0 ].colors; + class TextureLoader extends Loader { - for ( var i = 0, l = faces.length; i < l; i ++ ) { + constructor( manager ) { - faces[ i ].color.fromArray( morphColors, i * 3 ); + super( manager ); - } + } - } + load( url, onLoad, onProgress, onError ) { - } + const texture = new Texture(); - function parseAnimations( json, geometry ) { + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); - var outputAnimations = []; + loader.load( url, function ( image ) { - // parse old style Bone/Hierarchy animations - var animations = []; + texture.image = image; + texture.needsUpdate = true; - if ( json.animation !== undefined ) { + if ( onLoad !== undefined ) { - animations.push( json.animation ); + onLoad( texture ); } - if ( json.animations !== undefined ) { + }, onProgress, onError ); - if ( json.animations.length ) { + return texture; - animations = animations.concat( json.animations ); + } - } else { + } - animations.push( json.animations ); + class Light extends Object3D { - } + constructor( color, intensity = 1 ) { - } + super(); - for ( var i = 0; i < animations.length; i ++ ) { + this.isLight = true; - var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones ); - if ( clip ) outputAnimations.push( clip ); + this.type = 'Light'; - } - - // parse implicit morph animations - if ( geometry.morphTargets ) { + this.color = new Color( color ); + this.intensity = intensity; - // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary. - var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 ); - outputAnimations = outputAnimations.concat( morphAnimationClips ); + } - } + dispose() { - if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations; + // Empty here in base class; some subclasses override. - } + } - return function ( json, texturePath ) { + copy( source, recursive ) { - if ( json.data !== undefined ) { + super.copy( source, recursive ); - // Geometry 4.0 spec - json = json.data; + this.color.copy( source.color ); + this.intensity = source.intensity; - } + return this; - if ( json.scale !== undefined ) { + } - json.scale = 1.0 / json.scale; + toJSON( meta ) { - } else { + const data = super.toJSON( meta ); - json.scale = 1.0; + data.object.color = this.color.getHex(); + data.object.intensity = this.intensity; - } + if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); - var geometry = new Geometry(); + if ( this.distance !== undefined ) data.object.distance = this.distance; + if ( this.angle !== undefined ) data.object.angle = this.angle; + if ( this.decay !== undefined ) data.object.decay = this.decay; + if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - parseModel( json, geometry ); - parseSkin( json, geometry ); - parseMorphing( json, geometry ); - parseAnimations( json, geometry ); + if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); + if ( this.target !== undefined ) data.object.target = this.target.uuid; - geometry.computeFaceNormals(); - geometry.computeBoundingSphere(); + return data; - if ( json.materials === undefined || json.materials.length === 0 ) { + } - return { geometry: geometry }; + } - } else { + const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); + const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); + const _lookTarget$1 = /*@__PURE__*/ new Vector3(); - var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin ); + class LightShadow { - return { geometry: geometry, materials: materials }; + constructor( camera ) { - } + this.camera = camera; - }; + this.intensity = 1; - } )() + this.bias = 0; + this.normalBias = 0; + this.radius = 1; + this.blurSamples = 8; - } ); + this.mapSize = new Vector2( 512, 512 ); - /** - * @author mrdoob / http://mrdoob.com/ - */ + this.map = null; + this.mapPass = null; + this.matrix = new Matrix4(); - function ObjectLoader( manager ) { + this.autoUpdate = true; + this.needsUpdate = false; - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.texturePath = ''; + this._frustum = new Frustum(); + this._frameExtents = new Vector2( 1, 1 ); - } + this._viewportCount = 1; - Object.assign( ObjectLoader.prototype, { + this._viewports = [ - load: function ( url, onLoad, onProgress, onError ) { + new Vector4( 0, 0, 1, 1 ) - if ( this.texturePath === '' ) { + ]; - this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); + } - } + getViewportCount() { - var scope = this; + return this._viewportCount; - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { + } - var json = null; + getFrustum() { - try { + return this._frustum; - json = JSON.parse( text ); + } - } catch ( error ) { + updateMatrices( light ) { - if ( onError !== undefined ) onError( error ); + const shadowCamera = this.camera; + const shadowMatrix = this.matrix; - console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); + _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld$1 ); - return; + _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget$1 ); + shadowCamera.updateMatrixWorld(); - } + _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); - var metadata = json.metadata; + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + shadowMatrix.multiply( _projScreenMatrix$1 ); - console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' ); - return; + } - } + getViewport( viewportIndex ) { - scope.parse( json, onLoad ); + return this._viewports[ viewportIndex ]; - }, onProgress, onError ); + } - }, + getFrameExtents() { - setTexturePath: function ( value ) { + return this._frameExtents; - this.texturePath = value; + } - }, + dispose() { - setCrossOrigin: function ( value ) { + if ( this.map ) { - this.crossOrigin = value; + this.map.dispose(); - }, + } - parse: function ( json, onLoad ) { + if ( this.mapPass ) { - var shapes = this.parseShape( json.shapes ); - var geometries = this.parseGeometries( json.geometries, shapes ); + this.mapPass.dispose(); - var images = this.parseImages( json.images, function () { + } - if ( onLoad !== undefined ) onLoad( object ); + } - } ); + copy( source ) { - var textures = this.parseTextures( json.textures, images ); - var materials = this.parseMaterials( json.materials, textures ); + this.camera = source.camera.clone(); - var object = this.parseObject( json.object, geometries, materials ); + this.intensity = source.intensity; - if ( json.animations ) { + this.bias = source.bias; + this.radius = source.radius; - object.animations = this.parseAnimations( json.animations ); + this.mapSize.copy( source.mapSize ); - } + return this; - if ( json.images === undefined || json.images.length === 0 ) { + } - if ( onLoad !== undefined ) onLoad( object ); + clone() { - } + return new this.constructor().copy( this ); - return object; + } - }, + toJSON() { - parseShape: function ( json ) { + const object = {}; - var shapes = {}; + if ( this.intensity !== 1 ) object.intensity = this.intensity; + 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(); - if ( json !== undefined ) { + object.camera = this.camera.toJSON( false ).object; + delete object.camera.matrix; - for ( var i = 0, l = json.length; i < l; i ++ ) { + return object; - var shape = new Shape().fromJSON( json[ i ] ); + } - shapes[ shape.uuid ] = shape; + } - } + class SpotLightShadow extends LightShadow { - } + constructor() { - return shapes; + super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); - }, + this.isSpotLightShadow = true; - parseGeometries: function ( json, shapes ) { + this.focus = 1; - var geometries = {}; + } - if ( json !== undefined ) { + updateMatrices( light ) { - var geometryLoader = new JSONLoader(); - var bufferGeometryLoader = new BufferGeometryLoader(); + const camera = this.camera; - for ( var i = 0, l = json.length; i < l; i ++ ) { + const fov = RAD2DEG * 2 * light.angle * this.focus; + const aspect = this.mapSize.width / this.mapSize.height; + const far = light.distance || camera.far; - var geometry; - var data = json[ i ]; + if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { - switch ( data.type ) { + camera.fov = fov; + camera.aspect = aspect; + camera.far = far; + camera.updateProjectionMatrix(); - case 'PlaneGeometry': - case 'PlaneBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.widthSegments, - data.heightSegments - ); + super.updateMatrices( light ); - break; + } - case 'BoxGeometry': - case 'BoxBufferGeometry': - case 'CubeGeometry': // backwards compatible - - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.depth, - data.widthSegments, - data.heightSegments, - data.depthSegments - ); + copy( source ) { - break; + super.copy( source ); - case 'CircleGeometry': - case 'CircleBufferGeometry': + this.focus = source.focus; - geometry = new Geometries[ data.type ]( - data.radius, - data.segments, - data.thetaStart, - data.thetaLength - ); + return this; - break; + } - case 'CylinderGeometry': - case 'CylinderBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radiusTop, - data.radiusBottom, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); + } - break; + class SpotLight extends Light { - case 'ConeGeometry': - case 'ConeBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); + constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { - break; + super( color, intensity ); - case 'SphereGeometry': - case 'SphereBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.widthSegments, - data.heightSegments, - data.phiStart, - data.phiLength, - data.thetaStart, - data.thetaLength - ); + this.isSpotLight = true; - break; + this.type = 'SpotLight'; - case 'DodecahedronGeometry': - case 'DodecahedronBufferGeometry': - case 'IcosahedronGeometry': - case 'IcosahedronBufferGeometry': - case 'OctahedronGeometry': - case 'OctahedronBufferGeometry': - case 'TetrahedronGeometry': - case 'TetrahedronBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.detail - ); + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - break; + this.target = new Object3D(); - case 'RingGeometry': - case 'RingBufferGeometry': + this.distance = distance; + this.angle = angle; + this.penumbra = penumbra; + this.decay = decay; - geometry = new Geometries[ data.type ]( - data.innerRadius, - data.outerRadius, - data.thetaSegments, - data.phiSegments, - data.thetaStart, - data.thetaLength - ); + this.map = null; - break; + this.shadow = new SpotLightShadow(); - case 'TorusGeometry': - case 'TorusBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.radialSegments, - data.tubularSegments, - data.arc - ); + get power() { - break; + // compute the light's luminous power (in lumens) from its intensity (in candela) + // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd) + return this.intensity * Math.PI; - case 'TorusKnotGeometry': - case 'TorusKnotBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.tubularSegments, - data.radialSegments, - data.p, - data.q - ); + set power( power ) { - break; + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / Math.PI; - case 'LatheGeometry': - case 'LatheBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.points, - data.segments, - data.phiStart, - data.phiLength - ); + dispose() { - break; + this.shadow.dispose(); - case 'PolyhedronGeometry': - case 'PolyhedronBufferGeometry': + } - geometry = new Geometries[ data.type ]( - data.vertices, - data.indices, - data.radius, - data.details - ); + copy( source, recursive ) { - break; + super.copy( source, recursive ); - case 'ShapeGeometry': - case 'ShapeBufferGeometry': + this.distance = source.distance; + this.angle = source.angle; + this.penumbra = source.penumbra; + this.decay = source.decay; - var geometryShapes = []; + this.target = source.target.clone(); - for ( var i = 0, l = data.shapes.length; i < l; i ++ ) { + this.shadow = source.shadow.clone(); - var shape = shapes[ data.shapes[ i ] ]; + return this; - geometryShapes.push( shape ); + } - } + } - geometry = new Geometries[ data.type ]( - geometryShapes, - data.curveSegments - ); + const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); + const _lightPositionWorld = /*@__PURE__*/ new Vector3(); + const _lookTarget = /*@__PURE__*/ new Vector3(); - break; + class PointLightShadow extends LightShadow { - case 'BufferGeometry': + constructor() { - geometry = bufferGeometryLoader.parse( data ); + super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); - break; + this.isPointLightShadow = true; - case 'Geometry': + this._frameExtents = new Vector2( 4, 2 ); - geometry = geometryLoader.parse( data, this.texturePath ).geometry; + this._viewportCount = 6; - break; + this._viewports = [ + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction + + // positive X + new Vector4( 2, 1, 1, 1 ), + // negative X + new Vector4( 0, 1, 1, 1 ), + // positive Z + new Vector4( 3, 1, 1, 1 ), + // negative Z + new Vector4( 1, 1, 1, 1 ), + // positive Y + new Vector4( 3, 0, 1, 1 ), + // negative Y + new Vector4( 1, 0, 1, 1 ) + ]; - default: + this._cubeDirections = [ + new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), + new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) + ]; - console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' ); + this._cubeUps = [ + new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), + new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) + ]; - continue; + } - } + updateMatrices( light, viewportIndex = 0 ) { - geometry.uuid = data.uuid; + const camera = this.camera; + const shadowMatrix = this.matrix; - if ( data.name !== undefined ) geometry.name = data.name; + const far = light.distance || camera.far; - geometries[ data.uuid ] = geometry; + if ( far !== camera.far ) { - } + camera.far = far; + camera.updateProjectionMatrix(); } - return geometries; - - }, + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + camera.position.copy( _lightPositionWorld ); - parseMaterials: function ( json, textures ) { + _lookTarget.copy( camera.position ); + _lookTarget.add( this._cubeDirections[ viewportIndex ] ); + camera.up.copy( this._cubeUps[ viewportIndex ] ); + camera.lookAt( _lookTarget ); + camera.updateMatrixWorld(); - var materials = {}; + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - if ( json !== undefined ) { + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix ); - var loader = new MaterialLoader(); - loader.setTextures( textures ); + } - for ( var i = 0, l = json.length; i < l; i ++ ) { + } - var data = json[ i ]; + class PointLight extends Light { - if ( data.type === 'MultiMaterial' ) { + constructor( color, intensity, distance = 0, decay = 2 ) { - // Deprecated + super( color, intensity ); - var array = []; + this.isPointLight = true; - for ( var j = 0; j < data.materials.length; j ++ ) { + this.type = 'PointLight'; - array.push( loader.parse( data.materials[ j ] ) ); + this.distance = distance; + this.decay = decay; - } + this.shadow = new PointLightShadow(); - materials[ data.uuid ] = array; + } - } else { + get power() { - materials[ data.uuid ] = loader.parse( data ); + // compute the light's luminous power (in lumens) from its intensity (in candela) + // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd) + return this.intensity * 4 * Math.PI; - } + } - } + set power( power ) { - } + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / ( 4 * Math.PI ); - return materials; + } - }, + dispose() { - parseAnimations: function ( json ) { + this.shadow.dispose(); - var animations = []; + } - for ( var i = 0; i < json.length; i ++ ) { + copy( source, recursive ) { - var clip = AnimationClip.parse( json[ i ] ); + super.copy( source, recursive ); - animations.push( clip ); + this.distance = source.distance; + this.decay = source.decay; - } + this.shadow = source.shadow.clone(); - return animations; + return this; - }, + } - parseImages: function ( json, onLoad ) { + } - var scope = this; - var images = {}; + class DirectionalLightShadow extends LightShadow { - function loadImage( url ) { + constructor() { - scope.manager.itemStart( url ); + super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); - return loader.load( url, function () { + this.isDirectionalLightShadow = true; - scope.manager.itemEnd( url ); + } - }, undefined, function () { + } - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + class DirectionalLight extends Light { - } ); + constructor( color, intensity ) { - } + super( color, intensity ); - if ( json !== undefined && json.length > 0 ) { + this.isDirectionalLight = true; - var manager = new LoadingManager( onLoad ); + this.type = 'DirectionalLight'; - var loader = new ImageLoader( manager ); - loader.setCrossOrigin( this.crossOrigin ); + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - for ( var i = 0, l = json.length; i < l; i ++ ) { + this.target = new Object3D(); - var image = json[ i ]; - var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; + this.shadow = new DirectionalLightShadow(); - images[ image.uuid ] = loadImage( path ); + } - } + dispose() { - } + this.shadow.dispose(); - return images; + } - }, + copy( source ) { - parseTextures: function ( json, images ) { + super.copy( source ); - function parseConstant( value, type ) { + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); - if ( typeof value === 'number' ) return value; + return this; - console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); + } - return type[ value ]; + } - } + class AmbientLight extends Light { - var textures = {}; + constructor( color, intensity ) { - if ( json !== undefined ) { + super( color, intensity ); - for ( var i = 0, l = json.length; i < l; i ++ ) { + this.isAmbientLight = true; - var data = json[ i ]; + this.type = 'AmbientLight'; - if ( data.image === undefined ) { + } - console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); + } - } + class LoaderUtils { - if ( images[ data.image ] === undefined ) { + static decodeText( array ) { // @deprecated, r165 - console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); + console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); - } + if ( typeof TextDecoder !== 'undefined' ) { - var texture = new Texture( images[ data.image ] ); - texture.needsUpdate = true; + return new TextDecoder().decode( array ); - texture.uuid = data.uuid; + } - if ( data.name !== undefined ) texture.name = data.name; + // Avoid the String.fromCharCode.apply(null, array) shortcut, which + // throws a "maximum call stack size exceeded" error for large arrays. - if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + let s = ''; - if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); - if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); - if ( data.center !== undefined ) texture.center.fromArray( data.center ); - if ( data.rotation !== undefined ) texture.rotation = data.rotation; + for ( let i = 0, il = array.length; i < il; i ++ ) { - if ( data.wrap !== undefined ) { + // Implicitly assumes little-endian. + s += String.fromCharCode( array[ i ] ); - texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); - texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); + } - } + try { - if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); - if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); - if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; + // merges multi-byte utf-8 characters. - if ( data.flipY !== undefined ) texture.flipY = data.flipY; + return decodeURIComponent( escape( s ) ); - textures[ data.uuid ] = texture; + } catch ( e ) { // see #16358 - } + return s; } - return textures; + } - }, + static extractUrlBase( url ) { - parseObject: function () { + const index = url.lastIndexOf( '/' ); - var matrix = new Matrix4(); + if ( index === - 1 ) return './'; - return function parseObject( data, geometries, materials ) { + return url.slice( 0, index + 1 ); - var object; + } - function getGeometry( name ) { + static resolveURL( url, path ) { - if ( geometries[ name ] === undefined ) { + // Invalid URL + if ( typeof url !== 'string' || url === '' ) return ''; - console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); + // Host Relative URL + if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { - } + path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); - return geometries[ name ]; + } - } + // Absolute URL http://,https://,// + if ( /^(https?:)?\/\//i.test( url ) ) return url; - function getMaterial( name ) { + // Data URI + if ( /^data:.*,.*$/i.test( url ) ) return url; - if ( name === undefined ) return undefined; + // Blob URL + if ( /^blob:.*$/i.test( url ) ) return url; - if ( Array.isArray( name ) ) { + // Relative URL + return path + url; - var array = []; + } - for ( var i = 0, l = name.length; i < l; i ++ ) { + } - var uuid = name[ i ]; + const _matrix = /*@__PURE__*/ new Matrix4(); - if ( materials[ uuid ] === undefined ) { + class Raycaster { - console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); + constructor( origin, direction, near = 0, far = Infinity ) { - } + this.ray = new Ray( origin, direction ); + // direction is assumed to be normalized (for accurate distance calculations) - array.push( materials[ uuid ] ); + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); + + this.params = { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + }; - } + } - return array; + set( origin, direction ) { - } + // direction is assumed to be normalized (for accurate distance calculations) - if ( materials[ name ] === undefined ) { + this.ray.set( origin, direction ); - console.warn( 'THREE.ObjectLoader: Undefined material', name ); + } - } + setFromCamera( coords, camera ) { - return materials[ name ]; + 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; - switch ( data.type ) { + } else if ( camera.isOrthographicCamera ) { - case 'Scene': + this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera + this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + this.camera = camera; - object = new Scene(); + } else { - if ( data.background !== undefined ) { + console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); - if ( Number.isInteger( data.background ) ) { + } - object.background = new Color( data.background ); + } - } + setFromXRController( controller ) { - } + _matrix.identity().extractRotation( controller.matrixWorld ); - if ( data.fog !== undefined ) { + this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); - if ( data.fog.type === 'Fog' ) { + return this; - object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); + } - } else if ( data.fog.type === 'FogExp2' ) { + intersectObject( object, recursive = true, intersects = [] ) { - object.fog = new FogExp2( data.fog.color, data.fog.density ); + intersect( object, this, intersects, recursive ); - } + intersects.sort( ascSort ); - } + return intersects; - break; + } - case 'PerspectiveCamera': + intersectObjects( objects, recursive = true, intersects = [] ) { - object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); + for ( let i = 0, l = objects.length; i < l; i ++ ) { - if ( data.focus !== undefined ) object.focus = data.focus; - if ( data.zoom !== undefined ) object.zoom = data.zoom; - if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; - if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; - if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); + intersect( objects[ i ], this, intersects, recursive ); - break; + } - case 'OrthographicCamera': + intersects.sort( ascSort ); - object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); + return intersects; - break; + } - case 'AmbientLight': + } - object = new AmbientLight( data.color, data.intensity ); + function ascSort( a, b ) { - break; + return a.distance - b.distance; - case 'DirectionalLight': + } - object = new DirectionalLight( data.color, data.intensity ); + function intersect( object, raycaster, intersects, recursive ) { - break; + let propagate = true; - case 'PointLight': + if ( object.layers.test( raycaster.layers ) ) { - object = new PointLight( data.color, data.intensity, data.distance, data.decay ); + const result = object.raycast( raycaster, intersects ); - break; + if ( result === false ) propagate = false; - case 'RectAreaLight': + } - object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); + if ( propagate === true && recursive === true ) { - break; + const children = object.children; - 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 'SkinnedMesh': + for ( let i = 0, l = children.length; i < l; i ++ ) { - console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' ); + intersect( children[ i ], raycaster, intersects, true ); - case 'Mesh': + } - var geometry = getGeometry( data.geometry ); - var material = getMaterial( data.material ); + } - if ( geometry.bones && geometry.bones.length > 0 ) { + } - object = new SkinnedMesh( geometry, material ); + const _axis = /*@__PURE__*/ new Vector3(); + let _lineGeometry, _coneGeometry; - } else { + class ArrowHelper extends Object3D { - object = new Mesh( geometry, material ); + // dir is assumed to be normalized - } + constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - break; + super(); - case 'LOD': + this.type = 'ArrowHelper'; - object = new LOD(); + if ( _lineGeometry === undefined ) { - break; + _lineGeometry = new BufferGeometry(); + _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); - case 'Line': + _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); + _coneGeometry.translate( 0, - 0.5, 0 ); - object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); + } - break; + this.position.copy( origin ); - case 'LineLoop': + this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + this.line.matrixAutoUpdate = false; + this.add( this.line ); - object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); + this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); + this.cone.matrixAutoUpdate = false; + this.add( this.cone ); - break; + this.setDirection( dir ); + this.setLength( length, headLength, headWidth ); - case 'LineSegments': + } - object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); + setDirection( dir ) { - break; + // dir is assumed to be normalized - case 'PointCloud': - case 'Points': + if ( dir.y > 0.99999 ) { - object = new Points$1( getGeometry( data.geometry ), getMaterial( data.material ) ); + this.quaternion.set( 0, 0, 0, 1 ); - break; + } else if ( dir.y < - 0.99999 ) { - case 'Sprite': + this.quaternion.set( 1, 0, 0, 0 ); - object = new Sprite( getMaterial( data.material ) ); + } else { - break; + _axis.set( dir.z, 0, - dir.x ).normalize(); - case 'Group': + const radians = Math.acos( dir.y ); - object = new Group(); + this.quaternion.setFromAxisAngle( _axis, radians ); - break; + } - default: + } - object = new Object3D(); + setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - } + this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 + this.line.updateMatrix(); - object.uuid = data.uuid; + this.cone.scale.set( headWidth, headLength, headWidth ); + this.cone.position.y = length; + this.cone.updateMatrix(); - if ( data.name !== undefined ) object.name = data.name; - if ( data.matrix !== undefined ) { + } - matrix.fromArray( data.matrix ); - matrix.decompose( object.position, object.quaternion, object.scale ); + setColor( color ) { - } else { + this.line.material.color.set( color ); + this.cone.material.color.set( color ); - if ( data.position !== undefined ) object.position.fromArray( data.position ); - if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); - if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); - if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); + } - } + copy( source ) { - if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; - if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; + super.copy( source, false ); - if ( data.shadow ) { + this.line.copy( source.line ); + this.cone.copy( source.cone ); - if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; - if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; - if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); - if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); + return this; - } + } - if ( data.visible !== undefined ) object.visible = data.visible; - if ( data.userData !== undefined ) object.userData = data.userData; + dispose() { - if ( data.children !== undefined ) { + this.line.geometry.dispose(); + this.line.material.dispose(); + this.cone.geometry.dispose(); + this.cone.material.dispose(); - var children = data.children; + } - for ( var i = 0; i < children.length; i ++ ) { + } - object.add( this.parseObject( children[ i ], geometries, materials ) ); + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - } + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { + revision: REVISION, + } } ) ); - } + } - if ( data.type === 'LOD' ) { + if ( typeof window !== 'undefined' ) { - var levels = data.levels; + if ( window.__THREE__ ) { - for ( var l = 0; l < levels.length; l ++ ) { + console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); - var level = levels[ l ]; - var child = object.getObjectByProperty( 'uuid', level.object ); + } else { - if ( child !== undefined ) { + window.__THREE__ = REVISION; - object.addLevel( child, level.distance ); + } - } + } - } + // Marker types + var MARKER_ARROW = 0; + var MARKER_CUBE = 1; + var MARKER_SPHERE = 2; + var MARKER_CYLINDER = 3; + var MARKER_LINE_STRIP = 4; + var MARKER_LINE_LIST = 5; + var MARKER_CUBE_LIST = 6; + var MARKER_SPHERE_LIST = 7; + var MARKER_POINTS = 8; + var MARKER_TEXT_VIEW_FACING = 9; + var MARKER_MESH_RESOURCE = 10; + var MARKER_TRIANGLE_LIST = 11; - } + // Interactive marker feedback types + var INTERACTIVE_MARKER_KEEP_ALIVE = 0; + var INTERACTIVE_MARKER_POSE_UPDATE = 1; + var INTERACTIVE_MARKER_MENU_SELECT = 2; + var INTERACTIVE_MARKER_BUTTON_CLICK = 3; + var INTERACTIVE_MARKER_MOUSE_DOWN = 4; + var INTERACTIVE_MARKER_MOUSE_UP = 5; - return object; + // Interactive marker control types + var INTERACTIVE_MARKER_NONE = 0; + var INTERACTIVE_MARKER_MENU = 1; + var INTERACTIVE_MARKER_BUTTON = 2; + var INTERACTIVE_MARKER_MOVE_AXIS = 3; + var INTERACTIVE_MARKER_MOVE_PLANE = 4; + var INTERACTIVE_MARKER_ROTATE_AXIS = 5; + var INTERACTIVE_MARKER_MOVE_ROTATE = 6; + var INTERACTIVE_MARKER_MOVE_3D = 7; + var INTERACTIVE_MARKER_ROTATE_3D = 8; + var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; - }; + // Interactive marker rotation behavior + var INTERACTIVE_MARKER_INHERIT = 0; + var INTERACTIVE_MARKER_FIXED = 1; + var INTERACTIVE_MARKER_VIEW_FACING = 2; - }() + /** + * @function makeColorMaterial + * @description Create a THREE material based on the given RGBA values. + * + * @param r - the red value + * @param g - the green value + * @param b - the blue value + * @param a - the alpha value + * @returns the THREE material + */ + var makeColorMaterial = function makeColorMaterial(r, g, b, a) { + var color = new Color(); + color.setRGB(r, g, b); + if (a <= 0.99) { + return new MeshBasicMaterial({ + color: color.getHex(), + opacity: a + 0.1, + transparent: true, + depthWrite: true, + blendSrc: SrcAlphaFactor, + blendDst: OneMinusSrcAlphaFactor, + blendEquation: ReverseSubtractEquation, + blending: NormalBlending + }); + } else { + return new MeshPhongMaterial({ + color: color.getHex(), + opacity: a, + blending: NormalBlending + }); + } + }; - } ); + /** + * @function intersectPlane + * @description Return the intersection between the mouseray and the plane. + * + * @param mouseRay - the mouse ray + * @param planeOrigin - the origin of the plane + * @param planeNormal - the normal of the plane + * @returns the intersection point + */ + var intersectPlane = function intersectPlane(mouseRay, planeOrigin, planeNormal) { + var vector = new Vector3(); + var intersectPoint = new Vector3(); + vector.subVectors(planeOrigin, mouseRay.origin); + var dot = mouseRay.direction.dot(planeNormal); - var TEXTURE_MAPPING = { - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping - }; + // bail if ray and plane are parallel + if (Math.abs(dot) < mouseRay.precision) { + return undefined; + } - var TEXTURE_WRAPPING = { - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping + // calc distance to plane + var scalar = planeNormal.dot(vector) / dot; + intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); + return intersectPoint; }; - var TEXTURE_FILTER = { - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter + /** + * @function findClosestPoint + * @description Find the closest point on targetRay to any point on mouseRay. Math taken from + * http://paulbourke.net/geometry/lineline3d/ + * + * @param targetRay - the target ray to use + * @param mouseRay - the mouse ray + * @param the closest point between the two rays + */ + var findClosestPoint = function findClosestPoint(targetRay, mouseRay) { + var v13 = new Vector3(); + v13.subVectors(targetRay.origin, mouseRay.origin); + var v43 = mouseRay.direction.clone(); + var v21 = targetRay.direction.clone(); + var d1343 = v13.dot(v43); + var d4321 = v43.dot(v21); + var d1321 = v13.dot(v21); + var d4343 = v43.dot(v43); + var d2121 = v21.dot(v21); + var denom = d2121 * d4343 - d4321 * d4321; + // check within a delta + if (Math.abs(denom) <= 0.0001) { + return undefined; + } + var numer = d1343 * d4321 - d1321 * d4343; + var mua = numer / denom; + return mua; }; /** - * @author thespite / http://clicktorelease.com/ + * @function closestAxisPoint + * @description Find the closest point between the axis and the mouse. + * + * @param axisRay - the ray from the axis + * @param camera - the camera to project from + * @param mousePos - the mouse position + * @returns the closest axis point */ + var closestAxisPoint = function closestAxisPoint(axisRay, camera, mousePos) { + // project axis onto screen + var o = axisRay.origin.clone(); + o.project(camera); + var o2 = axisRay.direction.clone().add(axisRay.origin); + o2.project(camera); - function ImageBitmapLoader( manager ) { - - if ( typeof createImageBitmap === 'undefined' ) { - - console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); + // d is the axis vector in screen space (d = o2-o) + var d = o2.clone().sub(o); - } + // t is the 2d ray param of perpendicular projection of mousePos onto o + var tmp = new Vector2(); + // (t = (mousePos - o) * d / (d*d)) + var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); - if ( typeof fetch === 'undefined' ) { + // mp is the final 2d-projected mouse pos (mp = o + d*t) + var mp = new Vector2(); + mp.addVectors(o, d.clone().multiplyScalar(t)); - console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); + // go back to 3d by shooting a ray + var vector = new Vector3(mp.x, mp.y, 0.5); + vector.unproject(camera); + var mpRay = new Ray(camera.position, vector.sub(camera.position).normalize()); + return findClosestPoint(axisRay, mpRay); + }; - } + function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); + } - this.manager = manager !== undefined ? manager : DefaultLoadingManager; - this.options = undefined; + function _typeof(o) { + "@babel/helpers - typeof"; + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { + return typeof o; + } : function (o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); } - ImageBitmapLoader.prototype = { - - constructor: ImageBitmapLoader, + function toPrimitive(t, r) { + if ("object" != _typeof(t) || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r || "default"); + if ("object" != _typeof(i)) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return ("string" === r ? String : Number)(t); + } - setOptions: function setOptions( options ) { + function toPropertyKey(t) { + var i = toPrimitive(t, "string"); + return "symbol" == _typeof(i) ? i : i + ""; + } - this.options = options; + function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, toPropertyKey(o.key), o); + } + } + function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { + writable: !1 + }), e; + } - return this; + function _assertThisInitialized(e) { + if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return e; + } - }, + function _possibleConstructorReturn(t, e) { + if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; + if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); + return _assertThisInitialized(t); + } - load: function load( url, onLoad, onProgress, onError ) { + function _getPrototypeOf(t) { + return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { + return t.__proto__ || Object.getPrototypeOf(t); + }, _getPrototypeOf(t); + } - if ( url === undefined ) url = ''; + function _setPrototypeOf(t, e) { + return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { + return t.__proto__ = e, t; + }, _setPrototypeOf(t, e); + } - if ( this.path !== undefined ) url = this.path + url; + function _inherits(t, e) { + if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); + t.prototype = Object.create(e && e.prototype, { + constructor: { + value: t, + writable: !0, + configurable: !0 + } + }), Object.defineProperty(t, "prototype", { + writable: !1 + }), e && _setPrototypeOf(t, e); + } - var scope = this; + function _callSuper$z(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$z() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$z() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$z = function _isNativeReflectConstruct() { return !!t; })(); } - var cached = Cache.get( url ); + /** + * @fileOverview + * @author Julius Kammerl - jkammerl@willowgarage.com + */ - if ( cached !== undefined ) { + var DepthCloud = /*#__PURE__*/function (_THREE$Object3D) { + /** + * The DepthCloud object. + * + * @constructor + * @param options - object with following keys: + * + * * url - the URL of the stream + * * streamType (optional) - the stream type: mjpeg or vp8 video (defaults to vp8) + * * f (optional) - the camera's focal length (defaults to standard Kinect calibration) + * * maxDepthPerTile (optional) - the factor with which we control the desired depth range (defaults to 1.0) + * * pointSize (optional) - point size (pixels) for rendered point cloud + * * width (optional) - width of the video stream + * * height (optional) - height of the video stream + * * whiteness (optional) - blends rgb values to white (0..100) + * * varianceThreshold (optional) - threshold for variance filter, used for compression artifact removal + */ + function DepthCloud(options) { + var _this; + _classCallCheck(this, DepthCloud); + _this = _callSuper$z(this, DepthCloud); + options = options || {}; + _this.url = options.url; + _this.streamType = options.streamType || 'vp8'; + _this.f = options.f || 526; + _this.maxDepthPerTile = options.maxDepthPerTile || 1.0; + _this.pointSize = options.pointSize || 3; + _this.width = options.width || 1024; + _this.height = options.height || 1024; + _this.resolutionFactor = Math.max(_this.width, _this.height) / 1024; + _this.whiteness = options.whiteness || 0; + _this.varianceThreshold = options.varianceThreshold || 0.000016667; + _this.isMjpeg = _this.streamType.toLowerCase() === 'mjpeg'; + _this.video = document.createElement(_this.isMjpeg ? 'img' : 'video'); + _this.video.crossOrigin = 'Anonymous'; + _this.video.addEventListener(_this.isMjpeg ? 'load' : 'loadedmetadata', _this.metaLoaded.bind(_this), false); + if (!_this.isMjpeg) { + _this.video.loop = true; + } + _this.video.src = _this.url; + _this.video.setAttribute('crossorigin', 'Anonymous'); - scope.manager.itemStart( url ); + // define custom shaders + _this.vertex_shader = ['uniform sampler2D map;', '', 'uniform float width;', 'uniform float height;', 'uniform float nearClipping, farClipping;', '', 'uniform float pointSize;', 'uniform float zOffset;', '', 'uniform float focallength;', 'uniform float maxDepthPerTile;', 'uniform float resolutionFactor;', '', 'varying vec2 vUvP;', 'varying vec2 colorP;', '', 'varying float depthVariance;', 'varying float maskVal;', '', 'float sampleDepth(vec2 pos)', ' {', ' float depth;', ' ', ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', ' ', ' vec4 depthColor = texture2D( map, vUv );', ' ', ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', ' ', ' if (depth>0.99)', ' {', ' vec4 depthColor2 = texture2D( map, vUv2 );', ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', ' depth = 0.99+depth2;', ' }', ' ', ' return depth;', ' }', '', 'float median(float a, float b, float c)', ' {', ' float r=a;', ' ', ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', ' {', ' vec2 smp = decodeDepth(vec2(position.x, position.y));', ' float depth = smp.x;', ' depthVariance = smp.y;', ' ', ' float z = -depth;', ' ', ' pos = vec4(', ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', ' (- z + zOffset / 1000.0) * maxDepthPerTile,', ' 1.0);', ' ', ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', ' vec4 maskColor = texture2D( map, maskP );', ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', ' }', ' ', ' gl_PointSize = pointSize;', ' gl_Position = projectionMatrix * modelViewMatrix * pos;', ' ', '}'].join('\n'); + _this.fragment_shader = ['uniform sampler2D map;', 'uniform float varianceThreshold;', 'uniform float whiteness;', '', 'varying vec2 vUvP;', 'varying vec2 colorP;', '', 'varying float depthVariance;', 'varying float maskVal;', '', '', 'void main() {', ' ', ' vec4 color;', ' ', ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', ' { ', ' discard;', ' }', ' else ', ' {', ' color = texture2D( map, colorP );', ' ', ' float fader = whiteness /100.0;', ' ', ' color.r = color.r * (1.0-fader)+ fader;', ' ', ' color.g = color.g * (1.0-fader)+ fader;', ' ', ' color.b = color.b * (1.0-fader)+ fader;', ' ', ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', ' }', ' ', ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', ' ', '}'].join('\n'); + return _this; + } + _inherits(DepthCloud, _THREE$Object3D); + return _createClass(DepthCloud, [{ + key: "metaLoaded", + value: + /** + * Callback called when video metadata is ready + */ + function metaLoaded() { + this.metaLoaded = true; + this.initStreamer(); + } + }, { + key: "initStreamer", + value: + /** + * Callback called when video metadata is ready + */ + function initStreamer() { + var _this2 = this; + if (this.metaLoaded) { + this.texture = new Texture(this.video); + this.geometry = new BufferGeometry(); + for (var i = 0, l = this.width * this.height; i < l; i++) { + var vertex = new Vector3(); + vertex.x = i % this.width; + vertex.y = Math.floor(i / this.width); + this.geometry.vertices.push(vertex); + } + this.material = new ShaderMaterial({ + uniforms: { + 'map': { + type: 't', + value: this.texture + }, + 'width': { + type: 'f', + value: this.width + }, + 'height': { + type: 'f', + value: this.height + }, + 'focallength': { + type: 'f', + value: this.f + }, + 'pointSize': { + type: 'f', + value: this.pointSize + }, + 'zOffset': { + type: 'f', + value: 0 + }, + 'whiteness': { + type: 'f', + value: this.whiteness + }, + 'varianceThreshold': { + type: 'f', + value: this.varianceThreshold + }, + 'maxDepthPerTile': { + type: 'f', + value: this.maxDepthPerTile + }, + 'resolutionFactor': { + type: 'f', + value: this.resolutionFactor + } + }, + vertexShader: this.vertex_shader, + fragmentShader: this.fragment_shader + }); + this.mesh = new Points$1(this.geometry, this.material); + this.mesh.position.x = 0; + this.mesh.position.y = 0; + this.add(this.mesh); + setInterval(function () { + if (_this2.isMjpeg || _this2.video.readyState === _this2.video.HAVE_ENOUGH_DATA) { + _this2.texture.needsUpdate = true; + } + }, 1000 / 30); + } + } + }, { + key: "startStream", + value: + /** + * Start video playback + */ + function startStream() { + if (!this.isMjpeg) { + this.video.play(); + } + } + }, { + key: "stopStream", + value: + /** + * Stop video playback + */ + function stopStream() { + if (!this.isMjpeg) { + this.video.pause(); + } + } + }]); + }(Object3D); - setTimeout( function () { + function _superPropBase(t, o) { + for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); + return t; + } - if ( onLoad ) onLoad( cached ); + function _get() { + return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { + var p = _superPropBase(e, t); + if (p) { + var n = Object.getOwnPropertyDescriptor(p, t); + return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; + } + }, _get.apply(null, arguments); + } - scope.manager.itemEnd( url ); + function _callSuper$y(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$y() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$y() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$y = function _isNativeReflectConstruct() { return !!t; })(); } - }, 0 ); + /** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ - return cached; - - } - - fetch( url ).then( function ( res ) { - - return res.blob(); + var Arrow = /*#__PURE__*/function (_THREE$Mesh) { + /** + * A Arrow is a THREE object that can be used to display an arrow model. + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ + function Arrow(options) { + var _this; + _classCallCheck(this, Arrow); + options = options || {}; + var origin = options.origin || new Vector3(0, 0, 0); + var direction = options.direction || new Vector3(1, 0, 0); + var length = options.length || 1; + var headLength = options.headLength || 0.2; + var shaftDiameter = options.shaftDiameter || 0.05; + var headDiameter = options.headDiameter || 0.1; + var material = options.material || new MeshBasicMaterial(); + var shaftLength = length - headLength; - } ).then( function ( blob ) { + // create and merge geometry + var geometry = new CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, 12, 1); + var m = new Matrix4(); + m.setPosition(new Vector3(0, shaftLength * 0.5, 0)); + geometry.applyMatrix(m); - return createImageBitmap( blob, scope.options ); + // create the head + var coneGeometry = new CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); + m.setPosition(new Vector3(0, shaftLength + headLength * 0.5, 0)); + coneGeometry.applyMatrix(m); - } ).then( function ( imageBitmap ) { + // put the arrow together + geometry.merge(coneGeometry); + _this = _callSuper$y(this, Arrow, [geometry, material]); + _this.position.copy(origin); + _this.setDirection(direction); + return _this; + } + _inherits(Arrow, _THREE$Mesh); + return _createClass(Arrow, [{ + key: "setDirection", + value: + /** + * Set the direction of this arrow to that of the given vector. + * + * @param direction - the direction to set this arrow + */ + function setDirection(direction) { + var axis = new Vector3(); + if (direction.x === 0 && direction.z === 0) { + axis.set(1, 0, 0); + } else { + axis.set(0, 1, 0).cross(direction); + } + var radians = Math.acos(new Vector3(0, 1, 0).dot(direction.clone().normalize())); + this.matrix = new Matrix4().makeRotationAxis(axis.normalize(), radians); + this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); + } + }, { + key: "setLength", + value: + /** + * Set this arrow to be the given length. + * + * @param length - the new length of the arrow + */ + function setLength(length) { + this.scale.set(length, length, length); + } + }, { + key: "setColor", + value: + /** + * Set the color of this arrow to the given hex value. + * + * @param hex - the hex value of the color to use + */ + function setColor(hex) { + this.material.color.setHex(hex); + } + }, { + key: "dispose", + value: + /* + * Free memory of elements in this marker. + */ + function dispose() { + if (this.geometry !== undefined) { + this.geometry.dispose(); + } + if (this.material !== undefined) { + this.material.dispose(); + } + } + }]); + }(Mesh); - Cache.add( url, imageBitmap ); + class TGALoader extends DataTextureLoader { - if ( onLoad ) onLoad( imageBitmap ); + constructor( manager ) { - scope.manager.itemEnd( url ); + super( manager ); - } ).catch( function ( e ) { + } - if ( onError ) onError( e ); + parse( buffer ) { - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); + // reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js - } ); + function tgaCheckHeader( header ) { - }, + switch ( header.image_type ) { - setCrossOrigin: function ( /* value */ ) { + // check indexed type - return this; + case TGA_TYPE_INDEXED: + case TGA_TYPE_RLE_INDEXED: + if ( header.colormap_length > 256 || header.colormap_size !== 24 || header.colormap_type !== 1 ) { - }, + throw new Error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' ); - setPath: function ( value ) { + } - this.path = value; - return this; + break; - } + // check colormap type - }; + case TGA_TYPE_RGB: + case TGA_TYPE_GREY: + case TGA_TYPE_RLE_RGB: + case TGA_TYPE_RLE_GREY: + if ( header.colormap_type ) { - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * minimal class for proxing functions to Path. Replaces old "extractSubpaths()" - **/ + throw new Error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' ); - function ShapePath() { + } - this.type = 'ShapePath'; + break; - this.subPaths = []; - this.currentPath = null; + // What the need of a file without data ? - } + case TGA_TYPE_NO_DATA: + throw new Error( 'THREE.TGALoader: No data.' ); - Object.assign( ShapePath.prototype, { + // Invalid type ? - moveTo: function ( x, y ) { + default: + throw new Error( 'THREE.TGALoader: Invalid type ' + header.image_type ); - this.currentPath = new Path$1(); - this.subPaths.push( this.currentPath ); - this.currentPath.moveTo( x, y ); + } - }, + // check image width and height - lineTo: function ( x, y ) { + if ( header.width <= 0 || header.height <= 0 ) { - this.currentPath.lineTo( x, y ); + throw new Error( 'THREE.TGALoader: Invalid image size.' ); - }, + } - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { + // check image pixel size - this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); + if ( header.pixel_size !== 8 && header.pixel_size !== 16 && + header.pixel_size !== 24 && header.pixel_size !== 32 ) { - }, + throw new Error( 'THREE.TGALoader: Invalid pixel size ' + header.pixel_size ); - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + } - this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); + } - }, + // parse tga image buffer - splineThru: function ( pts ) { + function tgaParse( use_rle, use_pal, header, offset, data ) { - this.currentPath.splineThru( pts ); + let pixel_data, + palettes; - }, + const pixel_size = header.pixel_size >> 3; + const pixel_total = header.width * header.height * pixel_size; - toShapes: function ( isCCW, noHoles ) { + // read palettes - function toShapesNoHoles( inSubpaths ) { + if ( use_pal ) { - var shapes = []; + palettes = data.subarray( offset, offset += header.colormap_length * ( header.colormap_size >> 3 ) ); - for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) { + } - var tmpPath = inSubpaths[ i ]; + // read RLE - var tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; + if ( use_rle ) { - shapes.push( tmpShape ); + pixel_data = new Uint8Array( pixel_total ); - } + let c, count, i; + let shift = 0; + const pixels = new Uint8Array( pixel_size ); - return shapes; + while ( shift < pixel_total ) { - } + c = data[ offset ++ ]; + count = ( c & 0x7f ) + 1; - function isPointInsidePolygon( inPt, inPolygon ) { + // RLE pixels - var polyLen = inPolygon.length; + if ( c & 0x80 ) { - // inPt on polygon contour => immediate success or - // toggling of inside/outside at every single! intersection point of an edge - // with the horizontal line through inPt, left of inPt - // not counting lowerY endpoints of edges and whole edges on that line - var inside = false; - for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { + // bind pixel tmp array - var edgeLowPt = inPolygon[ p ]; - var edgeHighPt = inPolygon[ q ]; + for ( i = 0; i < pixel_size; ++ i ) { - var edgeDx = edgeHighPt.x - edgeLowPt.x; - var edgeDy = edgeHighPt.y - edgeLowPt.y; + pixels[ i ] = data[ offset ++ ]; - if ( Math.abs( edgeDy ) > Number.EPSILON ) { + } - // not parallel - if ( edgeDy < 0 ) { + // copy pixel array - edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; - edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; + for ( i = 0; i < count; ++ i ) { - } - if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; + pixel_data.set( pixels, shift + i * pixel_size ); - if ( inPt.y === edgeLowPt.y ) { + } - if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? - // continue; // no intersection or edgeLowPt => doesn't count !!! + shift += pixel_size * count; } else { - var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); - if ( perpEdge === 0 ) return true; // inPt is on contour ? - if ( perpEdge < 0 ) continue; - inside = ! inside; // true intersection left of inPt - - } - - } else { + // raw pixels - // parallel or collinear - if ( inPt.y !== edgeLowPt.y ) continue; // parallel - // edge lies on the same horizontal line as inPt - if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || - ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! - // continue; + count *= pixel_size; - } + for ( i = 0; i < count; ++ i ) { - } + pixel_data[ shift + i ] = data[ offset ++ ]; - return inside; + } - } + shift += count; - var isClockWise = ShapeUtils.isClockWise; + } - var subPaths = this.subPaths; - if ( subPaths.length === 0 ) return []; + } - if ( noHoles === true ) return toShapesNoHoles( subPaths ); + } else { + // raw pixels - var solid, tmpPath, tmpShape, shapes = []; + pixel_data = data.subarray( + offset, offset += ( use_pal ? header.width * header.height : pixel_total ) + ); - if ( subPaths.length === 1 ) { + } - tmpPath = subPaths[ 0 ]; - tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; - shapes.push( tmpShape ); - return shapes; + return { + pixel_data: pixel_data, + palettes: palettes + }; } - var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); - holesFirst = isCCW ? ! holesFirst : holesFirst; + function tgaGetImageData8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes ) { + + const colormap = palettes; + let color, i = 0, x, y; + const width = header.width; - // console.log("Holes first", holesFirst); + for ( y = y_start; y !== y_end; y += y_step ) { - var betterShapeHoles = []; - var newShapes = []; - var newShapeHoles = []; - var mainIdx = 0; - var tmpPoints; + for ( x = x_start; x !== x_end; x += x_step, i ++ ) { - newShapes[ mainIdx ] = undefined; - newShapeHoles[ mainIdx ] = []; + color = image[ i ]; + imageData[ ( x + width * y ) * 4 + 3 ] = 255; + imageData[ ( x + width * y ) * 4 + 2 ] = colormap[ ( color * 3 ) + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = colormap[ ( color * 3 ) + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = colormap[ ( color * 3 ) + 2 ]; - for ( var i = 0, l = subPaths.length; i < l; i ++ ) { + } - tmpPath = subPaths[ i ]; - tmpPoints = tmpPath.getPoints(); - solid = isClockWise( tmpPoints ); - solid = isCCW ? ! solid : solid; + } - if ( solid ) { + return imageData; - if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; + } - newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; - newShapes[ mainIdx ].s.curves = tmpPath.curves; + function tgaGetImageData16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - if ( holesFirst ) mainIdx ++; - newShapeHoles[ mainIdx ] = []; + let color, i = 0, x, y; + const width = header.width; - //console.log('cw', i); + for ( y = y_start; y !== y_end; y += y_step ) { - } else { + for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { - newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); + color = image[ i + 0 ] + ( image[ i + 1 ] << 8 ); + imageData[ ( x + width * y ) * 4 + 0 ] = ( color & 0x7C00 ) >> 7; + imageData[ ( x + width * y ) * 4 + 1 ] = ( color & 0x03E0 ) >> 2; + imageData[ ( x + width * y ) * 4 + 2 ] = ( color & 0x001F ) << 3; + imageData[ ( x + width * y ) * 4 + 3 ] = ( color & 0x8000 ) ? 0 : 255; - //console.log('ccw', i); + } } + return imageData; + } - // only Holes? -> probably all Shapes with wrong orientation - if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); + function tgaGetImageData24bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { + let i = 0, x, y; + const width = header.width; - if ( newShapes.length > 1 ) { + for ( y = y_start; y !== y_end; y += y_step ) { - var ambiguous = false; - var toChange = []; + for ( x = x_start; x !== x_end; x += x_step, i += 3 ) { - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + imageData[ ( x + width * y ) * 4 + 3 ] = 255; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; - betterShapeHoles[ sIdx ] = []; + } } - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + return imageData; - var sho = newShapeHoles[ sIdx ]; + } - for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) { + function tgaGetImageData32bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - var ho = sho[ hIdx ]; - var hole_unassigned = true; + let i = 0, x, y; + const width = header.width; - for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { + for ( y = y_start; y !== y_end; y += y_step ) { - if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { + for ( x = x_start; x !== x_end; x += x_step, i += 4 ) { - if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); - if ( hole_unassigned ) { + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ]; + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ]; + imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 3 ]; - hole_unassigned = false; - betterShapeHoles[ s2Idx ].push( ho ); + } - } else { + } - ambiguous = true; + return imageData; - } + } - } + function tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - } - if ( hole_unassigned ) { + let color, i = 0, x, y; + const width = header.width; - betterShapeHoles[ sIdx ].push( ho ); + for ( y = y_start; y !== y_end; y += y_step ) { - } + for ( x = x_start; x !== x_end; x += x_step, i ++ ) { + + color = image[ i ]; + imageData[ ( x + width * y ) * 4 + 0 ] = color; + imageData[ ( x + width * y ) * 4 + 1 ] = color; + imageData[ ( x + width * y ) * 4 + 2 ] = color; + imageData[ ( x + width * y ) * 4 + 3 ] = 255; } } - // console.log("ambiguous: ", ambiguous); - if ( toChange.length > 0 ) { - - // console.log("to change: ", toChange); - if ( ! ambiguous ) newShapeHoles = betterShapeHoles; - } + return imageData; } - var tmpHoles; + function tgaGetImageDataGrey16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { + + let i = 0, x, y; + const width = header.width; - for ( var i = 0, il = newShapes.length; i < il; i ++ ) { + for ( y = y_start; y !== y_end; y += y_step ) { - tmpShape = newShapes[ i ].s; - shapes.push( tmpShape ); - tmpHoles = newShapeHoles[ i ]; + for ( x = x_start; x !== x_end; x += x_step, i += 2 ) { - for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) { + imageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ]; + imageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 1 ]; - tmpShape.holes.push( tmpHoles[ j ].h ); + } } - } + return imageData; - //console.log("shape", shapes); + } - return shapes; + function getTgaRGBA( data, width, height, image, palette ) { - } + let x_start, + y_start, + x_step, + y_step, + x_end, + y_end; - } ); + switch ( ( header.flags & TGA_ORIGIN_MASK ) >> TGA_ORIGIN_SHIFT ) { - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author mrdoob / http://mrdoob.com/ - */ + default: + case TGA_ORIGIN_UL: + x_start = 0; + x_step = 1; + x_end = width; + y_start = 0; + y_step = 1; + y_end = height; + break; - function Font( data ) { + case TGA_ORIGIN_BL: + x_start = 0; + x_step = 1; + x_end = width; + y_start = height - 1; + y_step = - 1; + y_end = - 1; + break; - this.type = 'Font'; + case TGA_ORIGIN_UR: + x_start = width - 1; + x_step = - 1; + x_end = - 1; + y_start = 0; + y_step = 1; + y_end = height; + break; - this.data = data; + case TGA_ORIGIN_BR: + x_start = width - 1; + x_step = - 1; + x_end = - 1; + y_start = height - 1; + y_step = - 1; + y_end = - 1; + break; - } + } - Object.assign( Font.prototype, { + if ( use_grey ) { - isFont: true, + switch ( header.pixel_size ) { - generateShapes: function ( text, size, divisions ) { + case 8: + tgaGetImageDataGrey8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - function createPaths( text ) { + case 16: + tgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - var chars = String( text ).split( '' ); - var scale = size / data.resolution; - var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale; + default: + throw new Error( 'THREE.TGALoader: Format not supported.' ); - var offsetX = 0, offsetY = 0; + } - var paths = []; + } else { - for ( var i = 0; i < chars.length; i ++ ) { + switch ( header.pixel_size ) { - var char = chars[ i ]; + case 8: + tgaGetImageData8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image, palette ); + break; - if ( char === '\n' ) { + case 16: + tgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - offsetX = 0; - offsetY -= line_height; + case 24: + tgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - } else { + case 32: + tgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image ); + break; - var ret = createPath( char, scale, offsetX, offsetY ); - offsetX += ret.offsetX; - paths.push( ret.path ); + default: + throw new Error( 'THREE.TGALoader: Format not supported.' ); } } - return paths; + // Load image data according to specific method + // let func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits'; + // func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette ); + return data; } - function createPath( c, scale, offsetX, offsetY ) { - - var glyph = data.glyphs[ c ] || data.glyphs[ '?' ]; - - if ( ! glyph ) return; - - var path = new ShapePath(); - - var pts = []; - var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2, laste; - - if ( glyph.o ) { - - var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); - - for ( var i = 0, l = outline.length; i < l; ) { - - var action = outline[ i ++ ]; + // TGA constants + + const TGA_TYPE_NO_DATA = 0, + TGA_TYPE_INDEXED = 1, + TGA_TYPE_RGB = 2, + TGA_TYPE_GREY = 3, + TGA_TYPE_RLE_INDEXED = 9, + TGA_TYPE_RLE_RGB = 10, + TGA_TYPE_RLE_GREY = 11, + + TGA_ORIGIN_MASK = 0x30, + TGA_ORIGIN_SHIFT = 0x04, + TGA_ORIGIN_BL = 0x00, + TGA_ORIGIN_BR = 0x01, + TGA_ORIGIN_UL = 0x02, + TGA_ORIGIN_UR = 0x03; + + if ( buffer.length < 19 ) throw new Error( 'THREE.TGALoader: Not enough data to contain header.' ); + + let offset = 0; + + const content = new Uint8Array( buffer ), + header = { + id_length: content[ offset ++ ], + colormap_type: content[ offset ++ ], + image_type: content[ offset ++ ], + colormap_index: content[ offset ++ ] | content[ offset ++ ] << 8, + colormap_length: content[ offset ++ ] | content[ offset ++ ] << 8, + colormap_size: content[ offset ++ ], + origin: [ + content[ offset ++ ] | content[ offset ++ ] << 8, + content[ offset ++ ] | content[ offset ++ ] << 8 + ], + width: content[ offset ++ ] | content[ offset ++ ] << 8, + height: content[ offset ++ ] | content[ offset ++ ] << 8, + pixel_size: content[ offset ++ ], + flags: content[ offset ++ ] + }; - switch ( action ) { + // check tga if it is valid format - case 'm': // moveTo + tgaCheckHeader( header ); - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; + if ( header.id_length + offset > buffer.length ) { - path.moveTo( x, y ); + throw new Error( 'THREE.TGALoader: No data.' ); - break; + } - case 'l': // lineTo + // skip the needn't data - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; + offset += header.id_length; - path.lineTo( x, y ); + // get targa information about RLE compression and palette - break; + let use_rle = false, + use_pal = false, + use_grey = false; - case 'q': // quadraticCurveTo + switch ( header.image_type ) { - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; + case TGA_TYPE_RLE_INDEXED: + use_rle = true; + use_pal = true; + break; - path.quadraticCurveTo( cpx1, cpy1, cpx, cpy ); + case TGA_TYPE_INDEXED: + use_pal = true; + break; - laste = pts[ pts.length - 1 ]; + case TGA_TYPE_RLE_RGB: + use_rle = true; + break; - if ( laste ) { + case TGA_TYPE_RGB: + break; - laste.x; - laste.y; + case TGA_TYPE_RLE_GREY: + use_rle = true; + use_grey = true; + break; - + case TGA_TYPE_GREY: + use_grey = true; + break; - } + } - break; + // - case 'b': // bezierCurveTo + const imageData = new Uint8Array( header.width * header.height * 4 ); + const result = tgaParse( use_rle, use_pal, header, offset, content ); + getTgaRGBA( imageData, header.width, header.height, result.pixel_data, result.palettes ); - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; - cpx2 = outline[ i ++ ] * scale + offsetX; - cpy2 = outline[ i ++ ] * scale + offsetY; + return { - path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy ); + data: imageData, + width: header.width, + height: header.height, + flipY: true, + generateMipmaps: true, + minFilter: LinearMipmapLinearFilter, - laste = pts[ pts.length - 1 ]; + }; - if ( laste ) { + } - laste.x; - laste.y; + } - + function _callSuper$x(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$x() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$x() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$x = function _isNativeReflectConstruct() { return !!t; })(); } + var ColladaLoader = /*#__PURE__*/function (_Loader) { + function ColladaLoader() { + _classCallCheck(this, ColladaLoader); + return _callSuper$x(this, ColladaLoader, arguments); + } + _inherits(ColladaLoader, _Loader); + return _createClass(ColladaLoader, [{ + key: "load", + value: function load(url, onLoad, onProgress, onError) { + var scope = this; + var path = scope.path === '' ? LoaderUtils.extractUrlBase(url) : scope.path; + var 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(text, path)); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); + } + }, { + key: "parse", + value: function parse(text, path) { + function getElementsByTagName(xml, name) { + // Non recursive xml.getElementsByTagName() ... + + var array = []; + var childNodes = xml.childNodes; + for (var i = 0, l = childNodes.length; i < l; i++) { + var child = childNodes[i]; + if (child.nodeName === name) { + array.push(child); + } + } + return array; + } + function parseStrings(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parts[i]; + } + return array; + } + function parseFloats(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parseFloat(parts[i]); + } + return array; + } + function parseInts(text) { + if (text.length === 0) return []; + var parts = text.trim().split(/\s+/); + var array = new Array(parts.length); + for (var i = 0, l = parts.length; i < l; i++) { + array[i] = parseInt(parts[i]); + } + return array; + } + function parseId(text) { + return text.substring(1); + } + function generateId() { + return 'three_default_' + count++; + } + function isEmpty(object) { + return Object.keys(object).length === 0; + } - } + // asset - break; + function parseAsset(xml) { + return { + unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), + upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) + }; + } + function parseAssetUnit(xml) { + if (xml !== undefined && xml.hasAttribute('meter') === true) { + return parseFloat(xml.getAttribute('meter')); + } else { + return 1; // default 1 meter + } + } + function parseAssetUpAxis(xml) { + return xml !== undefined ? xml.textContent : 'Y_UP'; + } - } + // library - } + function parseLibrary(xml, libraryName, nodeName, parser) { + var library = getElementsByTagName(xml, libraryName)[0]; + if (library !== undefined) { + var elements = getElementsByTagName(library, nodeName); + for (var i = 0; i < elements.length; i++) { + parser(elements[i]); + } + } + } + function buildLibrary(data, builder) { + for (var name in data) { + var object = data[name]; + object.build = builder(data[name]); + } + } - } + // get - return { offsetX: glyph.ha * scale, path: path }; + function getBuild(data, builder) { + if (data.build !== undefined) return data.build; + data.build = builder(data); + return data.build; + } - } + // animation + + function parseAnimation(xml) { + var data = { + sources: {}, + samplers: {}, + channels: {} + }; + var hasChildren = false; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var id = void 0; + switch (child.nodeName) { + case 'source': + id = child.getAttribute('id'); + data.sources[id] = parseSource(child); + break; + case 'sampler': + id = child.getAttribute('id'); + data.samplers[id] = parseAnimationSampler(child); + break; + case 'channel': + id = child.getAttribute('target'); + data.channels[id] = parseAnimationChannel(child); + break; + case 'animation': + // hierarchy of related animations + parseAnimation(child); + hasChildren = true; + break; + default: + console.log(child); + } + } + if (hasChildren === false) { + // since 'id' attributes can be optional, it's necessary to generate a UUID for unqiue assignment - // + library.animations[xml.getAttribute('id') || MathUtils.generateUUID()] = data; + } + } + function parseAnimationSampler(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var id = parseId(child.getAttribute('source')); + var semantic = child.getAttribute('semantic'); + data.inputs[semantic] = id; + break; + } + } + return data; + } + function parseAnimationChannel(xml) { + var data = {}; + var target = xml.getAttribute('target'); - if ( size === undefined ) size = 100; + // parsing SID Addressing Syntax - var data = this.data; + var parts = target.split('/'); + var id = parts.shift(); + var sid = parts.shift(); - var paths = createPaths( text ); - var shapes = []; + // check selection syntax - for ( var p = 0, pl = paths.length; p < pl; p ++ ) { + var arraySyntax = sid.indexOf('(') !== -1; + var memberSyntax = sid.indexOf('.') !== -1; + if (memberSyntax) { + // member selection access - Array.prototype.push.apply( shapes, paths[ p ].toShapes() ); + parts = sid.split('.'); + sid = parts.shift(); + data.member = parts.shift(); + } else if (arraySyntax) { + // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. - } + var indices = sid.split('('); + sid = indices.shift(); + for (var i = 0; i < indices.length; i++) { + indices[i] = parseInt(indices[i].replace(/\)/, '')); + } + data.indices = indices; + } + data.id = id; + data.sid = sid; + data.arraySyntax = arraySyntax; + data.memberSyntax = memberSyntax; + data.sampler = parseId(xml.getAttribute('source')); + return data; + } + function buildAnimation(data) { + var tracks = []; + var channels = data.channels; + var samplers = data.samplers; + var sources = data.sources; + for (var target in channels) { + if (channels.hasOwnProperty(target)) { + var channel = channels[target]; + var sampler = samplers[channel.sampler]; + var inputId = sampler.inputs.INPUT; + var outputId = sampler.inputs.OUTPUT; + var inputSource = sources[inputId]; + var outputSource = sources[outputId]; + var animation = buildAnimationChannel(channel, inputSource, outputSource); + createKeyframeTracks(animation, tracks); + } + } + return tracks; + } + function getAnimation(id) { + return getBuild(library.animations[id], buildAnimation); + } + function buildAnimationChannel(channel, inputSource, outputSource) { + var node = library.nodes[channel.id]; + var object3D = getNode(node.id); + var transform = node.transforms[channel.sid]; + var defaultMatrix = node.matrix.clone().transpose(); + var time, stride; + var i, il, j, jl; + var data = {}; + + // the collada spec allows the animation of data in various ways. + // depending on the transform type (matrix, translate, rotate, scale), we execute different logic + + switch (transform) { + case 'matrix': + for (i = 0, il = inputSource.array.length; i < il; i++) { + time = inputSource.array[i]; + stride = i * outputSource.stride; + if (data[time] === undefined) data[time] = {}; + if (channel.arraySyntax === true) { + var value = outputSource.array[stride]; + var index = channel.indices[0] + 4 * channel.indices[1]; + data[time][index] = value; + } else { + for (j = 0, jl = outputSource.stride; j < jl; j++) { + data[time][j] = outputSource.array[stride + j]; + } + } + } + break; + case 'translate': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + case 'rotate': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + case 'scale': + console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); + break; + } + var keyframes = prepareAnimationData(data, defaultMatrix); + var animation = { + name: object3D.uuid, + keyframes: keyframes + }; + return animation; + } + function prepareAnimationData(data, defaultMatrix) { + var keyframes = []; - return shapes; + // transfer data into a sortable array - } + for (var time in data) { + keyframes.push({ + time: parseFloat(time), + value: data[time] + }); + } - } ); + // ensure keyframes are sorted by time - /** - * @author mrdoob / http://mrdoob.com/ - */ + keyframes.sort(ascending); - function FontLoader( manager ) { + // now we clean up all animation data, so we can use them for keyframe tracks - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + for (var i = 0; i < 16; i++) { + transformAnimationData(keyframes, i, defaultMatrix.elements[i]); + } + return keyframes; - } + // array sort function - Object.assign( FontLoader.prototype, { + function ascending(a, b) { + return a.time - b.time; + } + } + var position = new Vector3(); + var scale = new Vector3(); + var quaternion = new Quaternion(); + function createKeyframeTracks(animation, tracks) { + var keyframes = animation.keyframes; + var name = animation.name; + var times = []; + var positionData = []; + var quaternionData = []; + var scaleData = []; + for (var i = 0, l = keyframes.length; i < l; i++) { + var keyframe = keyframes[i]; + var time = keyframe.time; + var value = keyframe.value; + matrix.fromArray(value).transpose(); + matrix.decompose(position, quaternion, scale); + times.push(time); + positionData.push(position.x, position.y, position.z); + quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); + scaleData.push(scale.x, scale.y, scale.z); + } + if (positionData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.position', times, positionData)); + if (quaternionData.length > 0) tracks.push(new QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); + if (scaleData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.scale', times, scaleData)); + return tracks; + } + function transformAnimationData(keyframes, property, defaultValue) { + var keyframe; + var empty = true; + var i, l; - load: function ( url, onLoad, onProgress, onError ) { + // check, if values of a property are missing in our keyframes - var scope = this; + for (i = 0, l = keyframes.length; i < l; i++) { + keyframe = keyframes[i]; + if (keyframe.value[property] === undefined) { + keyframe.value[property] = null; // mark as missing + } else { + empty = false; + } + } + if (empty === true) { + // no values at all, so we set a default value - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { - - var json; - - try { - - json = JSON.parse( text ); - - } catch ( e ) { - - console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' ); - json = JSON.parse( text.substring( 65, text.length - 2 ) ); - - } - - var font = scope.parse( json ); - - if ( onLoad ) onLoad( font ); - - }, onProgress, onError ); - - }, - - parse: function ( json ) { - - return new Font( json ); - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - var context; - - var AudioContext = { - - getContext: function () { - - if ( context === undefined ) { - - context = new ( window.AudioContext || window.webkitAudioContext )(); - - } - - return context; - - }, - - setContext: function ( value ) { - - context = value; - - } - - }; - - /** - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ - - function AudioLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( AudioLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - loader.load( url, function ( buffer ) { - - var context = AudioContext.getContext(); - - context.decodeAudioData( buffer, function ( audioBuffer ) { - - onLoad( audioBuffer ); - - } ); - - }, onProgress, onError ); - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function StereoCamera() { - - this.type = 'StereoCamera'; - - this.aspect = 1; - - this.eyeSep = 0.064; - - this.cameraL = new PerspectiveCamera(); - this.cameraL.layers.enable( 1 ); - this.cameraL.matrixAutoUpdate = false; - - this.cameraR = new PerspectiveCamera(); - this.cameraR.layers.enable( 2 ); - this.cameraR.matrixAutoUpdate = false; - - } - - Object.assign( StereoCamera.prototype, { - - update: ( function () { - - var instance, focus, fov, aspect, near, far, zoom, eyeSep; - - var eyeRight = new Matrix4(); - var eyeLeft = new Matrix4(); - - return function update( camera ) { - - var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov || - aspect !== camera.aspect * this.aspect || near !== camera.near || - far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep; - - if ( needsUpdate ) { - - instance = this; - focus = camera.focus; - fov = camera.fov; - aspect = camera.aspect * this.aspect; - near = camera.near; - far = camera.far; - zoom = camera.zoom; - - // Off-axis stereoscopic effect based on - // http://paulbourke.net/stereographics/stereorender/ - - var projectionMatrix = camera.projectionMatrix.clone(); - eyeSep = this.eyeSep / 2; - var eyeSepOnProjection = eyeSep * near / focus; - var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom; - var xmin, xmax; - - // translate xOffset - - eyeLeft.elements[ 12 ] = - eyeSep; - eyeRight.elements[ 12 ] = eyeSep; - - // for left eye - - xmin = - ymax * aspect + eyeSepOnProjection; - xmax = ymax * aspect + eyeSepOnProjection; - - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); - - this.cameraL.projectionMatrix.copy( projectionMatrix ); - - // for right eye - - xmin = - ymax * aspect - eyeSepOnProjection; - xmax = ymax * aspect - eyeSepOnProjection; - - projectionMatrix.elements[ 0 ] = 2 * 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 ); - - }; - - } )() - - } ); - - /** - * Camera for rendering cube maps - * - renders scene into axis-aligned cube - * - * @author alteredq / http://alteredqualia.com/ - */ - - function CubeCamera( near, far, cubeResolution ) { - - Object3D.call( this ); - - this.type = 'CubeCamera'; - - var fov = 90, aspect = 1; - - var cameraPX = new PerspectiveCamera( fov, aspect, near, far ); - cameraPX.up.set( 0, - 1, 0 ); - cameraPX.lookAt( new Vector3( 1, 0, 0 ) ); - this.add( cameraPX ); - - var cameraNX = new PerspectiveCamera( fov, aspect, near, far ); - cameraNX.up.set( 0, - 1, 0 ); - cameraNX.lookAt( new Vector3( - 1, 0, 0 ) ); - this.add( cameraNX ); - - var cameraPY = new PerspectiveCamera( fov, aspect, near, far ); - cameraPY.up.set( 0, 0, 1 ); - cameraPY.lookAt( new Vector3( 0, 1, 0 ) ); - this.add( cameraPY ); - - var cameraNY = new PerspectiveCamera( fov, aspect, near, far ); - cameraNY.up.set( 0, 0, - 1 ); - cameraNY.lookAt( new Vector3( 0, - 1, 0 ) ); - this.add( cameraNY ); - - var cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraPZ.up.set( 0, - 1, 0 ); - cameraPZ.lookAt( new Vector3( 0, 0, 1 ) ); - this.add( cameraPZ ); - - var cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraNZ.up.set( 0, - 1, 0 ); - cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) ); - this.add( cameraNZ ); - - var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter }; - - this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options ); - this.renderTarget.texture.name = "CubeCamera"; - - this.update = function ( renderer, scene ) { - - if ( this.parent === null ) this.updateMatrixWorld(); - - var renderTarget = this.renderTarget; - var generateMipmaps = renderTarget.texture.generateMipmaps; - - renderTarget.texture.generateMipmaps = false; - - renderTarget.activeCubeFace = 0; - renderer.render( scene, cameraPX, renderTarget ); - - renderTarget.activeCubeFace = 1; - renderer.render( scene, cameraNX, renderTarget ); - - renderTarget.activeCubeFace = 2; - renderer.render( scene, cameraPY, renderTarget ); - - renderTarget.activeCubeFace = 3; - renderer.render( scene, cameraNY, renderTarget ); - - renderTarget.activeCubeFace = 4; - renderer.render( scene, cameraPZ, renderTarget ); - - renderTarget.texture.generateMipmaps = generateMipmaps; - - renderTarget.activeCubeFace = 5; - renderer.render( scene, cameraNZ, renderTarget ); - - renderer.setRenderTarget( null ); - - }; - - this.clear = function ( renderer, color, depth, stencil ) { - - var renderTarget = this.renderTarget; - - for ( var i = 0; i < 6; i ++ ) { - - renderTarget.activeCubeFace = i; - renderer.setRenderTarget( renderTarget ); - - renderer.clear( color, depth, stencil ); - - } - - renderer.setRenderTarget( null ); - - }; - - } - - CubeCamera.prototype = Object.create( Object3D.prototype ); - CubeCamera.prototype.constructor = CubeCamera; - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function AudioListener() { - - Object3D.call( this ); - - this.type = 'AudioListener'; - - this.context = AudioContext.getContext(); - - this.gain = this.context.createGain(); - this.gain.connect( this.context.destination ); - - this.filter = null; - - } - - AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: AudioListener, - - getInput: function () { - - return this.gain; - - }, - - removeFilter: function ( ) { - - if ( this.filter !== null ) { - - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); - this.gain.connect( this.context.destination ); - this.filter = null; - - } - - }, - - getFilter: function () { - - return this.filter; - - }, - - setFilter: function ( 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 ); - - }, - - getMasterVolume: function () { - - return this.gain.gain.value; - - }, - - setMasterVolume: function ( value ) { - - this.gain.gain.value = value; - - }, - - updateMatrixWorld: ( function () { - - var position = new Vector3(); - var quaternion = new Quaternion(); - var scale = new Vector3(); - - var orientation = new Vector3(); - - return function updateMatrixWorld( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - var listener = this.context.listener; - var up = this.up; - - this.matrixWorld.decompose( position, quaternion, scale ); - - orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - - if ( listener.positionX ) { - - listener.positionX.setValueAtTime( position.x, this.context.currentTime ); - listener.positionY.setValueAtTime( position.y, this.context.currentTime ); - listener.positionZ.setValueAtTime( position.z, this.context.currentTime ); - listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime ); - listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime ); - listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime ); - listener.upX.setValueAtTime( up.x, this.context.currentTime ); - listener.upY.setValueAtTime( up.y, this.context.currentTime ); - listener.upZ.setValueAtTime( up.z, this.context.currentTime ); - - } else { - - listener.setPosition( position.x, position.y, position.z ); - listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z ); - - } - - }; - - } )() - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ - - function Audio( listener ) { - - Object3D.call( this ); - - this.type = 'Audio'; - - this.context = listener.context; - - this.gain = this.context.createGain(); - this.gain.connect( listener.getInput() ); - - this.autoplay = false; - - this.buffer = null; - this.loop = false; - this.startTime = 0; - this.offset = 0; - this.playbackRate = 1; - this.isPlaying = false; - this.hasPlaybackControl = true; - this.sourceType = 'empty'; - - this.filters = []; - - } - - Audio.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Audio, - - getOutput: function () { - - return this.gain; - - }, - - setNodeSource: function ( audioNode ) { - - this.hasPlaybackControl = false; - this.sourceType = 'audioNode'; - this.source = audioNode; - this.connect(); - - return this; - - }, - - setBuffer: function ( audioBuffer ) { - - this.buffer = audioBuffer; - this.sourceType = 'buffer'; - - if ( this.autoplay ) this.play(); - - return this; - - }, - - play: function () { - - 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; - - } - - var source = this.context.createBufferSource(); - - source.buffer = this.buffer; - source.loop = this.loop; - source.onended = this.onEnded.bind( this ); - source.playbackRate.setValueAtTime( this.playbackRate, this.startTime ); - this.startTime = this.context.currentTime; - source.start( this.startTime, this.offset ); - - this.isPlaying = true; - - this.source = source; - - return this.connect(); - - }, - - pause: function () { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - if ( this.isPlaying === true ) { - - this.source.stop(); - this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate; - this.isPlaying = false; - - } - - return this; - - }, - - stop: function () { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - this.source.stop(); - this.offset = 0; - this.isPlaying = false; - - return this; - - }, - - connect: function () { - - if ( this.filters.length > 0 ) { - - this.source.connect( this.filters[ 0 ] ); - - for ( var 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() ); - - } - - return this; - - }, - - disconnect: function () { - - if ( this.filters.length > 0 ) { - - this.source.disconnect( this.filters[ 0 ] ); - - for ( var 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() ); - - } - - return this; - - }, - - getFilters: function () { - - return this.filters; - - }, - - setFilters: function ( value ) { - - if ( ! value ) value = []; - - if ( this.isPlaying === true ) { - - this.disconnect(); - this.filters = value; - this.connect(); - - } else { - - this.filters = value; - - } - - return this; - - }, - - getFilter: function () { - - return this.getFilters()[ 0 ]; - - }, - - setFilter: function ( filter ) { - - return this.setFilters( filter ? [ filter ] : [] ); - - }, - - setPlaybackRate: function ( 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.setValueAtTime( this.playbackRate, this.context.currentTime ); - - } - - return this; - - }, - - getPlaybackRate: function () { - - return this.playbackRate; - - }, - - onEnded: function () { - - this.isPlaying = false; - - }, - - getLoop: function () { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return false; - - } - - return this.loop; - - }, - - setLoop: function ( 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; - - }, - - getVolume: function () { - - return this.gain.gain.value; - - }, - - setVolume: function ( value ) { - - this.gain.gain.value = value; - - return this; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function PositionalAudio( listener ) { - - Audio.call( this, listener ); - - this.panner = this.context.createPanner(); - this.panner.connect( this.gain ); - - } - - PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), { - - constructor: PositionalAudio, - - getOutput: function () { - - return this.panner; - - }, - - getRefDistance: function () { - - return this.panner.refDistance; - - }, - - setRefDistance: function ( value ) { - - this.panner.refDistance = value; - - }, - - getRolloffFactor: function () { - - return this.panner.rolloffFactor; - - }, - - setRolloffFactor: function ( value ) { - - this.panner.rolloffFactor = value; - - }, - - getDistanceModel: function () { - - return this.panner.distanceModel; - - }, - - setDistanceModel: function ( value ) { - - this.panner.distanceModel = value; - - }, - - getMaxDistance: function () { - - return this.panner.maxDistance; - - }, - - setMaxDistance: function ( value ) { - - this.panner.maxDistance = value; - - }, - - updateMatrixWorld: ( function () { - - var position = new Vector3(); - - return function updateMatrixWorld( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - position.setFromMatrixPosition( this.matrixWorld ); - - this.panner.setPosition( position.x, position.y, position.z ); - - }; - - } )() - - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function AudioAnalyser( audio, fftSize ) { - - this.analyser = audio.context.createAnalyser(); - this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048; - - this.data = new Uint8Array( this.analyser.frequencyBinCount ); - - audio.getOutput().connect( this.analyser ); - - } - - Object.assign( AudioAnalyser.prototype, { - - getFrequencyData: function () { - - this.analyser.getByteFrequencyData( this.data ); - - return this.data; - - }, - - getAverageFrequency: function () { - - var value = 0, data = this.getFrequencyData(); - - for ( var i = 0; i < data.length; i ++ ) { - - value += data[ i ]; - - } - - return value / data.length; - - } - - } ); - - /** - * - * Buffered scene graph property that allows weighted accumulation. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function PropertyMixer( binding, typeName, valueSize ) { - - this.binding = binding; - this.valueSize = valueSize; - - var bufferType = Float64Array, - mixFunction; - - switch ( typeName ) { - - case 'quaternion': - mixFunction = this._slerp; - break; - - case 'string': - case 'bool': - bufferType = Array; - mixFunction = this._select; - break; - - default: - mixFunction = this._lerp; - - } - - this.buffer = new bufferType( valueSize * 4 ); - // layout: [ incoming | accu0 | accu1 | orig ] - // - // interpolators can use .buffer as their .result - // the data then goes to 'incoming' - // - // 'accu0' and 'accu1' are used frame-interleaved for - // the cumulative result and are compared to detect - // changes - // - // 'orig' stores the original state of the property - - this._mixBufferRegion = mixFunction; - - this.cumulativeWeight = 0; - - this.useCount = 0; - this.referenceCount = 0; - - } - - Object.assign( PropertyMixer.prototype, { - - // accumulate data in the 'incoming' region into 'accu' - accumulate: function ( accuIndex, weight ) { - - // note: happily accumulating nothing when weight = 0, the caller knows - // the weight and shouldn't have made the call in the first place - - var buffer = this.buffer, - stride = this.valueSize, - offset = accuIndex * stride + stride, - - currentWeight = this.cumulativeWeight; - - if ( currentWeight === 0 ) { - - // accuN := incoming * weight - - for ( var i = 0; i !== stride; ++ i ) { - - buffer[ offset + i ] = buffer[ i ]; - - } - - currentWeight = weight; - - } else { - - // accuN := accuN + incoming * weight - - currentWeight += weight; - var mix = weight / currentWeight; - this._mixBufferRegion( buffer, offset, 0, mix, stride ); - - } - - this.cumulativeWeight = currentWeight; - - }, - - // apply the state of 'accu' to the binding when accus differ - apply: function ( accuIndex ) { - - var stride = this.valueSize, - buffer = this.buffer, - offset = accuIndex * stride + stride, - - weight = this.cumulativeWeight, - - binding = this.binding; - - this.cumulativeWeight = 0; - - if ( weight < 1 ) { - - // accuN := accuN + original * ( 1 - cumulativeWeight ) - - var originalValueOffset = stride * 3; - - this._mixBufferRegion( - buffer, offset, originalValueOffset, 1 - weight, stride ); - - } - - for ( var i = stride, e = stride + stride; i !== e; ++ i ) { - - if ( buffer[ i ] !== buffer[ i + stride ] ) { - - // value has changed -> update scene graph - - binding.setValue( buffer, offset ); - break; - - } - - } - - }, - - // remember the state of the bound property and copy it to both accus - saveOriginalState: function () { - - var binding = this.binding; - - var buffer = this.buffer, - stride = this.valueSize, - - originalValueOffset = stride * 3; - - binding.getValue( buffer, originalValueOffset ); - - // accu[0..1] := orig -- initially detect changes against the original - for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) { - - buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; - - } - - this.cumulativeWeight = 0; - - }, - - // apply the state previously taken via 'saveOriginalState' to the binding - restoreOriginalState: function () { - - var originalValueOffset = this.valueSize * 3; - this.binding.setValue( this.buffer, originalValueOffset ); - - }, - - - // mix functions - - _select: function ( buffer, dstOffset, srcOffset, t, stride ) { - - if ( t >= 0.5 ) { - - for ( var i = 0; i !== stride; ++ i ) { - - buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; - - } - - } - - }, - - _slerp: function ( buffer, dstOffset, srcOffset, t ) { - - Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); - - }, - - _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) { - - var s = 1 - t; - - for ( var i = 0; i !== stride; ++ i ) { - - var j = dstOffset + i; - - buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; - - } - - } - - } ); - - /** - * - * A reference to a real property in the scene graph. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function Composite( targetGroup, path, optionalParsedPath ) { - - var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); - - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_( path, parsedPath ); - - } - - Object.assign( Composite.prototype, { - - getValue: function ( array, offset ) { - - this.bind(); // bind all binding - - var firstValidIndex = this._targetGroup.nCachedObjects_, - binding = this._bindings[ firstValidIndex ]; - - // and only call .getValue on the first - if ( binding !== undefined ) binding.getValue( array, offset ); - - }, - - setValue: function ( array, offset ) { - - var bindings = this._bindings; - - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { - - bindings[ i ].setValue( array, offset ); - - } - - }, - - bind: function () { - - var bindings = this._bindings; - - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { - - bindings[ i ].bind(); - - } - - }, - - unbind: function () { - - var bindings = this._bindings; - - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { - - bindings[ i ].unbind(); - - } - - } - - } ); - - - function PropertyBinding( rootNode, path, parsedPath ) { - - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); - - this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; - - this.rootNode = rootNode; - - } - - Object.assign( PropertyBinding, { - - Composite: Composite, - - create: function ( root, path, parsedPath ) { - - if ( ! ( root && root.isAnimationObjectGroup ) ) { - - return new PropertyBinding( root, path, parsedPath ); - - } else { - - return new PropertyBinding.Composite( root, path, parsedPath ); - - } - - }, - - /** - * Replaces spaces with underscores and removes unsupported characters from - * node names, to ensure compatibility with parseTrackName(). - * - * @param {string} name Node name to be sanitized. - * @return {string} - */ - sanitizeNodeName: function ( name ) { - - return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' ); - - }, - - parseTrackName: function () { - - // Parent directories, delimited by '/' or ':'. Currently unused, but must - // be matched to parse the rest of the track name. - var directoryRe = /((?:[\w-]+[\/:])*)/; - - // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. - var nodeRe = /([\w-\.]+)?/; - - // Object on target node, and accessor. Name may contain only word - // characters. Accessor may contain any character except closing bracket. - var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/; - - // Property and accessor. May contain only word characters. Accessor may - // contain any non-bracket characters. - var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/; - - var trackRe = new RegExp( '' - + '^' - + directoryRe.source - + nodeRe.source - + objectRe.source - + propertyRe.source - + '$' - ); - - var supportedObjectNames = [ 'material', 'materials', 'bones' ]; - - return function ( trackName ) { - - var matches = trackRe.exec( trackName ); - - if ( ! matches ) { - - throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); - - } - - var results = { - // directoryName: matches[ 1 ], // (tschw) currently unused - nodeName: matches[ 2 ], - objectName: matches[ 3 ], - objectIndex: matches[ 4 ], - propertyName: matches[ 5 ], // required - propertyIndex: matches[ 6 ] - }; - - var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); - - if ( lastDot !== undefined && lastDot !== - 1 ) { - - var objectName = results.nodeName.substring( lastDot + 1 ); - - // Object names must be checked against a whitelist. Otherwise, there - // is no way to parse 'foo.bar.baz': 'baz' must be a property, but - // 'bar' could be the objectName, or part of a nodeName (which can - // include '.' characters). - 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; - - }; - - }(), - - findNode: function ( root, nodeName ) { - - if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { - - return root; - - } - - // search into skeleton bones. - if ( root.skeleton ) { - - var searchSkeleton = function ( skeleton ) { - - for ( var i = 0; i < skeleton.bones.length; i ++ ) { - - var bone = skeleton.bones[ i ]; - - if ( bone.name === nodeName ) { - - return bone; - - } - - } - - return null; - - }; - - var bone = searchSkeleton( root.skeleton ); - - if ( bone ) { - - return bone; - - } - - } - - // search into node subtree. - if ( root.children ) { - - var searchNodeSubtree = function ( children ) { - - for ( var i = 0; i < children.length; i ++ ) { - - var childNode = children[ i ]; - - if ( childNode.name === nodeName || childNode.uuid === nodeName ) { - - return childNode; - - } - - var result = searchNodeSubtree( childNode.children ); - - if ( result ) return result; - - } - - return null; - - }; - - var subTreeNode = searchNodeSubtree( root.children ); - - if ( subTreeNode ) { - - return subTreeNode; - - } - - } - - return null; - - } - - } ); - - Object.assign( PropertyBinding.prototype, { // prototype, continued - - // these are used to "bind" a nonexistent property - _getValue_unavailable: function () {}, - _setValue_unavailable: function () {}, - - BindingType: { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 - }, - - Versioning: { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 - }, - - GetterByBindingType: [ - - function getValue_direct( buffer, offset ) { - - buffer[ offset ] = this.node[ this.propertyName ]; - - }, - - function getValue_array( buffer, offset ) { - - var source = this.resolvedProperty; - - for ( var i = 0, n = source.length; i !== n; ++ i ) { - - buffer[ offset ++ ] = source[ i ]; - - } - - }, - - function getValue_arrayElement( buffer, offset ) { - - buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; - - }, - - function getValue_toArray( buffer, offset ) { - - this.resolvedProperty.toArray( buffer, offset ); - - } - - ], - - SetterByBindingTypeAndVersioning: [ - - [ - // Direct - - function setValue_direct( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - - }, - - function setValue_direct_setNeedsUpdate( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; - - }, - - function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ], [ - - // EntireArray - - function setValue_array( buffer, offset ) { - - var dest = this.resolvedProperty; - - for ( var i = 0, n = dest.length; i !== n; ++ i ) { - - dest[ i ] = buffer[ offset ++ ]; - - } - - }, - - function setValue_array_setNeedsUpdate( buffer, offset ) { - - var dest = this.resolvedProperty; - - for ( var i = 0, n = dest.length; i !== n; ++ i ) { - - dest[ i ] = buffer[ offset ++ ]; - - } - - this.targetObject.needsUpdate = true; - - }, - - function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { - - var dest = this.resolvedProperty; - - for ( var i = 0, n = dest.length; i !== n; ++ i ) { - - dest[ i ] = buffer[ offset ++ ]; - - } - - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ], [ - - // ArrayElement - - function setValue_arrayElement( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - - }, - - function setValue_arrayElement_setNeedsUpdate( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; - - }, - - function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ], [ - - // HasToFromArray - - function setValue_fromArray( buffer, offset ) { - - this.resolvedProperty.fromArray( buffer, offset ); - - }, - - function setValue_fromArray_setNeedsUpdate( buffer, offset ) { - - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.needsUpdate = true; - - }, - - function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ] - - ], - - getValue: function getValue_unbound( targetArray, offset ) { - - this.bind(); - this.getValue( targetArray, offset ); - - // Note: This class uses a State pattern on a per-method basis: - // 'bind' sets 'this.getValue' / 'setValue' and shadows the - // prototype version of these methods with one that represents - // the bound state. When the property is not found, the methods - // become no-ops. - - }, - - setValue: function getValue_unbound( sourceArray, offset ) { - - this.bind(); - this.setValue( sourceArray, offset ); - - }, - - // create getter / setter pair for a property in the scene graph - bind: function () { - - var targetObject = this.node, - parsedPath = this.parsedPath, - - objectName = parsedPath.objectName, - propertyName = parsedPath.propertyName, - propertyIndex = parsedPath.propertyIndex; - - if ( ! targetObject ) { - - targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode; - - this.node = targetObject; - - } - - // set fail state so we can just 'return' on error - this.getValue = this._getValue_unavailable; - this.setValue = this._setValue_unavailable; - - // ensure there is a value node - if ( ! targetObject ) { - - console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' ); - return; - - } - - if ( objectName ) { - - var objectIndex = parsedPath.objectIndex; - - // special cases were we need to reach deeper into the hierarchy to get the face materials.... - 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; - - } - - // potential future optimization: skip this if propertyIndex is already an integer - // and convert the integer string to a true integer. - - targetObject = targetObject.skeleton.bones; - - // support resolving morphTarget names into indices. - for ( var i = 0; i < targetObject.length; i ++ ) { - - if ( targetObject[ i ].name === objectIndex ) { - - objectIndex = i; - break; - - } - - } - - break; - - default: - - if ( targetObject[ objectName ] === undefined ) { - - console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); - return; - - } - - targetObject = targetObject[ objectName ]; - - } - - - if ( objectIndex !== undefined ) { - - if ( targetObject[ objectIndex ] === undefined ) { - - console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); - return; - - } - - targetObject = targetObject[ objectIndex ]; - - } - - } - - // resolve property - var nodeProperty = targetObject[ propertyName ]; - - if ( nodeProperty === undefined ) { - - var nodeName = parsedPath.nodeName; - - console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + - '.' + propertyName + ' but it wasn\'t found.', targetObject ); - return; - - } - - // determine versioning scheme - var versioning = this.Versioning.None; - - if ( targetObject.needsUpdate !== undefined ) { // material - - versioning = this.Versioning.NeedsUpdate; - this.targetObject = targetObject; - - } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform - - versioning = this.Versioning.MatrixWorldNeedsUpdate; - this.targetObject = targetObject; - - } - - // determine how the property gets bound - var bindingType = this.BindingType.Direct; - - if ( propertyIndex !== undefined ) { - - // access a sub element of the property array (only primitives are supported right now) - - if ( propertyName === "morphTargetInfluences" ) { - - // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. - - // support resolving morphTarget names into indices. - if ( ! targetObject.geometry ) { - - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); - return; - - } - - if ( targetObject.geometry.isBufferGeometry ) { - - if ( ! targetObject.geometry.morphAttributes ) { - - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); - return; - - } - - for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) { - - if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) { - - propertyIndex = i; - break; - - } - - } - - - } else { - - if ( ! targetObject.geometry.morphTargets ) { - - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this ); - return; - - } - - for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) { - - if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) { - - propertyIndex = i; - break; - - } - - } - - } - - } - - bindingType = this.BindingType.ArrayElement; - - this.resolvedProperty = nodeProperty; - this.propertyIndex = propertyIndex; - - } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { - - // must use copy for Object3D.Euler/Quaternion - - bindingType = this.BindingType.HasFromToArray; - - this.resolvedProperty = nodeProperty; - - } else if ( Array.isArray( nodeProperty ) ) { - - bindingType = this.BindingType.EntireArray; - - this.resolvedProperty = nodeProperty; - - } else { - - this.propertyName = propertyName; - - } - - // select getter / setter - this.getValue = this.GetterByBindingType[ bindingType ]; - this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; - - }, - - unbind: function () { - - this.node = null; - - // back to the prototype version of getValue / setValue - // note: avoiding to mutate the shape of 'this' via 'delete' - this.getValue = this._getValue_unbound; - this.setValue = this._setValue_unbound; - - } - - } ); - - //!\ DECLARE ALIAS AFTER assign prototype ! - Object.assign( PropertyBinding.prototype, { - - // initial state of these methods that calls 'bind' - _getValue_unbound: PropertyBinding.prototype.getValue, - _setValue_unbound: PropertyBinding.prototype.setValue, - - } ); - - /** - * - * A group of objects that receives a shared animation state. - * - * Usage: - * - * - Add objects you would otherwise pass as 'root' to the - * constructor or the .clipAction method of AnimationMixer. - * - * - Instead pass this object as 'root'. - * - * - You can also add and remove objects later when the mixer - * is running. - * - * Note: - * - * Objects of this class appear as one object to the mixer, - * so cache control of the individual objects must be done - * on the group. - * - * Limitation: - * - * - The animated properties must be compatible among the - * all objects in the group. - * - * - A single property can either be controlled through a - * target group or directly, but not both. - * - * @author tschw - */ - - function AnimationObjectGroup() { - - this.uuid = _Math.generateUUID(); - - // cached objects followed by the active ones - this._objects = Array.prototype.slice.call( arguments ); - - this.nCachedObjects_ = 0; // threshold - // note: read by PropertyBinding.Composite - - var indices = {}; - this._indicesByUUID = indices; // for bookkeeping - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - indices[ arguments[ i ].uuid ] = i; - - } - - this._paths = []; // inside: string - this._parsedPaths = []; // inside: { we don't care, here } - this._bindings = []; // inside: Array< PropertyBinding > - this._bindingsIndicesByPath = {}; // inside: indices in these arrays - - var scope = this; - - this.stats = { - - objects: { - get total() { - - return scope._objects.length; - - }, - get inUse() { - - return this.total - scope.nCachedObjects_; - - } - }, - get bindingsPerObject() { - - return scope._bindings.length; - - } - - }; - - } - - Object.assign( AnimationObjectGroup.prototype, { - - isAnimationObjectGroup: true, - - add: function () { - - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - nBindings = bindings.length; - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - var object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ], - knownObject = undefined; - - if ( index === undefined ) { - - // unknown object -> add it to the ACTIVE region - - index = nObjects ++; - indicesByUUID[ uuid ] = index; - objects.push( object ); - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); - - } - - } else if ( index < nCachedObjects ) { - - knownObject = objects[ index ]; - - // move existing object to the ACTIVE region - - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ]; - - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; - - indicesByUUID[ uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = object; - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - binding = bindingsForPath[ index ]; - - bindingsForPath[ index ] = lastCached; - - if ( binding === undefined ) { - - // since we do not bother to create new bindings - // for objects that are cached, the binding may - // or may not exist - - binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); - - } - - bindingsForPath[ firstActiveIndex ] = binding; - - } - - } else if ( objects[ index ] !== knownObject ) { - - console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + - 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); - - } // else the object is already where we want it to be - - } // for arguments - - this.nCachedObjects_ = nCachedObjects; - - }, - - remove: function () { - - var objects = this._objects, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - var object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; - - if ( index !== undefined && index >= nCachedObjects ) { - - // move existing object into the CACHED region - - var lastCachedIndex = nCachedObjects ++, - firstActiveObject = objects[ lastCachedIndex ]; - - indicesByUUID[ firstActiveObject.uuid ] = index; - objects[ index ] = firstActiveObject; - - indicesByUUID[ uuid ] = lastCachedIndex; - objects[ lastCachedIndex ] = object; - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ], - firstActive = bindingsForPath[ lastCachedIndex ], - binding = bindingsForPath[ index ]; - - bindingsForPath[ index ] = firstActive; - bindingsForPath[ lastCachedIndex ] = binding; - - } - - } - - } // for arguments - - this.nCachedObjects_ = nCachedObjects; - - }, - - // remove & forget - uncache: function () { - - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - var object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; - - if ( index !== undefined ) { - - delete indicesByUUID[ uuid ]; - - if ( index < nCachedObjects ) { - - // object is cached, shrink the CACHED region - - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ], - lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; - - // last cached object takes this object's place - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; - - // last object goes to the activated slot and pop - indicesByUUID[ lastObject.uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = lastObject; - objects.pop(); - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - last = bindingsForPath[ lastIndex ]; - - bindingsForPath[ index ] = lastCached; - bindingsForPath[ firstActiveIndex ] = last; - bindingsForPath.pop(); - - } - - } else { - - // object is active, just swap with the last and pop - - var lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; - - indicesByUUID[ lastObject.uuid ] = index; - objects[ index ] = lastObject; - objects.pop(); - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ]; - - bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; - bindingsForPath.pop(); - - } - - } // cached or active - - } // if object is known - - } // for arguments - - this.nCachedObjects_ = nCachedObjects; - - }, - - // Internal interface used by befriended PropertyBinding.Composite: - - subscribe_: function ( path, parsedPath ) { - - // returns an array of bindings for the given path that is changed - // according to the contained objects in the group - - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ], - bindings = this._bindings; - - if ( index !== undefined ) return bindings[ index ]; - - var paths = this._paths, - parsedPaths = this._parsedPaths, - objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - bindingsForPath = new Array( nObjects ); - - index = bindings.length; - - indicesByPath[ path ] = index; - - paths.push( path ); - parsedPaths.push( parsedPath ); - bindings.push( bindingsForPath ); - - for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) { - - var object = objects[ i ]; - bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); - - } - - return bindingsForPath; - - }, - - unsubscribe_: function ( path ) { - - // tells the group to forget about a property path and no longer - // update the array previously obtained with 'subscribe_' - - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ]; - - if ( index !== undefined ) { - - var paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - lastBindingsIndex = bindings.length - 1, - lastBindings = bindings[ lastBindingsIndex ], - lastBindingsPath = path[ lastBindingsIndex ]; - - indicesByPath[ lastBindingsPath ] = index; - - bindings[ index ] = lastBindings; - bindings.pop(); - - parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; - parsedPaths.pop(); - - paths[ index ] = paths[ lastBindingsIndex ]; - paths.pop(); - - } - - } - - } ); - - /** - * - * Action provided by AnimationMixer for scheduling clip playback on specific - * objects. - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - * - */ - - function AnimationAction( mixer, clip, localRoot ) { - - this._mixer = mixer; - this._clip = clip; - this._localRoot = localRoot || null; - - var tracks = clip.tracks, - nTracks = tracks.length, - interpolants = new Array( nTracks ); - - var interpolantSettings = { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - }; - - for ( var i = 0; i !== nTracks; ++ i ) { - - var interpolant = tracks[ i ].createInterpolant( null ); - interpolants[ i ] = interpolant; - interpolant.settings = interpolantSettings; - - } - - this._interpolantSettings = interpolantSettings; - - this._interpolants = interpolants; // bound by the mixer - - // inside: PropertyMixer (managed by the mixer) - this._propertyBindings = new Array( nTracks ); - - this._cacheIndex = null; // for the memory manager - this._byClipCacheIndex = null; // for the memory manager - - this._timeScaleInterpolant = null; - this._weightInterpolant = null; - - this.loop = LoopRepeat; - this._loopCount = - 1; - - // global mixer time when the action is to be started - // it's set back to 'null' upon start of the action - this._startTime = null; - - // scaled local time of the action - // gets clamped or wrapped to 0..clip.duration according to loop - this.time = 0; - - this.timeScale = 1; - this._effectiveTimeScale = 1; - - this.weight = 1; - this._effectiveWeight = 1; - - this.repetitions = Infinity; // no. of repetitions when looping - - this.paused = false; // true -> zero effective time scale - this.enabled = true; // false -> zero effective weight - - this.clampWhenFinished = false; // keep feeding the last frame? - - this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate - this.zeroSlopeAtEnd = true; // clips for start, loop and end - - } - - Object.assign( AnimationAction.prototype, { - - // State & Scheduling - - play: function () { - - this._mixer._activateAction( this ); - - return this; - - }, - - stop: function () { - - this._mixer._deactivateAction( this ); - - return this.reset(); - - }, - - reset: function () { - - this.paused = false; - this.enabled = true; - - this.time = 0; // restart clip - this._loopCount = - 1; // forget previous loops - this._startTime = null; // forget scheduling - - return this.stopFading().stopWarping(); - - }, - - isRunning: function () { - - return this.enabled && ! this.paused && this.timeScale !== 0 && - this._startTime === null && this._mixer._isActiveAction( this ); - - }, - - // return true when play has been called - isScheduled: function () { - - return this._mixer._isActiveAction( this ); - - }, - - startAt: function ( time ) { - - this._startTime = time; - - return this; - - }, - - setLoop: function ( mode, repetitions ) { - - this.loop = mode; - this.repetitions = repetitions; - - return this; - - }, - - // Weight - - // set the weight stopping any scheduled fading - // although .enabled = false yields an effective weight of zero, this - // method does *not* change .enabled, because it would be confusing - setEffectiveWeight: function ( weight ) { - - this.weight = weight; - - // note: same logic as when updated at runtime - this._effectiveWeight = this.enabled ? weight : 0; - - return this.stopFading(); - - }, - - // return the weight considering fading and .enabled - getEffectiveWeight: function () { - - return this._effectiveWeight; - - }, - - fadeIn: function ( duration ) { - - return this._scheduleFading( duration, 0, 1 ); - - }, - - fadeOut: function ( duration ) { - - return this._scheduleFading( duration, 1, 0 ); - - }, - - crossFadeFrom: function ( fadeOutAction, duration, warp ) { - - fadeOutAction.fadeOut( duration ); - this.fadeIn( duration ); - - if ( warp ) { - - var fadeInDuration = this._clip.duration, - fadeOutDuration = fadeOutAction._clip.duration, - - startEndRatio = fadeOutDuration / fadeInDuration, - endStartRatio = fadeInDuration / fadeOutDuration; - - fadeOutAction.warp( 1.0, startEndRatio, duration ); - this.warp( endStartRatio, 1.0, duration ); - - } - - return this; - - }, - - crossFadeTo: function ( fadeInAction, duration, warp ) { - - return fadeInAction.crossFadeFrom( this, duration, warp ); - - }, - - stopFading: function () { - - var weightInterpolant = this._weightInterpolant; - - if ( weightInterpolant !== null ) { - - this._weightInterpolant = null; - this._mixer._takeBackControlInterpolant( weightInterpolant ); - - } - - return this; - - }, - - // Time Scale Control - - // set the time scale stopping any scheduled warping - // although .paused = true yields an effective time scale of zero, this - // method does *not* change .paused, because it would be confusing - setEffectiveTimeScale: function ( timeScale ) { - - this.timeScale = timeScale; - this._effectiveTimeScale = this.paused ? 0 : timeScale; - - return this.stopWarping(); - - }, - - // return the time scale considering warping and .paused - getEffectiveTimeScale: function () { - - return this._effectiveTimeScale; - - }, - - setDuration: function ( duration ) { - - this.timeScale = this._clip.duration / duration; - - return this.stopWarping(); - - }, - - syncWith: function ( action ) { - - this.time = action.time; - this.timeScale = action.timeScale; - - return this.stopWarping(); - - }, - - halt: function ( duration ) { - - return this.warp( this._effectiveTimeScale, 0, duration ); - - }, - - warp: function ( startTimeScale, endTimeScale, duration ) { - - var mixer = this._mixer, now = mixer.time, - interpolant = this._timeScaleInterpolant, - - timeScale = this.timeScale; - - if ( interpolant === null ) { - - interpolant = mixer._lendControlInterpolant(); - this._timeScaleInterpolant = interpolant; - - } - - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; - - times[ 0 ] = now; - times[ 1 ] = now + duration; - - values[ 0 ] = startTimeScale / timeScale; - values[ 1 ] = endTimeScale / timeScale; - - return this; - - }, - - stopWarping: function () { - - var timeScaleInterpolant = this._timeScaleInterpolant; - - if ( timeScaleInterpolant !== null ) { - - this._timeScaleInterpolant = null; - this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); - - } - - return this; - - }, - - // Object Accessors - - getMixer: function () { - - return this._mixer; - - }, - - getClip: function () { - - return this._clip; - - }, - - getRoot: function () { - - return this._localRoot || this._mixer._root; - - }, - - // Interna - - _update: function ( time, deltaTime, timeDirection, accuIndex ) { - - // called by the mixer - - if ( ! this.enabled ) { - - // call ._updateWeight() to update ._effectiveWeight - - this._updateWeight( time ); - return; - - } - - var startTime = this._startTime; - - if ( startTime !== null ) { - - // check for scheduled start of action - - var timeRunning = ( time - startTime ) * timeDirection; - if ( timeRunning < 0 || timeDirection === 0 ) { - - return; // yet to come / don't decide when delta = 0 - - } - - // start - - this._startTime = null; // unschedule - deltaTime = timeDirection * timeRunning; - - } - - // apply time scale and advance time - - deltaTime *= this._updateTimeScale( time ); - var clipTime = this._updateTime( deltaTime ); - - // note: _updateTime may disable the action resulting in - // an effective weight of 0 - - var weight = this._updateWeight( time ); - - if ( weight > 0 ) { - - var interpolants = this._interpolants; - var propertyMixers = this._propertyBindings; - - for ( var j = 0, m = interpolants.length; j !== m; ++ j ) { - - interpolants[ j ].evaluate( clipTime ); - propertyMixers[ j ].accumulate( accuIndex, weight ); - - } - - } - - }, - - _updateWeight: function ( time ) { - - var weight = 0; - - if ( this.enabled ) { - - weight = this.weight; - var interpolant = this._weightInterpolant; - - if ( interpolant !== null ) { - - var interpolantValue = interpolant.evaluate( time )[ 0 ]; - - weight *= interpolantValue; - - if ( time > interpolant.parameterPositions[ 1 ] ) { - - this.stopFading(); - - if ( interpolantValue === 0 ) { - - // faded out, disable - this.enabled = false; - - } - - } - - } - - } - - this._effectiveWeight = weight; - return weight; - - }, - - _updateTimeScale: function ( time ) { - - var timeScale = 0; - - if ( ! this.paused ) { - - timeScale = this.timeScale; - - var interpolant = this._timeScaleInterpolant; - - if ( interpolant !== null ) { - - var interpolantValue = interpolant.evaluate( time )[ 0 ]; - - timeScale *= interpolantValue; - - if ( time > interpolant.parameterPositions[ 1 ] ) { - - this.stopWarping(); - - if ( timeScale === 0 ) { - - // motion has halted, pause - this.paused = true; - - } else { - - // warp done - apply final time scale - this.timeScale = timeScale; - - } - - } - - } - - } - - this._effectiveTimeScale = timeScale; - return timeScale; - - }, - - _updateTime: function ( deltaTime ) { - - var time = this.time + deltaTime; - - if ( deltaTime === 0 ) return time; - - var duration = this._clip.duration, - - loop = this.loop, - loopCount = this._loopCount; - - if ( loop === LoopOnce ) { - - if ( loopCount === - 1 ) { - - // just started - - this._loopCount = 0; - this._setEndings( true, true, false ); - - } - - handle_stop: { - - if ( time >= duration ) { - - time = duration; - - } else if ( time < 0 ) { - - time = 0; - - } else break handle_stop; - - if ( this.clampWhenFinished ) this.paused = true; - else this.enabled = false; - - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime < 0 ? - 1 : 1 - } ); - - } - - } else { // repetitive Repeat or PingPong - - var pingPong = ( loop === LoopPingPong ); - - if ( loopCount === - 1 ) { - - // just started - - if ( deltaTime >= 0 ) { - - loopCount = 0; - - this._setEndings( true, this.repetitions === 0, pingPong ); - - } else { - - // when looping in reverse direction, the initial - // transition through zero counts as a repetition, - // so leave loopCount at -1 - - this._setEndings( this.repetitions === 0, true, pingPong ); - - } - - } - - if ( time >= duration || time < 0 ) { - - // wrap around - - var loopDelta = Math.floor( time / duration ); // signed - time -= duration * loopDelta; - - loopCount += Math.abs( loopDelta ); - - var pending = this.repetitions - loopCount; - - if ( pending < 0 ) { - - // have to stop (switch state, clamp time, fire event) - - if ( this.clampWhenFinished ) this.paused = true; - else this.enabled = false; - - time = deltaTime > 0 ? duration : 0; - - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime > 0 ? 1 : - 1 - } ); - - } else { - - // keep running - - if ( pending === 0 ) { - - // entering the last round - - var atStart = deltaTime < 0; - this._setEndings( atStart, ! atStart, pingPong ); - - } else { - - this._setEndings( false, false, pingPong ); - - } - - this._loopCount = loopCount; - - this._mixer.dispatchEvent( { - type: 'loop', action: this, loopDelta: loopDelta - } ); - - } - - } - - if ( pingPong && ( loopCount & 1 ) === 1 ) { - - // invert time for the "pong round" - - this.time = time; - return duration - time; - - } - - } - - this.time = time; - return time; - - }, - - _setEndings: function ( atStart, atEnd, pingPong ) { - - var settings = this._interpolantSettings; - - if ( pingPong ) { - - settings.endingStart = ZeroSlopeEnding; - settings.endingEnd = ZeroSlopeEnding; - - } else { - - // assuming for LoopOnce atStart == atEnd == true - - if ( atStart ) { - - settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; - - } else { - - settings.endingStart = WrapAroundEnding; - - } - - if ( atEnd ) { - - settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; - - } else { - - settings.endingEnd = WrapAroundEnding; - - } - - } - - }, - - _scheduleFading: function ( duration, weightNow, weightThen ) { - - var mixer = this._mixer, now = mixer.time, - interpolant = this._weightInterpolant; - - if ( interpolant === null ) { - - interpolant = mixer._lendControlInterpolant(); - this._weightInterpolant = interpolant; - - } - - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; - - times[ 0 ] = now; values[ 0 ] = weightNow; - times[ 1 ] = now + duration; values[ 1 ] = weightThen; - - return this; - - } - - } ); - - /** - * - * Player for AnimationClips. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function AnimationMixer( root ) { - - this._root = root; - this._initMemoryManager(); - this._accuIndex = 0; - - this.time = 0; - - this.timeScale = 1.0; - - } - - AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { - - constructor: AnimationMixer, - - _bindAction: function ( action, prototypeAction ) { - - var root = action._localRoot || this._root, - tracks = action._clip.tracks, - nTracks = tracks.length, - bindings = action._propertyBindings, - interpolants = action._interpolants, - rootUuid = root.uuid, - bindingsByRoot = this._bindingsByRootAndName, - bindingsByName = bindingsByRoot[ rootUuid ]; - - if ( bindingsByName === undefined ) { - - bindingsByName = {}; - bindingsByRoot[ rootUuid ] = bindingsByName; - - } - - for ( var i = 0; i !== nTracks; ++ i ) { - - var track = tracks[ i ], - trackName = track.name, - binding = bindingsByName[ trackName ]; - - if ( binding !== undefined ) { - - bindings[ i ] = binding; - - } else { - - binding = bindings[ i ]; - - if ( binding !== undefined ) { - - // existing binding, make sure the cache knows - - if ( binding._cacheIndex === null ) { - - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); - - } - - continue; - - } - - var path = prototypeAction && prototypeAction. - _propertyBindings[ i ].binding.parsedPath; - - binding = new PropertyMixer( - PropertyBinding.create( root, trackName, path ), - track.ValueTypeName, track.getValueSize() ); - - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); - - bindings[ i ] = binding; - - } - - interpolants[ i ].resultBuffer = binding.buffer; - - } - - }, - - _activateAction: function ( action ) { - - if ( ! this._isActiveAction( action ) ) { - - if ( action._cacheIndex === null ) { - - // this action has been forgotten by the cache, but the user - // appears to be still using it -> rebind - - var 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 ); - - } - - var bindings = action._propertyBindings; - - // increment reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( binding.useCount ++ === 0 ) { - - this._lendBinding( binding ); - binding.saveOriginalState(); - - } - - } - - this._lendAction( action ); - - } - - }, - - _deactivateAction: function ( action ) { - - if ( this._isActiveAction( action ) ) { - - var bindings = action._propertyBindings; - - // decrement reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( -- binding.useCount === 0 ) { - - binding.restoreOriginalState(); - this._takeBackBinding( binding ); - - } - - } - - this._takeBackAction( action ); - - } - - }, - - // Memory manager - - _initMemoryManager: function () { - - this._actions = []; // 'nActiveActions' followed by inactive ones - this._nActiveActions = 0; - - this._actionsByClip = {}; - // inside: - // { - // knownActions: Array< AnimationAction > - used as prototypes - // actionByRoot: AnimationAction - lookup - // } - - - this._bindings = []; // 'nActiveBindings' followed by inactive ones - this._nActiveBindings = 0; - - this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > - - - this._controlInterpolants = []; // same game as above - this._nActiveControlInterpolants = 0; - - var 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; - - } - } - - }; - - }, - - // Memory management for AnimationAction objects - - _isActiveAction: function ( action ) { - - var index = action._cacheIndex; - return index !== null && index < this._nActiveActions; - - }, - - _addInactiveAction: function ( action, clipUuid, rootUuid ) { - - var actions = this._actions, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; - - if ( actionsForClip === undefined ) { - - actionsForClip = { - - knownActions: [ action ], - actionByRoot: {} - - }; - - action._byClipCacheIndex = 0; - - actionsByClip[ clipUuid ] = actionsForClip; - - } else { - - var knownActions = actionsForClip.knownActions; - - action._byClipCacheIndex = knownActions.length; - knownActions.push( action ); - - } - - action._cacheIndex = actions.length; - actions.push( action ); - - actionsForClip.actionByRoot[ rootUuid ] = action; - - }, - - _removeInactiveAction: function ( action ) { - - var actions = this._actions, - lastInactiveAction = actions[ actions.length - 1 ], - cacheIndex = action._cacheIndex; - - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); - - action._cacheIndex = null; - - - var 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; - - - var actionByRoot = actionsForClip.actionByRoot, - rootUuid = ( action._localRoot || this._root ).uuid; - - delete actionByRoot[ rootUuid ]; - - if ( knownActionsForClip.length === 0 ) { - - delete actionsByClip[ clipUuid ]; - - } - - this._removeInactiveBindingsForAction( action ); - - }, - - _removeInactiveBindingsForAction: function ( action ) { - - var bindings = action._propertyBindings; - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( -- binding.referenceCount === 0 ) { - - this._removeInactiveBinding( binding ); - - } - - } - - }, - - _lendAction: function ( action ) { - - // [ active actions | inactive actions ] - // [ active actions >| inactive actions ] - // s a - // <-swap-> - // a s - - var 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: function ( action ) { - - // [ active actions | inactive actions ] - // [ active actions |< inactive actions ] - // a s - // <-swap-> - // s a - - var actions = this._actions, - prevIndex = action._cacheIndex, - - firstInactiveIndex = -- this._nActiveActions, - - lastActiveAction = actions[ firstInactiveIndex ]; - - action._cacheIndex = firstInactiveIndex; - actions[ firstInactiveIndex ] = action; - - lastActiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = lastActiveAction; - - }, - - // Memory management for PropertyMixer objects - - _addInactiveBinding: function ( binding, rootUuid, trackName ) { - - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], - - bindings = this._bindings; - - if ( bindingByName === undefined ) { - - bindingByName = {}; - bindingsByRoot[ rootUuid ] = bindingByName; - - } - - bindingByName[ trackName ] = binding; - - binding._cacheIndex = bindings.length; - bindings.push( binding ); - - }, - - _removeInactiveBinding: function ( binding ) { - - var 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 ]; - - remove_empty_map: { - - for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars - - delete bindingsByRoot[ rootUuid ]; - - } - - }, - - _lendBinding: function ( binding ) { - - var 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: function ( binding ) { - - var bindings = this._bindings, - prevIndex = binding._cacheIndex, - - firstInactiveIndex = -- this._nActiveBindings, - - lastActiveBinding = bindings[ firstInactiveIndex ]; - - binding._cacheIndex = firstInactiveIndex; - bindings[ firstInactiveIndex ] = binding; - - lastActiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = lastActiveBinding; - - }, - - - // Memory management of Interpolants for weight and time scale - - _lendControlInterpolant: function () { - - var interpolants = this._controlInterpolants, - lastActiveIndex = this._nActiveControlInterpolants ++, - interpolant = interpolants[ lastActiveIndex ]; - - if ( interpolant === undefined ) { - - interpolant = new LinearInterpolant( - new Float32Array( 2 ), new Float32Array( 2 ), - 1, this._controlInterpolantsResultBuffer ); - - interpolant.__cacheIndex = lastActiveIndex; - interpolants[ lastActiveIndex ] = interpolant; - - } - - return interpolant; - - }, - - _takeBackControlInterpolant: function ( interpolant ) { - - var interpolants = this._controlInterpolants, - prevIndex = interpolant.__cacheIndex, - - firstInactiveIndex = -- this._nActiveControlInterpolants, - - lastActiveInterpolant = interpolants[ firstInactiveIndex ]; - - interpolant.__cacheIndex = firstInactiveIndex; - interpolants[ firstInactiveIndex ] = interpolant; - - lastActiveInterpolant.__cacheIndex = prevIndex; - interpolants[ prevIndex ] = lastActiveInterpolant; - - }, - - _controlInterpolantsResultBuffer: new Float32Array( 1 ), - - // return an action for a clip optionally using a custom root target - // object (this method allocates a lot of dynamic memory in case a - // previously unknown clip/root combination is specified) - clipAction: function ( clip, optionalRoot ) { - - var root = optionalRoot || this._root, - rootUuid = root.uuid, - - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, - - clipUuid = clipObject !== null ? clipObject.uuid : clip, - - actionsForClip = this._actionsByClip[ clipUuid ], - prototypeAction = null; - - if ( actionsForClip !== undefined ) { - - var existingAction = - actionsForClip.actionByRoot[ rootUuid ]; - - if ( existingAction !== undefined ) { - - return existingAction; - - } - - // we know the clip, so we don't have to parse all - // the bindings again but can just copy - prototypeAction = actionsForClip.knownActions[ 0 ]; - - // also, take the clip from the prototype action - if ( clipObject === null ) - clipObject = prototypeAction._clip; - - } - - // clip must be known when specified via string - if ( clipObject === null ) return null; - - // allocate all resources required to run it - var newAction = new AnimationAction( this, clipObject, optionalRoot ); - - this._bindAction( newAction, prototypeAction ); - - // and make the action known to the memory manager - this._addInactiveAction( newAction, clipUuid, rootUuid ); - - return newAction; - - }, - - // get an existing action - existingAction: function ( clip, optionalRoot ) { - - var root = optionalRoot || this._root, - rootUuid = root.uuid, - - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, - - clipUuid = clipObject ? clipObject.uuid : clip, - - actionsForClip = this._actionsByClip[ clipUuid ]; - - if ( actionsForClip !== undefined ) { - - return actionsForClip.actionByRoot[ rootUuid ] || null; - - } - - return null; - - }, - - // deactivates all previously scheduled actions - stopAllAction: function () { - - var actions = this._actions, - nActions = this._nActiveActions, - bindings = this._bindings, - nBindings = this._nActiveBindings; - - this._nActiveActions = 0; - this._nActiveBindings = 0; - - for ( var i = 0; i !== nActions; ++ i ) { - - actions[ i ].reset(); - - } - - for ( var i = 0; i !== nBindings; ++ i ) { - - bindings[ i ].useCount = 0; - - } - - return this; - - }, - - // advance the time and update apply the animation - update: function ( deltaTime ) { - - deltaTime *= this.timeScale; - - var actions = this._actions, - nActions = this._nActiveActions, - - time = this.time += deltaTime, - timeDirection = Math.sign( deltaTime ), - - accuIndex = this._accuIndex ^= 1; - - // run active actions - - for ( var i = 0; i !== nActions; ++ i ) { - - var action = actions[ i ]; - - action._update( time, deltaTime, timeDirection, accuIndex ); - - } - - // update scene graph - - var bindings = this._bindings, - nBindings = this._nActiveBindings; - - for ( var i = 0; i !== nBindings; ++ i ) { - - bindings[ i ].apply( accuIndex ); - - } - - return this; - - }, - - // return this mixer's root target object - getRoot: function () { - - return this._root; - - }, - - // free all resources specific to a particular clip - uncacheClip: function ( clip ) { - - var actions = this._actions, - clipUuid = clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; - - if ( actionsForClip !== undefined ) { - - // note: just calling _removeInactiveAction would mess up the - // iteration state and also require updating the state we can - // just throw away - - var actionsToRemove = actionsForClip.knownActions; - - for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) { - - var action = actionsToRemove[ i ]; - - this._deactivateAction( action ); - - var 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 ]; - - } - - }, - - // free all resources specific to a particular root target object - uncacheRoot: function ( root ) { - - var rootUuid = root.uuid, - actionsByClip = this._actionsByClip; - - for ( var clipUuid in actionsByClip ) { - - var actionByRoot = actionsByClip[ clipUuid ].actionByRoot, - action = actionByRoot[ rootUuid ]; - - if ( action !== undefined ) { - - this._deactivateAction( action ); - this._removeInactiveAction( action ); - - } - - } - - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ]; - - if ( bindingByName !== undefined ) { - - for ( var trackName in bindingByName ) { - - var binding = bindingByName[ trackName ]; - binding.restoreOriginalState(); - this._removeInactiveBinding( binding ); - - } - - } - - }, - - // remove a targeted clip from the cache - uncacheAction: function ( clip, optionalRoot ) { - - var action = this.existingAction( clip, optionalRoot ); - - if ( action !== null ) { - - this._deactivateAction( action ); - this._removeInactiveAction( action ); - - } - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function Uniform( value ) { - - if ( typeof value === 'string' ) { - - console.warn( 'THREE.Uniform: Type parameter is no longer needed.' ); - value = arguments[ 1 ]; - - } - - this.value = value; - - } - - Uniform.prototype.clone = function () { - - return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); - - }; - - /** - * @author benaadams / https://twitter.com/ben_a_adams - */ - - function InstancedBufferGeometry() { - - BufferGeometry.call( this ); - - this.type = 'InstancedBufferGeometry'; - this.maxInstancedCount = undefined; - - } - - InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), { - - constructor: InstancedBufferGeometry, - - isInstancedBufferGeometry: true, - - copy: function ( source ) { - - BufferGeometry.prototype.copy.call( this, source ); - - this.maxInstancedCount = source.maxInstancedCount; - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - } - - } ); - - /** - * @author benaadams / https://twitter.com/ben_a_adams - */ - - function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) { - - this.uuid = _Math.generateUUID(); - - this.data = interleavedBuffer; - this.itemSize = itemSize; - this.offset = offset; - - this.normalized = normalized === true; - - } - - Object.defineProperties( InterleavedBufferAttribute.prototype, { - - count: { - - get: function () { - - return this.data.count; - - } - - }, - - array: { - - get: function () { - - return this.data.array; - - } - - } - - } ); - - Object.assign( InterleavedBufferAttribute.prototype, { - - isInterleavedBufferAttribute: true, - - setX: function ( index, x ) { - - this.data.array[ index * this.data.stride + this.offset ] = x; - - return this; - - }, - - setY: function ( index, y ) { - - this.data.array[ index * this.data.stride + this.offset + 1 ] = y; - - return this; - - }, - - setZ: function ( index, z ) { - - this.data.array[ index * this.data.stride + this.offset + 2 ] = z; - - return this; - - }, - - setW: function ( index, w ) { - - this.data.array[ index * this.data.stride + this.offset + 3 ] = w; - - return this; - - }, - - getX: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset ]; - - }, - - getY: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset + 1 ]; - - }, - - getZ: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset + 2 ]; - - }, - - getW: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset + 3 ]; - - }, - - setXY: function ( index, x, y ) { - - index = index * this.data.stride + this.offset; - - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - - return this; - - }, - - setXYZ: function ( index, x, y, z ) { - - index = index * this.data.stride + this.offset; - - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; - - return this; - - }, - - setXYZW: function ( index, x, y, z, w ) { - - index = index * this.data.stride + this.offset; - - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; - this.data.array[ index + 3 ] = w; - - return this; - - } - - } ); - - /** - * @author benaadams / https://twitter.com/ben_a_adams - */ - - function InterleavedBuffer( array, stride ) { - - this.uuid = _Math.generateUUID(); - - this.array = array; - this.stride = stride; - this.count = array !== undefined ? array.length / stride : 0; - - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; - - this.onUploadCallback = function () {}; - - this.version = 0; - - } - - Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', { - - set: function ( value ) { - - if ( value === true ) this.version ++; - - } - - } ); - - Object.assign( InterleavedBuffer.prototype, { - - isInterleavedBuffer: true, - - setArray: function ( array ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.count = array !== undefined ? array.length / this.stride : 0; - this.array = array; - - }, - - setDynamic: function ( value ) { - - this.dynamic = value; - - return this; - - }, - - copy: function ( source ) { - - this.array = new source.array.constructor( source.array ); - this.count = source.count; - this.stride = source.stride; - this.dynamic = source.dynamic; - - return this; - - }, - - copyAt: function ( index1, attribute, index2 ) { - - index1 *= this.stride; - index2 *= attribute.stride; - - for ( var i = 0, l = this.stride; i < l; i ++ ) { - - this.array[ index1 + i ] = attribute.array[ index2 + i ]; - - } - - return this; - - }, - - set: function ( value, offset ) { - - if ( offset === undefined ) offset = 0; - - this.array.set( value, offset ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - onUpload: function ( callback ) { - - this.onUploadCallback = callback; - - return this; - - } - - } ); - - /** - * @author benaadams / https://twitter.com/ben_a_adams - */ - - function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) { - - InterleavedBuffer.call( this, array, stride ); - - this.meshPerAttribute = meshPerAttribute || 1; - - } - - InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), { - - constructor: InstancedInterleavedBuffer, - - isInstancedInterleavedBuffer: true, - - copy: function ( source ) { - - InterleavedBuffer.prototype.copy.call( this, source ); - - this.meshPerAttribute = source.meshPerAttribute; - - return this; - - } - - } ); - - /** - * @author benaadams / https://twitter.com/ben_a_adams - */ - - function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) { - - BufferAttribute.call( this, array, itemSize ); - - this.meshPerAttribute = meshPerAttribute || 1; - - } - - InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), { - - constructor: InstancedBufferAttribute, - - isInstancedBufferAttribute: true, - - copy: function ( source ) { - - BufferAttribute.prototype.copy.call( this, source ); - - this.meshPerAttribute = source.meshPerAttribute; - - return this; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author bhouston / http://clara.io/ - * @author stephomi / http://stephaneginier.com/ - */ - - function Raycaster( origin, direction, near, far ) { - - this.ray = new Ray( origin, direction ); - // direction is assumed to be normalized (for accurate distance calculations) - - this.near = near || 0; - this.far = far || Infinity; - - this.params = { - Mesh: {}, - Line: {}, - LOD: {}, - Points: { threshold: 1 }, - Sprite: {} - }; - - Object.defineProperties( this.params, { - PointCloud: { - get: function () { - - console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); - return this.Points; - - } - } - } ); - - } - - function ascSort( a, b ) { - - return a.distance - b.distance; - - } - - function intersectObject( object, raycaster, intersects, recursive ) { - - if ( object.visible === false ) return; - - object.raycast( raycaster, intersects ); - - if ( recursive === true ) { - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - intersectObject( children[ i ], raycaster, intersects, true ); - - } - - } - - } - - Object.assign( Raycaster.prototype, { - - linePrecision: 1, - - set: function ( origin, direction ) { - - // direction is assumed to be normalized (for accurate distance calculations) - - this.ray.set( origin, direction ); - - }, - - setFromCamera: function ( coords, camera ) { - - if ( ( camera && 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(); - - } else if ( ( camera && camera.isOrthographicCamera ) ) { - - this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera - this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); - - } else { - - console.error( 'THREE.Raycaster: Unsupported camera type.' ); - - } - - }, - - intersectObject: function ( object, recursive ) { - - var intersects = []; - - intersectObject( object, this, intersects, recursive ); - - intersects.sort( ascSort ); - - return intersects; - - }, - - intersectObjects: function ( objects, recursive ) { - - var intersects = []; - - if ( Array.isArray( objects ) === false ) { - - console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); - return intersects; - - } - - for ( var i = 0, l = objects.length; i < l; i ++ ) { - - intersectObject( objects[ i ], this, intersects, recursive ); - - } - - intersects.sort( ascSort ); - - return intersects; - - } - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function Clock( autoStart ) { - - this.autoStart = ( autoStart !== undefined ) ? autoStart : true; - - this.startTime = 0; - this.oldTime = 0; - this.elapsedTime = 0; - - this.running = false; - - } - - Object.assign( Clock.prototype, { - - start: function () { - - this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 - - this.oldTime = this.startTime; - this.elapsedTime = 0; - this.running = true; - - }, - - stop: function () { - - this.getElapsedTime(); - this.running = false; - this.autoStart = false; - - }, - - getElapsedTime: function () { - - this.getDelta(); - return this.elapsedTime; - - }, - - getDelta: function () { - - var diff = 0; - - if ( this.autoStart && ! this.running ) { - - this.start(); - return 0; - - } - - if ( this.running ) { - - var newTime = ( typeof performance === 'undefined' ? Date : performance ).now(); - - diff = ( newTime - this.oldTime ) / 1000; - this.oldTime = newTime; - - this.elapsedTime += diff; - - } - - return diff; - - } - - } ); - - /** - * @author bhouston / http://clara.io - * @author WestLangley / http://github.com/WestLangley - * - * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system - * - * The poles (phi) are at the positive and negative y axis. - * The equator starts at positive z. - */ - - function Spherical( radius, phi, theta ) { - - this.radius = ( radius !== undefined ) ? radius : 1.0; - this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole - this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere - - return this; - - } - - Object.assign( Spherical.prototype, { - - set: function ( radius, phi, theta ) { - - this.radius = radius; - this.phi = phi; - this.theta = theta; - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( other ) { - - this.radius = other.radius; - this.phi = other.phi; - this.theta = other.theta; - - return this; - - }, - - // restrict phi to be betwee EPS and PI-EPS - makeSafe: function () { - - var EPS = 0.000001; - this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); - - return this; - - }, - - setFromVector3: function ( vec3 ) { - - this.radius = vec3.length(); - - if ( this.radius === 0 ) { - - this.theta = 0; - this.phi = 0; - - } else { - - this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis - this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle - - } - - return this; - - } - - } ); - - /** - * @author Mugen87 / https://github.com/Mugen87 - * - * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system - * - */ - - function Cylindrical( radius, theta, y ) { - - this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane - this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis - this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane - - return this; - - } - - Object.assign( Cylindrical.prototype, { - - set: function ( radius, theta, y ) { - - this.radius = radius; - this.theta = theta; - this.y = y; - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( other ) { - - this.radius = other.radius; - this.theta = other.theta; - this.y = other.y; - - return this; - - }, - - setFromVector3: function ( vec3 ) { - - this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z ); - this.theta = Math.atan2( vec3.x, vec3.z ); - this.y = vec3.y; - - return this; - - } - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function ImmediateRenderObject( material ) { - - Object3D.call( this ); - - this.material = material; - this.render = function ( /* renderCallback */ ) {}; - - } - - ImmediateRenderObject.prototype = Object.create( Object3D.prototype ); - ImmediateRenderObject.prototype.constructor = ImmediateRenderObject; - - ImmediateRenderObject.prototype.isImmediateRenderObject = true; - - /** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function VertexNormalsHelper( object, size, hex, linewidth ) { - - this.object = object; - - this.size = ( size !== undefined ) ? size : 1; - - var color = ( hex !== undefined ) ? hex : 0xff0000; - - var width = ( linewidth !== undefined ) ? linewidth : 1; - - // - - var nNormals = 0; - - var objGeometry = this.object.geometry; - - if ( objGeometry && objGeometry.isGeometry ) { - - nNormals = objGeometry.faces.length * 3; - - } else if ( objGeometry && objGeometry.isBufferGeometry ) { - - nNormals = objGeometry.attributes.normal.count; - - } - - // - - var geometry = new BufferGeometry(); - - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); - - geometry.addAttribute( 'position', positions ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); - - // - - this.matrixAutoUpdate = false; - - this.update(); - - } - - VertexNormalsHelper.prototype = Object.create( LineSegments.prototype ); - VertexNormalsHelper.prototype.constructor = VertexNormalsHelper; - - VertexNormalsHelper.prototype.update = ( function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); - - return function update() { - - var keys = [ 'a', 'b', 'c' ]; - - this.object.updateMatrixWorld( true ); - - normalMatrix.getNormalMatrix( this.object.matrixWorld ); - - var matrixWorld = this.object.matrixWorld; - - var position = this.geometry.attributes.position; - - // - - var objGeometry = this.object.geometry; - - if ( objGeometry && objGeometry.isGeometry ) { - - var vertices = objGeometry.vertices; - - var faces = objGeometry.faces; - - var idx = 0; - - for ( var i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - - var vertex = vertices[ face[ keys[ j ] ] ]; - - var normal = face.vertexNormals[ j ]; - - v1.copy( vertex ).applyMatrix4( matrixWorld ); - - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); - - position.setXYZ( idx, v1.x, v1.y, v1.z ); - - idx = idx + 1; - - position.setXYZ( idx, v2.x, v2.y, v2.z ); - - idx = idx + 1; - - } - - } - - } else if ( objGeometry && objGeometry.isBufferGeometry ) { - - var objPos = objGeometry.attributes.position; - - var objNorm = objGeometry.attributes.normal; - - var idx = 0; - - // for simplicity, ignore index and drawcalls, and render every normal - - for ( var j = 0, jl = objPos.count; j < jl; j ++ ) { - - v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); - - v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) ); - - v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); - - position.setXYZ( idx, v1.x, v1.y, v1.z ); - - idx = idx + 1; - - position.setXYZ( idx, v2.x, v2.y, v2.z ); - - idx = idx + 1; - - } - - } - - position.needsUpdate = true; - - }; - - }() ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function SpotLightHelper( light, color ) { - - Object3D.call( this ); - - this.light = light; - this.light.updateMatrixWorld(); - - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; - - this.color = color; - - var geometry = new BufferGeometry(); - - var 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 ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { - - var p1 = ( i / l ) * Math.PI * 2; - var p2 = ( j / l ) * Math.PI * 2; - - positions.push( - Math.cos( p1 ), Math.sin( p1 ), 1, - Math.cos( p2 ), Math.sin( p2 ), 1 - ); - - } - - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - - var material = new LineBasicMaterial( { fog: false } ); - - this.cone = new LineSegments( geometry, material ); - this.add( this.cone ); - - this.update(); - - } - - SpotLightHelper.prototype = Object.create( Object3D.prototype ); - SpotLightHelper.prototype.constructor = SpotLightHelper; - - SpotLightHelper.prototype.dispose = function () { - - this.cone.geometry.dispose(); - this.cone.material.dispose(); - - }; - - SpotLightHelper.prototype.update = function () { - - var vector = new Vector3(); - var vector2 = new Vector3(); - - return function update() { - - this.light.updateMatrixWorld(); - - var coneLength = this.light.distance ? this.light.distance : 1000; - var coneWidth = coneLength * Math.tan( this.light.angle ); - - this.cone.scale.set( coneWidth, coneWidth, coneLength ); - - vector.setFromMatrixPosition( this.light.matrixWorld ); - vector2.setFromMatrixPosition( this.light.target.matrixWorld ); - - this.cone.lookAt( vector2.sub( vector ) ); - - if ( this.color !== undefined ) { - - this.cone.material.color.set( this.color ); - - } else { - - this.cone.material.color.copy( this.light.color ); - - } - - }; - - }(); - - /** - * @author Sean Griffin / http://twitter.com/sgrif - * @author Michael Guerrero / http://realitymeltdown.com - * @author mrdoob / http://mrdoob.com/ - * @author ikerr / http://verold.com - * @author Mugen87 / https://github.com/Mugen87 - */ - - function getBoneList( object ) { - - var boneList = []; - - if ( object && object.isBone ) { - - boneList.push( object ); - - } - - for ( var i = 0; i < object.children.length; i ++ ) { - - boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); - - } - - return boneList; - - } - - function SkeletonHelper( object ) { - - var bones = getBoneList( object ); - - var geometry = new BufferGeometry(); - - var vertices = []; - var colors = []; - - var color1 = new Color( 0, 0, 1 ); - var color2 = new Color( 0, 1, 0 ); - - for ( var i = 0; i < bones.length; i ++ ) { - - var 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.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } ); - - LineSegments.call( this, geometry, material ); - - this.root = object; - this.bones = bones; - - this.matrix = object.matrixWorld; - this.matrixAutoUpdate = false; - - } - - SkeletonHelper.prototype = Object.create( LineSegments.prototype ); - SkeletonHelper.prototype.constructor = SkeletonHelper; - - SkeletonHelper.prototype.updateMatrixWorld = function () { - - var vector = new Vector3(); - - var boneMatrix = new Matrix4(); - var matrixWorldInv = new Matrix4(); - - return function updateMatrixWorld( force ) { - - var bones = this.bones; - - var geometry = this.geometry; - var position = geometry.getAttribute( 'position' ); - - matrixWorldInv.getInverse( this.root.matrixWorld ); - - for ( var i = 0, j = 0; i < bones.length; i ++ ) { - - var bone = bones[ i ]; - - if ( bone.parent && bone.parent.isBone ) { - - boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j, vector.x, vector.y, vector.z ); - - boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j + 1, vector.x, vector.y, vector.z ); - - j += 2; - - } - - } - - geometry.getAttribute( 'position' ).needsUpdate = true; - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - }; - - }(); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - - function PointLightHelper( light, sphereSize, color ) { - - this.light = light; - this.light.updateMatrixWorld(); - - this.color = color; - - var geometry = new SphereBufferGeometry( sphereSize, 4, 2 ); - var material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - - Mesh.call( this, geometry, material ); - - this.matrix = this.light.matrixWorld; - this.matrixAutoUpdate = false; - - this.update(); - - - /* - var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); - var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); - - this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); - this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); - - var d = light.distance; - - if ( d === 0.0 ) { - - this.lightDistance.visible = false; - - } else { - - this.lightDistance.scale.set( d, d, d ); - - } - - this.add( this.lightDistance ); - */ - - } - - PointLightHelper.prototype = Object.create( Mesh.prototype ); - PointLightHelper.prototype.constructor = PointLightHelper; - - PointLightHelper.prototype.dispose = function () { - - this.geometry.dispose(); - this.material.dispose(); - - }; - - PointLightHelper.prototype.update = function () { - - if ( this.color !== undefined ) { - - this.material.color.set( this.color ); - - } else { - - this.material.color.copy( this.light.color ); - - } - - /* - var d = this.light.distance; - - if ( d === 0.0 ) { - - this.lightDistance.visible = false; - - } else { - - this.lightDistance.visible = true; - this.lightDistance.scale.set( d, d, d ); - - } - */ - - }; - - /** - * @author abelnation / http://github.com/abelnation - * @author Mugen87 / http://github.com/Mugen87 - * @author WestLangley / http://github.com/WestLangley - */ - - function RectAreaLightHelper( light, color ) { - - Object3D.call( this ); - - this.light = light; - this.light.updateMatrixWorld(); - - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; - - this.color = color; - - var material = new LineBasicMaterial( { fog: false } ); - - var geometry = new BufferGeometry(); - - geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) ); - - this.line = new Line( geometry, material ); - this.add( this.line ); - - - this.update(); - - } - - RectAreaLightHelper.prototype = Object.create( Object3D.prototype ); - RectAreaLightHelper.prototype.constructor = RectAreaLightHelper; - - RectAreaLightHelper.prototype.dispose = function () { - - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); - - }; - - RectAreaLightHelper.prototype.update = function () { - - // calculate new dimensions of the helper - - var hx = this.light.width * 0.5; - var hy = this.light.height * 0.5; - - var position = this.line.geometry.attributes.position; - var array = position.array; - - // update vertices - - array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0; - array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0; - array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0; - array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0; - array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0; - - position.needsUpdate = true; - - if ( this.color !== undefined ) { - - this.line.material.color.set( this.color ); - - } else { - - this.line.material.color.copy( this.light.color ); - - } - - }; - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function HemisphereLightHelper( light, size, color ) { - - Object3D.call( this ); - - this.light = light; - this.light.updateMatrixWorld(); - - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; - - this.color = color; - - var geometry = new OctahedronBufferGeometry( size ); - geometry.rotateY( Math.PI * 0.5 ); - - this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - if ( this.color === undefined ) this.material.vertexColors = VertexColors; - - var position = geometry.getAttribute( 'position' ); - var colors = new Float32Array( position.count * 3 ); - - geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); - - this.add( new Mesh( geometry, this.material ) ); - - this.update(); - - } - - HemisphereLightHelper.prototype = Object.create( Object3D.prototype ); - HemisphereLightHelper.prototype.constructor = HemisphereLightHelper; - - HemisphereLightHelper.prototype.dispose = function () { - - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); - - }; - - HemisphereLightHelper.prototype.update = function () { - - var vector = new Vector3(); - - var color1 = new Color(); - var color2 = new Color(); - - return function update() { - - var mesh = this.children[ 0 ]; - - if ( this.color !== undefined ) { - - this.material.color.set( this.color ); - - } else { - - var colors = mesh.geometry.getAttribute( 'color' ); - - color1.copy( this.light.color ); - color2.copy( this.light.groundColor ); - - for ( var i = 0, l = colors.count; i < l; i ++ ) { - - var color = ( i < ( l / 2 ) ) ? color1 : color2; - - colors.setXYZ( i, color.r, color.g, color.b ); - - } - - colors.needsUpdate = true; - - } - - mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); - - }; - - }(); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function GridHelper( size, divisions, color1, color2 ) { - - size = size || 10; - divisions = divisions || 10; - color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); - color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); - - var center = divisions / 2; - var step = size / divisions; - var halfSize = size / 2; - - var vertices = [], colors = []; - - for ( var 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 ); - - var color = i === center ? color1 : color2; - - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - - } - - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); - - LineSegments.call( this, geometry, material ); - - } - - GridHelper.prototype = Object.create( LineSegments.prototype ); - GridHelper.prototype.constructor = GridHelper; - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - * @author Hectate / http://www.github.com/Hectate - */ - - function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) { - - radius = radius || 10; - radials = radials || 16; - circles = circles || 8; - divisions = divisions || 64; - color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); - color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); - - var vertices = []; - var colors = []; - - var x, z; - var v, i, j, r, color; - - // create the radials - - for ( i = 0; i <= radials; i ++ ) { - - v = ( i / radials ) * ( Math.PI * 2 ); - - x = Math.sin( v ) * radius; - z = Math.cos( v ) * radius; - - vertices.push( 0, 0, 0 ); - vertices.push( x, 0, z ); - - color = ( i & 1 ) ? color1 : color2; - - colors.push( color.r, color.g, color.b ); - colors.push( color.r, color.g, color.b ); - - } - - // create the circles - - for ( i = 0; i <= circles; i ++ ) { - - color = ( i & 1 ) ? color1 : color2; - - r = radius - ( radius / circles * i ); - - for ( j = 0; j < divisions; j ++ ) { - - // first vertex - - v = ( j / divisions ) * ( Math.PI * 2 ); - - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; - - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); - - // second vertex - - v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); - - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; - - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); - - } - - } - - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); - - LineSegments.call( this, geometry, material ); - - } - - PolarGridHelper.prototype = Object.create( LineSegments.prototype ); - PolarGridHelper.prototype.constructor = PolarGridHelper; - - /** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function FaceNormalsHelper( object, size, hex, linewidth ) { - - // FaceNormalsHelper only supports THREE.Geometry - - this.object = object; - - this.size = ( size !== undefined ) ? size : 1; - - var color = ( hex !== undefined ) ? hex : 0xffff00; - - var width = ( linewidth !== undefined ) ? linewidth : 1; - - // - - var nNormals = 0; - - var objGeometry = this.object.geometry; - - if ( objGeometry && objGeometry.isGeometry ) { - - nNormals = objGeometry.faces.length; - - } else { - - console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' ); - - } - - // - - var geometry = new BufferGeometry(); - - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); - - geometry.addAttribute( 'position', positions ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); - - // - - this.matrixAutoUpdate = false; - this.update(); - - } - - FaceNormalsHelper.prototype = Object.create( LineSegments.prototype ); - FaceNormalsHelper.prototype.constructor = FaceNormalsHelper; - - FaceNormalsHelper.prototype.update = ( function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); - - return function update() { - - this.object.updateMatrixWorld( true ); - - normalMatrix.getNormalMatrix( this.object.matrixWorld ); - - var matrixWorld = this.object.matrixWorld; - - var position = this.geometry.attributes.position; - - // - - var objGeometry = this.object.geometry; - - var vertices = objGeometry.vertices; - - var faces = objGeometry.faces; - - var idx = 0; - - for ( var i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - var normal = face.normal; - - v1.copy( vertices[ face.a ] ) - .add( vertices[ face.b ] ) - .add( vertices[ face.c ] ) - .divideScalar( 3 ) - .applyMatrix4( matrixWorld ); - - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); - - position.setXYZ( idx, v1.x, v1.y, v1.z ); - - idx = idx + 1; - - position.setXYZ( idx, v2.x, v2.y, v2.z ); - - idx = idx + 1; - - } - - position.needsUpdate = true; - - }; - - }() ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function DirectionalLightHelper( light, size, color ) { - - Object3D.call( this ); - - this.light = light; - this.light.updateMatrixWorld(); - - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; - - this.color = color; - - if ( size === undefined ) size = 1; - - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( [ - - size, size, 0, - size, size, 0, - size, - size, 0, - - size, - size, 0, - - size, size, 0 - ], 3 ) ); - - var material = new LineBasicMaterial( { fog: false } ); - - this.lightPlane = new Line( geometry, material ); - this.add( this.lightPlane ); - - geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); - - this.targetLine = new Line( geometry, material ); - this.add( this.targetLine ); - - this.update(); - - } - - DirectionalLightHelper.prototype = Object.create( Object3D.prototype ); - DirectionalLightHelper.prototype.constructor = DirectionalLightHelper; - - DirectionalLightHelper.prototype.dispose = function () { - - this.lightPlane.geometry.dispose(); - this.lightPlane.material.dispose(); - this.targetLine.geometry.dispose(); - this.targetLine.material.dispose(); - - }; - - DirectionalLightHelper.prototype.update = function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - var v3 = new Vector3(); - - return function update() { - - v1.setFromMatrixPosition( this.light.matrixWorld ); - v2.setFromMatrixPosition( this.light.target.matrixWorld ); - v3.subVectors( v2, v1 ); - - this.lightPlane.lookAt( v3 ); - - if ( this.color !== undefined ) { - - 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( v3 ); - this.targetLine.scale.z = v3.length(); - - }; - - }(); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - shows frustum, line of sight and up of the camera - * - suitable for fast updates - * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html - */ - - function CameraHelper( camera ) { - - var geometry = new BufferGeometry(); - var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } ); - - var vertices = []; - var colors = []; - - var pointMap = {}; - - // colors - - var colorFrustum = new Color( 0xffaa00 ); - var colorCone = new Color( 0xff0000 ); - var colorUp = new Color( 0x00aaff ); - var colorTarget = new Color( 0xffffff ); - var colorCross = new Color( 0x333333 ); - - // near - - addLine( 'n1', 'n2', colorFrustum ); - addLine( 'n2', 'n4', colorFrustum ); - addLine( 'n4', 'n3', colorFrustum ); - addLine( 'n3', 'n1', colorFrustum ); - - // far - - addLine( 'f1', 'f2', colorFrustum ); - addLine( 'f2', 'f4', colorFrustum ); - addLine( 'f4', 'f3', colorFrustum ); - addLine( 'f3', 'f1', colorFrustum ); - - // sides - - addLine( 'n1', 'f1', colorFrustum ); - addLine( 'n2', 'f2', colorFrustum ); - addLine( 'n3', 'f3', colorFrustum ); - addLine( 'n4', 'f4', colorFrustum ); - - // cone - - addLine( 'p', 'n1', colorCone ); - addLine( 'p', 'n2', colorCone ); - addLine( 'p', 'n3', colorCone ); - addLine( 'p', 'n4', colorCone ); - - // up - - addLine( 'u1', 'u2', colorUp ); - addLine( 'u2', 'u3', colorUp ); - addLine( 'u3', 'u1', colorUp ); - - // target - - addLine( 'c', 't', colorTarget ); - addLine( 'p', 'c', colorCross ); - - // cross - - addLine( 'cn1', 'cn2', colorCross ); - addLine( 'cn3', 'cn4', colorCross ); - - addLine( 'cf1', 'cf2', colorCross ); - addLine( 'cf3', 'cf4', colorCross ); - - function addLine( a, b, color ) { - - addPoint( a, color ); - addPoint( b, color ); - - } - - function addPoint( id, color ) { - - vertices.push( 0, 0, 0 ); - colors.push( color.r, color.g, color.b ); - - if ( pointMap[ id ] === undefined ) { - - pointMap[ id ] = []; - - } - - pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); - - } - - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - LineSegments.call( this, geometry, material ); - - this.camera = camera; - if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); - - this.matrix = camera.matrixWorld; - this.matrixAutoUpdate = false; - - this.pointMap = pointMap; - - this.update(); - - } - - CameraHelper.prototype = Object.create( LineSegments.prototype ); - CameraHelper.prototype.constructor = CameraHelper; - - CameraHelper.prototype.update = function () { - - var geometry, pointMap; - - var vector = new Vector3(); - var camera = new Camera(); - - function setPoint( point, x, y, z ) { - - vector.set( x, y, z ).unproject( camera ); - - var points = pointMap[ point ]; - - if ( points !== undefined ) { - - var position = geometry.getAttribute( 'position' ); - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - position.setXYZ( points[ i ], vector.x, vector.y, vector.z ); - - } - - } - - } - - return function update() { - - geometry = this.geometry; - pointMap = this.pointMap; - - var w = 1, h = 1; - - // we need just camera projection matrix - // world matrix must be identity - - camera.projectionMatrix.copy( this.camera.projectionMatrix ); - - // center / target - - setPoint( 'c', 0, 0, - 1 ); - setPoint( 't', 0, 0, 1 ); - - // near - - setPoint( 'n1', - w, - h, - 1 ); - setPoint( 'n2', w, - h, - 1 ); - setPoint( 'n3', - w, h, - 1 ); - setPoint( 'n4', w, h, - 1 ); - - // far - - setPoint( 'f1', - w, - h, 1 ); - setPoint( 'f2', w, - h, 1 ); - setPoint( 'f3', - w, h, 1 ); - setPoint( 'f4', w, h, 1 ); - - // up - - setPoint( 'u1', w * 0.7, h * 1.1, - 1 ); - setPoint( 'u2', - w * 0.7, h * 1.1, - 1 ); - setPoint( 'u3', 0, h * 2, - 1 ); - - // cross - - setPoint( 'cf1', - w, 0, 1 ); - setPoint( 'cf2', w, 0, 1 ); - setPoint( 'cf3', 0, - h, 1 ); - setPoint( 'cf4', 0, h, 1 ); - - setPoint( 'cn1', - w, 0, - 1 ); - setPoint( 'cn2', w, 0, - 1 ); - setPoint( 'cn3', 0, - h, - 1 ); - setPoint( 'cn4', 0, h, - 1 ); - - geometry.getAttribute( 'position' ).needsUpdate = true; - - }; - - }(); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - */ - - function BoxHelper( object, color ) { - - this.object = object; - - if ( color === undefined ) color = 0xffff00; - - var 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 ] ); - var positions = new Float32Array( 8 * 3 ); - - var geometry = new BufferGeometry(); - geometry.setIndex( new BufferAttribute( indices, 1 ) ); - geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); - - this.matrixAutoUpdate = false; - - this.update(); - - } - - BoxHelper.prototype = Object.create( LineSegments.prototype ); - BoxHelper.prototype.constructor = BoxHelper; - - BoxHelper.prototype.update = ( function () { - - var box = new Box3(); - - return function update( object ) { - - if ( object !== undefined ) { - - console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); - - } - - if ( this.object !== undefined ) { - - box.setFromObject( this.object ); - - } - - if ( box.isEmpty() ) return; - - var min = box.min; - var max = box.max; - - /* - 5____4 - 1/___0/| - | 6__|_7 - 2/___3/ - - 0: max.x, max.y, max.z - 1: min.x, max.y, max.z - 2: min.x, min.y, max.z - 3: max.x, min.y, max.z - 4: max.x, max.y, min.z - 5: min.x, max.y, min.z - 6: min.x, min.y, min.z - 7: max.x, min.y, min.z - */ - - var position = this.geometry.attributes.position; - var array = position.array; - - array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; - array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; - array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; - array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; - array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; - array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; - array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; - array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; - - position.needsUpdate = true; - - this.geometry.computeBoundingSphere(); - - }; - - } )(); - - BoxHelper.prototype.setFromObject = function ( object ) { - - this.object = object; - this.update(); - - return this; - - }; - - /** - * @author WestLangley / http://github.com/WestLangley - */ - - function Box3Helper( box, hex ) { - - this.type = 'Box3Helper'; - - this.box = box; - - var color = ( hex !== undefined ) ? hex : 0xffff00; - - var 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 ] ); - - var 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 ]; - - var geometry = new BufferGeometry(); - - geometry.setIndex( new BufferAttribute( indices, 1 ) ); - - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); - - this.geometry.computeBoundingSphere(); - - } - - Box3Helper.prototype = Object.create( LineSegments.prototype ); - Box3Helper.prototype.constructor = Box3Helper; - - Box3Helper.prototype.updateMatrixWorld = function ( force ) { - - var box = this.box; - - if ( box.isEmpty() ) return; - - box.getCenter( this.position ); - - box.getSize( this.scale ); - - this.scale.multiplyScalar( 0.5 ); - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - }; - - /** - * @author WestLangley / http://github.com/WestLangley - */ - - function PlaneHelper( plane, size, hex ) { - - this.type = 'PlaneHelper'; - - this.plane = plane; - - this.size = ( size === undefined ) ? 1 : size; - - var color = ( hex !== undefined ) ? hex : 0xffff00; - - var 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, 0, 0, 1, 0, 0, 0 ]; - - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - geometry.computeBoundingSphere(); - - Line.call( this, geometry, new LineBasicMaterial( { color: color } ) ); - - // - - var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ]; - - var geometry2 = new BufferGeometry(); - geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); - geometry2.computeBoundingSphere(); - - this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) ); - - } - - PlaneHelper.prototype = Object.create( Line.prototype ); - PlaneHelper.prototype.constructor = PlaneHelper; - - PlaneHelper.prototype.updateMatrixWorld = function ( force ) { - - var scale = - this.plane.constant; - - if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter - - this.scale.set( 0.5 * this.size, 0.5 * this.size, scale ); - - this.lookAt( this.plane.normal ); - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - }; - - /** - * @author WestLangley / http://github.com/WestLangley - * @author zz85 / http://github.com/zz85 - * @author bhouston / http://clara.io - * - * Creates an arrow for visualizing directions - * - * Parameters: - * dir - Vector3 - * origin - Vector3 - * length - Number - * color - color in hex value - * headLength - Number - * headWidth - Number - */ - - var lineGeometry; - var coneGeometry; - - function ArrowHelper( dir, origin, length, color, headLength, headWidth ) { - - // dir is assumed to be normalized - - Object3D.call( this ); - - if ( color === undefined ) color = 0xffff00; - if ( length === undefined ) length = 1; - if ( headLength === undefined ) headLength = 0.2 * length; - if ( headWidth === undefined ) headWidth = 0.2 * headLength; - - if ( lineGeometry === undefined ) { - - lineGeometry = new BufferGeometry(); - lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); - - coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 ); - coneGeometry.translate( 0, - 0.5, 0 ); - - } - - this.position.copy( origin ); - - this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) ); - this.line.matrixAutoUpdate = false; - this.add( this.line ); - - this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) ); - this.cone.matrixAutoUpdate = false; - this.add( this.cone ); - - this.setDirection( dir ); - this.setLength( length, headLength, headWidth ); - - } - - ArrowHelper.prototype = Object.create( Object3D.prototype ); - ArrowHelper.prototype.constructor = ArrowHelper; - - ArrowHelper.prototype.setDirection = ( function () { - - var axis = new Vector3(); - var radians; - - return function setDirection( dir ) { - - // dir is assumed to be normalized - - 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(); - - radians = Math.acos( dir.y ); - - this.quaternion.setFromAxisAngle( axis, radians ); - - } - - }; - - }() ); - - ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) { - - if ( headLength === undefined ) headLength = 0.2 * length; - if ( headWidth === undefined ) headWidth = 0.2 * headLength; - - this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 ); - this.line.updateMatrix(); - - this.cone.scale.set( headWidth, headLength, headWidth ); - this.cone.position.y = length; - this.cone.updateMatrix(); - - }; - - ArrowHelper.prototype.setColor = function ( color ) { - - this.line.material.color.copy( color ); - this.cone.material.color.copy( color ); - - }; - - /** - * @author sroucheray / http://sroucheray.org/ - * @author mrdoob / http://mrdoob.com/ - */ - - function AxesHelper( size ) { - - size = size || 1; - - var vertices = [ - 0, 0, 0, size, 0, 0, - 0, 0, 0, 0, size, 0, - 0, 0, 0, 0, 0, size - ]; - - var colors = [ - 1, 0, 0, 1, 0.6, 0, - 0, 1, 0, 0.6, 1, 0, - 0, 0, 1, 0, 0.6, 1 - ]; - - var geometry = new BufferGeometry(); - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - var material = new LineBasicMaterial( { vertexColors: VertexColors } ); - - LineSegments.call( this, geometry, material ); - - } - - AxesHelper.prototype = Object.create( LineSegments.prototype ); - AxesHelper.prototype.constructor = AxesHelper; - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - var SceneUtils = { - - createMultiMaterialObject: function ( geometry, materials ) { - - var group = new Group(); - - for ( var i = 0, l = materials.length; i < l; i ++ ) { - - group.add( new Mesh( geometry, materials[ i ] ) ); - - } - - return group; - - }, - - detach: function ( child, parent, scene ) { - - child.applyMatrix( parent.matrixWorld ); - parent.remove( child ); - scene.add( child ); - - }, - - attach: function ( child, scene, parent ) { - - child.applyMatrix( new Matrix4().getInverse( parent.matrixWorld ) ); - - scene.remove( child ); - parent.add( child ); - - } - - }; - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function Face4( a, b, c, d, normal, color, materialIndex ) { - - console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' ); - return new Face3( a, b, c, normal, color, materialIndex ); - - } - - var LineStrip = 0; - - var LinePieces = 1; - - function MeshFaceMaterial( materials ) { - - console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' ); - return materials; - - } - - function MultiMaterial( materials ) { - - if ( materials === undefined ) materials = []; - - console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' ); - materials.isMultiMaterial = true; - materials.materials = materials; - materials.clone = function () { - - return materials.slice(); - - }; - return materials; - - } - - function PointCloud( geometry, material ) { - - console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' ); - return new Points$1( geometry, material ); - - } - - function Particle( material ) { - - console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' ); - return new Sprite( material ); - - } - - function ParticleSystem( geometry, material ) { - - console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' ); - return new Points$1( geometry, material ); - - } - - function PointCloudMaterial( parameters ) { - - console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); - - } - - function ParticleBasicMaterial( parameters ) { - - console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); - - } - - function ParticleSystemMaterial( parameters ) { - - console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' ); - return new PointsMaterial( parameters ); - - } - - function Vertex( x, y, z ) { - - console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' ); - return new Vector3( x, y, z ); - - } - - // - - function DynamicBufferAttribute( array, itemSize ) { - - console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' ); - return new BufferAttribute( array, itemSize ).setDynamic( true ); - - } - - function Int8Attribute( array, itemSize ) { - - console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' ); - return new Int8BufferAttribute( array, itemSize ); - - } - - function Uint8Attribute( array, itemSize ) { - - console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' ); - return new Uint8BufferAttribute( array, itemSize ); - - } - - function Uint8ClampedAttribute( array, itemSize ) { - - console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' ); - return new Uint8ClampedBufferAttribute( array, itemSize ); - - } - - function Int16Attribute( array, itemSize ) { - - console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' ); - return new Int16BufferAttribute( array, itemSize ); - - } - - function Uint16Attribute( array, itemSize ) { - - console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' ); - return new Uint16BufferAttribute( array, itemSize ); - - } - - function Int32Attribute( array, itemSize ) { - - console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' ); - return new Int32BufferAttribute( array, itemSize ); - - } - - function Uint32Attribute( array, itemSize ) { - - console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' ); - return new Uint32BufferAttribute( array, itemSize ); - - } - - function Float32Attribute( array, itemSize ) { - - console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' ); - return new Float32BufferAttribute( array, itemSize ); - - } - - function Float64Attribute( array, itemSize ) { - - console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' ); - return new Float64BufferAttribute( array, itemSize ); - - } - - // - - Curve.create = function ( construct, getPoint ) { - - console.log( 'THREE.Curve.create() has been deprecated' ); - - construct.prototype = Object.create( Curve.prototype ); - construct.prototype.constructor = construct; - construct.prototype.getPoint = getPoint; - - return construct; - - }; - - // - - Object.assign( CurvePath.prototype, { - - createPointsGeometry: function ( divisions ) { - - console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); - - // generate geometry from path points (for Line or Points objects) - - var pts = this.getPoints( divisions ); - return this.createGeometry( pts ); - - }, - - createSpacedPointsGeometry: function ( divisions ) { - - console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); - - // generate geometry from equidistant sampling along the path - - var pts = this.getSpacedPoints( divisions ); - return this.createGeometry( pts ); - - }, - - createGeometry: function ( points ) { - - console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); - - var geometry = new Geometry(); - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); - - } - - return geometry; - - } - - } ); - - // - - Object.assign( Path$1.prototype, { - - fromPoints: function ( points ) { - - console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' ); - this.setFromPoints( points ); - - } - - } ); - - // - - function ClosedSplineCurve3( points ) { - - console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' ); - - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; - this.closed = true; - - } - - ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype ); - - // - - function SplineCurve3( points ) { - - console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' ); - - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; - - } - - SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype ); - - // - - function Spline( points ) { - - console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' ); - - CatmullRomCurve3.call( this, points ); - this.type = 'catmullrom'; - - } - - Spline.prototype = Object.create( CatmullRomCurve3.prototype ); - - Object.assign( Spline.prototype, { - - initFromArray: function ( /* a */ ) { - - console.error( 'THREE.Spline: .initFromArray() has been removed.' ); - - }, - getControlPointsArray: function ( /* optionalTarget */ ) { - - console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' ); - - }, - reparametrizeByArcLength: function ( /* samplingCoef */ ) { - - console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' ); - - } - - } ); - - // - - function AxisHelper( size ) { - - console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' ); - return new AxesHelper( size ); - - } - - function BoundingBoxHelper( object, color ) { - - console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' ); - return new BoxHelper( object, color ); - - } - - function EdgesHelper( object, hex ) { - - console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' ); - return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) ); - - } - - GridHelper.prototype.setColors = function () { - - console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' ); - - }; - - SkeletonHelper.prototype.update = function () { - - console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' ); - - }; - - function WireframeHelper( object, hex ) { - - console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' ); - return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) ); - - } - - // - - Object.assign( Loader.prototype, { - - extractUrlBase: function ( url ) { - - console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' ); - return LoaderUtils.extractUrlBase( url ); - - } - - } ); - - function XHRLoader( manager ) { - - console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' ); - return new FileLoader( manager ); - - } - - function BinaryTextureLoader( manager ) { - - console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' ); - return new DataTextureLoader( manager ); - - } - - // - - Object.assign( Box2.prototype, { - - center: function ( optionalTarget ) { - - console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); - - }, - empty: function () { - - console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' ); - return this.isEmpty(); - - }, - isIntersectionBox: function ( box ) { - - console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); - - }, - size: function ( optionalTarget ) { - - console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' ); - return this.getSize( optionalTarget ); - - } - } ); - - Object.assign( Box3.prototype, { - - center: function ( optionalTarget ) { - - console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); - - }, - empty: function () { - - console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' ); - return this.isEmpty(); - - }, - isIntersectionBox: function ( box ) { - - console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); - - }, - isIntersectionSphere: function ( sphere ) { - - console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); - return this.intersectsSphere( sphere ); - - }, - size: function ( optionalTarget ) { - - console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' ); - return this.getSize( optionalTarget ); - - } - } ); - - Line3.prototype.center = function ( optionalTarget ) { - - console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' ); - return this.getCenter( optionalTarget ); - - }; - - Object.assign( _Math, { - - random16: function () { - - console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' ); - return Math.random(); - - }, - - nearestPowerOfTwo: function ( value ) { - - console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' ); - return _Math.floorPowerOfTwo( value ); - - }, - - nextPowerOfTwo: function ( value ) { - - console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' ); - return _Math.ceilPowerOfTwo( value ); - - } - - } ); - - Object.assign( Matrix3.prototype, { - - flattenToArrayOffset: function ( array, offset ) { - - console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); - return this.toArray( array, offset ); - - }, - multiplyVector3: function ( vector ) { - - console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' ); - return vector.applyMatrix3( this ); - - }, - multiplyVector3Array: function ( /* a */ ) { - - console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' ); - - }, - applyToBuffer: function ( buffer /*, offset, length */ ) { - - console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); - return this.applyToBufferAttribute( buffer ); - - }, - applyToVector3Array: function ( /* array, offset, length */ ) { - - console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' ); - - } - - } ); - - Object.assign( Matrix4.prototype, { - - extractPosition: function ( m ) { - - console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' ); - return this.copyPosition( m ); - - }, - flattenToArrayOffset: function ( array, offset ) { - - console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); - return this.toArray( array, offset ); - - }, - getPosition: function () { - - var v1; - - return function getPosition() { - - if ( v1 === undefined ) v1 = new Vector3(); - console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); - return v1.setFromMatrixColumn( this, 3 ); - - }; - - }(), - setRotationFromQuaternion: function ( q ) { - - console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); - return this.makeRotationFromQuaternion( q ); - - }, - multiplyToArray: function () { - - console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' ); - - }, - multiplyVector3: function ( vector ) { - - console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); - - }, - multiplyVector4: function ( vector ) { - - console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); - - }, - multiplyVector3Array: function ( /* a */ ) { - - console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' ); - - }, - rotateAxis: function ( v ) { - - console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); - v.transformDirection( this ); - - }, - crossVector: function ( vector ) { - - console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); - return vector.applyMatrix4( this ); - - }, - translate: function () { - - console.error( 'THREE.Matrix4: .translate() has been removed.' ); - - }, - rotateX: function () { - - console.error( 'THREE.Matrix4: .rotateX() has been removed.' ); - - }, - rotateY: function () { - - console.error( 'THREE.Matrix4: .rotateY() has been removed.' ); - - }, - rotateZ: function () { - - console.error( 'THREE.Matrix4: .rotateZ() has been removed.' ); - - }, - rotateByAxis: function () { - - console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); - - }, - applyToBuffer: function ( buffer /*, offset, length */ ) { - - console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); - return this.applyToBufferAttribute( buffer ); - - }, - applyToVector3Array: function ( /* array, offset, length */ ) { - - console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' ); - - }, - makeFrustum: function ( left, right, bottom, top, near, far ) { - - console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' ); - return this.makePerspective( left, right, top, bottom, near, far ); - - } - - } ); - - Plane.prototype.isIntersectionLine = function ( line ) { - - console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' ); - return this.intersectsLine( line ); - - }; - - Quaternion.prototype.multiplyVector3 = function ( vector ) { - - console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' ); - return vector.applyQuaternion( this ); - - }; - - Object.assign( Ray.prototype, { - - isIntersectionBox: function ( box ) { - - console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' ); - return this.intersectsBox( box ); - - }, - isIntersectionPlane: function ( plane ) { - - console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' ); - return this.intersectsPlane( plane ); - - }, - isIntersectionSphere: function ( sphere ) { - - console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); - return this.intersectsSphere( sphere ); - - } - - } ); - - Object.assign( Shape.prototype, { - - extractAllPoints: function ( divisions ) { - - console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' ); - return this.extractPoints( divisions ); - - }, - extrude: function ( options ) { - - console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' ); - return new ExtrudeGeometry( this, options ); - - }, - makeGeometry: function ( options ) { - - console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' ); - return new ShapeGeometry( this, options ); - - } - - } ); - - Object.assign( Vector2.prototype, { - - fromAttribute: function ( attribute, index, offset ) { - - console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); - - }, - distanceToManhattan: function ( v ) { - - console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); - return this.manhattanDistanceTo( v ); - - }, - lengthManhattan: function () { - - console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); - - } - - } ); - - Object.assign( Vector3.prototype, { - - setEulerFromRotationMatrix: function () { - - console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' ); - - }, - setEulerFromQuaternion: function () { - - console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' ); - - }, - getPositionFromMatrix: function ( m ) { - - console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' ); - return this.setFromMatrixPosition( m ); - - }, - getScaleFromMatrix: function ( m ) { - - console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' ); - return this.setFromMatrixScale( m ); - - }, - getColumnFromMatrix: function ( index, matrix ) { - - console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' ); - return this.setFromMatrixColumn( matrix, index ); - - }, - applyProjection: function ( m ) { - - console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' ); - return this.applyMatrix4( m ); - - }, - fromAttribute: function ( attribute, index, offset ) { - - console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); - - }, - distanceToManhattan: function ( v ) { - - console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); - return this.manhattanDistanceTo( v ); - - }, - lengthManhattan: function () { - - console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); - - } - - } ); - - Object.assign( Vector4.prototype, { - - fromAttribute: function ( attribute, index, offset ) { - - console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' ); - return this.fromBufferAttribute( attribute, index, offset ); - - }, - lengthManhattan: function () { - - console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' ); - return this.manhattanLength(); - - } - - } ); - - // - - Geometry.prototype.computeTangents = function () { - - console.warn( 'THREE.Geometry: .computeTangents() has been removed.' ); - - }; - - Object.assign( Object3D.prototype, { - - getChildByName: function ( name ) { - - console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' ); - return this.getObjectByName( name ); - - }, - renderDepth: function () { - - console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' ); - - }, - translate: function ( distance, axis ) { - - console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' ); - return this.translateOnAxis( axis, distance ); - - } - - } ); - - Object.defineProperties( Object3D.prototype, { - - eulerOrder: { - get: function () { - - console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); - return this.rotation.order; - - }, - set: function ( value ) { - - console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); - this.rotation.order = value; - - } - }, - useQuaternion: { - get: function () { - - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); - - }, - set: function () { - - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); - - } - } - - } ); - - Object.defineProperties( LOD.prototype, { - - objects: { - get: function () { - - console.warn( 'THREE.LOD: .objects has been renamed to .levels.' ); - return this.levels; - - } - } - - } ); - - Object.defineProperty( Skeleton.prototype, 'useVertexTexture', { - - get: function () { - - console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); - - }, - set: function () { - - console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); - - } - - } ); - - Object.defineProperty( Curve.prototype, '__arcLengthDivisions', { - - get: function () { - - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - return this.arcLengthDivisions; - - }, - set: function ( value ) { - - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - this.arcLengthDivisions = value; - - } - - } ); - - // - - PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) { - - console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " + - "Use .setFocalLength and .filmGauge for a photographic setup." ); - - if ( filmGauge !== undefined ) this.filmGauge = filmGauge; - this.setFocalLength( focalLength ); - - }; - - // - - Object.defineProperties( Light.prototype, { - onlyShadow: { - set: function () { - - console.warn( 'THREE.Light: .onlyShadow has been removed.' ); - - } - }, - shadowCameraFov: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' ); - this.shadow.camera.fov = value; - - } - }, - shadowCameraLeft: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' ); - this.shadow.camera.left = value; - - } - }, - shadowCameraRight: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' ); - this.shadow.camera.right = value; - - } - }, - shadowCameraTop: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' ); - this.shadow.camera.top = value; - - } - }, - shadowCameraBottom: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' ); - this.shadow.camera.bottom = value; - - } - }, - shadowCameraNear: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' ); - this.shadow.camera.near = value; - - } - }, - shadowCameraFar: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' ); - this.shadow.camera.far = value; - - } - }, - shadowCameraVisible: { - set: function () { - - console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' ); - - } - }, - shadowBias: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' ); - this.shadow.bias = value; - - } - }, - shadowDarkness: { - set: function () { - - console.warn( 'THREE.Light: .shadowDarkness has been removed.' ); - - } - }, - shadowMapWidth: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' ); - this.shadow.mapSize.width = value; - - } - }, - shadowMapHeight: { - set: function ( value ) { - - console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' ); - this.shadow.mapSize.height = value; - - } - } - } ); - - // - - Object.defineProperties( BufferAttribute.prototype, { - - length: { - get: function () { - - console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' ); - return this.array.length; - - } - } - - } ); - - Object.assign( BufferGeometry.prototype, { - - addIndex: function ( index ) { - - console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' ); - this.setIndex( index ); - - }, - addDrawCall: function ( start, count, indexOffset ) { - - if ( indexOffset !== undefined ) { - - console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' ); - - } - console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' ); - this.addGroup( start, count ); - - }, - clearDrawCalls: function () { - - console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' ); - this.clearGroups(); - - }, - computeTangents: function () { - - console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' ); - - }, - computeOffsets: function () { - - console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' ); - - } - - } ); - - Object.defineProperties( BufferGeometry.prototype, { - - drawcalls: { - get: function () { - - console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' ); - return this.groups; - - } - }, - offsets: { - get: function () { - - console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' ); - return this.groups; - - } - } - - } ); - - // - - Object.defineProperties( Uniform.prototype, { - - dynamic: { - set: function () { - - console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' ); - - } - }, - onUpdate: { - value: function () { - - console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' ); - return this; - - } - } - - } ); - - // - - Object.defineProperties( Material.prototype, { - - wrapAround: { - get: function () { - - console.warn( 'THREE.Material: .wrapAround has been removed.' ); - - }, - set: function () { - - console.warn( 'THREE.Material: .wrapAround has been removed.' ); - - } - }, - wrapRGB: { - get: function () { - - console.warn( 'THREE.Material: .wrapRGB has been removed.' ); - return new Color(); - - } - }, - - shading: { - get: function () { - - console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - - }, - set: function ( value ) { - - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( value === FlatShading ); - - } - } - - } ); - - Object.defineProperties( MeshPhongMaterial.prototype, { - - metal: { - get: function () { - - console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' ); - return false; - - }, - set: function () { - - console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' ); - - } - } - - } ); - - Object.defineProperties( ShaderMaterial.prototype, { - - derivatives: { - get: function () { - - console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); - return this.extensions.derivatives; - - }, - set: function ( value ) { - - console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); - this.extensions.derivatives = value; - - } - } - - } ); - - // - - Object.assign( WebGLRenderer.prototype, { - - getCurrentRenderTarget: function () { - - console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' ); - return this.getRenderTarget(); - - }, - - getMaxAnisotropy: function () { - - console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' ); - return this.capabilities.getMaxAnisotropy(); - - }, - - getPrecision: function () { - - console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' ); - return this.capabilities.precision; - - }, - - resetGLState: function () { - - console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' ); - return this.state.reset(); - - }, - - supportsFloatTextures: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' ); - return this.extensions.get( 'OES_texture_float' ); - - }, - supportsHalfFloatTextures: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' ); - return this.extensions.get( 'OES_texture_half_float' ); - - }, - supportsStandardDerivatives: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' ); - return this.extensions.get( 'OES_standard_derivatives' ); - - }, - supportsCompressedTextureS3TC: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' ); - return this.extensions.get( 'WEBGL_compressed_texture_s3tc' ); - - }, - supportsCompressedTexturePVRTC: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' ); - return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - - }, - supportsBlendMinMax: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' ); - return this.extensions.get( 'EXT_blend_minmax' ); - - }, - supportsVertexTextures: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' ); - return this.capabilities.vertexTextures; - - }, - supportsInstancedArrays: function () { - - console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' ); - return this.extensions.get( 'ANGLE_instanced_arrays' ); - - }, - enableScissorTest: function ( boolean ) { - - console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' ); - this.setScissorTest( boolean ); - - }, - initMaterial: function () { - - console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' ); - - }, - addPrePlugin: function () { - - console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' ); - - }, - addPostPlugin: function () { - - console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' ); - - }, - updateShadowMap: function () { - - console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' ); - - } - - } ); - - Object.defineProperties( WebGLRenderer.prototype, { - - shadowMapEnabled: { - get: function () { - - return this.shadowMap.enabled; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' ); - this.shadowMap.enabled = value; - - } - }, - shadowMapType: { - get: function () { - - return this.shadowMap.type; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' ); - this.shadowMap.type = value; - - } - }, - shadowMapCullFace: { - get: function () { - - return this.shadowMap.cullFace; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' ); - this.shadowMap.cullFace = value; - - } - } - } ); - - Object.defineProperties( WebGLShadowMap.prototype, { - - cullFace: { - get: function () { - - return this.renderReverseSided ? CullFaceFront : CullFaceBack; - - }, - set: function ( cullFace ) { - - var value = ( cullFace !== CullFaceBack ); - console.warn( "WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to " + value + "." ); - this.renderReverseSided = value; - - } - } - - } ); - - // - - Object.defineProperties( WebGLRenderTarget.prototype, { - - wrapS: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); - return this.texture.wrapS; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); - this.texture.wrapS = value; - - } - }, - wrapT: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); - return this.texture.wrapT; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); - this.texture.wrapT = value; - - } - }, - magFilter: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); - return this.texture.magFilter; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); - this.texture.magFilter = value; - - } - }, - minFilter: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); - return this.texture.minFilter; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); - this.texture.minFilter = value; - - } - }, - anisotropy: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); - return this.texture.anisotropy; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); - this.texture.anisotropy = value; - - } - }, - offset: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); - return this.texture.offset; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); - this.texture.offset = value; - - } - }, - repeat: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); - return this.texture.repeat; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); - this.texture.repeat = value; - - } - }, - format: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); - return this.texture.format; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); - this.texture.format = value; - - } - }, - type: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); - return this.texture.type; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); - this.texture.type = value; - - } - }, - generateMipmaps: { - get: function () { - - console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); - return this.texture.generateMipmaps; - - }, - set: function ( value ) { - - console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); - this.texture.generateMipmaps = value; - - } - } - - } ); - - // - - Object.assign( WebVRManager.prototype, { - - getStandingMatrix: function () { - - console.warn( 'THREE.WebVRManager: .getStandingMatrix() has been removed.' ); - - } - - } ); - - Object.defineProperties( WebVRManager.prototype, { - - standing: { - set: function ( /* value */ ) { - - console.warn( 'THREE.WebVRManager: .standing has been removed.' ); - - } - } - - } ); - - // - - Audio.prototype.load = function ( file ) { - - console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' ); - var scope = this; - var audioLoader = new AudioLoader(); - audioLoader.load( file, function ( buffer ) { - - scope.setBuffer( buffer ); - - } ); - return this; - - }; - - AudioAnalyser.prototype.getData = function () { - - console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' ); - return this.getFrequencyData(); - - }; - - // - - CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) { - - console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' ); - return this.update( renderer, scene ); - - }; - - // - - var GeometryUtils = { - - merge: function ( geometry1, geometry2, materialIndexOffset ) { - - console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); - var matrix; - - if ( geometry2.isMesh ) { - - geometry2.matrixAutoUpdate && geometry2.updateMatrix(); - - matrix = geometry2.matrix; - geometry2 = geometry2.geometry; - - } - - geometry1.merge( geometry2, matrix, materialIndexOffset ); - - }, - - center: function ( geometry ) { - - console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); - return geometry.center(); - - } - - }; - - var ImageUtils = { - - crossOrigin: undefined, - - loadTexture: function ( url, mapping, onLoad, onError ) { - - console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' ); - - var loader = new TextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); - - var texture = loader.load( url, onLoad, undefined, onError ); - - if ( mapping ) texture.mapping = mapping; - - return texture; - - }, - - loadTextureCube: function ( urls, mapping, onLoad, onError ) { - - console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' ); - - var loader = new CubeTextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); - - var texture = loader.load( urls, onLoad, undefined, onError ); - - if ( mapping ) texture.mapping = mapping; - - return texture; - - }, - - loadCompressedTexture: function () { - - console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ); - - }, - - loadCompressedTextureCube: function () { - - console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ); - - } - - }; - - // - - function Projector() { - - console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' ); - - this.projectVector = function ( vector, camera ) { - - console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); - vector.project( camera ); - - }; - - this.unprojectVector = function ( vector, camera ) { - - console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); - vector.unproject( camera ); - - }; - - this.pickingRay = function () { - - console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' ); - - }; - - } - - // - - function CanvasRenderer() { - - console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' ); - - this.domElement = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - this.clear = function () {}; - this.render = function () {}; - this.setClearColor = function () {}; - this.setSize = function () {}; - - } - - var THREE$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - WebGLRenderTargetCube: WebGLRenderTargetCube, - WebGLRenderTarget: WebGLRenderTarget, - WebGLRenderer: WebGLRenderer, - ShaderLib: ShaderLib, - UniformsLib: UniformsLib, - UniformsUtils: UniformsUtils, - ShaderChunk: ShaderChunk, - FogExp2: FogExp2, - Fog: Fog, - Scene: Scene, - LensFlare: LensFlare, - Sprite: Sprite, - LOD: LOD, - SkinnedMesh: SkinnedMesh, - Skeleton: Skeleton, - Bone: Bone, - Mesh: Mesh, - LineSegments: LineSegments, - LineLoop: LineLoop, - Line: Line, - Points: Points$1, - Group: Group, - VideoTexture: VideoTexture, - DataTexture: DataTexture, - CompressedTexture: CompressedTexture, - CubeTexture: CubeTexture, - CanvasTexture: CanvasTexture, - DepthTexture: DepthTexture, - Texture: Texture, - CompressedTextureLoader: CompressedTextureLoader, - DataTextureLoader: DataTextureLoader, - CubeTextureLoader: CubeTextureLoader, - TextureLoader: TextureLoader, - ObjectLoader: ObjectLoader, - MaterialLoader: MaterialLoader, - BufferGeometryLoader: BufferGeometryLoader, - DefaultLoadingManager: DefaultLoadingManager, - LoadingManager: LoadingManager, - JSONLoader: JSONLoader, - ImageLoader: ImageLoader, - ImageBitmapLoader: ImageBitmapLoader, - FontLoader: FontLoader, - FileLoader: FileLoader, - Loader: Loader, - LoaderUtils: LoaderUtils, - Cache: Cache, - AudioLoader: AudioLoader, - SpotLightShadow: SpotLightShadow, - SpotLight: SpotLight, - PointLight: PointLight, - RectAreaLight: RectAreaLight, - HemisphereLight: HemisphereLight, - DirectionalLightShadow: DirectionalLightShadow, - DirectionalLight: DirectionalLight, - AmbientLight: AmbientLight, - LightShadow: LightShadow, - Light: Light, - StereoCamera: StereoCamera, - PerspectiveCamera: PerspectiveCamera, - OrthographicCamera: OrthographicCamera, - CubeCamera: CubeCamera, - ArrayCamera: ArrayCamera, - Camera: Camera, - AudioListener: AudioListener, - PositionalAudio: PositionalAudio, - AudioContext: AudioContext, - AudioAnalyser: AudioAnalyser, - Audio: Audio, - VectorKeyframeTrack: VectorKeyframeTrack, - StringKeyframeTrack: StringKeyframeTrack, - QuaternionKeyframeTrack: QuaternionKeyframeTrack, - NumberKeyframeTrack: NumberKeyframeTrack, - ColorKeyframeTrack: ColorKeyframeTrack, - BooleanKeyframeTrack: BooleanKeyframeTrack, - PropertyMixer: PropertyMixer, - PropertyBinding: PropertyBinding, - KeyframeTrack: KeyframeTrack, - AnimationUtils: AnimationUtils, - AnimationObjectGroup: AnimationObjectGroup, - AnimationMixer: AnimationMixer, - AnimationClip: AnimationClip, - Uniform: Uniform, - InstancedBufferGeometry: InstancedBufferGeometry, - BufferGeometry: BufferGeometry, - Geometry: Geometry, - InterleavedBufferAttribute: InterleavedBufferAttribute, - InstancedInterleavedBuffer: InstancedInterleavedBuffer, - InterleavedBuffer: InterleavedBuffer, - InstancedBufferAttribute: InstancedBufferAttribute, - Face3: Face3, - Object3D: Object3D, - Raycaster: Raycaster, - Layers: Layers, - EventDispatcher: EventDispatcher, - Clock: Clock, - QuaternionLinearInterpolant: QuaternionLinearInterpolant, - LinearInterpolant: LinearInterpolant, - DiscreteInterpolant: DiscreteInterpolant, - CubicInterpolant: CubicInterpolant, - Interpolant: Interpolant, - Triangle: Triangle, - Math: _Math, - Spherical: Spherical, - Cylindrical: Cylindrical, - Plane: Plane, - Frustum: Frustum, - Sphere: Sphere, - Ray: Ray, - Matrix4: Matrix4, - Matrix3: Matrix3, - Box3: Box3, - Box2: Box2, - Line3: Line3, - Euler: Euler, - Vector4: Vector4, - Vector3: Vector3, - Vector2: Vector2, - Quaternion: Quaternion, - Color: Color, - ImmediateRenderObject: ImmediateRenderObject, - VertexNormalsHelper: VertexNormalsHelper, - SpotLightHelper: SpotLightHelper, - SkeletonHelper: SkeletonHelper, - PointLightHelper: PointLightHelper, - RectAreaLightHelper: RectAreaLightHelper, - HemisphereLightHelper: HemisphereLightHelper, - GridHelper: GridHelper, - PolarGridHelper: PolarGridHelper, - FaceNormalsHelper: FaceNormalsHelper, - DirectionalLightHelper: DirectionalLightHelper, - CameraHelper: CameraHelper, - BoxHelper: BoxHelper, - Box3Helper: Box3Helper, - PlaneHelper: PlaneHelper, - ArrowHelper: ArrowHelper, - AxesHelper: AxesHelper, - Shape: Shape, - Path: Path$1, - ShapePath: ShapePath, - Font: Font, - CurvePath: CurvePath, - Curve: Curve, - ShapeUtils: ShapeUtils, - SceneUtils: SceneUtils, - WebGLUtils: WebGLUtils, - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry, - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material, - Float64BufferAttribute: Float64BufferAttribute, - Float32BufferAttribute: Float32BufferAttribute, - Uint32BufferAttribute: Uint32BufferAttribute, - Int32BufferAttribute: Int32BufferAttribute, - Uint16BufferAttribute: Uint16BufferAttribute, - Int16BufferAttribute: Int16BufferAttribute, - Uint8ClampedBufferAttribute: Uint8ClampedBufferAttribute, - Uint8BufferAttribute: Uint8BufferAttribute, - Int8BufferAttribute: Int8BufferAttribute, - BufferAttribute: BufferAttribute, - ArcCurve: ArcCurve, - CatmullRomCurve3: CatmullRomCurve3, - CubicBezierCurve: CubicBezierCurve, - CubicBezierCurve3: CubicBezierCurve3, - EllipseCurve: EllipseCurve, - LineCurve: LineCurve, - LineCurve3: LineCurve3, - QuadraticBezierCurve: QuadraticBezierCurve, - QuadraticBezierCurve3: QuadraticBezierCurve3, - SplineCurve: SplineCurve, - REVISION: REVISION, - MOUSE: MOUSE, - CullFaceNone: CullFaceNone, - CullFaceBack: CullFaceBack, - CullFaceFront: CullFaceFront, - CullFaceFrontBack: CullFaceFrontBack, - FrontFaceDirectionCW: FrontFaceDirectionCW, - FrontFaceDirectionCCW: FrontFaceDirectionCCW, - BasicShadowMap: BasicShadowMap, - PCFShadowMap: PCFShadowMap, - PCFSoftShadowMap: PCFSoftShadowMap, - FrontSide: FrontSide, - BackSide: BackSide, - DoubleSide: DoubleSide, - FlatShading: FlatShading, - SmoothShading: SmoothShading, - NoColors: NoColors, - FaceColors: FaceColors, - VertexColors: VertexColors, - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending, - AddEquation: AddEquation, - SubtractEquation: SubtractEquation, - ReverseSubtractEquation: ReverseSubtractEquation, - MinEquation: MinEquation, - MaxEquation: MaxEquation, - ZeroFactor: ZeroFactor, - OneFactor: OneFactor, - SrcColorFactor: SrcColorFactor, - OneMinusSrcColorFactor: OneMinusSrcColorFactor, - SrcAlphaFactor: SrcAlphaFactor, - OneMinusSrcAlphaFactor: OneMinusSrcAlphaFactor, - DstAlphaFactor: DstAlphaFactor, - OneMinusDstAlphaFactor: OneMinusDstAlphaFactor, - DstColorFactor: DstColorFactor, - OneMinusDstColorFactor: OneMinusDstColorFactor, - SrcAlphaSaturateFactor: SrcAlphaSaturateFactor, - NeverDepth: NeverDepth, - AlwaysDepth: AlwaysDepth, - LessDepth: LessDepth, - LessEqualDepth: LessEqualDepth, - EqualDepth: EqualDepth, - GreaterEqualDepth: GreaterEqualDepth, - GreaterDepth: GreaterDepth, - NotEqualDepth: NotEqualDepth, - MultiplyOperation: MultiplyOperation, - MixOperation: MixOperation, - AddOperation: AddOperation, - NoToneMapping: NoToneMapping, - LinearToneMapping: LinearToneMapping, - ReinhardToneMapping: ReinhardToneMapping, - Uncharted2ToneMapping: Uncharted2ToneMapping, - CineonToneMapping: CineonToneMapping, - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping, - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping, - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter, - UnsignedByteType: UnsignedByteType, - ByteType: ByteType, - ShortType: ShortType, - UnsignedShortType: UnsignedShortType, - IntType: IntType, - UnsignedIntType: UnsignedIntType, - FloatType: FloatType, - HalfFloatType: HalfFloatType, - UnsignedShort4444Type: UnsignedShort4444Type, - UnsignedShort5551Type: UnsignedShort5551Type, - UnsignedShort565Type: UnsignedShort565Type, - UnsignedInt248Type: UnsignedInt248Type, - AlphaFormat: AlphaFormat, - RGBFormat: RGBFormat, - RGBAFormat: RGBAFormat, - LuminanceFormat: LuminanceFormat, - LuminanceAlphaFormat: LuminanceAlphaFormat, - RGBEFormat: RGBEFormat, - DepthFormat: DepthFormat, - DepthStencilFormat: DepthStencilFormat, - RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format, - RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format, - RGBA_S3TC_DXT3_Format: RGBA_S3TC_DXT3_Format, - RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format, - RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format, - RGB_PVRTC_2BPPV1_Format: RGB_PVRTC_2BPPV1_Format, - RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format, - RGBA_PVRTC_2BPPV1_Format: RGBA_PVRTC_2BPPV1_Format, - RGB_ETC1_Format: RGB_ETC1_Format, - LoopOnce: LoopOnce, - LoopRepeat: LoopRepeat, - LoopPingPong: LoopPingPong, - InterpolateDiscrete: InterpolateDiscrete, - InterpolateLinear: InterpolateLinear, - InterpolateSmooth: InterpolateSmooth, - ZeroCurvatureEnding: ZeroCurvatureEnding, - ZeroSlopeEnding: ZeroSlopeEnding, - WrapAroundEnding: WrapAroundEnding, - TrianglesDrawMode: TrianglesDrawMode, - TriangleStripDrawMode: TriangleStripDrawMode, - TriangleFanDrawMode: TriangleFanDrawMode, - LinearEncoding: LinearEncoding, - sRGBEncoding: sRGBEncoding, - GammaEncoding: GammaEncoding, - RGBEEncoding: RGBEEncoding, - LogLuvEncoding: LogLuvEncoding, - RGBM7Encoding: RGBM7Encoding, - RGBM16Encoding: RGBM16Encoding, - RGBDEncoding: RGBDEncoding, - BasicDepthPacking: BasicDepthPacking, - RGBADepthPacking: RGBADepthPacking, - CubeGeometry: BoxGeometry, - Face4: Face4, - LineStrip: LineStrip, - LinePieces: LinePieces, - MeshFaceMaterial: MeshFaceMaterial, - MultiMaterial: MultiMaterial, - PointCloud: PointCloud, - Particle: Particle, - ParticleSystem: ParticleSystem, - PointCloudMaterial: PointCloudMaterial, - ParticleBasicMaterial: ParticleBasicMaterial, - ParticleSystemMaterial: ParticleSystemMaterial, - Vertex: Vertex, - DynamicBufferAttribute: DynamicBufferAttribute, - Int8Attribute: Int8Attribute, - Uint8Attribute: Uint8Attribute, - Uint8ClampedAttribute: Uint8ClampedAttribute, - Int16Attribute: Int16Attribute, - Uint16Attribute: Uint16Attribute, - Int32Attribute: Int32Attribute, - Uint32Attribute: Uint32Attribute, - Float32Attribute: Float32Attribute, - Float64Attribute: Float64Attribute, - ClosedSplineCurve3: ClosedSplineCurve3, - SplineCurve3: SplineCurve3, - Spline: Spline, - AxisHelper: AxisHelper, - BoundingBoxHelper: BoundingBoxHelper, - EdgesHelper: EdgesHelper, - WireframeHelper: WireframeHelper, - XHRLoader: XHRLoader, - BinaryTextureLoader: BinaryTextureLoader, - GeometryUtils: GeometryUtils, - ImageUtils: ImageUtils, - Projector: Projector, - CanvasRenderer: CanvasRenderer - }); - - var THREE = Object.assign({}, THREE$1); - - // Marker types - var MARKER_ARROW = 0; - var MARKER_CUBE = 1; - var MARKER_SPHERE = 2; - var MARKER_CYLINDER = 3; - var MARKER_LINE_STRIP = 4; - var MARKER_LINE_LIST = 5; - var MARKER_CUBE_LIST = 6; - var MARKER_SPHERE_LIST = 7; - var MARKER_POINTS = 8; - var MARKER_TEXT_VIEW_FACING = 9; - var MARKER_MESH_RESOURCE = 10; - var MARKER_TRIANGLE_LIST = 11; - - // Interactive marker feedback types - var INTERACTIVE_MARKER_KEEP_ALIVE = 0; - var INTERACTIVE_MARKER_POSE_UPDATE = 1; - var INTERACTIVE_MARKER_MENU_SELECT = 2; - var INTERACTIVE_MARKER_BUTTON_CLICK = 3; - var INTERACTIVE_MARKER_MOUSE_DOWN = 4; - var INTERACTIVE_MARKER_MOUSE_UP = 5; - - // Interactive marker control types - var INTERACTIVE_MARKER_NONE = 0; - var INTERACTIVE_MARKER_MENU = 1; - var INTERACTIVE_MARKER_BUTTON = 2; - var INTERACTIVE_MARKER_MOVE_AXIS = 3; - var INTERACTIVE_MARKER_MOVE_PLANE = 4; - var INTERACTIVE_MARKER_ROTATE_AXIS = 5; - var INTERACTIVE_MARKER_MOVE_ROTATE = 6; - var INTERACTIVE_MARKER_MOVE_3D = 7; - var INTERACTIVE_MARKER_ROTATE_3D = 8; - var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; - - // Interactive marker rotation behavior - var INTERACTIVE_MARKER_INHERIT = 0; - var INTERACTIVE_MARKER_FIXED = 1; - var INTERACTIVE_MARKER_VIEW_FACING = 2; - - /** - * @function makeColorMaterial - * @description Create a THREE material based on the given RGBA values. - * - * @param r - the red value - * @param g - the green value - * @param b - the blue value - * @param a - the alpha value - * @returns the THREE material - */ - var makeColorMaterial = function(r, g, b, a) { - var color = new THREE.Color(); - color.setRGB(r, g, b); - if (a <= 0.99) { - return new THREE.MeshBasicMaterial({ - color : color.getHex(), - opacity : a + 0.1, - transparent : true, - depthWrite : true, - blendSrc : THREE.SrcAlphaFactor, - blendDst : THREE.OneMinusSrcAlphaFactor, - blendEquation : THREE.ReverseSubtractEquation, - blending : THREE.NormalBlending - }); - } else { - return new THREE.MeshPhongMaterial({ - color : color.getHex(), - opacity : a, - blending : THREE.NormalBlending - }); - } - }; - - /** - * @function intersectPlane - * @description Return the intersection between the mouseray and the plane. - * - * @param mouseRay - the mouse ray - * @param planeOrigin - the origin of the plane - * @param planeNormal - the normal of the plane - * @returns the intersection point - */ - var intersectPlane = function(mouseRay, planeOrigin, planeNormal) { - var vector = new THREE.Vector3(); - var intersectPoint = new THREE.Vector3(); - vector.subVectors(planeOrigin, mouseRay.origin); - var dot = mouseRay.direction.dot(planeNormal); - - // bail if ray and plane are parallel - if (Math.abs(dot) < mouseRay.precision) { - return undefined; - } - - // calc distance to plane - var scalar = planeNormal.dot(vector) / dot; - - intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); - return intersectPoint; - }; - - /** - * @function findClosestPoint - * @description Find the closest point on targetRay to any point on mouseRay. Math taken from - * http://paulbourke.net/geometry/lineline3d/ - * - * @param targetRay - the target ray to use - * @param mouseRay - the mouse ray - * @param the closest point between the two rays - */ - var findClosestPoint = function(targetRay, mouseRay) { - var v13 = new THREE.Vector3(); - v13.subVectors(targetRay.origin, mouseRay.origin); - var v43 = mouseRay.direction.clone(); - var v21 = targetRay.direction.clone(); - var d1343 = v13.dot(v43); - var d4321 = v43.dot(v21); - var d1321 = v13.dot(v21); - var d4343 = v43.dot(v43); - var d2121 = v21.dot(v21); - - var denom = d2121 * d4343 - d4321 * d4321; - // check within a delta - if (Math.abs(denom) <= 0.0001) { - return undefined; - } - var numer = d1343 * d4321 - d1321 * d4343; - - var mua = numer / denom; - return mua; - }; - - /** - * @function closestAxisPoint - * @description Find the closest point between the axis and the mouse. - * - * @param axisRay - the ray from the axis - * @param camera - the camera to project from - * @param mousePos - the mouse position - * @returns the closest axis point - */ - var closestAxisPoint = function(axisRay, camera, mousePos) { - // project axis onto screen - var o = axisRay.origin.clone(); - o.project(camera); - var o2 = axisRay.direction.clone().add(axisRay.origin); - o2.project(camera); - - // d is the axis vector in screen space (d = o2-o) - var d = o2.clone().sub(o); - - // t is the 2d ray param of perpendicular projection of mousePos onto o - var tmp = new THREE.Vector2(); - // (t = (mousePos - o) * d / (d*d)) - var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); - - // mp is the final 2d-projected mouse pos (mp = o + d*t) - var mp = new THREE.Vector2(); - mp.addVectors(o, d.clone().multiplyScalar(t)); - - // go back to 3d by shooting a ray - var vector = new THREE.Vector3(mp.x, mp.y, 0.5); - vector.unproject(camera); - var mpRay = new THREE.Ray(camera.position, vector.sub(camera.position).normalize()); - - return findClosestPoint(axisRay, mpRay); - }; - - /** - * @fileOverview - * @author Julius Kammerl - jkammerl@willowgarage.com - */ - - class DepthCloud extends THREE.Object3D { - - /** - * The DepthCloud object. - * - * @constructor - * @param options - object with following keys: - * - * * url - the URL of the stream - * * streamType (optional) - the stream type: mjpeg or vp8 video (defaults to vp8) - * * f (optional) - the camera's focal length (defaults to standard Kinect calibration) - * * maxDepthPerTile (optional) - the factor with which we control the desired depth range (defaults to 1.0) - * * pointSize (optional) - point size (pixels) for rendered point cloud - * * width (optional) - width of the video stream - * * height (optional) - height of the video stream - * * whiteness (optional) - blends rgb values to white (0..100) - * * varianceThreshold (optional) - threshold for variance filter, used for compression artifact removal - */ - constructor(options) { - super(); - options = options || {}; - - this.url = options.url; - this.streamType = options.streamType || 'vp8'; - this.f = options.f || 526; - this.maxDepthPerTile = options.maxDepthPerTile || 1.0; - this.pointSize = options.pointSize || 3; - this.width = options.width || 1024; - this.height = options.height || 1024; - this.resolutionFactor = Math.max(this.width, this.height) / 1024; - this.whiteness = options.whiteness || 0; - this.varianceThreshold = options.varianceThreshold || 0.000016667; - - this.isMjpeg = this.streamType.toLowerCase() === 'mjpeg'; - - this.video = document.createElement(this.isMjpeg ? 'img' : 'video'); - this.video.crossOrigin = 'Anonymous'; - this.video.addEventListener(this.isMjpeg ? 'load' : 'loadedmetadata', this.metaLoaded.bind(this), false); - - if (!this.isMjpeg) { - this.video.loop = true; - } - - this.video.src = this.url; - this.video.setAttribute('crossorigin', 'Anonymous'); - - // define custom shaders - this.vertex_shader = [ - 'uniform sampler2D map;', - '', - 'uniform float width;', - 'uniform float height;', - 'uniform float nearClipping, farClipping;', - '', - 'uniform float pointSize;', - 'uniform float zOffset;', - '', - 'uniform float focallength;', - 'uniform float maxDepthPerTile;', - 'uniform float resolutionFactor;', - '', - 'varying vec2 vUvP;', - 'varying vec2 colorP;', - '', - 'varying float depthVariance;', - 'varying float maskVal;', - '', - 'float sampleDepth(vec2 pos)', - ' {', - ' float depth;', - ' ', - ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', - ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', - ' ', - ' vec4 depthColor = texture2D( map, vUv );', - ' ', - ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', - ' ', - ' if (depth>0.99)', - ' {', - ' vec4 depthColor2 = texture2D( map, vUv2 );', - ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', - ' depth = 0.99+depth2;', - ' }', - ' ', - ' return depth;', - ' }', - '', - 'float median(float a, float b, float c)', - ' {', - ' float r=a;', - ' ', - ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', - ' {', - ' vec2 smp = decodeDepth(vec2(position.x, position.y));', - ' float depth = smp.x;', - ' depthVariance = smp.y;', - ' ', - ' float z = -depth;', - ' ', - ' pos = vec4(', - ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', - ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', - ' (- z + zOffset / 1000.0) * maxDepthPerTile,', - ' 1.0);', - ' ', - ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', - ' vec4 maskColor = texture2D( map, maskP );', - ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', - ' }', - ' ', - ' gl_PointSize = pointSize;', - ' gl_Position = projectionMatrix * modelViewMatrix * pos;', - ' ', - '}' - ].join('\n'); - - this.fragment_shader = [ - 'uniform sampler2D map;', - 'uniform float varianceThreshold;', - 'uniform float whiteness;', - '', - 'varying vec2 vUvP;', - 'varying vec2 colorP;', - '', - 'varying float depthVariance;', - 'varying float maskVal;', - '', - '', - 'void main() {', - ' ', - ' vec4 color;', - ' ', - ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', - ' { ', - ' discard;', - ' }', - ' else ', - ' {', - ' color = texture2D( map, colorP );', - ' ', - ' float fader = whiteness /100.0;', - ' ', - ' color.r = color.r * (1.0-fader)+ fader;', - ' ', - ' color.g = color.g * (1.0-fader)+ fader;', - ' ', - ' color.b = color.b * (1.0-fader)+ fader;', - ' ', - ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', - ' }', - ' ', - ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', - ' ', - '}' - ].join('\n'); - }; - - /** - * Callback called when video metadata is ready - */ - metaLoaded() { - this.metaLoaded = true; - this.initStreamer(); - }; - - /** - * Callback called when video metadata is ready - */ - initStreamer() { - - if (this.metaLoaded) { - this.texture = new THREE.Texture(this.video); - this.geometry = new THREE.Geometry(); - - for (var i = 0, l = this.width * this.height; i < l; i++) { - - var vertex = new THREE.Vector3(); - vertex.x = (i % this.width); - vertex.y = Math.floor(i / this.width); - - this.geometry.vertices.push(vertex); - } - - this.material = new THREE.ShaderMaterial({ - uniforms : { - 'map' : { - type : 't', - value : this.texture - }, - 'width' : { - type : 'f', - value : this.width - }, - 'height' : { - type : 'f', - value : this.height - }, - 'focallength' : { - type : 'f', - value : this.f - }, - 'pointSize' : { - type : 'f', - value : this.pointSize - }, - 'zOffset' : { - type : 'f', - value : 0 - }, - 'whiteness' : { - type : 'f', - value : this.whiteness - }, - 'varianceThreshold' : { - type : 'f', - value : this.varianceThreshold - }, - 'maxDepthPerTile': { - type : 'f', - value : this.maxDepthPerTile - }, - 'resolutionFactor': { - type : 'f', - value : this.resolutionFactor - }, - }, - vertexShader : this.vertex_shader, - fragmentShader : this.fragment_shader - }); - - this.mesh = new THREE.ParticleSystem(this.geometry, this.material); - this.mesh.position.x = 0; - this.mesh.position.y = 0; - this.add(this.mesh); - - setInterval(() => { - if (this.isMjpeg || this.video.readyState === this.video.HAVE_ENOUGH_DATA) { - this.texture.needsUpdate = true; - } - }, 1000 / 30); - } - }; - - /** - * Start video playback - */ - startStream() { - if (!this.isMjpeg) { - this.video.play(); - } - }; - - /** - * Stop video playback - */ - stopStream() { - if (!this.isMjpeg) { - this.video.pause(); - } - }; - } - - /** - * @fileOverview - * @author David Gossow - dgossow@willowgarage.com - */ - - class Arrow extends THREE.Mesh { - - /** - * A Arrow is a THREE object that can be used to display an arrow model. - * - * @constructor - * @param options - object with following keys: - * - * * origin (optional) - the origin of the arrow - * * direction (optional) - the direction vector of the arrow - * * length (optional) - the length of the arrow - * * headLength (optional) - the head length of the arrow - * * shaftDiameter (optional) - the shaft diameter of the arrow - * * headDiameter (optional) - the head diameter of the arrow - * * material (optional) - the material to use for this arrow - */ - constructor(options) { - options = options || {}; - var origin = options.origin || new THREE.Vector3(0, 0, 0); - var direction = options.direction || new THREE.Vector3(1, 0, 0); - var length = options.length || 1; - var headLength = options.headLength || 0.2; - var shaftDiameter = options.shaftDiameter || 0.05; - var headDiameter = options.headDiameter || 0.1; - var material = options.material || new THREE.MeshBasicMaterial(); - - var shaftLength = length - headLength; - - // create and merge geometry - var geometry = new THREE.CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, - 12, 1); - var m = new THREE.Matrix4(); - m.setPosition(new THREE.Vector3(0, shaftLength * 0.5, 0)); - geometry.applyMatrix(m); - - // create the head - var coneGeometry = new THREE.CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); - m.setPosition(new THREE.Vector3(0, shaftLength + (headLength * 0.5), 0)); - coneGeometry.applyMatrix(m); - - // put the arrow together - geometry.merge(coneGeometry); - - super(geometry, material); - - this.position.copy(origin); - this.setDirection(direction); - }; - - /** - * Set the direction of this arrow to that of the given vector. - * - * @param direction - the direction to set this arrow - */ - setDirection(direction) { - var axis = new THREE.Vector3(); - if(direction.x === 0 && direction.z === 0){ - axis.set(1, 0, 0); - } else { - axis.set(0, 1, 0).cross(direction); - } - var radians = Math.acos(new THREE.Vector3(0, 1, 0).dot(direction.clone().normalize())); - this.matrix = new THREE.Matrix4().makeRotationAxis(axis.normalize(), radians); - this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); - }; - - /** - * Set this arrow to be the given length. - * - * @param length - the new length of the arrow - */ - setLength(length) { - this.scale.set(length, length, length); - }; - - /** - * Set the color of this arrow to the given hex value. - * - * @param hex - the hex value of the color to use - */ - setColor(hex) { - this.material.color.setHex(hex); - }; - - /* - * Free memory of elements in this marker. - */ - dispose() { - if (this.geometry !== undefined) { - this.geometry.dispose(); - } - if (this.material !== undefined) { - this.material.dispose(); - } - }; - } - - /** - * @fileOverview - * @author aleeper / http://adamleeper.com/ - * @author mrdoob / http://mrdoob.com/ - * @author gero3 / https://github.com/gero3 - * @author Mugen87 / https://github.com/Mugen87 - * - * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. - * - * Supports both binary and ASCII encoded files, with automatic detection of type. - * - * The loader returns a non-indexed buffer geometry. - * - * Limitations: - * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). - * There is perhaps some question as to how valid it is to always assume little-endian-ness. - * ASCII decoding assumes file is UTF-8. - * - * Usage: - * var loader = new THREE.STLLoader(); - * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { - * scene.add( new THREE.Mesh( geometry ) ); - * }); - * - * For binary STLs geometry might contain colors for vertices. To use it: - * // use the same code to load STL as above - * if (geometry.hasColors) { - * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors }); - * } else { .... } - * var mesh = new THREE.Mesh( geometry, material ); - */ - - THREE.STLLoader = function (manager) { - - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; - - }; - - THREE.STLLoader.prototype = { - - constructor: THREE.STLLoader, - - load: function (url, onLoad, onProgress, onError) { - - var scope = this; - - var loader = new THREE.FileLoader(scope.manager); - loader.setResponseType('arraybuffer'); - loader.load(url, function (text) { - - onLoad(scope.parse(text)); - - }, onProgress, onError); - - }, - - parse: function (data) { - - function isBinary(data) { - - var expect, face_size, n_faces, reader; - reader = new DataView(data); - face_size = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8); - n_faces = reader.getUint32(80, true); - expect = 80 + (32 / 8) + (n_faces * face_size); - - if (expect === reader.byteLength) { - - return true; - - } - - // An ASCII STL data must begin with 'solid ' as the first six bytes. - // However, ASCII STLs lacking the SPACE after the 'd' are known to be - // plentiful. So, check the first 5 bytes for 'solid'. - - // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' - - var solid = [115, 111, 108, 105, 100]; - - for (var i = 0; i < 5; i++) { - - // If solid[ i ] does not match the i-th byte, then it is not an - // ASCII STL; hence, it is binary and return true. - - if (solid[i] != reader.getUint8(i, false)) return true; - - } - - // First 5 bytes read "solid"; declare it to be an ASCII STL - - return false; - - } - - function parseBinary(data) { - - var reader = new DataView(data); - var faces = reader.getUint32(80, true); - - var r, g, b, hasColors = false, colors; - var defaultR, defaultG, defaultB, alpha; - - // process STL header - // check for default color in header ("COLOR=rgba" sequence). - - for (var index = 0; index < 80 - 10; index++) { - - if ((reader.getUint32(index, false) == 0x434F4C4F /*COLO*/) && - (reader.getUint8(index + 4) == 0x52 /*'R'*/) && - (reader.getUint8(index + 5) == 0x3D /*'='*/)) { - - hasColors = true; - colors = []; - - defaultR = reader.getUint8(index + 6) / 255; - defaultG = reader.getUint8(index + 7) / 255; - defaultB = reader.getUint8(index + 8) / 255; - alpha = reader.getUint8(index + 9) / 255; - - } - - } - - var dataOffset = 84; - var faceLength = 12 * 4 + 2; - - var geometry = new THREE.BufferGeometry(); - - var vertices = []; - var normals = []; - - for (var face = 0; face < faces; face++) { - - var start = dataOffset + face * faceLength; - var normalX = reader.getFloat32(start, true); - var normalY = reader.getFloat32(start + 4, true); - var normalZ = reader.getFloat32(start + 8, true); - - if (hasColors) { - - var packedColor = reader.getUint16(start + 48, true); - - if ((packedColor & 0x8000) === 0) { - - // facet has its own unique color - - r = (packedColor & 0x1F) / 31; - g = ((packedColor >> 5) & 0x1F) / 31; - b = ((packedColor >> 10) & 0x1F) / 31; - - } else { - - r = defaultR; - g = defaultG; - b = defaultB; - - } - - } - - for (var i = 1; i <= 3; i++) { - - var vertexstart = start + i * 12; - - vertices.push(reader.getFloat32(vertexstart, true)); - vertices.push(reader.getFloat32(vertexstart + 4, true)); - vertices.push(reader.getFloat32(vertexstart + 8, true)); - - normals.push(normalX, normalY, normalZ); - - if (hasColors) { - - colors.push(r, g, b); - - } - - } - - } - - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); - - if (hasColors) { - - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); - geometry.hasColors = true; - geometry.alpha = alpha; - - } - - return geometry; - - } - - function parseASCII(data) { - - var geometry = new THREE.BufferGeometry(); - var patternFace = /facet([\s\S]*?)endfacet/g; - var faceCounter = 0; - - var patternFloat = /[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source; - var patternVertex = new RegExp('vertex' + patternFloat + patternFloat + patternFloat, 'g'); - var patternNormal = new RegExp('normal' + patternFloat + patternFloat + patternFloat, 'g'); - - var vertices = []; - var normals = []; - - var normal = new THREE.Vector3(); - - var result; - - while ((result = patternFace.exec(data)) !== null) { - - var vertexCountPerFace = 0; - var normalCountPerFace = 0; - - var text = result[0]; - - while ((result = patternNormal.exec(text)) !== null) { - - normal.x = parseFloat(result[1]); - normal.y = parseFloat(result[2]); - normal.z = parseFloat(result[3]); - normalCountPerFace++; - - } - - while ((result = patternVertex.exec(text)) !== null) { - - vertices.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])); - normals.push(normal.x, normal.y, normal.z); - vertexCountPerFace++; - - } - - // every face have to own ONE valid normal - - if (normalCountPerFace !== 1) { - - console.error('THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter); - - } - - // each face have to own THREE valid vertices - - if (vertexCountPerFace !== 3) { - - console.error('THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter); - - } - - faceCounter++; - - } - - geometry.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); - geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normals, 3)); - - return geometry; - - } - - function ensureString(buffer) { - - if (typeof buffer !== 'string') { - - var array_buffer = new Uint8Array(buffer); - - if (window.TextDecoder !== undefined) { - - return new TextDecoder().decode(array_buffer); - - } - - var str = ''; - - for (var i = 0, il = buffer.byteLength; i < il; i++) { - - str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian - - } - - return str; - - } else { - - return buffer; - - } - - } - - function ensureBinary(buffer) { - - if (typeof buffer === 'string') { - - var array_buffer = new Uint8Array(buffer.length); - for (var i = 0; i < buffer.length; i++) { - - array_buffer[i] = buffer.charCodeAt(i) & 0xff; // implicitly assumes little-endian - - } - return array_buffer.buffer || array_buffer; - - } else { - - return buffer; - - } - - } - - // start - - var binData = ensureBinary(data); - - return isBinary(binData) ? parseBinary(binData) : parseASCII(ensureString(data)); - - } - - }; - - /** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * - * @Modified by Jose Rojas from OBJLoader.js@r106 - * - */ - - // o object_name | g group_name - var object_pattern = /^[og]\s*(.+)?/; - // mtllib file_reference - var material_library_pattern = /^mtllib /; - // usemtl material_name - var material_use_pattern = /^usemtl /; - - function ParserState() { - - var state = { - objects: [], - object: {}, - - vertices: [], - normals: [], - colors: [], - uvs: [], - - materialLibraries: [], - - startObject: function ( name, fromDeclaration ) { - - // If the current object (initial from reset) is not from a g/o declaration in the parsed - // file. We need to use it for the first parsed g/o to keep things in sync. - if ( this.object && this.object.fromDeclaration === false ) { - - this.object.name = name; - this.object.fromDeclaration = ( fromDeclaration !== false ); - return; - - } - - var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); - - if ( this.object && typeof this.object._finalize === 'function' ) { - - this.object._finalize( true ); - - } - - this.object = { - name: name || '', - fromDeclaration: ( fromDeclaration !== false ), - - geometry: { - vertices: [], - normals: [], - colors: [], - uvs: [] - }, - materials: [], - smooth: true, - - startMaterial: function ( name, libraries ) { - - var previous = this._finalize( false ); - - // New usemtl declaration overwrites an inherited material, except if faces were declared - // after the material, then it must be preserved for proper MultiMaterial continuation. - if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { - - this.materials.splice( previous.index, 1 ); - - } - - var material = { - index: this.materials.length, - name: name || '', - mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), - smooth: ( previous !== undefined ? previous.smooth : this.smooth ), - groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), - groupEnd: - 1, - groupCount: - 1, - inherited: false, - - clone: function ( index ) { - - var cloned = { - index: ( typeof index === 'number' ? index : this.index ), - name: this.name, - mtllib: this.mtllib, - smooth: this.smooth, - groupStart: 0, - groupEnd: - 1, - groupCount: - 1, - inherited: false - }; - cloned.clone = this.clone.bind( cloned ); - return cloned; - - } - }; - - this.materials.push( material ); - - return material; - - }, - - currentMaterial: function () { - - if ( this.materials.length > 0 ) { - - return this.materials[ this.materials.length - 1 ]; - - } - - return undefined; - - }, - - _finalize: function ( end ) { - - var lastMultiMaterial = this.currentMaterial(); - if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { - - lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; - lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; - lastMultiMaterial.inherited = false; - - } - - // Ignore objects tail materials if no face declarations followed them before a new o/g started. - if ( end && this.materials.length > 1 ) { - - for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { - - if ( this.materials[ mi ].groupCount <= 0 ) { - - this.materials.splice( mi, 1 ); - - } - - } - - } - - // Guarantee at least one empty material, this makes the creation later more straight forward. - if ( end && this.materials.length === 0 ) { - - this.materials.push( { - name: '', - smooth: this.smooth - } ); - - } - - return lastMultiMaterial; - - } - }; - - // Inherit previous objects material. - // Spec tells us that a declared material must be set to all objects until a new material is declared. - // If a usemtl declaration is encountered while this new object is being parsed, it will - // overwrite the inherited material. Exception being that there was already face declarations - // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - - if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - - var declared = previousMaterial.clone( 0 ); - declared.inherited = true; - this.object.materials.push( declared ); - - } - - this.objects.push( this.object ); - - }, - - finalize: function () { - - if ( this.object && typeof this.object._finalize === 'function' ) { - - this.object._finalize( true ); - - } - - }, - - parseVertexIndex: function ( value, len ) { - - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - - }, - - parseNormalIndex: function ( value, len ) { - - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - - }, - - parseUVIndex: function ( value, len ) { - - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; - - }, - - addVertex: function ( a, b, c ) { - - var src = this.vertices; - var dst = this.object.geometry.vertices; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - - }, - - addVertexPoint: function ( a ) { - - var src = this.vertices; - var dst = this.object.geometry.vertices; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - - }, - - addVertexLine: function ( a ) { - - var src = this.vertices; - var dst = this.object.geometry.vertices; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - - }, - - addNormal: function ( a, b, c ) { - - var src = this.normals; - var dst = this.object.geometry.normals; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - - }, - - addColor: function ( a, b, c ) { - - var src = this.colors; - var dst = this.object.geometry.colors; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - - }, - - addUV: function ( a, b, c ) { - - var src = this.uvs; - var dst = this.object.geometry.uvs; - - dst.push( src[ a + 0 ], src[ a + 1 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ] ); - - }, - - addUVLine: function ( a ) { - - var src = this.uvs; - var dst = this.object.geometry.uvs; - - dst.push( src[ a + 0 ], src[ a + 1 ] ); - - }, - - addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { - - var vLen = this.vertices.length; - - var ia = this.parseVertexIndex( a, vLen ); - var ib = this.parseVertexIndex( b, vLen ); - var ic = this.parseVertexIndex( c, vLen ); - - this.addVertex( ia, ib, ic ); - - if ( ua !== undefined && ua !== '' ) { - - var uvLen = this.uvs.length; - ia = this.parseUVIndex( ua, uvLen ); - ib = this.parseUVIndex( ub, uvLen ); - ic = this.parseUVIndex( uc, uvLen ); - this.addUV( ia, ib, ic ); - - } - - if ( na !== undefined && na !== '' ) { - - // Normals are many times the same. If so, skip function call and parseInt. - var nLen = this.normals.length; - ia = this.parseNormalIndex( na, nLen ); - - ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); - ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); - - this.addNormal( ia, ib, ic ); - - } - - if ( this.colors.length > 0 ) { - - this.addColor( ia, ib, ic ); - - } - - }, - - addPointGeometry: function ( vertices ) { - - this.object.geometry.type = 'Points'; - - var vLen = this.vertices.length; - - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { - - this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); - - } - - }, - - addLineGeometry: function ( vertices, uvs ) { - - this.object.geometry.type = 'Line'; - - var vLen = this.vertices.length; - var uvLen = this.uvs.length; - - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { - - this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); - - } - - for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { - - this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); - - } - - } - - }; - - state.startObject( '', false ); - - return state; - - } - - THREE.OBJLoader = function( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - - this.materials = null; - - }; - - THREE.OBJLoader.prototype = { - - constructor: THREE.OBJLoader, - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new THREE.FileLoader( scope.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text ) ); - - }, onProgress, onError ); - - }, - - setPath: function ( value ) { - - this.path = value; - - return this; - - }, - - setMaterials: function ( materials ) { - - this.materials = materials; - - return this; - - }, - - parse: function ( text ) { - - console.time( 'OBJLoader' ); - - var state = new ParserState(); - - if ( text.indexOf( '\r\n' ) !== - 1 ) { - - // This is faster than String.split with regex that splits on both - text = text.replace( /\r\n/g, '\n' ); - - } - - if ( text.indexOf( '\\\n' ) !== - 1 ) { - - // join lines separated by a line continuation character (\) - text = text.replace( /\\\n/g, '' ); - - } - - var lines = text.split( '\n' ); - var line = '', lineFirstChar = ''; - var lineLength = 0; - var result = []; - - // Faster to just trim left side of the line. Use if available. - var trimLeft = ( typeof ''.trimLeft === 'function' ); - - for ( var i = 0, l = lines.length; i < l; i ++ ) { - - line = lines[ i ]; - - line = trimLeft ? line.trimLeft() : line.trim(); - - lineLength = line.length; - - if ( lineLength === 0 ) continue; - - lineFirstChar = line.charAt( 0 ); - - // @todo invoke passed in handler if any - if ( lineFirstChar === '#' ) continue; - - if ( lineFirstChar === 'v' ) { - - var data = line.split( /\s+/ ); - - switch ( data[ 0 ] ) { - - case 'v': - state.vertices.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - if ( data.length === 8 ) { - - state.colors.push( - parseFloat( data[ 4 ] ), - parseFloat( data[ 5 ] ), - parseFloat( data[ 6 ] ) - - ); - - } - break; - case 'vn': - state.normals.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - break; - case 'vt': - state.uvs.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ) - ); - break; - - } - - } else if ( lineFirstChar === 'f' ) { - - var lineData = line.substr( 1 ).trim(); - var vertexData = lineData.split( /\s+/ ); - var faceVertices = []; - - // Parse the face vertex data into an easy to work with format - - for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { - - var vertex = vertexData[ j ]; - - if ( vertex.length > 0 ) { - - var vertexParts = vertex.split( '/' ); - faceVertices.push( vertexParts ); - - } - - } - - // Draw an edge between the first vertex and all subsequent vertices to form an n-gon - - var v1 = faceVertices[ 0 ]; - - for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { - - var v2 = faceVertices[ j ]; - var v3 = faceVertices[ j + 1 ]; - - state.addFace( - v1[ 0 ], v2[ 0 ], v3[ 0 ], - v1[ 1 ], v2[ 1 ], v3[ 1 ], - v1[ 2 ], v2[ 2 ], v3[ 2 ] - ); - - } - - } else if ( lineFirstChar === 'l' ) { - - var lineParts = line.substring( 1 ).trim().split( " " ); - var lineVertices = [], lineUVs = []; - - if ( line.indexOf( "/" ) === - 1 ) { - - lineVertices = lineParts; - - } else { - - for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { - - var parts = lineParts[ li ].split( "/" ); - - if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); - if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); - - } - - } - state.addLineGeometry( lineVertices, lineUVs ); - - } else if ( lineFirstChar === 'p' ) { - - var lineData = line.substr( 1 ).trim(); - var pointData = lineData.split( " " ); - - state.addPointGeometry( pointData ); - - } else if ( ( result = object_pattern.exec( line ) ) !== null ) { - - // o object_name - // or - // g group_name - - // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 - // var name = result[ 0 ].substr( 1 ).trim(); - var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); - - state.startObject( name ); - - } else if ( material_use_pattern.test( line ) ) { - - // material - - state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); - - } else if ( material_library_pattern.test( line ) ) { - - // mtl file - - state.materialLibraries.push( line.substring( 7 ).trim() ); - - } else if ( lineFirstChar === 's' ) { - - result = line.split( ' ' ); - - // smooth shading - - // @todo Handle files that have varying smooth values for a set of faces inside one geometry, - // but does not define a usemtl for each face set. - // This should be detected and a dummy material created (later MultiMaterial and geometry groups). - // This requires some care to not create extra material on each smooth value for "normal" obj files. - // where explicit usemtl defines geometry groups. - // Example asset: examples/models/obj/cerberus/Cerberus.obj - - /* - * http://paulbourke.net/dataformats/obj/ - * or - * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf - * - * From chapter "Grouping" Syntax explanation "s group_number": - * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. - * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form - * surfaces, smoothing groups are either turned on or off; there is no difference between values greater - * than 0." - */ - if ( result.length > 1 ) { - - var value = result[ 1 ].trim().toLowerCase(); - state.object.smooth = ( value !== '0' && value !== 'off' ); - - } else { - - // ZBrush can produce "s" lines #11707 - state.object.smooth = true; - - } - var material = state.object.currentMaterial(); - if ( material ) material.smooth = state.object.smooth; - - } else { - - // Handle null terminated files without exception - if ( line === '\0' ) continue; - - throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); - - } - - } - - state.finalize(); - - var container = new THREE.Object3D(); - container.materialLibraries = [].concat( state.materialLibraries ); - - for ( var i = 0, l = state.objects.length; i < l; i ++ ) { - - var object = state.objects[ i ]; - var geometry = object.geometry; - var materials = object.materials; - var isLine = ( geometry.type === 'Line' ); - var isPoints = ( geometry.type === 'Points' ); - var hasVertexColors = false; - - // Skip o/g line declarations that did not follow with any faces - if ( geometry.vertices.length === 0 ) continue; - - var buffergeometry = new THREE.BufferGeometry(); - - buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); - - if ( geometry.normals.length > 0 ) { - - buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); - - } else { - - buffergeometry.computeVertexNormals(); - - } - - if ( geometry.colors.length > 0 ) { - - hasVertexColors = true; - buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); - - } - - if ( geometry.uvs.length > 0 ) { - - buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); - - } - - // Create materials - - var createdMaterials = []; - - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - - var sourceMaterial = materials[ mi ]; - var material = undefined; - - if ( this.materials !== null ) { - - material = this.materials.create( sourceMaterial.name ); - - // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. - if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { - - var materialLine = new THREE.LineBasicMaterial(); - THREE.Material.prototype.copy.call( materialLine, material ); - materialLine.color.copy( material.color ); - materialLine.lights = false; - material = materialLine; - - } else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { - - var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); - THREE.Material.prototype.copy.call( materialPoints, material ); - materialPoints.color.copy( material.color ); - materialPoints.map = material.map; - materialPoints.lights = false; - material = materialPoints; - - } - - } - - if ( ! material ) { - - if ( isLine ) { - - material = new THREE.LineBasicMaterial(); - - } else if ( isPoints ) { - - material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); - - } else { - - material = new THREE.MeshPhongMaterial(); - - } - - material.name = sourceMaterial.name; - - } - - material.flatShading = sourceMaterial.smooth ? false : true; - material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; - - createdMaterials.push( material ); - - } - - // Create mesh - - var mesh; - - if ( createdMaterials.length > 1 ) { - - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - - var sourceMaterial = materials[ mi ]; - buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); - - } - - if ( isLine ) { - - mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); - - } else if ( isPoints ) { - - mesh = new THREE.Points( buffergeometry, createdMaterials ); - - } else { - - mesh = new THREE.Mesh( buffergeometry, createdMaterials ); - - } - - } else { - - if ( isLine ) { - - mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); - - } else if ( isPoints ) { - - mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); - - } else { - - mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); - - } - - } - - mesh.name = object.name; - - container.add( mesh ); - - } - - console.timeEnd( 'OBJLoader' ); - - return container; - - } - - }; - - /** - * @fileOverview - * Loads a Wavefront .mtl file specifying materials - * - * @author angelxuanchang - */ - - THREE.MTLLoader = function ( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - - }; - - THREE.MTLLoader.prototype = { - - constructor: THREE.MTLLoader, - - crossOrigin: 'anonymous', - - /** - * Loads and parses a MTL asset from a URL. - * - * @param {String} url - URL to the MTL file. - * @param {Function} [onLoad] - Callback invoked with the loaded object. - * @param {Function} [onProgress] - Callback for download progress. - * @param {Function} [onError] - Callback for download errors. - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to load. - */ - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var path = ( this.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path; - - var loader = new THREE.FileLoader( this.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text, path ) ); - - }, onProgress, onError ); - - }, - - /** - * Set base path for resolving references. - * If set this path will be prepended to each loaded and found reference. - * - * @see setResourcePath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setPath: function ( path ) { - - this.path = path; - return this; - - }, - - /** - * Set base path for additional resources like textures. - * - * @see setPath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.setResourcePath( 'assets/textures/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setResourcePath: function ( path ) { - - this.resourcePath = path; - return this; - - }, - - setTexturePath: function ( path ) { - - console.warn( 'THREE.MTLLoader: .setTexturePath() has been renamed to .setResourcePath().' ); - return this.setResourcePath( path ); - - }, - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setMaterialOptions: function ( value ) { - - this.materialOptions = value; - return this; - - }, - - /** - * Parses a MTL file. - * - * @param {String} text - Content of MTL file - * @return {THREE.MTLLoader.MaterialCreator} - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to parse. - */ - parse: function ( text, path ) { - - var lines = text.split( '\n' ); - var info = {}; - var delimiter_pattern = /\s+/; - var materialsInfo = {}; - - for ( var i = 0; i < lines.length; i ++ ) { - - var line = lines[ i ]; - line = line.trim(); - - if ( line.length === 0 || line.charAt( 0 ) === '#' ) { - - // Blank line or comment ignore - continue; - - } - - var pos = line.indexOf( ' ' ); - - var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; - key = key.toLowerCase(); - - var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; - value = value.trim(); - - if ( key === 'newmtl' ) { - - // New material - - info = { name: value }; - materialsInfo[ value ] = info; - - } else { - - if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { - - var ss = value.split( delimiter_pattern, 3 ); - info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; - - } else { - - info[ key ] = value; - - } - - } - - } - - var materialCreator = new THREE.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions ); - materialCreator.setCrossOrigin( this.crossOrigin ); - materialCreator.setManager( this.manager ); - materialCreator.setMaterials( materialsInfo ); - return materialCreator; - - } - - }; - - /** - * Create a new THREE-MTLLoader.MaterialCreator - * @param baseUrl - Url relative to which textures are loaded - * @param options - Set of options on how to construct the materials - * side: Which side to apply the material - * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide - * wrap: What type of wrapping to apply for textures - * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping - * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 - * Default: false, assumed to be already normalized - * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's - * Default: false - * @constructor - */ - - THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) { - - this.baseUrl = baseUrl || ''; - this.options = options; - this.materialsInfo = {}; - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; - - this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide; - this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping; - - }; - - THREE.MTLLoader.MaterialCreator.prototype = { - - constructor: THREE.MTLLoader.MaterialCreator, - - crossOrigin: 'anonymous', - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setManager: function ( value ) { - - this.manager = value; - - }, - - setMaterials: function ( materialsInfo ) { - - this.materialsInfo = this.convert( materialsInfo ); - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; - - }, - - convert: function ( materialsInfo ) { - - if ( ! this.options ) return materialsInfo; - - var converted = {}; - - for ( var mn in materialsInfo ) { - - // Convert materials info into normalized form based on options - - var mat = materialsInfo[ mn ]; - - var covmat = {}; - - converted[ mn ] = covmat; - - for ( var prop in mat ) { - - var save = true; - var value = mat[ prop ]; - var lprop = prop.toLowerCase(); - - switch ( lprop ) { - - case 'kd': - case 'ka': - case 'ks': - - // Diffuse color (color under white light) using RGB values - - if ( this.options && this.options.normalizeRGB ) { - - value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; - - } - - if ( this.options && this.options.ignoreZeroRGBs ) { - - if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { - - // ignore - - save = false; - - } - - } - - break; - - } - - if ( save ) { - - covmat[ lprop ] = value; - - } - - } - - } - - return converted; - - }, - - preload: function () { - - for ( var mn in this.materialsInfo ) { - - this.create( mn ); - - } - - }, - - getIndex: function ( materialName ) { - - return this.nameLookup[ materialName ]; - - }, - - getAsArray: function () { - - var index = 0; - - for ( var mn in this.materialsInfo ) { - - this.materialsArray[ index ] = this.create( mn ); - this.nameLookup[ mn ] = index; - index ++; - - } - - return this.materialsArray; - - }, - - create: function ( materialName ) { - - if ( this.materials[ materialName ] === undefined ) { - - this.createMaterial_( materialName ); - - } - - return this.materials[ materialName ]; - - }, - - createMaterial_: function ( materialName ) { - - // Create material - - var scope = this; - var mat = this.materialsInfo[ materialName ]; - var params = { - - name: materialName, - side: this.side - - }; - - function resolveURL( baseUrl, url ) { - - if ( typeof url !== 'string' || url === '' ) - return ''; - - // Absolute URL - if ( /^https?:\/\//i.test( url ) ) return url; - - return baseUrl + url; - - } - - function setMapForType( mapType, value ) { - - if ( params[ mapType ] ) return; // Keep the first encountered texture - - var texParams = scope.getTextureParams( value, params ); - var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); - - map.repeat.copy( texParams.scale ); - map.offset.copy( texParams.offset ); - - map.wrapS = scope.wrap; - map.wrapT = scope.wrap; - - params[ mapType ] = map; - - } - - for ( var prop in mat ) { - - var value = mat[ prop ]; - var n; - - if ( value === '' ) continue; - - switch ( prop.toLowerCase() ) { - - // Ns is material specular exponent - - case 'kd': - - // Diffuse color (color under white light) using RGB values - - params.color = new THREE.Color().fromArray( value ); - - break; - - case 'ks': - - // Specular color (color when light is reflected from shiny surface) using RGB values - params.specular = new THREE.Color().fromArray( value ); - - break; - - case 'ke': - - // Emissive using RGB values - params.emissive = new THREE.Color().fromArray( value ); - - break; - - case 'map_kd': - - // Diffuse texture map - - setMapForType( "map", value ); - - break; - - case 'map_ks': - - // Specular map - - setMapForType( "specularMap", value ); - - break; - - case 'map_ke': - - // Emissive map - - setMapForType( "emissiveMap", value ); - - break; - - case 'norm': - - setMapForType( "normalMap", value ); - - break; - - case 'map_bump': - case 'bump': - - // Bump texture map - - setMapForType( "bumpMap", value ); - - break; - - case 'map_d': - - // Alpha map - - setMapForType( "alphaMap", value ); - params.transparent = true; - - break; - - case 'ns': - - // The specular exponent (defines the focus of the specular highlight) - // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. - - params.shininess = parseFloat( value ); - - break; - - case 'd': - n = parseFloat( value ); - - if ( n < 1 ) { - - params.opacity = n; - params.transparent = true; - - } - - break; - - case 'tr': - n = parseFloat( value ); - - if ( this.options && this.options.invertTrProperty ) n = 1 - n; - - if ( n > 0 ) { - - params.opacity = 1 - n; - params.transparent = true; - - } - - break; - - } - - } - - this.materials[ materialName ] = new THREE.MeshPhongMaterial( params ); - return this.materials[ materialName ]; - - }, - - getTextureParams: function ( value, matParams ) { - - var texParams = { - - scale: new THREE.Vector2( 1, 1 ), - offset: new THREE.Vector2( 0, 0 ) - - }; - - var items = value.split( /\s+/ ); - var pos; - - pos = items.indexOf( '-bm' ); - - if ( pos >= 0 ) { - - matParams.bumpScale = parseFloat( items[ pos + 1 ] ); - items.splice( pos, 2 ); - - } - - pos = items.indexOf( '-s' ); - - if ( pos >= 0 ) { - - texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! - - } - - pos = items.indexOf( '-o' ); - - if ( pos >= 0 ) { - - texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! - - } - - texParams.url = items.join( ' ' ).trim(); - return texParams; - - }, - - loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { - - var texture; - var loader = THREE.Loader.Handlers.get( url ); - var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager; - - if ( loader === null ) { - - loader = new THREE.TextureLoader( manager ); - - } - - if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); - texture = loader.load( url, onLoad, onProgress, onError ); - - if ( mapping !== undefined ) texture.mapping = mapping; - - return texture; - - } - - }; - - /** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - * @Modified by Jihoon Lee from ColladerLoader.js@r88 - * To support rviz compatible collada viewing. - * See: #202 why it is forked. - * - * It is a fork from ColladerLoader.js in three.js. It follows three.js license. - */ - - THREE.ColladaLoader = function (manager) { - - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; - - }; - - THREE.ColladaLoader.prototype = { - - constructor: THREE.ColladaLoader, - - crossOrigin: 'Anonymous', - - load: function (url, onLoad, onProgress, onError) { - - var scope = this; - - var path = THREE.Loader.prototype.extractUrlBase(url); - - var loader = new THREE.FileLoader(scope.manager); - loader.load(url, function (text) { - - onLoad(scope.parse(text, path)); - - }, onProgress, onError); - - }, - - options: { - - set convertUpAxis(value) { - - console.warn('THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.'); - - } - - }, - - setCrossOrigin: function (value) { - - this.crossOrigin = value; - - }, - - parse: function (text, path) { - - function getElementsByTagName(xml, name) { - - // Non recursive xml.getElementsByTagName() ... - - var array = []; - var childNodes = xml.childNodes; - - for (var i = 0, l = childNodes.length; i < l; i++) { - - var child = childNodes[i]; - - if (child.nodeName === name) { - - array.push(child); + for (i = 0, l = keyframes.length; i < l; i++) { + keyframe = keyframes[i]; + keyframe.value[property] = defaultValue; + } + } else { + // filling gaps + createMissingKeyframes(keyframes, property); } - - } - - return array; - - } - - function parseStrings(text) { - - if (text.length === 0) return []; - - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); - - for (var i = 0, l = parts.length; i < l; i++) { - - array[i] = parts[i]; - } - - return array; - - } - - function parseFloats(text) { - - if (text.length === 0) return []; - - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); - - for (var i = 0, l = parts.length; i < l; i++) { - - array[i] = parseFloat(parts[i]); - + function createMissingKeyframes(keyframes, property) { + var prev, next; + for (var i = 0, l = keyframes.length; i < l; i++) { + var keyframe = keyframes[i]; + if (keyframe.value[property] === null) { + prev = getPrev(keyframes, i, property); + next = getNext(keyframes, i, property); + if (prev === null) { + keyframe.value[property] = next.value[property]; + continue; + } + if (next === null) { + keyframe.value[property] = prev.value[property]; + continue; + } + interpolate(keyframe, prev, next, property); + } + } } - - return array; - - } - - function parseInts(text) { - - if (text.length === 0) return []; - - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); - - for (var i = 0, l = parts.length; i < l; i++) { - - array[i] = parseInt(parts[i]); - + function getPrev(keyframes, i, property) { + while (i >= 0) { + var keyframe = keyframes[i]; + if (keyframe.value[property] !== null) return keyframe; + i--; + } + return null; } - - return array; - - } - - function parseId(text) { - - return text.substring(1); - - } - - function generateId() { - - return 'three_default_' + (count++); - - } - - function isEmpty(object) { - - return Object.keys(object).length === 0; - - } - - // asset - - function parseAsset(xml) { - - return { - unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), - upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) - }; - - } - - function parseAssetUnit(xml) { - - return xml !== undefined ? parseFloat(xml.getAttribute('meter')) : 1; - - } - - function parseAssetUpAxis(xml) { - - return xml !== undefined ? xml.textContent : 'Y_UP'; - - } - - // library - - function parseLibrary(xml, libraryName, nodeName, parser) { - - var library = getElementsByTagName(xml, libraryName)[0]; - - if (library !== undefined) { - - var elements = getElementsByTagName(library, nodeName); - - for (var i = 0; i < elements.length; i++) { - - parser(elements[i]); - + function getNext(keyframes, i, property) { + while (i < keyframes.length) { + var keyframe = keyframes[i]; + if (keyframe.value[property] !== null) return keyframe; + i++; } - + return null; } - - } - - function buildLibrary(data, builder) { - - for (var name in data) { - - var object = data[name]; - object.build = builder(data[name]); - + function interpolate(key, prev, next, property) { + if (next.time - prev.time === 0) { + key.value[property] = prev.value[property]; + return; + } + key.value[property] = (key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time) + prev.value[property]; } - } - - // get - - function getBuild(data, builder) { - - if (data.build !== undefined) return data.build; - - data.build = builder(data); - - return data.build; - - } - - // animation - - function parseAnimation(xml) { - - var data = { - sources: {}, - samplers: {}, - channels: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - var id; - - switch (child.nodeName) { - - case 'source': - id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; - - case 'sampler': - id = child.getAttribute('id'); - data.samplers[id] = parseAnimationSampler(child); - break; - - case 'channel': - id = child.getAttribute('target'); - data.channels[id] = parseAnimationChannel(child); - break; - - default: - console.log(child); - + // animation clips + + function parseAnimationClip(xml) { + var data = { + name: xml.getAttribute('id') || 'default', + start: parseFloat(xml.getAttribute('start') || 0), + end: parseFloat(xml.getAttribute('end') || 0), + animations: [] + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'instance_animation': + data.animations.push(parseId(child.getAttribute('url'))); + break; + } } - + library.clips[xml.getAttribute('id')] = data; } - - library.animations[xml.getAttribute('id')] = data; - - } - - function parseAnimationSampler(xml) { - - var data = { - inputs: {}, - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - data.inputs[semantic] = id; - break; - + function buildAnimationClip(data) { + var tracks = []; + var name = data.name; + var duration = data.end - data.start || -1; + var animations = data.animations; + for (var i = 0, il = animations.length; i < il; i++) { + var animationTracks = getAnimation(animations[i]); + for (var j = 0, jl = animationTracks.length; j < jl; j++) { + tracks.push(animationTracks[j]); + } } - + return new AnimationClip(name, duration, tracks); + } + function getAnimationClip(id) { + return getBuild(library.clips[id], buildAnimationClip); } - return data; - - } - - function parseAnimationChannel(xml) { - - var data = {}; - - var target = xml.getAttribute('target'); - - // parsing SID Addressing Syntax - - var parts = target.split('/'); - - var id = parts.shift(); - var sid = parts.shift(); - - // check selection syntax - - var arraySyntax = (sid.indexOf('(') !== - 1); - var memberSyntax = (sid.indexOf('.') !== - 1); - - if (memberSyntax) { - - // member selection access - - parts = sid.split('.'); - sid = parts.shift(); - data.member = parts.shift(); - - } else if (arraySyntax) { - - // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. - - var indices = sid.split('('); - sid = indices.shift(); - - for (var i = 0; i < indices.length; i++) { - - indices[i] = parseInt(indices[i].replace(/\)/, '')); - + // controller + + function parseController(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'skin': + // there is exactly one skin per controller + data.id = parseId(child.getAttribute('source')); + data.skin = parseSkin(child); + break; + case 'morph': + data.id = parseId(child.getAttribute('source')); + console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); + break; + } } - - data.indices = indices; - + library.controllers[xml.getAttribute('id')] = data; } - - data.id = id; - data.sid = sid; - - data.arraySyntax = arraySyntax; - data.memberSyntax = memberSyntax; - - data.sampler = parseId(xml.getAttribute('source')); - - return data; - - } - - function buildAnimation(data) { - - var tracks = []; - - var channels = data.channels; - var samplers = data.samplers; - var sources = data.sources; - - for (var target in channels) { - - if (channels.hasOwnProperty(target)) { - - var channel = channels[target]; - var sampler = samplers[channel.sampler]; - - var inputId = sampler.inputs.INPUT; - var outputId = sampler.inputs.OUTPUT; - - var inputSource = sources[inputId]; - var outputSource = sources[outputId]; - - var animation = buildAnimationChannel(channel, inputSource, outputSource); - - createKeyframeTracks(animation, tracks); - + function parseSkin(xml) { + var data = { + sources: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'bind_shape_matrix': + data.bindShapeMatrix = parseFloats(child.textContent); + break; + case 'source': + var id = child.getAttribute('id'); + data.sources[id] = parseSource(child); + break; + case 'joints': + data.joints = parseJoints(child); + break; + case 'vertex_weights': + data.vertexWeights = parseVertexWeights(child); + break; + } } - + return data; } + function parseJoints(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var semantic = child.getAttribute('semantic'); + var id = parseId(child.getAttribute('source')); + data.inputs[semantic] = id; + break; + } + } + return data; + } + function parseVertexWeights(xml) { + var data = { + inputs: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var semantic = child.getAttribute('semantic'); + var id = parseId(child.getAttribute('source')); + var offset = parseInt(child.getAttribute('offset')); + data.inputs[semantic] = { + id: id, + offset: offset + }; + break; + case 'vcount': + data.vcount = parseInts(child.textContent); + break; + case 'v': + data.v = parseInts(child.textContent); + break; + } + } + return data; + } + function buildController(data) { + var build = { + id: data.id + }; + var geometry = library.geometries[build.id]; + if (data.skin !== undefined) { + build.skin = buildSkin(data.skin); + + // we enhance the 'sources' property of the corresponding geometry with our skin data + + geometry.sources.skinIndices = build.skin.indices; + geometry.sources.skinWeights = build.skin.weights; + } + return build; + } + function buildSkin(data) { + var BONE_LIMIT = 4; + var build = { + joints: [], + // this must be an array to preserve the joint order + indices: { + array: [], + stride: BONE_LIMIT + }, + weights: { + array: [], + stride: BONE_LIMIT + } + }; + var sources = data.sources; + var vertexWeights = data.vertexWeights; + var vcount = vertexWeights.vcount; + var v = vertexWeights.v; + var jointOffset = vertexWeights.inputs.JOINT.offset; + var weightOffset = vertexWeights.inputs.WEIGHT.offset; + var jointSource = data.sources[data.joints.inputs.JOINT]; + var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; + var weights = sources[vertexWeights.inputs.WEIGHT.id].array; + var stride = 0; + var i, j, l; + + // process skin data for each vertex + + for (i = 0, l = vcount.length; i < l; i++) { + var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex + var vertexSkinData = []; + for (j = 0; j < jointCount; j++) { + var skinIndex = v[stride + jointOffset]; + var weightId = v[stride + weightOffset]; + var skinWeight = weights[weightId]; + vertexSkinData.push({ + index: skinIndex, + weight: skinWeight + }); + stride += 2; + } - return tracks; - - } - - function getAnimation(id) { - - return getBuild(library.animations[id], buildAnimation); - - } - - function buildAnimationChannel(channel, inputSource, outputSource) { - - var node = library.nodes[channel.id]; - var object3D = getNode(node.id); - - var transform = node.transforms[channel.sid]; - var defaultMatrix = node.matrix.clone().transpose(); - - var time, stride; - var i, il, j, jl; - - var data = {}; - - // the collada spec allows the animation of data in various ways. - // depending on the transform type (matrix, translate, rotate, scale), we execute different logic - - switch (transform) { - - case 'matrix': - - for (i = 0, il = inputSource.array.length; i < il; i++) { - - time = inputSource.array[i]; - stride = i * outputSource.stride; - - if (data[time] === undefined) data[time] = {}; - - if (channel.arraySyntax === true) { + // we sort the joints in descending order based on the weights. + // this ensures, we only procced the most important joints of the vertex - var value = outputSource.array[stride]; - var index = channel.indices[0] + 4 * channel.indices[1]; + vertexSkinData.sort(descending); - data[time][index] = value; + // now we provide for each vertex a set of four index and weight values. + // the order of the skin data matches the order of vertices + for (j = 0; j < BONE_LIMIT; j++) { + var d = vertexSkinData[j]; + if (d !== undefined) { + build.indices.array.push(d.index); + build.weights.array.push(d.weight); } else { - - for (j = 0, jl = outputSource.stride; j < jl; j++) { - - data[time][j] = outputSource.array[stride + j]; - - } - + build.indices.array.push(0); + build.weights.array.push(0); } - } + } - break; - - case 'translate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; - - case 'rotate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; - - case 'scale': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; - - } - - var keyframes = prepareAnimationData(data, defaultMatrix); - - var animation = { - name: object3D.uuid, - keyframes: keyframes - }; - - return animation; - - } - - function prepareAnimationData(data, defaultMatrix) { + // setup bind matrix - var keyframes = []; + if (data.bindShapeMatrix) { + build.bindMatrix = new Matrix4().fromArray(data.bindShapeMatrix).transpose(); + } else { + build.bindMatrix = new Matrix4().identity(); + } - // transfer data into a sortable array + // process bones and inverse bind matrix data - for (var time in data) { + for (i = 0, l = jointSource.array.length; i < l; i++) { + var name = jointSource.array[i]; + var boneInverse = new Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); + build.joints.push({ + name: name, + boneInverse: boneInverse + }); + } + return build; - keyframes.push({ time: parseFloat(time), value: data[time] }); + // array sort function + function descending(a, b) { + return b.weight - a.weight; + } } - - // ensure keyframes are sorted by time - - keyframes.sort(ascending); - - // now we clean up all animation data, so we can use them for keyframe tracks - - for (var i = 0; i < 16; i++) { - - transformAnimationData(keyframes, i, defaultMatrix.elements[i]); - + function getController(id) { + return getBuild(library.controllers[id], buildController); } - return keyframes; - - // array sort function - - function ascending(a, b) { - - return a.time - b.time; + // image + function parseImage(xml) { + var data = { + init_from: getElementsByTagName(xml, 'init_from')[0].textContent + }; + library.images[xml.getAttribute('id')] = data; } - - } - - var position = new THREE.Vector3(); - var scale = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); - - function createKeyframeTracks(animation, tracks) { - - var keyframes = animation.keyframes; - var name = animation.name; - - var times = []; - var positionData = []; - var quaternionData = []; - var scaleData = []; - - for (var i = 0, l = keyframes.length; i < l; i++) { - - var keyframe = keyframes[i]; - - var time = keyframe.time; - var value = keyframe.value; - - matrix.fromArray(value).transpose(); - matrix.decompose(position, quaternion, scale); - - times.push(time); - positionData.push(position.x, position.y, position.z); - quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); - scaleData.push(scale.x, scale.y, scale.z); - + function buildImage(data) { + if (data.build !== undefined) return data.build; + return data.init_from; } - - if (positionData.length > 0) tracks.push(new THREE.VectorKeyframeTrack(name + '.position', times, positionData)); - if (quaternionData.length > 0) tracks.push(new THREE.QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); - if (scaleData.length > 0) tracks.push(new THREE.VectorKeyframeTrack(name + '.scale', times, scaleData)); - - return tracks; - - } - - function transformAnimationData(keyframes, property, defaultValue) { - - var keyframe; - - var empty = true; - var i, l; - - // check, if values of a property are missing in our keyframes - - for (i = 0, l = keyframes.length; i < l; i++) { - - keyframe = keyframes[i]; - - if (keyframe.value[property] === undefined) { - - keyframe.value[property] = null; // mark as missing - - } else { - - empty = false; - + function getImage(id) { + var data = library.images[id]; + if (data !== undefined) { + return getBuild(data, buildImage); } - + console.warn('THREE.ColladaLoader: Couldn\'t find image with ID:', id); + return null; } - if (empty === true) { - - // no values at all, so we set a default value - - for (i = 0, l = keyframes.length; i < l; i++) { - - keyframe = keyframes[i]; - - keyframe.value[property] = defaultValue; + // effect + function parseEffect(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'profile_COMMON': + data.profile = parseEffectProfileCOMMON(child); + break; + } } - - } else { - - // filling gaps - - createMissingKeyframes(keyframes, property); - + library.effects[xml.getAttribute('id')] = data; } - - } - - function createMissingKeyframes(keyframes, property) { - - var prev, next; - - for (var i = 0, l = keyframes.length; i < l; i++) { - - var keyframe = keyframes[i]; - - if (keyframe.value[property] === null) { - - prev = getPrev(keyframes, i, property); - next = getNext(keyframes, i, property); - - if (prev === null) { - - keyframe.value[property] = next.value[property]; - continue; - + function parseEffectProfileCOMMON(xml) { + var data = { + surfaces: {}, + samplers: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'newparam': + parseEffectNewparam(child, data); + break; + case 'technique': + data.technique = parseEffectTechnique(child); + break; + case 'extra': + data.extra = parseEffectExtra(child); + break; } - - if (next === null) { - - keyframe.value[property] = prev.value[property]; - continue; - + } + return data; + } + function parseEffectNewparam(xml, data) { + var sid = xml.getAttribute('sid'); + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'surface': + data.surfaces[sid] = parseEffectSurface(child); + break; + case 'sampler2D': + data.samplers[sid] = parseEffectSampler(child); + break; } - - interpolate(keyframe, prev, next, property); - } - } - - } - - function getPrev(keyframes, i, property) { - - while (i >= 0) { - - var keyframe = keyframes[i]; - - if (keyframe.value[property] !== null) return keyframe; - - i--; - + function parseEffectSurface(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'init_from': + data.init_from = child.textContent; + break; + } + } + return data; } - - return null; - - } - - function getNext(keyframes, i, property) { - - while (i < keyframes.length) { - - var keyframe = keyframes[i]; - - if (keyframe.value[property] !== null) return keyframe; - - i++; - + function parseEffectSampler(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'source': + data.source = child.textContent; + break; + } + } + return data; } - - return null; - - } - - function interpolate(key, prev, next, property) { - - if ((next.time - prev.time) === 0) { - - key.value[property] = prev.value[property]; - return; - + function parseEffectTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'constant': + case 'lambert': + case 'blinn': + case 'phong': + data.type = child.nodeName; + data.parameters = parseEffectParameters(child); + break; + case 'extra': + data.extra = parseEffectExtra(child); + break; + } + } + return data; } - - key.value[property] = ((key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time)) + prev.value[property]; - - } - - // animation clips - - function parseAnimationClip(xml) { - - var data = { - name: xml.getAttribute('id') || 'default', - start: parseFloat(xml.getAttribute('start') || 0), - end: parseFloat(xml.getAttribute('end') || 0), - animations: [] - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'instance_animation': - data.animations.push(parseId(child.getAttribute('url'))); - break; - + function parseEffectParameters(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'emission': + case 'diffuse': + case 'specular': + case 'bump': + case 'ambient': + case 'shininess': + case 'transparency': + data[child.nodeName] = parseEffectParameter(child); + break; + case 'transparent': + data[child.nodeName] = { + opaque: child.hasAttribute('opaque') ? child.getAttribute('opaque') : 'A_ONE', + data: parseEffectParameter(child) + }; + break; + } } - + return data; } - - library.clips[xml.getAttribute('id')] = data; - - } - - function buildAnimationClip(data) { - - var tracks = []; - - var name = data.name; - var duration = (data.end - data.start) || - 1; - var animations = data.animations; - - for (var i = 0, il = animations.length; i < il; i++) { - - var animationTracks = getAnimation(animations[i]); - - for (var j = 0, jl = animationTracks.length; j < jl; j++) { - - tracks.push(animationTracks[j]); - + function parseEffectParameter(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'color': + data[child.nodeName] = parseFloats(child.textContent); + break; + case 'float': + data[child.nodeName] = parseFloat(child.textContent); + break; + case 'texture': + data[child.nodeName] = { + id: child.getAttribute('texture'), + extra: parseEffectParameterTexture(child) + }; + break; + } } - + return data; } - - return new THREE.AnimationClip(name, duration, tracks); - - } - - function getAnimationClip(id) { - - return getBuild(library.clips[id], buildAnimationClip); - - } - - // controller - - function parseController(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'skin': - // there is exactly one skin per controller - data.id = parseId(child.getAttribute('source')); - data.skin = parseSkin(child); - break; - - case 'morph': - data.id = parseId(child.getAttribute('source')); - console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); - break; - + function parseEffectParameterTexture(xml) { + var data = { + technique: {} + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'extra': + parseEffectParameterTextureExtra(child, data); + break; + } } - + return data; } - - library.controllers[xml.getAttribute('id')] = data; - - } - - function parseSkin(xml) { - - var data = { - sources: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'bind_shape_matrix': - data.bindShapeMatrix = parseFloats(child.textContent); - break; - - case 'source': - var id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; - - case 'joints': - data.joints = parseJoints(child); - break; - - case 'vertex_weights': - data.vertexWeights = parseVertexWeights(child); - break; - + function parseEffectParameterTextureExtra(xml, data) { + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique': + parseEffectParameterTextureExtraTechnique(child, data); + break; + } + } + } + function parseEffectParameterTextureExtraTechnique(xml, data) { + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'repeatU': + case 'repeatV': + case 'offsetU': + case 'offsetV': + data.technique[child.nodeName] = parseFloat(child.textContent); + break; + case 'wrapU': + case 'wrapV': + // some files have values for wrapU/wrapV which become NaN via parseInt + + if (child.textContent.toUpperCase() === 'TRUE') { + data.technique[child.nodeName] = 1; + } else if (child.textContent.toUpperCase() === 'FALSE') { + data.technique[child.nodeName] = 0; + } else { + data.technique[child.nodeName] = parseInt(child.textContent); + } + break; + case 'bump': + data[child.nodeName] = parseEffectExtraTechniqueBump(child); + break; + } + } + } + function parseEffectExtra(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique': + data.technique = parseEffectExtraTechnique(child); + break; + } + } + return data; + } + function parseEffectExtraTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'double_sided': + data[child.nodeName] = parseInt(child.textContent); + break; + case 'bump': + data[child.nodeName] = parseEffectExtraTechniqueBump(child); + break; + } + } + return data; + } + function parseEffectExtraTechniqueBump(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'texture': + data[child.nodeName] = { + id: child.getAttribute('texture'), + texcoord: child.getAttribute('texcoord'), + extra: parseEffectParameterTexture(child) + }; + break; + } } - + return data; + } + function buildEffect(data) { + return data; + } + function getEffect(id) { + return getBuild(library.effects[id], buildEffect); } - return data; - - } - - function parseJoints(xml) { - - var data = { - inputs: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - data.inputs[semantic] = id; + // material + + function parseMaterial(xml) { + var data = { + name: xml.getAttribute('name') + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'instance_effect': + data.url = parseId(child.getAttribute('url')); + break; + } + } + library.materials[xml.getAttribute('id')] = data; + } + function getTextureLoader(image) { + var loader; + var extension = image.slice((image.lastIndexOf('.') - 1 >>> 0) + 2); // http://www.jstips.co/en/javascript/get-file-extension/ + extension = extension.toLowerCase(); + switch (extension) { + case 'tga': + loader = tgaLoader; break; - + default: + loader = textureLoader; } - + return loader; } - - return data; - - } - - function parseVertexWeights(xml) { - - var data = { - inputs: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - var offset = parseInt(child.getAttribute('offset')); - data.inputs[semantic] = { id: id, offset: offset }; + function buildMaterial(data) { + var effect = getEffect(data.url); + var technique = effect.profile.technique; + var material; + switch (technique.type) { + case 'phong': + case 'blinn': + material = new MeshPhongMaterial(); break; - - case 'vcount': - data.vcount = parseInts(child.textContent); + case 'lambert': + material = new MeshLambertMaterial(); break; - - case 'v': - data.v = parseInts(child.textContent); + default: + material = new MeshBasicMaterial(); break; - } + material.name = data.name || ''; + function getTexture(textureObject) { + var colorSpace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var sampler = effect.profile.samplers[textureObject.id]; + var image = null; - } - - return data; - - } - - function buildController(data) { - - var build = { - id: data.id - }; - - var geometry = library.geometries[build.id]; - - if (data.skin !== undefined) { - - build.skin = buildSkin(data.skin); + // get image - // we enhance the 'sources' property of the corresponding geometry with our skin data - - geometry.sources.skinIndices = build.skin.indices; - geometry.sources.skinWeights = build.skin.weights; - - } - - return build; - - } - - function buildSkin(data) { - - var BONE_LIMIT = 4; + if (sampler !== undefined) { + var surface = effect.profile.surfaces[sampler.source]; + image = getImage(surface.init_from); + } else { + console.warn('THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530).'); + image = getImage(textureObject.id); + } - var build = { - joints: [], // this must be an array to preserve the joint order - indices: { - array: [], - stride: BONE_LIMIT - }, - weights: { - array: [], - stride: BONE_LIMIT + // create texture if image is avaiable + + if (image !== null) { + var loader = getTextureLoader(image); + if (loader !== undefined) { + var texture = loader.load(image); + var extra = textureObject.extra; + if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { + var _technique = extra.technique; + texture.wrapS = _technique.wrapU ? RepeatWrapping : ClampToEdgeWrapping; + texture.wrapT = _technique.wrapV ? RepeatWrapping : ClampToEdgeWrapping; + texture.offset.set(_technique.offsetU || 0, _technique.offsetV || 0); + texture.repeat.set(_technique.repeatU || 1, _technique.repeatV || 1); + } else { + texture.wrapS = RepeatWrapping; + texture.wrapT = RepeatWrapping; + } + if (colorSpace !== null) { + texture.colorSpace = colorSpace; + } + return texture; + } else { + console.warn('THREE.ColladaLoader: Loader for texture %s not found.', image); + return null; + } + } else { + console.warn('THREE.ColladaLoader: Couldn\'t create texture with ID:', textureObject.id); + return null; + } } - }; - - var sources = data.sources; - var vertexWeights = data.vertexWeights; - - var vcount = vertexWeights.vcount; - var v = vertexWeights.v; - var jointOffset = vertexWeights.inputs.JOINT.offset; - var weightOffset = vertexWeights.inputs.WEIGHT.offset; - - var jointSource = data.sources[data.joints.inputs.JOINT]; - var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; - - var weights = sources[vertexWeights.inputs.WEIGHT.id].array; - var stride = 0; - - var i, j, l; - - // procces skin data for each vertex - - for (i = 0, l = vcount.length; i < l; i++) { - - var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex - var vertexSkinData = []; - - for (j = 0; j < jointCount; j++) { - - var skinIndex = v[stride + jointOffset]; - var weightId = v[stride + weightOffset]; - var skinWeight = weights[weightId]; - - vertexSkinData.push({ index: skinIndex, weight: skinWeight }); - - stride += 2; - + var parameters = technique.parameters; + for (var key in parameters) { + var parameter = parameters[key]; + switch (key) { + case 'diffuse': + if (parameter.color) material.color.fromArray(parameter.color); + if (parameter.texture) material.map = getTexture(parameter.texture, SRGBColorSpace); + break; + case 'specular': + if (parameter.color && material.specular) material.specular.fromArray(parameter.color); + if (parameter.texture) material.specularMap = getTexture(parameter.texture); + break; + case 'bump': + if (parameter.texture) material.normalMap = getTexture(parameter.texture); + break; + case 'ambient': + if (parameter.texture) material.lightMap = getTexture(parameter.texture, SRGBColorSpace); + break; + case 'shininess': + if (parameter["float"] && material.shininess) material.shininess = parameter["float"]; + break; + case 'emission': + if (parameter.color && material.emissive) material.emissive.fromArray(parameter.color); + if (parameter.texture) material.emissiveMap = getTexture(parameter.texture, SRGBColorSpace); + break; + } } + material.color.convertSRGBToLinear(); + if (material.specular) material.specular.convertSRGBToLinear(); + if (material.emissive) material.emissive.convertSRGBToLinear(); - // we sort the joints in descending order based on the weights. - // this ensures, we only procced the most important joints of the vertex + // - vertexSkinData.sort(descending); + var transparent = parameters['transparent']; + var transparency = parameters['transparency']; - // now we provide for each vertex a set of four index and weight values. - // the order of the skin data matches the order of vertices + // does not exist but - for (j = 0; j < BONE_LIMIT; j++) { + if (transparency === undefined && transparent) { + transparency = { + "float": 1 + }; + } - var d = vertexSkinData[j]; + // does not exist but - if (d !== undefined) { + if (transparent === undefined && transparency) { + transparent = { + opaque: 'A_ONE', + data: { + color: [1, 1, 1, 1] + } + }; + } + if (transparent && transparency) { + // handle case if a texture exists but no color - build.indices.array.push(d.index); - build.weights.array.push(d.weight); + if (transparent.data.texture) { + // we do not set an alpha map (see #13792) + material.transparent = true; } else { - - build.indices.array.push(0); - build.weights.array.push(0); - + var color = transparent.data.color; + switch (transparent.opaque) { + case 'A_ONE': + material.opacity = color[3] * transparency["float"]; + break; + case 'RGB_ZERO': + material.opacity = 1 - color[0] * transparency["float"]; + break; + case 'A_ZERO': + material.opacity = 1 - color[3] * transparency["float"]; + break; + case 'RGB_ONE': + material.opacity = color[0] * transparency["float"]; + break; + default: + console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.', transparent.opaque); + } + if (material.opacity < 1) material.transparent = true; } - } + // + + if (technique.extra !== undefined && technique.extra.technique !== undefined) { + var techniques = technique.extra.technique; + for (var k in techniques) { + var v = techniques[k]; + switch (k) { + case 'double_sided': + material.side = v === 1 ? DoubleSide : FrontSide; + break; + case 'bump': + material.normalMap = getTexture(v.texture); + material.normalScale = new Vector2(1, 1); + break; + } + } + } + return material; } - - // setup bind matrix - - build.bindMatrix = new THREE.Matrix4().fromArray(data.bindShapeMatrix).transpose(); - - // process bones and inverse bind matrix data - - for (i = 0, l = jointSource.array.length; i < l; i++) { - - var name = jointSource.array[i]; - var boneInverse = new THREE.Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); - - build.joints.push({ name: name, boneInverse: boneInverse }); - + function getMaterial(id) { + return getBuild(library.materials[id], buildMaterial); } - return build; - - // array sort function - - function descending(a, b) { - - return b.weight - a.weight; - + // camera + + function parseCamera(xml) { + var data = { + name: xml.getAttribute('name') + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'optics': + data.optics = parseCameraOptics(child); + break; + } + } + library.cameras[xml.getAttribute('id')] = data; } - - } - - function getController(id) { - - return getBuild(library.controllers[id], buildController); - - } - - // image - - function parseImage(xml) { - - var data = { - init_from: getElementsByTagName(xml, 'init_from')[0].textContent - }; - - library.images[xml.getAttribute('id')] = data; - - } - - function buildImage(data) { - - if (data.build !== undefined) return data.build; - - return data.init_from; - - } - - function getImage(id) { - - return getBuild(library.images[id], buildImage); - - } - - // effect - - function parseEffect(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'profile_COMMON': - data.profile = parseEffectProfileCOMMON(child); - break; - + function parseCameraOptics(xml) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'technique_common': + return parseCameraTechnique(child); + } } - + return {}; } - - library.effects[xml.getAttribute('id')] = data; - - } - - function parseEffectProfileCOMMON(xml) { - - var data = { - surfaces: {}, - samplers: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'newparam': - parseEffectNewparam(child, data); + function parseCameraTechnique(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'perspective': + case 'orthographic': + data.technique = child.nodeName; + data.parameters = parseCameraParameters(child); + break; + } + } + return data; + } + function parseCameraParameters(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'xfov': + case 'yfov': + case 'xmag': + case 'ymag': + case 'znear': + case 'zfar': + case 'aspect_ratio': + data[child.nodeName] = parseFloat(child.textContent); + break; + } + } + return data; + } + function buildCamera(data) { + var camera; + switch (data.optics.technique) { + case 'perspective': + camera = new PerspectiveCamera(data.optics.parameters.yfov, data.optics.parameters.aspect_ratio, data.optics.parameters.znear, data.optics.parameters.zfar); break; - - case 'technique': - data.technique = parseEffectTechnique(child); + case 'orthographic': + var ymag = data.optics.parameters.ymag; + var xmag = data.optics.parameters.xmag; + var aspectRatio = data.optics.parameters.aspect_ratio; + xmag = xmag === undefined ? ymag * aspectRatio : xmag; + ymag = ymag === undefined ? xmag / aspectRatio : ymag; + xmag *= 0.5; + ymag *= 0.5; + camera = new OrthographicCamera(-xmag, xmag, ymag, -ymag, + // left, right, top, bottom + data.optics.parameters.znear, data.optics.parameters.zfar); + break; + default: + camera = new PerspectiveCamera(); break; - } - + camera.name = data.name || ''; + return camera; + } + function getCamera(id) { + var data = library.cameras[id]; + if (data !== undefined) { + return getBuild(data, buildCamera); + } + console.warn('THREE.ColladaLoader: Couldn\'t find camera with ID:', id); + return null; } - return data; - - } - - function parseEffectNewparam(xml, data) { - - var sid = xml.getAttribute('sid'); - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { + // light - case 'surface': - data.surfaces[sid] = parseEffectSurface(child); + function parseLight(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + data = parseLightTechnique(child); + break; + } + } + library.lights[xml.getAttribute('id')] = data; + } + function parseLightTechnique(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'directional': + case 'point': + case 'spot': + case 'ambient': + data.technique = child.nodeName; + data.parameters = parseLightParameters(child); + } + } + return data; + } + function parseLightParameters(xml) { + var data = {}; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'color': + var array = parseFloats(child.textContent); + data.color = new Color().fromArray(array).convertSRGBToLinear(); + break; + case 'falloff_angle': + data.falloffAngle = parseFloat(child.textContent); + break; + case 'quadratic_attenuation': + var f = parseFloat(child.textContent); + data.distance = f ? Math.sqrt(1 / f) : 0; + break; + } + } + return data; + } + function buildLight(data) { + var light; + switch (data.technique) { + case 'directional': + light = new DirectionalLight(); break; - - case 'sampler2D': - data.samplers[sid] = parseEffectSampler(child); + case 'point': + light = new PointLight(); + break; + case 'spot': + light = new SpotLight(); + break; + case 'ambient': + light = new AmbientLight(); break; - } - + if (data.parameters.color) light.color.copy(data.parameters.color); + if (data.parameters.distance) light.distance = data.parameters.distance; + return light; } - - } - - function parseEffectSurface(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'init_from': - data.init_from = child.textContent; - break; - + function getLight(id) { + var data = library.lights[id]; + if (data !== undefined) { + return getBuild(data, buildLight); } - + console.warn('THREE.ColladaLoader: Couldn\'t find light with ID:', id); + return null; } - return data; - - } - - function parseEffectSampler(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'source': - data.source = child.textContent; - break; - + // geometry + + function parseGeometry(xml) { + var data = { + name: xml.getAttribute('name'), + sources: {}, + vertices: {}, + primitives: [] + }; + var mesh = getElementsByTagName(xml, 'mesh')[0]; + + // the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep + if (mesh === undefined) return; + for (var i = 0; i < mesh.childNodes.length; i++) { + var child = mesh.childNodes[i]; + if (child.nodeType !== 1) continue; + var id = child.getAttribute('id'); + switch (child.nodeName) { + case 'source': + data.sources[id] = parseSource(child); + break; + case 'vertices': + // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; + data.vertices = parseGeometryVertices(child); + break; + case 'polygons': + console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); + break; + case 'lines': + case 'linestrips': + case 'polylist': + case 'triangles': + data.primitives.push(parseGeometryPrimitive(child)); + break; + default: + console.log(child); + } + } + library.geometries[xml.getAttribute('id')] = data; + } + function parseSource(xml) { + var data = { + array: [], + stride: 3 + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'float_array': + data.array = parseFloats(child.textContent); + break; + case 'Name_array': + data.array = parseStrings(child.textContent); + break; + case 'technique_common': + var accessor = getElementsByTagName(child, 'accessor')[0]; + if (accessor !== undefined) { + data.stride = parseInt(accessor.getAttribute('stride')); + } + break; + } + } + return data; + } + function parseGeometryVertices(xml) { + var data = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + } + return data; + } + function parseGeometryPrimitive(xml) { + var primitive = { + type: xml.nodeName, + material: xml.getAttribute('material'), + count: parseInt(xml.getAttribute('count')), + inputs: {}, + stride: 0, + hasUV: false + }; + for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'input': + var id = parseId(child.getAttribute('source')); + var semantic = child.getAttribute('semantic'); + var offset = parseInt(child.getAttribute('offset')); + var set = parseInt(child.getAttribute('set')); + var inputname = set > 0 ? semantic + set : semantic; + primitive.inputs[inputname] = { + id: id, + offset: offset + }; + primitive.stride = Math.max(primitive.stride, offset + 1); + if (semantic === 'TEXCOORD') primitive.hasUV = true; + break; + case 'vcount': + primitive.vcount = parseInts(child.textContent); + break; + case 'p': + primitive.p = parseInts(child.textContent); + break; + } + } + return primitive; + } + function groupPrimitives(primitives) { + var build = {}; + for (var i = 0; i < primitives.length; i++) { + var primitive = primitives[i]; + if (build[primitive.type] === undefined) build[primitive.type] = []; + build[primitive.type].push(primitive); } - + return build; } - - return data; - - } - - function parseEffectTechnique(xml) { - - var data = {}; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'constant': - case 'lambert': - case 'blinn': - case 'phong': - data.type = child.nodeName; - data.parameters = parseEffectParameters(child); - break; - + function checkUVCoordinates(primitives) { + var count = 0; + for (var i = 0, l = primitives.length; i < l; i++) { + var primitive = primitives[i]; + if (primitive.hasUV === true) { + count++; + } + } + if (count > 0 && count < primitives.length) { + primitives.uvsNeedsFix = true; } - } + function buildGeometry(data) { + var build = {}; + var sources = data.sources; + var vertices = data.vertices; + var primitives = data.primitives; + if (primitives.length === 0) return {}; - return data; - - } - - function parseEffectParameters(xml) { - - var data = {}; + // our goal is to create one buffer geometry for a single type of primitives + // first, we group all primitives by their type - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + var groupedPrimitives = groupPrimitives(primitives); + for (var type in groupedPrimitives) { + var primitiveType = groupedPrimitives[type]; - var child = xml.childNodes[i]; + // second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines) - if (child.nodeType !== 1) continue; + checkUVCoordinates(primitiveType); - switch (child.nodeName) { - - case 'emission': - case 'diffuse': - case 'specular': - case 'shininess': - case 'transparent': - case 'transparency': - data[child.nodeName] = parseEffectParameter(child); - break; + // third, create a buffer geometry for each type of primitives + build[type] = buildGeometryType(primitiveType, sources, vertices); } - + return build; } + function buildGeometryType(primitives, sources, vertices) { + var build = {}; + var position = { + array: [], + stride: 0 + }; + var normal = { + array: [], + stride: 0 + }; + var uv = { + array: [], + stride: 0 + }; + var uv1 = { + array: [], + stride: 0 + }; + var color = { + array: [], + stride: 0 + }; + var skinIndex = { + array: [], + stride: 4 + }; + var skinWeight = { + array: [], + stride: 4 + }; + var geometry = new BufferGeometry(); + var materialKeys = []; + var start = 0; + for (var p = 0; p < primitives.length; p++) { + var primitive = primitives[p]; + var inputs = primitive.inputs; + + // groups + + var _count = 0; + switch (primitive.type) { + case 'lines': + case 'linestrips': + _count = primitive.count * 2; + break; + case 'triangles': + _count = primitive.count * 3; + break; + case 'polylist': + for (var g = 0; g < primitive.count; g++) { + var vc = primitive.vcount[g]; + switch (vc) { + case 3: + _count += 3; // single triangle + break; + case 4: + _count += 6; // quad, subdivided into two triangles + break; + default: + _count += (vc - 2) * 3; // polylist with more than four vertices + break; + } + } + break; + default: + console.warn('THREE.ColladaLoader: Unknow primitive type:', primitive.type); + } + geometry.addGroup(start, _count, p); + start += _count; - return data; + // material - } + if (primitive.material) { + materialKeys.push(primitive.material); + } - function parseEffectParameter(xml) { + // geometry data + + for (var name in inputs) { + var input = inputs[name]; + switch (name) { + case 'VERTEX': + for (var key in vertices) { + var id = vertices[key]; + switch (key) { + case 'POSITION': + var prevLength = position.array.length; + buildGeometryData(primitive, sources[id], input.offset, position.array); + position.stride = sources[id].stride; + if (sources.skinWeights && sources.skinIndices) { + buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); + buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + } + + // see #3803 + + if (primitive.hasUV === false && primitives.uvsNeedsFix === true) { + var _count2 = (position.array.length - prevLength) / position.stride; + for (var i = 0; i < _count2; i++) { + // fill missing uv coordinates + + uv.array.push(0, 0); + } + } + break; + case 'NORMAL': + buildGeometryData(primitive, sources[id], input.offset, normal.array); + normal.stride = sources[id].stride; + break; + case 'COLOR': + buildGeometryData(primitive, sources[id], input.offset, color.array); + color.stride = sources[id].stride; + break; + case 'TEXCOORD': + buildGeometryData(primitive, sources[id], input.offset, uv.array); + uv.stride = sources[id].stride; + break; + case 'TEXCOORD1': + buildGeometryData(primitive, sources[id], input.offset, uv1.array); + uv.stride = sources[id].stride; + break; + default: + console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + } + } + break; + case 'NORMAL': + buildGeometryData(primitive, sources[input.id], input.offset, normal.array); + normal.stride = sources[input.id].stride; + break; + case 'COLOR': + buildGeometryData(primitive, sources[input.id], input.offset, color.array, true); + color.stride = sources[input.id].stride; + break; + case 'TEXCOORD': + buildGeometryData(primitive, sources[input.id], input.offset, uv.array); + uv.stride = sources[input.id].stride; + break; + case 'TEXCOORD1': + buildGeometryData(primitive, sources[input.id], input.offset, uv1.array); + uv1.stride = sources[input.id].stride; + break; + } + } + } - var data = {}; + // build geometry + + if (position.array.length > 0) geometry.setAttribute('position', new Float32BufferAttribute(position.array, position.stride)); + if (normal.array.length > 0) geometry.setAttribute('normal', new Float32BufferAttribute(normal.array, normal.stride)); + if (color.array.length > 0) geometry.setAttribute('color', new Float32BufferAttribute(color.array, color.stride)); + if (uv.array.length > 0) geometry.setAttribute('uv', new Float32BufferAttribute(uv.array, uv.stride)); + if (uv1.array.length > 0) geometry.setAttribute('uv1', new Float32BufferAttribute(uv1.array, uv1.stride)); + if (skinIndex.array.length > 0) geometry.setAttribute('skinIndex', new Float32BufferAttribute(skinIndex.array, skinIndex.stride)); + if (skinWeight.array.length > 0) geometry.setAttribute('skinWeight', new Float32BufferAttribute(skinWeight.array, skinWeight.stride)); + build.data = geometry; + build.type = primitives[0].type; + build.materialKeys = materialKeys; + return build; + } + function buildGeometryData(primitive, source, offset, array) { + var isColor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + var indices = primitive.p; + var stride = primitive.stride; + var vcount = primitive.vcount; + function pushVector(i) { + var index = indices[i + offset] * sourceStride; + var length = index + sourceStride; + for (; index < length; index++) { + array.push(sourceArray[index]); + } + if (isColor) { + // convert the vertex colors from srgb to linear if present + var startIndex = array.length - sourceStride - 1; + tempColor.setRGB(array[startIndex + 0], array[startIndex + 1], array[startIndex + 2]).convertSRGBToLinear(); + array[startIndex + 0] = tempColor.r; + array[startIndex + 1] = tempColor.g; + array[startIndex + 2] = tempColor.b; + } + } + var sourceArray = source.array; + var sourceStride = source.stride; + if (primitive.vcount !== undefined) { + var index = 0; + for (var i = 0, l = vcount.length; i < l; i++) { + var _count3 = vcount[i]; + if (_count3 === 4) { + var a = index + stride * 0; + var b = index + stride * 1; + var c = index + stride * 2; + var d = index + stride * 3; + pushVector(a); + pushVector(b); + pushVector(d); + pushVector(b); + pushVector(c); + pushVector(d); + } else if (_count3 === 3) { + var _a = index + stride * 0; + var _b = index + stride * 1; + var _c = index + stride * 2; + pushVector(_a); + pushVector(_b); + pushVector(_c); + } else if (_count3 > 4) { + for (var k = 1, kl = _count3 - 2; k <= kl; k++) { + var _a2 = index + stride * 0; + var _b2 = index + stride * k; + var _c2 = index + stride * (k + 1); + pushVector(_a2); + pushVector(_b2); + pushVector(_c2); + } + } + index += stride * _count3; + } + } else { + for (var _i = 0, _l = indices.length; _i < _l; _i += stride) { + pushVector(_i); + } + } + } + function getGeometry(id) { + return getBuild(library.geometries[id], buildGeometry); + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // kinematics + + function parseKinematicsModel(xml) { + var data = { + name: xml.getAttribute('name') || '', + joints: {}, + links: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + parseKinematicsTechniqueCommon(child, data); + break; + } + } + library.kinematicsModels[xml.getAttribute('id')] = data; + } + function buildKinematicsModel(data) { + if (data.build !== undefined) return data.build; + return data; + } + function getKinematicsModel(id) { + return getBuild(library.kinematicsModels[id], buildKinematicsModel); + } + function parseKinematicsTechniqueCommon(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'joint': + data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); + break; + case 'link': + data.links.push(parseKinematicsLink(child)); + break; + } + } + } + function parseKinematicsJoint(xml) { + var data; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'prismatic': + case 'revolute': + data = parseKinematicsJointParameter(child); + break; + } + } + return data; + } + function parseKinematicsJointParameter(xml) { + var data = { + sid: xml.getAttribute('sid'), + name: xml.getAttribute('name') || '', + axis: new Vector3(), + limits: { + min: 0, + max: 0 + }, + type: xml.nodeName, + "static": false, + zeroPosition: 0, + middlePosition: 0 + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'axis': + var array = parseFloats(child.textContent); + data.axis.fromArray(array); + break; + case 'limits': + var max = child.getElementsByTagName('max')[0]; + var min = child.getElementsByTagName('min')[0]; + data.limits.max = parseFloat(max.textContent); + data.limits.min = parseFloat(min.textContent); + break; + } + } - var child = xml.childNodes[i]; + // if min is equal to or greater than max, consider the joint static - if (child.nodeType !== 1) continue; + if (data.limits.min >= data.limits.max) { + data["static"] = true; + } - switch (child.nodeName) { + // calculate middle position - case 'color': - data[child.nodeName] = parseFloats(child.textContent); + data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + return data; + } + function parseKinematicsLink(xml) { + var data = { + sid: xml.getAttribute('sid'), + name: xml.getAttribute('name') || '', + attachments: [], + transforms: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'attachment_full': + data.attachments.push(parseKinematicsAttachment(child)); + break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push(parseKinematicsTransform(child)); + break; + } + } + return data; + } + function parseKinematicsAttachment(xml) { + var data = { + joint: xml.getAttribute('joint').split('/').pop(), + transforms: [], + links: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'link': + data.links.push(parseKinematicsLink(child)); + break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push(parseKinematicsTransform(child)); + break; + } + } + return data; + } + function parseKinematicsTransform(xml) { + var data = { + type: xml.nodeName + }; + var array = parseFloats(xml.textContent); + switch (data.type) { + case 'matrix': + data.obj = new Matrix4(); + data.obj.fromArray(array).transpose(); break; - - case 'float': - data[child.nodeName] = parseFloat(child.textContent); + case 'translate': + data.obj = new Vector3(); + data.obj.fromArray(array); break; - - case 'texture': - data[child.nodeName] = { id: child.getAttribute('texture'), extra: parseEffectParameterTexture(child) }; + case 'rotate': + data.obj = new Vector3(); + data.obj.fromArray(array); + data.angle = MathUtils.degToRad(array[3]); break; - } - + return data; } - return data; - - } - - function parseEffectParameterTexture(xml) { - - var data = { - technique: {} - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'extra': - parseEffectParameterTextureExtra(child, data); - break; - + // physics + + function parsePhysicsModel(xml) { + var data = { + name: xml.getAttribute('name') || '', + rigidBodies: {} + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'rigid_body': + data.rigidBodies[child.getAttribute('name')] = {}; + parsePhysicsRigidBody(child, data.rigidBodies[child.getAttribute('name')]); + break; + } } - + library.physicsModels[xml.getAttribute('id')] = data; } - - return data; - - } - - function parseEffectParameterTextureExtra(xml, data) { - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'technique': - parseEffectParameterTextureExtraTechnique(child, data); - break; - + function parsePhysicsRigidBody(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'technique_common': + parsePhysicsTechniqueCommon(child, data); + break; + } + } + } + function parsePhysicsTechniqueCommon(xml, data) { + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'inertia': + data.inertia = parseFloats(child.textContent); + break; + case 'mass': + data.mass = parseFloats(child.textContent)[0]; + break; + } } - } - } - - function parseEffectParameterTextureExtraTechnique(xml, data) { - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; - - switch (child.nodeName) { - - case 'repeatU': - case 'repeatV': - case 'offsetU': - case 'offsetV': - data.technique[child.nodeName] = parseFloat(child.textContent); - break; - - case 'wrapU': - case 'wrapV': - - // some files have values for wrapU/wrapV which become NaN via parseInt - - if (child.textContent.toUpperCase() === 'TRUE') { - - data.technique[child.nodeName] = 1; - - } else if (child.textContent.toUpperCase() === 'FALSE') { - - data.technique[child.nodeName] = 0; - + // scene + + function parseKinematicsScene(xml) { + var data = { + bindJointAxis: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'bind_joint_axis': + data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); + break; + } + } + library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + } + function parseKinematicsBindJointAxis(xml) { + var data = { + target: xml.getAttribute('target').split('/').pop() + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + switch (child.nodeName) { + case 'axis': + var param = child.getElementsByTagName('param')[0]; + data.axis = param.textContent; + var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; + data.jointIndex = tmpJointIndex.substring(0, tmpJointIndex.length - 1); + break; + } + } + return data; + } + function buildKinematicsScene(data) { + if (data.build !== undefined) return data.build; + return data; + } + function getKinematicsScene(id) { + return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + } + function setupKinematics() { + var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; + var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; + var visualSceneId = Object.keys(library.visualScenes)[0]; + if (kinematicsModelId === undefined || kinematicsSceneId === undefined) return; + var kinematicsModel = getKinematicsModel(kinematicsModelId); + var kinematicsScene = getKinematicsScene(kinematicsSceneId); + var visualScene = getVisualScene(visualSceneId); + var bindJointAxis = kinematicsScene.bindJointAxis; + var jointMap = {}; + for (var i = 0, l = bindJointAxis.length; i < l; i++) { + var axis = bindJointAxis[i]; + + // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' + + var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); + if (targetElement) { + // get the parent of the transform element + + var parentVisualElement = targetElement.parentElement; + + // connect the joint of the kinematics model with the element in the visual scene + + connect(axis.jointIndex, parentVisualElement); + } + } + function connect(jointIndex, visualElement) { + var visualElementName = visualElement.getAttribute('name'); + var joint = kinematicsModel.joints[jointIndex]; + visualScene.traverse(function (object) { + if (object.name === visualElementName) { + jointMap[jointIndex] = { + object: object, + transforms: buildTransformList(visualElement), + joint: joint, + position: joint.zeroPosition + }; + } + }); + } + var m0 = new Matrix4(); + kinematics = { + joints: kinematicsModel && kinematicsModel.joints, + getJointValue: function getJointValue(jointIndex) { + var jointData = jointMap[jointIndex]; + if (jointData) { + return jointData.position; } else { - - data.technique[child.nodeName] = parseInt(child.textContent); - + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); } - - break; - + }, + setJointValue: function setJointValue(jointIndex, value) { + var jointData = jointMap[jointIndex]; + if (jointData) { + var joint = jointData.joint; + if (value > joint.limits.max || value < joint.limits.min) { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + } else if (joint["static"]) { + console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + } else { + var object = jointData.object; + var _axis = joint.axis; + var transforms = jointData.transforms; + matrix.identity(); + + // each update, we have to apply all transforms in the correct order + + for (var _i2 = 0; _i2 < transforms.length; _i2++) { + var transform = transforms[_i2]; + + // if there is a connection of the transform node with a joint, apply the joint value + + if (transform.sid && transform.sid.indexOf(jointIndex) !== -1) { + switch (joint.type) { + case 'revolute': + matrix.multiply(m0.makeRotationAxis(_axis, MathUtils.degToRad(value))); + break; + case 'prismatic': + matrix.multiply(m0.makeTranslation(_axis.x * value, _axis.y * value, _axis.z * value)); + break; + default: + console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); + break; + } + } else { + switch (transform.type) { + case 'matrix': + matrix.multiply(transform.obj); + break; + case 'translate': + matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); + break; + case 'scale': + matrix.scale(transform.obj); + break; + case 'rotate': + matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); + break; + } + } + } + object.matrix.copy(matrix); + object.matrix.decompose(object.position, object.quaternion, object.scale); + jointMap[jointIndex].position = value; + } + } else { + console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + } + } + }; + } + function buildTransformList(node) { + var transforms = []; + var xml = collada.querySelector('[id="' + node.id + '"]'); + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var array = void 0, + _vector = void 0; + switch (child.nodeName) { + case 'matrix': + array = parseFloats(child.textContent); + var _matrix = new Matrix4().fromArray(array).transpose(); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _matrix + }); + break; + case 'translate': + case 'scale': + array = parseFloats(child.textContent); + _vector = new Vector3().fromArray(array); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _vector + }); + break; + case 'rotate': + array = parseFloats(child.textContent); + _vector = new Vector3().fromArray(array); + var angle = MathUtils.degToRad(array[3]); + transforms.push({ + sid: child.getAttribute('sid'), + type: child.nodeName, + obj: _vector, + angle: angle + }); + break; + } } - + return transforms; } - } - - function buildEffect(data) { - - return data; - - } - - function getEffect(id) { - - return getBuild(library.effects[id], buildEffect); - - } - - // material - - function parseMaterial(xml) { - - var data = { - name: xml.getAttribute('name') - }; - - for (var i = 0, l = xml.childNodes.length; i < l; i++) { - - var child = xml.childNodes[i]; - - if (child.nodeType !== 1) continue; + // nodes - switch (child.nodeName) { + function prepareNodes(xml) { + var elements = xml.getElementsByTagName('node'); - case 'instance_effect': - data.url = parseId(child.getAttribute('url')); - break; + // ensure all node elements have id attributes + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (element.hasAttribute('id') === false) { + element.setAttribute('id', generateId()); + } } - } - - library.materials[xml.getAttribute('id')] = data; - - } - - function buildMaterial(data) { - - var effect = getEffect(data.url); - var technique = effect.profile.technique; - - var material; - - switch (technique.type) { - - case 'phong': - case 'blinn': - material = new THREE.MeshPhongMaterial(); - break; - - case 'lambert': - material = new THREE.MeshLambertMaterial(); - break; - - default: - material = new THREE.MeshBasicMaterial(); - break; - + var matrix = new Matrix4(); + var vector = new Vector3(); + function parseNode(xml) { + var data = { + name: xml.getAttribute('name') || '', + type: xml.getAttribute('type'), + id: xml.getAttribute('id'), + sid: xml.getAttribute('sid'), + matrix: new Matrix4(), + nodes: [], + instanceCameras: [], + instanceControllers: [], + instanceLights: [], + instanceGeometries: [], + instanceNodes: [], + transforms: {} + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + if (child.nodeType !== 1) continue; + var array = void 0; + switch (child.nodeName) { + case 'node': + data.nodes.push(child.getAttribute('id')); + parseNode(child); + break; + case 'instance_camera': + data.instanceCameras.push(parseId(child.getAttribute('url'))); + break; + case 'instance_controller': + data.instanceControllers.push(parseNodeInstance(child)); + break; + case 'instance_light': + data.instanceLights.push(parseId(child.getAttribute('url'))); + break; + case 'instance_geometry': + data.instanceGeometries.push(parseNodeInstance(child)); + break; + case 'instance_node': + data.instanceNodes.push(parseId(child.getAttribute('url'))); + break; + case 'matrix': + array = parseFloats(child.textContent); + data.matrix.multiply(matrix.fromArray(array).transpose()); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'translate': + array = parseFloats(child.textContent); + vector.fromArray(array); + data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'rotate': + array = parseFloats(child.textContent); + var angle = MathUtils.degToRad(array[3]); + data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'scale': + array = parseFloats(child.textContent); + data.matrix.scale(vector.fromArray(array)); + data.transforms[child.getAttribute('sid')] = child.nodeName; + break; + case 'extra': + break; + default: + console.log(child); + } + } + if (hasNode(data.id)) { + console.warn('THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id); + } else { + library.nodes[data.id] = data; + } + return data; } + function parseNodeInstance(xml) { + var data = { + id: parseId(xml.getAttribute('url')), + materials: {}, + skeletons: [] + }; + for (var i = 0; i < xml.childNodes.length; i++) { + var child = xml.childNodes[i]; + switch (child.nodeName) { + case 'bind_material': + var instances = child.getElementsByTagName('instance_material'); + for (var j = 0; j < instances.length; j++) { + var instance = instances[j]; + var symbol = instance.getAttribute('symbol'); + var target = instance.getAttribute('target'); + data.materials[symbol] = parseId(target); + } + break; + case 'skeleton': + data.skeletons.push(parseId(child.textContent)); + break; + } + } + return data; + } + function buildSkeleton(skeletons, joints) { + var boneData = []; + var sortedBoneData = []; + var i, j, data; + + // a skeleton can have multiple root bones. collada expresses this + // situtation with multiple "skeleton" tags per controller instance + + for (i = 0; i < skeletons.length; i++) { + var skeleton = skeletons[i]; + var root = void 0; + if (hasNode(skeleton)) { + root = getNode(skeleton); + buildBoneHierarchy(root, joints, boneData); + } else if (hasVisualScene(skeleton)) { + // handle case where the skeleton refers to the visual scene (#13335) + + var visualScene = library.visualScenes[skeleton]; + var children = visualScene.children; + for (var _j = 0; _j < children.length; _j++) { + var child = children[_j]; + if (child.type === 'JOINT') { + var _root = getNode(child.id); + buildBoneHierarchy(_root, joints, boneData); + } + } + } else { + console.error('THREE.ColladaLoader: Unable to find root bone of skeleton with ID:', skeleton); + } + } - material.name = data.name; - - function getTexture(textureObject) { - - var sampler = effect.profile.samplers[textureObject.id]; - - if (sampler !== undefined) { - - var surface = effect.profile.surfaces[sampler.source]; - - var texture = textureLoader.load(getImage(surface.init_from)); + // sort bone data (the order is defined in the corresponding controller) - var extra = textureObject.extra; + for (i = 0; i < joints.length; i++) { + for (j = 0; j < boneData.length; j++) { + data = boneData[j]; + if (data.bone.name === joints[i].name) { + sortedBoneData[i] = data; + data.processed = true; + break; + } + } + } - if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { + // add unprocessed bone data at the end of the list - var technique = extra.technique; + for (i = 0; i < boneData.length; i++) { + data = boneData[i]; + if (data.processed === false) { + sortedBoneData.push(data); + data.processed = true; + } + } - texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; - texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; + // setup arrays for skeleton creation - texture.offset.set(technique.offsetU || 0, technique.offsetV || 0); - texture.repeat.set(technique.repeatU || 1, technique.repeatV || 1); + var bones = []; + var boneInverses = []; + for (i = 0; i < sortedBoneData.length; i++) { + data = sortedBoneData[i]; + bones.push(data.bone); + boneInverses.push(data.boneInverse); + } + return new Skeleton(bones, boneInverses); + } + function buildBoneHierarchy(root, joints, boneData) { + // setup bone data from visual scene - } else { + root.traverse(function (object) { + if (object.isBone === true) { + var boneInverse; - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; + // retrieve the boneInverse from the controller data + for (var i = 0; i < joints.length; i++) { + var joint = joints[i]; + if (joint.name === object.name) { + boneInverse = joint.boneInverse; + break; + } + } + if (boneInverse === undefined) { + // Unfortunately, there can be joints in the visual scene that are not part of the + // corresponding controller. In this case, we have to create a dummy boneInverse matrix + // for the respective bone. This bone won't affect any vertices, because there are no skin indices + // and weights defined for it. But we still have to add the bone to the sorted bone list in order to + // ensure a correct animation of the model. + + boneInverse = new Matrix4(); + } + boneData.push({ + bone: object, + boneInverse: boneInverse, + processed: false + }); } + }); + } + function buildNode(data) { + var objects = []; + var matrix = data.matrix; + var nodes = data.nodes; + var type = data.type; + var instanceCameras = data.instanceCameras; + var instanceControllers = data.instanceControllers; + var instanceLights = data.instanceLights; + var instanceGeometries = data.instanceGeometries; + var instanceNodes = data.instanceNodes; + + // nodes + + for (var i = 0, l = nodes.length; i < l; i++) { + objects.push(getNode(nodes[i])); + } - return texture; + // instance cameras + for (var _i3 = 0, _l2 = instanceCameras.length; _i3 < _l2; _i3++) { + var instanceCamera = getCamera(instanceCameras[_i3]); + if (instanceCamera !== null) { + objects.push(instanceCamera.clone()); + } } - console.error('THREE.ColladaLoader: Undefined sampler', textureObject.id); + // instance controllers + + for (var _i4 = 0, _l3 = instanceControllers.length; _i4 < _l3; _i4++) { + var instance = instanceControllers[_i4]; + var controller = getController(instance.id); + var geometries = getGeometry(controller.id); + var newObjects = buildObjects(geometries, instance.materials); + var skeletons = instance.skeletons; + var joints = controller.skin.joints; + var skeleton = buildSkeleton(skeletons, joints); + for (var j = 0, jl = newObjects.length; j < jl; j++) { + var _object = newObjects[j]; + if (_object.isSkinnedMesh) { + _object.bind(skeleton, controller.skin.bindMatrix); + _object.normalizeSkinWeights(); + } + objects.push(_object); + } + } - return null; + // instance lights - } + for (var _i5 = 0, _l4 = instanceLights.length; _i5 < _l4; _i5++) { + var instanceLight = getLight(instanceLights[_i5]); + if (instanceLight !== null) { + objects.push(instanceLight.clone()); + } + } - var parameters = technique.parameters; + // instance geometries - for (var key in parameters) { + for (var _i6 = 0, _l5 = instanceGeometries.length; _i6 < _l5; _i6++) { + var _instance = instanceGeometries[_i6]; - var parameter = parameters[key]; + // a single geometry instance in collada can lead to multiple object3Ds. + // this is the case when primitives are combined like triangles and lines - switch (key) { + var _geometries = getGeometry(_instance.id); + var _newObjects = buildObjects(_geometries, _instance.materials); + for (var _j2 = 0, _jl = _newObjects.length; _j2 < _jl; _j2++) { + objects.push(_newObjects[_j2]); + } + } - case 'diffuse': - if (parameter.color) material.color.fromArray(parameter.color); - if (parameter.texture) material.map = getTexture(parameter.texture); - break; - case 'specular': - if (parameter.color && material.specular) material.specular.fromArray(parameter.color); - if (parameter.texture) material.specularMap = getTexture(parameter.texture); - break; - case 'shininess': - if (parameter.float && material.shininess) - material.shininess = parameter.float; - break; - case 'emission': - if (parameter.color && material.emissive) - material.emissive.fromArray(parameter.color); - break; - case 'transparent': - // if ( parameter.texture ) material.alphaMap = getTexture( parameter.texture ); - material.transparent = true; - break; - case 'transparency': - if (parameter.float !== undefined) material.opacity = parameter.float; - material.transparent = true; - break; + // instance nodes + for (var _i7 = 0, _l6 = instanceNodes.length; _i7 < _l6; _i7++) { + objects.push(getNode(instanceNodes[_i7]).clone()); } - + var object; + if (nodes.length === 0 && objects.length === 1) { + object = objects[0]; + } else { + object = type === 'JOINT' ? new Bone() : new Group(); + for (var _i8 = 0; _i8 < objects.length; _i8++) { + object.add(objects[_i8]); + } + } + object.name = type === 'JOINT' ? data.sid : data.name; + object.matrix.copy(matrix); + object.matrix.decompose(object.position, object.quaternion, object.scale); + return object; } + var fallbackMaterial = new MeshBasicMaterial({ + name: Loader.DEFAULT_MATERIAL_NAME, + color: 0xff00ff + }); + function resolveMaterialBinding(keys, instanceMaterials) { + var materials = []; + for (var i = 0, l = keys.length; i < l; i++) { + var id = instanceMaterials[keys[i]]; + if (id === undefined) { + console.warn('THREE.ColladaLoader: Material with key %s not found. Apply fallback material.', keys[i]); + materials.push(fallbackMaterial); + } else { + materials.push(getMaterial(id)); + } + } + return materials; + } + function buildObjects(geometries, instanceMaterials) { + var objects = []; + for (var type in geometries) { + var geometry = geometries[type]; + var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); - return material; + // handle case if no materials are defined - } + if (materials.length === 0) { + if (type === 'lines' || type === 'linestrips') { + materials.push(new LineBasicMaterial()); + } else { + materials.push(new MeshPhongMaterial()); + } + } - function getMaterial(id) { + // Collada allows to use phong and lambert materials with lines. Replacing these cases with LineBasicMaterial. - return getBuild(library.materials[id], buildMaterial); + if (type === 'lines' || type === 'linestrips') { + for (var i = 0, l = materials.length; i < l; i++) { + var _material = materials[i]; + if (_material.isMeshPhongMaterial === true || _material.isMeshLambertMaterial === true) { + var lineMaterial = new LineBasicMaterial(); - } + // copy compatible properties - // camera + lineMaterial.color.copy(_material.color); + lineMaterial.opacity = _material.opacity; + lineMaterial.transparent = _material.transparent; - function parseCamera(xml) { + // replace material - var data = { - name: xml.getAttribute('name') - }; + materials[i] = lineMaterial; + } + } + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // regard skinning - var child = xml.childNodes[i]; + var skinning = geometry.data.attributes.skinIndex !== undefined; - if (child.nodeType !== 1) continue; + // choose between a single or multi materials (material array) - switch (child.nodeName) { + var material = materials.length === 1 ? materials[0] : materials; - case 'optics': - data.optics = parseCameraOptics(child); - break; + // now create a specific 3D object + var object = void 0; + switch (type) { + case 'lines': + object = new LineSegments(geometry.data, material); + break; + case 'linestrips': + object = new Line(geometry.data, material); + break; + case 'triangles': + case 'polylist': + if (skinning) { + object = new SkinnedMesh(geometry.data, material); + } else { + object = new Mesh(geometry.data, material); + } + break; + } + objects.push(object); } - + return objects; + } + function hasNode(id) { + return library.nodes[id] !== undefined; + } + function getNode(id) { + return getBuild(library.nodes[id], buildNode); } - library.cameras[xml.getAttribute('id')] = data; - - } - - function parseCameraOptics(xml) { - - for (var i = 0; i < xml.childNodes.length; i++) { - - var child = xml.childNodes[i]; - - switch (child.nodeName) { - - case 'technique_common': - return parseCameraTechnique(child); + // visual scenes + function parseVisualScene(xml) { + var data = { + name: xml.getAttribute('name'), + children: [] + }; + prepareNodes(xml); + var elements = getElementsByTagName(xml, 'node'); + for (var i = 0; i < elements.length; i++) { + data.children.push(parseNode(elements[i])); } - + library.visualScenes[xml.getAttribute('id')] = data; } - - return {}; - - } - - function parseCameraTechnique(xml) { - - var data = {}; - - for (var i = 0; i < xml.childNodes.length; i++) { - - var child = xml.childNodes[i]; - - switch (child.nodeName) { - - case 'perspective': - case 'orthographic': - - data.technique = child.nodeName; - data.parameters = parseCameraParameters(child); - - break; - + function buildVisualScene(data) { + var group = new Group(); + group.name = data.name; + var children = data.children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + group.add(getNode(child.id)); } - + return group; + } + function hasVisualScene(id) { + return library.visualScenes[id] !== undefined; + } + function getVisualScene(id) { + return getBuild(library.visualScenes[id], buildVisualScene); } - return data; - - } - - function parseCameraParameters(xml) { - - var data = {}; - - for (var i = 0; i < xml.childNodes.length; i++) { - - var child = xml.childNodes[i]; - - switch (child.nodeName) { - - case 'xfov': - case 'yfov': - case 'xmag': - case 'ymag': - case 'znear': - case 'zfar': - case 'aspect_ratio': - data[child.nodeName] = parseFloat(child.textContent); - break; + // scenes + function parseScene(xml) { + var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; + return getVisualScene(parseId(instance.getAttribute('url'))); + } + function setupAnimations() { + var clips = library.clips; + if (isEmpty(clips) === true) { + if (isEmpty(library.animations) === false) { + // if there are animations but no clips, we create a default clip for playback + + var tracks = []; + for (var id in library.animations) { + var animationTracks = getAnimation(id); + for (var i = 0, l = animationTracks.length; i < l; i++) { + tracks.push(animationTracks[i]); + } + } + animations.push(new AnimationClip('default', -1, tracks)); + } + } else { + for (var _id in clips) { + animations.push(getAnimationClip(_id)); + } } - } - return data; - - } - - function buildCamera(data) { - - var camera; - - switch (data.optics.technique) { - - case 'perspective': - camera = new THREE.PerspectiveCamera( - data.optics.parameters.yfov, - data.optics.parameters.aspect_ratio, - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; - - case 'orthographic': - var ymag = data.optics.parameters.ymag; - var xmag = data.optics.parameters.xmag; - var aspectRatio = data.optics.parameters.aspect_ratio; + // convert the parser error element into text with each child elements text + // separated by new lines. - xmag = (xmag === undefined) ? (ymag * aspectRatio) : xmag; - ymag = (ymag === undefined) ? (xmag / aspectRatio) : ymag; + function parserErrorToText(parserError) { + var result = ''; + var stack = [parserError]; + while (stack.length) { + var node = stack.shift(); + if (node.nodeType === Node.TEXT_NODE) { + result += node.textContent; + } else { + result += '\n'; + stack.push.apply(stack, node.childNodes); + } + } + return result.trim(); + } + if (text.length === 0) { + return { + scene: new Scene() + }; + } + var xml = new DOMParser().parseFromString(text, 'application/xml'); + var collada = getElementsByTagName(xml, 'COLLADA')[0]; + var parserError = xml.getElementsByTagName('parsererror')[0]; + if (parserError !== undefined) { + // Chrome will return parser error with a div in it + + var errorElement = getElementsByTagName(parserError, 'div')[0]; + var errorText; + if (errorElement) { + errorText = errorElement.textContent; + } else { + errorText = parserErrorToText(parserError); + } + console.error('THREE.ColladaLoader: Failed to parse collada file.\n', errorText); + return null; + } - xmag *= 0.5; - ymag *= 0.5; + // metadata + + var version = collada.getAttribute('version'); + console.debug('THREE.ColladaLoader: File version', version); + var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); + var textureLoader = new TextureLoader(this.manager); + textureLoader.setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin); + var tgaLoader; + if (TGALoader) { + tgaLoader = new TGALoader(this.manager); + tgaLoader.setPath(this.resourcePath || path); + } - camera = new THREE.OrthographicCamera( - - xmag, xmag, ymag, - ymag, // left, right, top, bottom - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + // - default: - camera = new THREE.PerspectiveCamera(); - break; + var tempColor = new Color(); + var animations = []; + var kinematics = {}; + var count = 0; - } + // - camera.name = data.name; + var library = { + animations: {}, + clips: {}, + controllers: {}, + images: {}, + effects: {}, + materials: {}, + cameras: {}, + lights: {}, + geometries: {}, + nodes: {}, + visualScenes: {}, + kinematicsModels: {}, + physicsModels: {}, + kinematicsScenes: {} + }; + parseLibrary(collada, 'library_animations', 'animation', parseAnimation); + parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); + parseLibrary(collada, 'library_controllers', 'controller', parseController); + parseLibrary(collada, 'library_images', 'image', parseImage); + parseLibrary(collada, 'library_effects', 'effect', parseEffect); + parseLibrary(collada, 'library_materials', 'material', parseMaterial); + parseLibrary(collada, 'library_cameras', 'camera', parseCamera); + parseLibrary(collada, 'library_lights', 'light', parseLight); + parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); + parseLibrary(collada, 'library_nodes', 'node', parseNode); + parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); + parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); + parseLibrary(collada, 'library_physics_models', 'physics_model', parsePhysicsModel); + parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + buildLibrary(library.animations, buildAnimation); + buildLibrary(library.clips, buildAnimationClip); + buildLibrary(library.controllers, buildController); + buildLibrary(library.images, buildImage); + buildLibrary(library.effects, buildEffect); + buildLibrary(library.materials, buildMaterial); + buildLibrary(library.cameras, buildCamera); + buildLibrary(library.lights, buildLight); + buildLibrary(library.geometries, buildGeometry); + buildLibrary(library.visualScenes, buildVisualScene); + setupAnimations(); + setupKinematics(); + var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + scene.animations = animations; + + // if ( asset.upAxis === 'Z_UP' ) { + + // console.warn( 'THREE.ColladaLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted, see #24289.' ); + // scene.rotation.set( - Math.PI / 2, 0, 0 ); + + // } + + scene.scale.multiplyScalar(asset.unit); + return { + get animations() { + console.warn('THREE.ColladaLoader: Please access animations over scene.animations now.'); + return animations; + }, + kinematics: kinematics, + library: library, + scene: scene + }; + } + }]); + }(Loader); - return camera; + // o object_name | g group_name + const _object_pattern = /^[og]\s*(.+)?/; + // mtllib file_reference + const _material_library_pattern = /^mtllib /; + // usemtl material_name + const _material_use_pattern = /^usemtl /; + // usemap map_name + const _map_use_pattern = /^usemap /; + const _face_vertex_data_separator_pattern = /\s+/; - } + const _vA = new Vector3(); + const _vB = new Vector3(); + const _vC = new Vector3(); - function getCamera(id) { - var data = library.cameras[id]; - if (data !== undefined) { - return getBuild(data, buildCamera); - } - return null; - } + const _ab = new Vector3(); + const _cb = new Vector3(); - // light + const _color = new Color(); - function parseLight(xml) { + function ParserState() { - var data = {}; + const state = { + objects: [], + object: {}, - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + vertices: [], + normals: [], + colors: [], + uvs: [], - var child = xml.childNodes[i]; + materials: {}, + materialLibraries: [], - if (child.nodeType !== 1) continue; + startObject: function ( name, fromDeclaration ) { - switch (child.nodeName) { + // If the current object (initial from reset) is not from a g/o declaration in the parsed + // file. We need to use it for the first parsed g/o to keep things in sync. + if ( this.object && this.object.fromDeclaration === false ) { - case 'technique_common': - data = parseLightTechnique(child); - break; + this.object.name = name; + this.object.fromDeclaration = ( fromDeclaration !== false ); + return; - } + } - } + const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); - library.lights[xml.getAttribute('id')] = data; + if ( this.object && typeof this.object._finalize === 'function' ) { - } + this.object._finalize( true ); - function parseLightTechnique(xml) { + } - var data = {}; + this.object = { + name: name || '', + fromDeclaration: ( fromDeclaration !== false ), - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + geometry: { + vertices: [], + normals: [], + colors: [], + uvs: [], + hasUVIndices: false + }, + materials: [], + smooth: true, - var child = xml.childNodes[i]; + startMaterial: function ( name, libraries ) { - if (child.nodeType !== 1) continue; + const previous = this._finalize( false ); - switch (child.nodeName) { + // New usemtl declaration overwrites an inherited material, except if faces were declared + // after the material, then it must be preserved for proper MultiMaterial continuation. + if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { - case 'directional': - case 'point': - case 'spot': - case 'ambient': + this.materials.splice( previous.index, 1 ); - data.technique = child.nodeName; - data.parameters = parseLightParameters(child); + } - } + const material = { + index: this.materials.length, + name: name || '', + mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), + smooth: ( previous !== undefined ? previous.smooth : this.smooth ), + groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), + groupEnd: - 1, + groupCount: - 1, + inherited: false, + + clone: function ( index ) { + + const cloned = { + index: ( typeof index === 'number' ? index : this.index ), + name: this.name, + mtllib: this.mtllib, + smooth: this.smooth, + groupStart: 0, + groupEnd: - 1, + groupCount: - 1, + inherited: false + }; + cloned.clone = this.clone.bind( cloned ); + return cloned; - } + } + }; - return data; + this.materials.push( material ); - } + return material; - function parseLightParameters(xml) { + }, - var data = {}; + currentMaterial: function () { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + if ( this.materials.length > 0 ) { - var child = xml.childNodes[i]; + return this.materials[ this.materials.length - 1 ]; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + return undefined; - case 'color': - var array = parseFloats(child.textContent); - data.color = new THREE.Color().fromArray(array); - break; + }, - case 'falloff_angle': - data.falloffAngle = parseFloat(child.textContent); - break; + _finalize: function ( end ) { - case 'quadratic_attenuation': - var f = parseFloat(child.textContent); - data.distance = f ? Math.sqrt(1 / f) : 0; - break; + const lastMultiMaterial = this.currentMaterial(); + if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { - } + lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; + lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; + lastMultiMaterial.inherited = false; - } + } - return data; + // Ignore objects tail materials if no face declarations followed them before a new o/g started. + if ( end && this.materials.length > 1 ) { - } + for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) { - function buildLight(data) { + if ( this.materials[ mi ].groupCount <= 0 ) { - var light; + this.materials.splice( mi, 1 ); - switch (data.technique) { + } - case 'directional': - light = new THREE.DirectionalLight(); - break; + } - case 'point': - light = new THREE.PointLight(); - break; + } - case 'spot': - light = new THREE.SpotLight(); - break; + // Guarantee at least one empty material, this makes the creation later more straight forward. + if ( end && this.materials.length === 0 ) { - case 'ambient': - light = new THREE.AmbientLight(); - break; + this.materials.push( { + name: '', + smooth: this.smooth + } ); - } + } - if (data.parameters.color) light.color.copy(data.parameters.color); - if (data.parameters.distance) light.distance = data.parameters.distance; + return lastMultiMaterial; - return light; + } + }; - } + // Inherit previous objects material. + // Spec tells us that a declared material must be set to all objects until a new material is declared. + // If a usemtl declaration is encountered while this new object is being parsed, it will + // overwrite the inherited material. Exception being that there was already face declarations + // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - // geometry + if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - function parseGeometry(xml) { + const declared = previousMaterial.clone( 0 ); + declared.inherited = true; + this.object.materials.push( declared ); - var data = { - name: xml.getAttribute('name'), - sources: {}, - vertices: {}, - primitives: [] - }; + } - var mesh = getElementsByTagName(xml, 'mesh')[0]; + this.objects.push( this.object ); - for (var i = 0; i < mesh.childNodes.length; i++) { + }, - var child = mesh.childNodes[i]; + finalize: function () { - if (child.nodeType !== 1) continue; + if ( this.object && typeof this.object._finalize === 'function' ) { - var id = child.getAttribute('id'); + this.object._finalize( true ); - switch (child.nodeName) { + } - case 'source': - data.sources[id] = parseSource(child); - break; + }, - case 'vertices': - // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; - data.vertices = parseGeometryVertices(child); - break; + parseVertexIndex: function ( value, len ) { - case 'polygons': - console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); - break; + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - case 'lines': - case 'linestrips': - case 'polylist': - case 'triangles': - data.primitives.push(parseGeometryPrimitive(child)); - break; + }, - default: - console.log(child); + parseNormalIndex: function ( value, len ) { - } + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - } + }, - library.geometries[xml.getAttribute('id')] = data; + parseUVIndex: function ( value, len ) { - } + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; - function parseSource(xml) { + }, - var data = { - array: [], - stride: 3 - }; + addVertex: function ( a, b, c ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const src = this.vertices; + const dst = this.object.geometry.vertices; - var child = xml.childNodes[i]; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - if (child.nodeType !== 1) continue; + }, - switch (child.nodeName) { + addVertexPoint: function ( a ) { - case 'float_array': - data.array = parseFloats(child.textContent); - break; + const src = this.vertices; + const dst = this.object.geometry.vertices; - case 'Name_array': - data.array = parseStrings(child.textContent); - break; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - case 'technique_common': - var accessor = getElementsByTagName(child, 'accessor')[0]; + }, - if (accessor !== undefined) { + addVertexLine: function ( a ) { - data.stride = parseInt(accessor.getAttribute('stride')); + const src = this.vertices; + const dst = this.object.geometry.vertices; - } - break; + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - } + }, - } + addNormal: function ( a, b, c ) { - return data; + const src = this.normals; + const dst = this.object.geometry.normals; - } + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - function parseGeometryVertices(xml) { + }, - var data = {}; + addFaceNormal: function ( a, b, c ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const src = this.vertices; + const dst = this.object.geometry.normals; - var child = xml.childNodes[i]; + _vA.fromArray( src, a ); + _vB.fromArray( src, b ); + _vC.fromArray( src, c ); - if (child.nodeType !== 1) continue; + _cb.subVectors( _vC, _vB ); + _ab.subVectors( _vA, _vB ); + _cb.cross( _ab ); - data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + _cb.normalize(); - } + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); - return data; + }, - } + addColor: function ( a, b, c ) { - function parseGeometryPrimitive(xml) { + const src = this.colors; + const dst = this.object.geometry.colors; - var primitive = { - type: xml.nodeName, - material: xml.getAttribute('material'), - count: parseInt(xml.getAttribute('count')), - inputs: {}, - stride: 0 - }; + if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + }, - var child = xml.childNodes[i]; + addUV: function ( a, b, c ) { - if (child.nodeType !== 1) continue; + const src = this.uvs; + const dst = this.object.geometry.uvs; - switch (child.nodeName) { + dst.push( src[ a + 0 ], src[ a + 1 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ] ); - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - var offset = parseInt(child.getAttribute('offset')); - primitive.inputs[semantic] = { id: id, offset: offset }; - primitive.stride = Math.max(primitive.stride, offset + 1); - break; + }, - case 'vcount': - primitive.vcount = parseInts(child.textContent); - break; + addDefaultUV: function () { - case 'p': - primitive.p = parseInts(child.textContent); - break; + const dst = this.object.geometry.uvs; - } + dst.push( 0, 0 ); + dst.push( 0, 0 ); + dst.push( 0, 0 ); - } + }, - return primitive; + addUVLine: function ( a ) { - } + const src = this.uvs; + const dst = this.object.geometry.uvs; - function groupPrimitives(primitives) { + dst.push( src[ a + 0 ], src[ a + 1 ] ); - var build = {}; + }, - for (var i = 0; i < primitives.length; i++) { + addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { - var primitive = primitives[i]; + const vLen = this.vertices.length; - if (build[primitive.type] === undefined) build[primitive.type] = []; + let ia = this.parseVertexIndex( a, vLen ); + let ib = this.parseVertexIndex( b, vLen ); + let ic = this.parseVertexIndex( c, vLen ); - build[primitive.type].push(primitive); + this.addVertex( ia, ib, ic ); + this.addColor( ia, ib, ic ); - } + // normals - return build; + if ( na !== undefined && na !== '' ) { - } + const nLen = this.normals.length; - function buildGeometry(data) { + ia = this.parseNormalIndex( na, nLen ); + ib = this.parseNormalIndex( nb, nLen ); + ic = this.parseNormalIndex( nc, nLen ); - var build = {}; + this.addNormal( ia, ib, ic ); - var sources = data.sources; - var vertices = data.vertices; - var primitives = data.primitives; + } else { - if (primitives.length === 0) return {}; + this.addFaceNormal( ia, ib, ic ); - // our goal is to create one buffer geoemtry for a single type of primitives - // first, we group all primitives by their type + } - var groupedPrimitives = groupPrimitives(primitives); + // uvs - for (var type in groupedPrimitives) { + if ( ua !== undefined && ua !== '' ) { - // second, we create for each type of primitives (polylist,triangles or lines) a buffer geometry + const uvLen = this.uvs.length; - build[type] = buildGeometryType(groupedPrimitives[type], sources, vertices); + ia = this.parseUVIndex( ua, uvLen ); + ib = this.parseUVIndex( ub, uvLen ); + ic = this.parseUVIndex( uc, uvLen ); - } + this.addUV( ia, ib, ic ); - return build; + this.object.geometry.hasUVIndices = true; - } + } else { - function buildGeometryType(primitives, sources, vertices) { + // add placeholder values (for inconsistent face definitions) - var build = {}; + this.addDefaultUV(); - var position = { array: [], stride: 0 }; - var normal = { array: [], stride: 0 }; - var uv = { array: [], stride: 0 }; - var color = { array: [], stride: 0 }; + } - var skinIndex = { array: [], stride: 4 }; - var skinWeight = { array: [], stride: 4 }; + }, - var geometry = new THREE.BufferGeometry(); + addPointGeometry: function ( vertices ) { - var materialKeys = []; + this.object.geometry.type = 'Points'; - var start = 0, count = 0; + const vLen = this.vertices.length; - for (var p = 0; p < primitives.length; p++) { + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - var primitive = primitives[p]; - var inputs = primitive.inputs; - var triangleCount = 1; + const index = this.parseVertexIndex( vertices[ vi ], vLen ); - if (primitive.vcount && primitive.vcount[0] === 4) { + this.addVertexPoint( index ); + this.addColor( index ); - triangleCount = 2; // one quad -> two triangles + } - } + }, - // groups + addLineGeometry: function ( vertices, uvs ) { - if (primitive.type === 'lines' || primitive.type === 'linestrips') { + this.object.geometry.type = 'Line'; - count = primitive.count * 2; + const vLen = this.vertices.length; + const uvLen = this.uvs.length; - } else { + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - count = primitive.count * 3 * triangleCount; + this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); - } + } - geometry.addGroup(start, count, p); - start += count; + for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { - // material + this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); - if (primitive.material) { + } - materialKeys.push(primitive.material); + } - } + }; - // geometry data + state.startObject( '', false ); - for (var name in inputs) { + return state; - var input = inputs[name]; + } - switch (name) { + // - case 'VERTEX': - for (var key in vertices) { + class OBJLoader extends Loader { - var id = vertices[key]; + constructor( manager ) { - switch (key) { + super( manager ); - case 'POSITION': - buildGeometryData(primitive, sources[id], input.offset, position.array); - position.stride = sources[id].stride; + this.materials = null; - if (sources.skinWeights && sources.skinIndices) { + } - buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); - buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + load( url, onLoad, onProgress, onError ) { - } - break; + const scope = this; - case 'NORMAL': - buildGeometryData(primitive, sources[id], input.offset, normal.array); - normal.stride = sources[id].stride; - break; + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - case 'COLOR': - buildGeometryData(primitive, sources[id], input.offset, color.array); - color.stride = sources[id].stride; - break; + try { - case 'TEXCOORD': - buildGeometryData(primitive, sources[id], input.offset, uv.array); - uv.stride = sources[id].stride; - break; + onLoad( scope.parse( text ) ); - default: - console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + } catch ( e ) { - } + if ( onError ) { - } - break; + onError( e ); - case 'NORMAL': - buildGeometryData(primitive, sources[input.id], input.offset, normal.array); - normal.stride = sources[input.id].stride; - break; + } else { - case 'COLOR': - buildGeometryData(primitive, sources[input.id], input.offset, color.array); - color.stride = sources[input.id].stride; - break; + console.error( e ); - case 'TEXCOORD': - buildGeometryData(primitive, sources[input.id], input.offset, uv.array); - uv.stride = sources[input.id].stride; - break; + } - } + scope.manager.itemError( url ); - } + } - } + }, onProgress, onError ); - // build geometry + } - if (position.array.length > 0) geometry.addAttribute('position', new THREE.Float32BufferAttribute(position.array, position.stride)); - if (normal.array.length > 0) geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normal.array, normal.stride)); - if (color.array.length > 0) geometry.addAttribute('color', new THREE.Float32BufferAttribute(color.array, color.stride)); - if (uv.array.length > 0) geometry.addAttribute('uv', new THREE.Float32BufferAttribute(uv.array, uv.stride)); + setMaterials( materials ) { - if (skinIndex.array.length > 0) geometry.addAttribute('skinIndex', new THREE.Float32BufferAttribute(skinIndex.array, skinIndex.stride)); - if (skinWeight.array.length > 0) geometry.addAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeight.array, skinWeight.stride)); + this.materials = materials; - build.data = geometry; - build.type = primitives[0].type; - build.materialKeys = materialKeys; + return this; - return build; + } - } + parse( text ) { - function buildGeometryData(primitive, source, offset, array) { + const state = new ParserState(); - var indices = primitive.p; - var stride = primitive.stride; - var vcount = primitive.vcount; + if ( text.indexOf( '\r\n' ) !== - 1 ) { - function pushVector(i) { + // This is faster than String.split with regex that splits on both + text = text.replace( /\r\n/g, '\n' ); - var index = indices[i + offset] * sourceStride; - var length = index + sourceStride; + } - for (; index < length; index++) { + if ( text.indexOf( '\\\n' ) !== - 1 ) { - array.push(sourceArray[index]); + // join lines separated by a line continuation character (\) + text = text.replace( /\\\n/g, '' ); - } + } - } + const lines = text.split( '\n' ); + let result = []; - var maxcount = 0; + for ( let i = 0, l = lines.length; i < l; i ++ ) { - var sourceArray = source.array; - var sourceStride = source.stride; + const line = lines[ i ].trimStart(); - if (primitive.vcount !== undefined) { + if ( line.length === 0 ) continue; - var index = 0; + const lineFirstChar = line.charAt( 0 ); - for (var i = 0, l = vcount.length; i < l; i++) { + // @todo invoke passed in handler if any + if ( lineFirstChar === '#' ) continue; // skip comments - var count = vcount[i]; + if ( lineFirstChar === 'v' ) { - if (count === 4) { + const data = line.split( _face_vertex_data_separator_pattern ); - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; - var d = index + stride * 3; + switch ( data[ 0 ] ) { - pushVector(a); pushVector(b); pushVector(d); - pushVector(b); pushVector(c); pushVector(d); + case 'v': + state.vertices.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + if ( data.length >= 7 ) { - } else if (count === 3) { + _color.setRGB( + parseFloat( data[ 4 ] ), + parseFloat( data[ 5 ] ), + parseFloat( data[ 6 ] ) + ).convertSRGBToLinear(); - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; + state.colors.push( _color.r, _color.g, _color.b ); - pushVector(a); pushVector(b); pushVector(c); + } else { - } else { + // if no colors are defined, add placeholders so color and vertex indices match - maxcount = Math.max(maxcount, count); + state.colors.push( undefined, undefined, undefined ); - } + } - index += stride * count; + break; + case 'vn': + state.normals.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + break; + case 'vt': + state.uvs.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ) + ); + break; - } + } - if (maxcount > 0) { + } else if ( lineFirstChar === 'f' ) { - console.log('THREE.ColladaLoader: Geometry has faces with more than 4 vertices.'); + const lineData = line.slice( 1 ).trim(); + const vertexData = lineData.split( _face_vertex_data_separator_pattern ); + const faceVertices = []; - } + // Parse the face vertex data into an easy to work with format - } else { + for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) { - for (var i = 0, l = indices.length; i < l; i += stride) { + const vertex = vertexData[ j ]; - pushVector(i); + if ( vertex.length > 0 ) { - } + const vertexParts = vertex.split( '/' ); + faceVertices.push( vertexParts ); - } + } - } + } - function getGeometry(id) { + // Draw an edge between the first vertex and all subsequent vertices to form an n-gon - return getBuild(library.geometries[id], buildGeometry); + const v1 = faceVertices[ 0 ]; - } + for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { - // kinematics + const v2 = faceVertices[ j ]; + const v3 = faceVertices[ j + 1 ]; - function parseKinematicsModel(xml) { + state.addFace( + v1[ 0 ], v2[ 0 ], v3[ 0 ], + v1[ 1 ], v2[ 1 ], v3[ 1 ], + v1[ 2 ], v2[ 2 ], v3[ 2 ] + ); - var data = { - name: xml.getAttribute('name') || '', - joints: {}, - links: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + } else if ( lineFirstChar === 'l' ) { - var child = xml.childNodes[i]; + const lineParts = line.substring( 1 ).trim().split( ' ' ); + let lineVertices = []; + const lineUVs = []; - if (child.nodeType !== 1) continue; + if ( line.indexOf( '/' ) === - 1 ) { - switch (child.nodeName) { + lineVertices = lineParts; - case 'technique_common': - parseKinematicsTechniqueCommon(child, data); - break; + } else { - } + for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) { - } + const parts = lineParts[ li ].split( '/' ); - library.kinematicsModels[xml.getAttribute('id')] = data; + if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] ); + if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] ); - } + } - function buildKinematicsModel(data) { + } - if (data.build !== undefined) return data.build; + state.addLineGeometry( lineVertices, lineUVs ); - return data; + } else if ( lineFirstChar === 'p' ) { - } + const lineData = line.slice( 1 ).trim(); + const pointData = lineData.split( ' ' ); - function getKinematicsModel(id) { + state.addPointGeometry( pointData ); - return getBuild(library.kinematicsModels[id], buildKinematicsModel); + } else if ( ( result = _object_pattern.exec( line ) ) !== null ) { - } + // o object_name + // or + // g group_name - function parseKinematicsTechniqueCommon(xml, data) { + // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 + // let name = result[ 0 ].slice( 1 ).trim(); + const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 ); - for (var i = 0; i < xml.childNodes.length; i++) { + state.startObject( name ); - var child = xml.childNodes[i]; + } else if ( _material_use_pattern.test( line ) ) { - if (child.nodeType !== 1) continue; + // material - switch (child.nodeName) { + state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); - case 'joint': - data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); - break; + } else if ( _material_library_pattern.test( line ) ) { - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + // mtl file - } + state.materialLibraries.push( line.substring( 7 ).trim() ); - } + } else if ( _map_use_pattern.test( line ) ) { - } + // the line is parsed but ignored since the loader assumes textures are defined MTL files + // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) - function parseKinematicsJoint(xml) { + console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); - var data; + } else if ( lineFirstChar === 's' ) { - for (var i = 0; i < xml.childNodes.length; i++) { + result = line.split( ' ' ); - var child = xml.childNodes[i]; + // smooth shading - if (child.nodeType !== 1) continue; + // @todo Handle files that have varying smooth values for a set of faces inside one geometry, + // but does not define a usemtl for each face set. + // This should be detected and a dummy material created (later MultiMaterial and geometry groups). + // This requires some care to not create extra material on each smooth value for "normal" obj files. + // where explicit usemtl defines geometry groups. + // Example asset: examples/models/obj/cerberus/Cerberus.obj - switch (child.nodeName) { + /* + * http://paulbourke.net/dataformats/obj/ + * + * From chapter "Grouping" Syntax explanation "s group_number": + * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. + * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form + * surfaces, smoothing groups are either turned on or off; there is no difference between values greater + * than 0." + */ + if ( result.length > 1 ) { - case 'prismatic': - case 'revolute': - data = parseKinematicsJointParameter(child); - break; + const value = result[ 1 ].trim().toLowerCase(); + state.object.smooth = ( value !== '0' && value !== 'off' ); - } + } else { - } + // ZBrush can produce "s" lines #11707 + state.object.smooth = true; - return data; + } - } + const material = state.object.currentMaterial(); + if ( material ) material.smooth = state.object.smooth; - function parseKinematicsJointParameter(xml, data) { + } else { - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - axis: new THREE.Vector3(), - limits: { - min: 0, - max: 0 - }, - type: xml.nodeName, - static: false, - zeroPosition: 0, - middlePosition: 0 - }; + // Handle null terminated files without exception + if ( line === '\0' ) continue; - for (var i = 0; i < xml.childNodes.length; i++) { + console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + state.finalize(); - case 'axis': - var array = parseFloats(child.textContent); - data.axis.fromArray(array); - break; - case 'limits': - var max = child.getElementsByTagName('max')[0]; - var min = child.getElementsByTagName('min')[0]; + const container = new Group(); + container.materialLibraries = [].concat( state.materialLibraries ); - data.limits.max = parseFloat(max.textContent); - data.limits.min = parseFloat(min.textContent); - break; + const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); - } + if ( hasPrimitives === true ) { - } + for ( let i = 0, l = state.objects.length; i < l; i ++ ) { - // if min is equal to or greater than max, consider the joint static + const object = state.objects[ i ]; + const geometry = object.geometry; + const materials = object.materials; + const isLine = ( geometry.type === 'Line' ); + const isPoints = ( geometry.type === 'Points' ); + let hasVertexColors = false; - if (data.limits.min >= data.limits.max) { + // Skip o/g line declarations that did not follow with any faces + if ( geometry.vertices.length === 0 ) continue; - data.static = true; + const buffergeometry = new BufferGeometry(); - } + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) ); - // calculate middle position + if ( geometry.normals.length > 0 ) { - data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) ); - return data; + } - } + if ( geometry.colors.length > 0 ) { - function parseKinematicsLink(xml) { + hasVertexColors = true; + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) ); - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - attachments: [], - transforms: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( geometry.hasUVIndices === true ) { - var child = xml.childNodes[i]; + buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) ); - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + // Create materials - case 'attachment_full': - data.attachments.push(parseKinematicsAttachment(child)); - break; + const createdMaterials = []; - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - } + const sourceMaterial = materials[ mi ]; + const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors; + let material = state.materials[ materialHash ]; - } + if ( this.materials !== null ) { - return data; + material = this.materials.create( sourceMaterial.name ); - } + // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. + if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) { - function parseKinematicsAttachment(xml) { + const materialLine = new LineBasicMaterial(); + Material.prototype.copy.call( materialLine, material ); + materialLine.color.copy( material.color ); + material = materialLine; - var data = { - joint: xml.getAttribute('joint').split('/').pop(), - transforms: [], - links: [] - }; + } else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } ); + Material.prototype.copy.call( materialPoints, material ); + materialPoints.color.copy( material.color ); + materialPoints.map = material.map; + material = materialPoints; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + if ( material === undefined ) { - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + if ( isLine ) { - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + material = new LineBasicMaterial(); - } + } else if ( isPoints ) { - } + material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - return data; + } else { - } + material = new MeshPhongMaterial(); - function parseKinematicsTransform(xml) { + } - var data = { - type: xml.nodeName - }; + material.name = sourceMaterial.name; + material.flatShading = sourceMaterial.smooth ? false : true; + material.vertexColors = hasVertexColors; - var array = parseFloats(xml.textContent); + state.materials[ materialHash ] = material; - switch (data.type) { + } - case 'matrix': - data.obj = new THREE.Matrix4(); - data.obj.fromArray(array).transpose(); - break; + createdMaterials.push( material ); - case 'translate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - break; + } - case 'rotate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - data.angle = THREE.Math.degToRad(array[3]); - break; + // Create mesh - } + let mesh; - return data; + if ( createdMaterials.length > 1 ) { - } + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - function parseKinematicsScene(xml) { + const sourceMaterial = materials[ mi ]; + buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); - var data = { - bindJointAxis: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( isLine ) { - var child = xml.childNodes[i]; + mesh = new LineSegments( buffergeometry, createdMaterials ); - if (child.nodeType !== 1) continue; + } else if ( isPoints ) { - switch (child.nodeName) { + mesh = new Points$1( buffergeometry, createdMaterials ); - case 'bind_joint_axis': - data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); - break; + } else { - } + mesh = new Mesh( buffergeometry, createdMaterials ); - } + } - library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + } else { - } + if ( isLine ) { - function parseKinematicsBindJointAxis(xml) { + mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] ); - var data = { - target: xml.getAttribute('target').split('/').pop() - }; + } else if ( isPoints ) { - for (var i = 0; i < xml.childNodes.length; i++) { + mesh = new Points$1( buffergeometry, createdMaterials[ 0 ] ); - var child = xml.childNodes[i]; + } else { - if (child.nodeType !== 1) continue; + mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] ); - switch (child.nodeName) { + } - case 'axis': - var param = child.getElementsByTagName('param')[0]; - data.axis = param.textContent; - var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; - data.jointIndex = tmpJointIndex.substr(0, tmpJointIndex.length - 1); - break; + } - } + mesh.name = object.name; - } + container.add( mesh ); - return data; + } - } + } else { - function buildKinematicsScene(data) { + // if there is only the default parser state object with no geometry data, interpret data as point cloud - if (data.build !== undefined) return data.build; + if ( state.vertices.length > 0 ) { - return data; + const material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - } + const buffergeometry = new BufferGeometry(); - function getKinematicsScene(id) { + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) ); - return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { - } + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) ); + material.vertexColors = true; - function setupKinematics() { + } - var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; - var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; - var visualSceneId = Object.keys(library.visualScenes)[0]; + const points = new Points$1( buffergeometry, material ); + container.add( points ); - if (kinematicsModelId === undefined || kinematicsSceneId === undefined) return; + } - var kinematicsModel = getKinematicsModel(kinematicsModelId); - var kinematicsScene = getKinematicsScene(kinematicsSceneId); - var visualScene = getVisualScene(visualSceneId); + } - var bindJointAxis = kinematicsScene.bindJointAxis; - var jointMap = {}; + return container; - for (var i = 0, l = bindJointAxis.length; i < l; i++) { + } - var axis = bindJointAxis[i]; + } - // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' + /** + * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. + * + * Supports both binary and ASCII encoded files, with automatic detection of type. + * + * The loader returns a non-indexed buffer geometry. + * + * Limitations: + * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). + * There is perhaps some question as to how valid it is to always assume little-endian-ness. + * ASCII decoding assumes file is UTF-8. + * + * Usage: + * const loader = new STLLoader(); + * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { + * scene.add( new THREE.Mesh( geometry ) ); + * }); + * + * For binary STLs geometry might contain colors for vertices. To use it: + * // use the same code to load STL as above + * if (geometry.hasColors) { + * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true }); + * } else { .... } + * const mesh = new THREE.Mesh( geometry, material ); + * + * For ASCII STLs containing multiple solids, each solid is assigned to a different group. + * Groups can be used to assign a different color by defining an array of materials with the same length of + * geometry.groups and passing it to the Mesh constructor: + * + * const mesh = new THREE.Mesh( geometry, material ); + * + * For example: + * + * const materials = []; + * const nGeometryGroups = geometry.groups.length; + * + * const colorMap = ...; // Some logic to index colors. + * + * for (let i = 0; i < nGeometryGroups; i++) { + * + * const material = new THREE.MeshPhongMaterial({ + * color: colorMap[i], + * wireframe: false + * }); + * + * } + * + * materials.push(material); + * const mesh = new THREE.Mesh(geometry, materials); + */ - var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); - if (targetElement) { + class STLLoader extends Loader { - // get the parent of the transfrom element + constructor( manager ) { - var parentVisualElement = targetElement.parentElement; + super( manager ); - // connect the joint of the kinematics model with the element in the visual scene + } - connect(axis.jointIndex, parentVisualElement); + load( url, onLoad, onProgress, onError ) { - } + const scope = this; - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); - function connect(jointIndex, visualElement) { + loader.load( url, function ( text ) { - var visualElementName = visualElement.getAttribute('name'); - var joint = kinematicsModel.joints[jointIndex]; + try { - visualScene.traverse(function (object) { + onLoad( scope.parse( text ) ); - if (object.name === visualElementName) { + } catch ( e ) { - jointMap[jointIndex] = { - object: object, - transforms: buildTransformList(visualElement), - joint: joint, - position: joint.zeroPosition - }; + if ( onError ) { - } + onError( e ); - }); + } else { - } + console.error( e ); - var m0 = new THREE.Matrix4(); + } - kinematics = { + scope.manager.itemError( url ); - joints: kinematicsModel && kinematicsModel.joints, + } - getJointValue: function (jointIndex) { + }, onProgress, onError ); - var jointData = jointMap[jointIndex]; + } - if (jointData) { + parse( data ) { - return jointData.position; + function isBinary( data ) { - } else { + const reader = new DataView( data ); + const face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 ); + const n_faces = reader.getUint32( 80, true ); + const expect = 80 + ( 32 / 8 ) + ( n_faces * face_size ); - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); + if ( expect === reader.byteLength ) { - } + return true; - }, + } - setJointValue: function (jointIndex, value) { + // An ASCII STL data must begin with 'solid ' as the first six bytes. + // However, ASCII STLs lacking the SPACE after the 'd' are known to be + // plentiful. So, check the first 5 bytes for 'solid'. - var jointData = jointMap[jointIndex]; + // Several encodings, such as UTF-8, precede the text with up to 5 bytes: + // https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding + // Search for "solid" to start anywhere after those prefixes. - if (jointData) { + // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' - var joint = jointData.joint; + const solid = [ 115, 111, 108, 105, 100 ]; - if (value > joint.limits.max || value < joint.limits.min) { + for ( let off = 0; off < 5; off ++ ) { - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + // If "solid" text is matched to the current offset, declare it to be an ASCII STL. - } else if (joint.static) { + if ( matchDataViewAt( solid, reader, off ) ) return false; - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + } - } else { + // Couldn't find "solid" text at the beginning; it is binary STL. - var object = jointData.object; - var axis = joint.axis; - var transforms = jointData.transforms; + return true; - matrix.identity(); + } - // each update, we have to apply all transforms in the correct order + function matchDataViewAt( query, reader, offset ) { - for (var i = 0; i < transforms.length; i++) { + // Check if each byte in query matches the corresponding byte from the current offset - var transform = transforms[i]; + for ( let i = 0, il = query.length; i < il; i ++ ) { - // if there is a connection of the transform node with a joint, apply the joint value + if ( query[ i ] !== reader.getUint8( offset + i ) ) return false; - if (transform.sid && transform.sid.indexOf(jointIndex) !== - 1) { + } - switch (joint.type) { + return true; - case 'revolute': - matrix.multiply(m0.makeRotationAxis(axis, THREE.Math.degToRad(value))); - break; + } - case 'prismatic': - matrix.multiply(m0.makeTranslation(axis.x * value, axis.y * value, axis.z * value)); - break; + function parseBinary( data ) { - default: - console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); - break; + const reader = new DataView( data ); + const faces = reader.getUint32( 80, true ); - } + let r, g, b, hasColors = false, colors; + let defaultR, defaultG, defaultB, alpha; - } else { + // process STL header + // check for default color in header ("COLOR=rgba" sequence). - switch (transform.type) { + for ( let index = 0; index < 80 - 10; index ++ ) { - case 'matrix': - matrix.multiply(transform.obj); - break; + if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) && + ( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) && + ( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) { - case 'translate': - matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); - break; + hasColors = true; + colors = new Float32Array( faces * 3 * 3 ); - case 'scale': - matrix.scale(transform.obj); - break; + defaultR = reader.getUint8( index + 6 ) / 255; + defaultG = reader.getUint8( index + 7 ) / 255; + defaultB = reader.getUint8( index + 8 ) / 255; + alpha = reader.getUint8( index + 9 ) / 255; - case 'rotate': - matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); - break; + } - } + } - } + const dataOffset = 84; + const faceLength = 12 * 4 + 2; - } + const geometry = new BufferGeometry(); - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + const vertices = new Float32Array( faces * 3 * 3 ); + const normals = new Float32Array( faces * 3 * 3 ); - jointMap[jointIndex].position = value; + const color = new Color(); - } + for ( let face = 0; face < faces; face ++ ) { - } else { + const start = dataOffset + face * faceLength; + const normalX = reader.getFloat32( start, true ); + const normalY = reader.getFloat32( start + 4, true ); + const normalZ = reader.getFloat32( start + 8, true ); - console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + if ( hasColors ) { - } + const packedColor = reader.getUint16( start + 48, true ); - } + if ( ( packedColor & 0x8000 ) === 0 ) { - }; + // facet has its own unique color - } + r = ( packedColor & 0x1F ) / 31; + g = ( ( packedColor >> 5 ) & 0x1F ) / 31; + b = ( ( packedColor >> 10 ) & 0x1F ) / 31; - function buildTransformList(node) { + } else { - var transforms = []; + r = defaultR; + g = defaultG; + b = defaultB; - var xml = collada.querySelector('[id="' + node.id + '"]'); + } - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + for ( let i = 1; i <= 3; i ++ ) { - if (child.nodeType !== 1) continue; + const vertexstart = start + i * 12; + const componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 ); - switch (child.nodeName) { + vertices[ componentIdx ] = reader.getFloat32( vertexstart, true ); + vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true ); + vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true ); - case 'matrix': - var array = parseFloats(child.textContent); - var matrix = new THREE.Matrix4().fromArray(array).transpose(); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: matrix - }); - break; + normals[ componentIdx ] = normalX; + normals[ componentIdx + 1 ] = normalY; + normals[ componentIdx + 2 ] = normalZ; - case 'translate': - case 'scale': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector - }); - break; + if ( hasColors ) { - case 'rotate': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - var angle = THREE.Math.degToRad(array[3]); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector, - angle: angle - }); - break; + color.set( r, g, b ).convertSRGBToLinear(); - } + colors[ componentIdx ] = color.r; + colors[ componentIdx + 1 ] = color.g; + colors[ componentIdx + 2 ] = color.b; - } + } - return transforms; + } - } + } - // nodes + geometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) ); - function prepareNodes(xml) { + if ( hasColors ) { - var elements = xml.getElementsByTagName('node'); + geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); + geometry.hasColors = true; + geometry.alpha = alpha; - // ensure all node elements have id attributes + } - for (var i = 0; i < elements.length; i++) { + return geometry; - var element = elements[i]; + } - if (element.hasAttribute('id') === false) { + function parseASCII( data ) { - element.setAttribute('id', generateId()); + const geometry = new BufferGeometry(); + const patternSolid = /solid([\s\S]*?)endsolid/g; + const patternFace = /facet([\s\S]*?)endfacet/g; + const patternName = /solid\s(.+)/; + let faceCounter = 0; - } + const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source; + const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' ); + const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' ); - } + const vertices = []; + const normals = []; + const groupNames = []; - } + const normal = new Vector3(); - var matrix = new THREE.Matrix4(); - var vector = new THREE.Vector3(); - - function parseNode(xml) { - - var data = { - name: xml.getAttribute('name') || '', - type: xml.getAttribute('type'), - id: xml.getAttribute('id'), - sid: xml.getAttribute('sid'), - matrix: new THREE.Matrix4(), - nodes: [], - instanceCameras: [], - instanceControllers: [], - instanceLights: [], - instanceGeometries: [], - instanceNodes: [], - transforms: {} - }; + let result; - for (var i = 0; i < xml.childNodes.length; i++) { + let groupCount = 0; + let startVertex = 0; + let endVertex = 0; - var child = xml.childNodes[i]; + while ( ( result = patternSolid.exec( data ) ) !== null ) { - if (child.nodeType !== 1) continue; + startVertex = endVertex; - switch (child.nodeName) { + const solid = result[ 0 ]; - case 'node': - data.nodes.push(child.getAttribute('id')); - parseNode(child); - break; + const name = ( result = patternName.exec( solid ) ) !== null ? result[ 1 ] : ''; + groupNames.push( name ); - case 'instance_camera': - data.instanceCameras.push(parseId(child.getAttribute('url'))); - break; + while ( ( result = patternFace.exec( solid ) ) !== null ) { - case 'instance_controller': - data.instanceControllers.push(parseNodeInstance(child)); - break; + let vertexCountPerFace = 0; + let normalCountPerFace = 0; - case 'instance_light': - data.instanceLights.push(parseId(child.getAttribute('url'))); - break; + const text = result[ 0 ]; - case 'instance_geometry': - data.instanceGeometries.push(parseNodeInstance(child)); - break; + while ( ( result = patternNormal.exec( text ) ) !== null ) { - case 'instance_node': - data.instanceNodes.push(parseId(child.getAttribute('url'))); - break; + normal.x = parseFloat( result[ 1 ] ); + normal.y = parseFloat( result[ 2 ] ); + normal.z = parseFloat( result[ 3 ] ); + normalCountPerFace ++; - case 'matrix': - var array = parseFloats(child.textContent); - data.matrix.multiply(matrix.fromArray(array).transpose()); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + } - case 'translate': - var array = parseFloats(child.textContent); - vector.fromArray(array); - data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + while ( ( result = patternVertex.exec( text ) ) !== null ) { - case 'rotate': - var array = parseFloats(child.textContent); - var angle = THREE.Math.degToRad(array[3]); - data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) ); + normals.push( normal.x, normal.y, normal.z ); + vertexCountPerFace ++; + endVertex ++; - case 'scale': - var array = parseFloats(child.textContent); - data.matrix.scale(vector.fromArray(array)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + } - case 'extra': - break; + // every face have to own ONE valid normal - default: - console.log(child); + if ( normalCountPerFace !== 1 ) { - } + console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter ); - } + } - library.nodes[data.id] = data; + // each face have to own THREE valid vertices - return data; + if ( vertexCountPerFace !== 3 ) { - } + console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter ); - function parseNodeInstance(xml) { + } - var data = { - id: parseId(xml.getAttribute('url')), - materials: {}, - skeletons: [] - }; + faceCounter ++; - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + const start = startVertex; + const count = endVertex - startVertex; - switch (child.nodeName) { + geometry.userData.groupNames = groupNames; - case 'bind_material': - var instances = child.getElementsByTagName('instance_material'); + geometry.addGroup( start, count, groupCount ); + groupCount ++; - for (var j = 0; j < instances.length; j++) { + } - var instance = instances[j]; - var symbol = instance.getAttribute('symbol'); - var target = instance.getAttribute('target'); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - data.materials[symbol] = parseId(target); + return geometry; - } + } - break; + function ensureString( buffer ) { - case 'skeleton': - data.skeletons.push(parseId(child.textContent)); - break; + if ( typeof buffer !== 'string' ) { - } + return new TextDecoder().decode( buffer ); - } + } - return data; + return buffer; - } + } - function buildSkeleton(skeletons, joints) { + function ensureBinary( buffer ) { - var boneData = []; - var sortedBoneData = []; + if ( typeof buffer === 'string' ) { - var i, j, data; + const array_buffer = new Uint8Array( buffer.length ); + for ( let i = 0; i < buffer.length; i ++ ) { - // a skeleton can have multiple root bones. collada expresses this - // situtation with multiple "skeleton" tags per controller instance + array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian - for (i = 0; i < skeletons.length; i++) { + } - var skeleton = skeletons[i]; - var root = getNode(skeleton); + return array_buffer.buffer || array_buffer; - // setup bone data for a single bone hierarchy + } else { - buildBoneHierarchy(root, joints, boneData); + return buffer; - } + } - // sort bone data (the order is defined in the corresponding controller) + } - for (i = 0; i < joints.length; i++) { + // start - for (j = 0; j < boneData.length; j++) { + const binData = ensureBinary( data ); - data = boneData[j]; + return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) ); - if (data.bone.name === joints[i].name) { + } - sortedBoneData[i] = data; - data.processed = true; - break; + } - } + /** + * Loads a Wavefront .mtl file specifying materials + */ - } + class MTLLoader extends Loader { - } + constructor( manager ) { - // add unprocessed bone data at the end of the list + super( manager ); - for (i = 0; i < boneData.length; i++) { + } - data = boneData[i]; + /** + * Loads and parses a MTL asset from a URL. + * + * @param {String} url - URL to the MTL file. + * @param {Function} [onLoad] - Callback invoked with the loaded object. + * @param {Function} [onProgress] - Callback for download progress. + * @param {Function} [onError] - Callback for download errors. + * + * @see setPath setResourcePath + * + * @note In order for relative texture references to resolve correctly + * you must call setResourcePath() explicitly prior to load. + */ + load( url, onLoad, onProgress, onError ) { - if (data.processed === false) { + const scope = this; - sortedBoneData.push(data); - data.processed = true; + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - } + try { - // setup arrays for skeleton creation + onLoad( scope.parse( text, path ) ); - var bones = []; - var boneInverses = []; + } catch ( e ) { - for (i = 0; i < sortedBoneData.length; i++) { + if ( onError ) { - data = sortedBoneData[i]; + onError( e ); - bones.push(data.bone); - boneInverses.push(data.boneInverse); + } else { - } + console.error( e ); - return new THREE.Skeleton(bones, boneInverses); + } - } + scope.manager.itemError( url ); - function buildBoneHierarchy(root, joints, boneData) { + } - // setup bone data from visual scene + }, onProgress, onError ); - root.traverse(function (object) { + } - if (object.isBone === true) { + setMaterialOptions( value ) { - var boneInverse; + this.materialOptions = value; + return this; - // retrieve the boneInverse from the controller data + } - for (var i = 0; i < joints.length; i++) { + /** + * Parses a MTL file. + * + * @param {String} text - Content of MTL file + * @return {MaterialCreator} + * + * @see setPath setResourcePath + * + * @note In order for relative texture references to resolve correctly + * you must call setResourcePath() explicitly prior to parse. + */ + parse( text, path ) { - var joint = joints[i]; + const lines = text.split( '\n' ); + let info = {}; + const delimiter_pattern = /\s+/; + const materialsInfo = {}; - if (joint.name === object.name) { + for ( let i = 0; i < lines.length; i ++ ) { - boneInverse = joint.boneInverse; - break; + let line = lines[ i ]; + line = line.trim(); - } + if ( line.length === 0 || line.charAt( 0 ) === '#' ) { - } + // Blank line or comment ignore + continue; - if (boneInverse === undefined) { + } - // Unfortunately, there can be joints in the visual scene that are not part of the - // corresponding controller. In this case, we have to create a dummy boneInverse matrix - // for the respective bone. This bone won't affect any vertices, because there are no skin indices - // and weights defined for it. But we still have to add the bone to the sorted bone list in order to - // ensure a correct animation of the model. + const pos = line.indexOf( ' ' ); - boneInverse = new THREE.Matrix4(); + let key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; + key = key.toLowerCase(); - } + let value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; + value = value.trim(); - boneData.push({ bone: object, boneInverse: boneInverse, processed: false }); + if ( key === 'newmtl' ) { - } + // New material - }); + info = { name: value }; + materialsInfo[ value ] = info; - } + } else { - function buildNode(data) { + if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { - var objects = []; + const ss = value.split( delimiter_pattern, 3 ); + info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; - var matrix = data.matrix; - var nodes = data.nodes; - var type = data.type; - var instanceCameras = data.instanceCameras; - var instanceControllers = data.instanceControllers; - var instanceLights = data.instanceLights; - var instanceGeometries = data.instanceGeometries; - var instanceNodes = data.instanceNodes; + } else { - // nodes + info[ key ] = value; - for (var i = 0, l = nodes.length; i < l; i++) { + } - objects.push(getNode(nodes[i])); + } - } + } - // instance cameras + const materialCreator = new MaterialCreator( this.resourcePath || path, this.materialOptions ); + materialCreator.setCrossOrigin( this.crossOrigin ); + materialCreator.setManager( this.manager ); + materialCreator.setMaterials( materialsInfo ); + return materialCreator; - for (var i = 0, l = instanceCameras.length; i < l; i++) { + } - var instanceCamera = getCamera(instanceCameras[i]); + } - if (instanceCamera !== null) { + /** + * Create a new MTLLoader.MaterialCreator + * @param baseUrl - Url relative to which textures are loaded + * @param options - Set of options on how to construct the materials + * side: Which side to apply the material + * FrontSide (default), THREE.BackSide, THREE.DoubleSide + * wrap: What type of wrapping to apply for textures + * RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping + * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 + * Default: false, assumed to be already normalized + * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's + * Default: false + * @constructor + */ - objects.push(instanceCamera.clone()); + class MaterialCreator { - } + constructor( baseUrl = '', options = {} ) { + this.baseUrl = baseUrl; + this.options = options; + this.materialsInfo = {}; + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; - } + this.crossOrigin = 'anonymous'; - // instance controllers + this.side = ( this.options.side !== undefined ) ? this.options.side : FrontSide; + this.wrap = ( this.options.wrap !== undefined ) ? this.options.wrap : RepeatWrapping; - for (var i = 0, l = instanceControllers.length; i < l; i++) { + } - var instance = instanceControllers[i]; - var controller = getController(instance.id); - var geometries = getGeometry(controller.id); - var newObjects = buildObjects(geometries, instance.materials); + setCrossOrigin( value ) { - var skeletons = instance.skeletons; - var joints = controller.skin.joints; + this.crossOrigin = value; + return this; - var skeleton = buildSkeleton(skeletons, joints); + } - for (var j = 0, jl = newObjects.length; j < jl; j++) { + setManager( value ) { - var object = newObjects[j]; + this.manager = value; - if (object.isSkinnedMesh) { + } - object.bind(skeleton, controller.skin.bindMatrix); - object.normalizeSkinWeights(); + setMaterials( materialsInfo ) { - } + this.materialsInfo = this.convert( materialsInfo ); + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; - objects.push(object); + } - } + convert( materialsInfo ) { - } + if ( ! this.options ) return materialsInfo; - // instance lights + const converted = {}; - for (var i = 0, l = instanceLights.length; i < l; i++) { - var instanceCamera = getCamera(instanceCameras[i]); + for ( const mn in materialsInfo ) { - if (instanceCamera !== null) { + // Convert materials info into normalized form based on options - objects.push(instanceCamera.clone()); + const mat = materialsInfo[ mn ]; - } + const covmat = {}; - } + converted[ mn ] = covmat; - // instance geometries + for ( const prop in mat ) { - for (var i = 0, l = instanceGeometries.length; i < l; i++) { + let save = true; + let value = mat[ prop ]; + const lprop = prop.toLowerCase(); - var instance = instanceGeometries[i]; + switch ( lprop ) { - // a single geometry instance in collada can lead to multiple object3Ds. - // this is the case when primitives are combined like triangles and lines + case 'kd': + case 'ka': + case 'ks': - var geometries = getGeometry(instance.id); - var newObjects = buildObjects(geometries, instance.materials); + // Diffuse color (color under white light) using RGB values - for (var j = 0, jl = newObjects.length; j < jl; j++) { + if ( this.options && this.options.normalizeRGB ) { - objects.push(newObjects[j]); + value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; - } + } - } + if ( this.options && this.options.ignoreZeroRGBs ) { - // instance nodes + if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { - for (var i = 0, l = instanceNodes.length; i < l; i++) { + // ignore - objects.push(getNode(instanceNodes[i]).clone()); + save = false; - } + } - var object; + } - if (nodes.length === 0 && objects.length === 1) { + break; - object = objects[0]; + } - } else { + if ( save ) { - object = (type === 'JOINT') ? new THREE.Bone() : new THREE.Object3D(); + covmat[ lprop ] = value; - for (var i = 0; i < objects.length; i++) { + } - object.add(objects[i]); + } - } + } - } + return converted; - object.name = (type === 'JOINT') ? data.sid : data.name; - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + } - return object; + preload() { - } + for ( const mn in this.materialsInfo ) { - function resolveMaterialBinding(keys, instanceMaterials) { + this.create( mn ); - var materials = []; + } - for (var i = 0, l = keys.length; i < l; i++) { + } - var id = instanceMaterials[keys[i]]; - materials.push(getMaterial(id)); + getIndex( materialName ) { - } + return this.nameLookup[ materialName ]; - return materials; + } - } + getAsArray() { - function buildObjects(geometries, instanceMaterials) { + let index = 0; - var objects = []; + for ( const mn in this.materialsInfo ) { - for (var type in geometries) { + this.materialsArray[ index ] = this.create( mn ); + this.nameLookup[ mn ] = index; + index ++; - var geometry = geometries[type]; + } - var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); + return this.materialsArray; - // handle case if no materials are defined + } - if (materials.length === 0) { + create( materialName ) { - if (type === 'lines' || type === 'linestrips') { + if ( this.materials[ materialName ] === undefined ) { - materials.push(new THREE.LineBasicMaterial()); + this.createMaterial_( materialName ); - } else { + } - materials.push(new THREE.MeshPhongMaterial()); + return this.materials[ materialName ]; - } + } - } + createMaterial_( materialName ) { - // regard skinning + // Create material - var skinning = (geometry.data.attributes.skinIndex !== undefined); + const scope = this; + const mat = this.materialsInfo[ materialName ]; + const params = { - if (skinning) { + name: materialName, + side: this.side - for (var i = 0, l = materials.length; i < l; i++) { + }; - materials[i].skinning = true; + function resolveURL( baseUrl, url ) { - } + if ( typeof url !== 'string' || url === '' ) + return ''; - } + // Absolute URL + if ( /^https?:\/\//i.test( url ) ) return url; - // choose between a single or multi materials (material array) + return baseUrl + url; - var material = (materials.length === 1) ? materials[0] : materials; + } - // now create a specific 3D object + function setMapForType( mapType, value ) { - var object; + if ( params[ mapType ] ) return; // Keep the first encountered texture - switch (type) { + const texParams = scope.getTextureParams( value, params ); + const map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); - case 'lines': - object = new THREE.LineSegments(geometry.data, material); - break; + map.repeat.copy( texParams.scale ); + map.offset.copy( texParams.offset ); - case 'linestrips': - object = new THREE.Line(geometry.data, material); - break; + map.wrapS = scope.wrap; + map.wrapT = scope.wrap; - case 'triangles': - case 'polylist': - if (skinning) { + if ( mapType === 'map' || mapType === 'emissiveMap' ) { - object = new THREE.SkinnedMesh(geometry.data, material); + map.colorSpace = SRGBColorSpace; - } else { + } - object = new THREE.Mesh(geometry.data, material); + params[ mapType ] = map; - } - break; + } - } + for ( const prop in mat ) { - objects.push(object); + const value = mat[ prop ]; + let n; - } + if ( value === '' ) continue; - return objects; + switch ( prop.toLowerCase() ) { - } + // Ns is material specular exponent - function getNode(id) { + case 'kd': - return getBuild(library.nodes[id], buildNode); + // Diffuse color (color under white light) using RGB values - } + params.color = new Color().fromArray( value ).convertSRGBToLinear(); - // visual scenes + break; - function parseVisualScene(xml) { + case 'ks': - var data = { - name: xml.getAttribute('name'), - children: [] - }; + // Specular color (color when light is reflected from shiny surface) using RGB values + params.specular = new Color().fromArray( value ).convertSRGBToLinear(); - prepareNodes(xml); + break; - var elements = getElementsByTagName(xml, 'node'); + case 'ke': - for (var i = 0; i < elements.length; i++) { + // Emissive using RGB values + params.emissive = new Color().fromArray( value ).convertSRGBToLinear(); - data.children.push(parseNode(elements[i])); + break; - } + case 'map_kd': - library.visualScenes[xml.getAttribute('id')] = data; + // Diffuse texture map - } + setMapForType( 'map', value ); - function buildVisualScene(data) { + break; - var group = new THREE.Object3D(); - group.name = data.name; + case 'map_ks': - var children = data.children; + // Specular map - for (var i = 0; i < children.length; i++) { + setMapForType( 'specularMap', value ); - var child = children[i]; + break; - if (child.id === null) { + case 'map_ke': - group.add(buildNode(child)); + // Emissive map - } else { + setMapForType( 'emissiveMap', value ); - // if there is an ID, let's try to get the finished build (e.g. joints are already build) + break; - group.add(getNode(child.id)); + case 'norm': - } + setMapForType( 'normalMap', value ); - } + break; - return group; + case 'map_bump': + case 'bump': - } + // Bump texture map - function getVisualScene(id) { + setMapForType( 'bumpMap', value ); - return getBuild(library.visualScenes[id], buildVisualScene); + break; - } + case 'map_d': - // scenes + // Alpha map - function parseScene(xml) { + setMapForType( 'alphaMap', value ); + params.transparent = true; - var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; - return getVisualScene(parseId(instance.getAttribute('url'))); + break; - } + case 'ns': - function setupAnimations() { + // The specular exponent (defines the focus of the specular highlight) + // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. - var clips = library.clips; + params.shininess = parseFloat( value ); - if (isEmpty(clips) === true) { + break; - if (isEmpty(library.animations) === false) { + case 'd': + n = parseFloat( value ); - // if there are animations but no clips, we create a default clip for playback + if ( n < 1 ) { - var tracks = []; + params.opacity = n; + params.transparent = true; - for (var id in library.animations) { + } - var animationTracks = getAnimation(id); + break; - for (var i = 0, l = animationTracks.length; i < l; i++) { + case 'tr': + n = parseFloat( value ); - tracks.push(animationTracks[i]); + if ( this.options && this.options.invertTrProperty ) n = 1 - n; - } + if ( n > 0 ) { - } + params.opacity = 1 - n; + params.transparent = true; - animations.push(new THREE.AnimationClip('default', - 1, tracks)); + } - } + break; - } else { + } - for (var id in clips) { + } - animations.push(getAnimationClip(id)); + this.materials[ materialName ] = new MeshPhongMaterial( params ); + return this.materials[ materialName ]; - } + } - } + getTextureParams( value, matParams ) { - } + const texParams = { - console.time('THREE.ColladaLoader'); + scale: new Vector2( 1, 1 ), + offset: new Vector2( 0, 0 ) - if (text.length === 0) { + }; - return { scene: new THREE.Scene() }; + const items = value.split( /\s+/ ); + let pos; - } + pos = items.indexOf( '-bm' ); - console.time('THREE.ColladaLoader: DOMParser'); + if ( pos >= 0 ) { - var xml = new DOMParser().parseFromString(text, 'application/xml'); + matParams.bumpScale = parseFloat( items[ pos + 1 ] ); + items.splice( pos, 2 ); - console.timeEnd('THREE.ColladaLoader: DOMParser'); + } - var collada = getElementsByTagName(xml, 'COLLADA')[0]; + pos = items.indexOf( '-s' ); - // metadata + if ( pos >= 0 ) { - var version = collada.getAttribute('version'); - console.log('THREE.ColladaLoader: File version', version); + texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! - var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); - var textureLoader = new THREE.TextureLoader(this.manager); - textureLoader.setPath(path).setCrossOrigin(this.crossOrigin); + } - // + pos = items.indexOf( '-o' ); - var animations = []; - var kinematics = {}; - var count = 0; + if ( pos >= 0 ) { - // + texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! - var library = { - animations: {}, - clips: {}, - controllers: {}, - images: {}, - effects: {}, - materials: {}, - cameras: {}, - lights: {}, - geometries: {}, - nodes: {}, - visualScenes: {}, - kinematicsModels: {}, - kinematicsScenes: {} - }; + } - console.time('THREE.ColladaLoader: Parse'); + texParams.url = items.join( ' ' ).trim(); + return texParams; - parseLibrary(collada, 'library_animations', 'animation', parseAnimation); - parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); - parseLibrary(collada, 'library_controllers', 'controller', parseController); - parseLibrary(collada, 'library_images', 'image', parseImage); - parseLibrary(collada, 'library_effects', 'effect', parseEffect); - parseLibrary(collada, 'library_materials', 'material', parseMaterial); - parseLibrary(collada, 'library_cameras', 'camera', parseCamera); - parseLibrary(collada, 'library_lights', 'light', parseLight); - parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); - parseLibrary(collada, 'library_nodes', 'node', parseNode); - parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); - parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); - parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + } - console.timeEnd('THREE.ColladaLoader: Parse'); + loadTexture( url, mapping, onLoad, onProgress, onError ) { - console.time('THREE.ColladaLoader: Build'); + const manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager; + let loader = manager.getHandler( url ); - buildLibrary(library.animations, buildAnimation); - buildLibrary(library.clips, buildAnimationClip); - buildLibrary(library.controllers, buildController); - buildLibrary(library.images, buildImage); - buildLibrary(library.effects, buildEffect); - buildLibrary(library.materials, buildMaterial); - buildLibrary(library.cameras, buildCamera); - buildLibrary(library.lights, buildLight); - buildLibrary(library.geometries, buildGeometry); - buildLibrary(library.visualScenes, buildVisualScene); + if ( loader === null ) { - console.timeEnd('THREE.ColladaLoader: Build'); + loader = new TextureLoader( manager ); - setupAnimations(); - setupKinematics(); + } - var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); - /* - * up_axis of some robot models in ROS world aren't properly set because - * rviz ignores this field. Thus, ignores Z_UP to show urdfs just like rviz. - * See https://github.com/ros-visualization/rviz/issues/1045 for the detail - if ( asset.upAxis === 'Z_UP' ) { + const texture = loader.load( url, onLoad, onProgress, onError ); - scene.rotation.x = - Math.PI / 2; + if ( mapping !== undefined ) texture.mapping = mapping; - } - */ + return texture; - scene.scale.multiplyScalar(asset.unit); + } - console.timeEnd('THREE.ColladaLoader'); + } - return { - animations: animations, - kinematics: kinematics, - library: library, - scene: scene - }; + var MeshLoader = { + onError: function onError(error) { + console.error(error); + }, + loaders: { + 'dae': function dae(meshRes, uri, options) { + var loader = new ColladaLoader(options.loader); + console.log('Loading collada: ' + uri); + loader.load(uri, function (collada_mesh) { + var model = collada_mesh.scene; + meshRes.add(model); + console.log('Done loading collada'); + }); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + return loader; + }, + 'obj': function obj(meshRes, uri, options) { + options.material; + var loader = new OBJLoader(options.loader); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + //Reload the mesh again after materials have been loaded + // @todo: this should be improved so that the file doesn't need to be + // reloaded however that would involve more changes within the OBJLoader. + function onMaterialsLoaded(loader, materials) { + loader.setMaterials(materials).load(uri, function OBJMaterialsReady(obj) { + // add the container group + meshRes.add(obj); + }, null, MeshLoader.onError); + } + loader.load(uri, function OBJFileReady(obj) { + var baseUri = LoaderUtils.extractUrlBase(uri); + if (obj.materialLibraries.length) { + // load the material libraries + var materialUri = obj.materialLibraries[0]; + new MTLLoader(options.loader).setPath(baseUri).load(materialUri, function (materials) { + materials.preload(); + onMaterialsLoaded(loader, materials); + }, null, MeshLoader.onError); + } else { + // add the container group + meshRes.add(obj); + } + }, /*onProgress=*/null, MeshLoader.onError); + return loader; + }, + 'stl': function stl(meshRes, uri, options) { + var material = options.material; + var loader = new STLLoader(options.loader); + { + loader.load(uri, function (geometry) { + geometry.computeVertexNormals(); + var mesh; + if (material !== null) { + mesh = new Mesh(geometry, material); + } else { + mesh = new Mesh(geometry, new MeshBasicMaterial({ + color: 0x999999 + })); + } + meshRes.add(mesh); + }, /*onProgress=*/null, MeshLoader.onError); + } + return loader; + } } - }; - /** - * @fileOverview - * @author Jose Rojas - jrojas@redlinesolutions.co - */ - - /** - * MeshLoader is a singleton factory class for using various helper classes to - * load mesh files of different types. - * - * It consists of one dictionary property 'loaders'. The dictionary keys consist - * of the file extension for each supported loader type. The dictionary values - * are functions used to construct the loader objects. The functions have the - * following parameters: - * - * * meshRes - the MeshResource that will contain the loaded mesh - * * uri - the uri path to the mesh file - * @returns loader object - */ - var MeshLoader = { - onError: function(error) { - console.error(error); - }, - loaders: { - 'dae': function(meshRes, uri, options) { - const material = options.material; - const loader = new THREE.ColladaLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - loader.load( - uri, - function colladaReady(collada) { - // check for a scale factor in ColladaLoader2 - // add a texture to anything that is missing one - if(material !== null) { - collada.scene.traverse(function(child) { - if(child instanceof THREE.Mesh) { - if(child.material === undefined) { - child.material = material; - } - } - }); - } - - meshRes.add(collada.scene); - }, - /*onProgress=*/null, - MeshLoader.onError); - return loader; - }, - - 'obj': function(meshRes, uri, options) { - options.material; - const loader = new THREE.OBJLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - - //Reload the mesh again after materials have been loaded - // @todo: this should be improved so that the file doesn't need to be - // reloaded however that would involve more changes within the OBJLoader. - function onMaterialsLoaded(loader, materials) { - loader. - setMaterials(materials). - load( - uri, - function OBJMaterialsReady(obj) { - // add the container group - meshRes.add(obj); - }, - null, - MeshLoader.onError); - } - - loader.load( - uri, - function OBJFileReady(obj) { - - const baseUri = THREE.LoaderUtils.extractUrlBase( uri ); - - if (obj.materialLibraries.length) { - // load the material libraries - const materialUri = obj.materialLibraries[0]; - new THREE.MTLLoader(options.loader).setPath(baseUri).load( - materialUri, - function(materials) { - materials.preload(); - onMaterialsLoaded(loader, materials); - }, - null, - MeshLoader.onError - ); - } else { - // add the container group - meshRes.add(obj); - } - - }, - /*onProgress=*/null, - MeshLoader.onError - ); - return loader; - }, - - 'stl': function(meshRes, uri, options) { - const material = options.material; - const loader = new THREE.STLLoader(options.loader); - { - loader.load(uri, - function ( geometry ) { - geometry.computeFaceNormals(); - var mesh; - if(material !== null) { - mesh = new THREE.Mesh( geometry, material ); - } else { - mesh = new THREE.Mesh( geometry, - new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); - } - meshRes.add(mesh); - }, - /*onProgress=*/null, - MeshLoader.onError); - } - return loader; - } - - } - }; + function _callSuper$w(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$w() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$w() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$w = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -51896,8 +42184,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Russell Toris - rctoris@wpi.edu */ - class MeshResource extends THREE.Object3D { - + var MeshResource = /*#__PURE__*/function (_THREE$Object3D) { /** * A MeshResource is an THREE object that will load from a external mesh file. Currently loads * Collada files. @@ -51910,40 +42197,45 @@ var ROS3D = (function (exports, ROSLIB) { * * material (optional) - the material to use for the object * * warnings (optional) - if warnings should be printed */ - constructor(options) { - super(); + function MeshResource(options) { + var _this; + _classCallCheck(this, MeshResource); + _this = _callSuper$w(this, MeshResource); options = options || {}; var path = options.path || '/'; var resource = options.resource; options.material || null; - this.warnings = options.warnings; - + _this.warnings = options.warnings; // check for a trailing '/' if (path.substr(path.length - 1) !== '/') { path += '/'; } - var uri = path + resource; var fileType = uri.substr(-3).toLowerCase(); // check the type var loaderFunc = MeshLoader.loaders[fileType]; if (loaderFunc) { - loaderFunc(this, uri, options); + loaderFunc(_this, uri, options); } else { console.warn('Unsupported loader for file type: \'' + fileType + '\''); } - }; - } + return _this; + } + _inherits(MeshResource, _THREE$Object3D); + return _createClass(MeshResource); + }(Object3D); + + function _callSuper$v(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$v() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$v() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$v = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class TriangleList extends THREE.Object3D { - + var TriangleList = /*#__PURE__*/function (_THREE$Object3D) { /** * A TriangleList is a THREE object that can be used to display a list of triangles as a geometry. * @@ -51954,69 +42246,87 @@ var ROS3D = (function (exports, ROSLIB) { * * vertices - the array of vertices to use * * colors - the associated array of colors to use */ - constructor(options) { + function TriangleList(options) { + var _this; + _classCallCheck(this, TriangleList); options = options || {}; - var material = options.material || new THREE.MeshBasicMaterial(); + var material = options.material || new MeshBasicMaterial(); var vertices = options.vertices; var colors = options.colors; - - super(); + _this = _callSuper$v(this, TriangleList); // set the material to be double sided - material.side = THREE.DoubleSide; - - // construct the geometry - var geometry = new THREE.Geometry(); - for (i = 0; i < vertices.length; i++) { - geometry.vertices.push(new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)); + material.side = DoubleSide; + + // Construct the geometry + var geometry = new BufferGeometry(); + var verticesArray = new Float32Array(vertices.length * 3); + for (var _i = 0; _i < vertices.length; _i++) { + verticesArray[_i * 3] = vertices[_i].x; + verticesArray[_i * 3 + 1] = vertices[_i].y; + verticesArray[_i * 3 + 2] = vertices[_i].z; } + geometry.setAttribute('position', new BufferAttribute(verticesArray, 3)); - // set the colors + // Set the colors var i, j; if (colors.length === vertices.length) { - // use per-vertex color - for (i = 0; i < vertices.length; i += 3) { - var faceVert = new THREE.Face3(i, i + 1, i + 2); - for (j = i * 3; j < i * 3 + 3; i++) { - var color = new THREE.Color(); - color.setRGB(colors[i].r, colors[i].g, colors[i].b); - faceVert.vertexColors.push(color); - } - geometry.faces.push(faceVert); + // Use per-vertex color + var vertexColors = new Float32Array(colors.length * 3); + for (i = 0; i < colors.length; i++) { + vertexColors[i * 3] = colors[i].r; + vertexColors[i * 3 + 1] = colors[i].g; + vertexColors[i * 3 + 2] = colors[i].b; } - material.vertexColors = THREE.VertexColors; + geometry.setAttribute('color', new BufferAttribute(vertexColors, 3)); + material.vertexColors = true; } else if (colors.length === vertices.length / 3) { - // use per-triangle color - for (i = 0; i < vertices.length; i += 3) { - var faceTri = new THREE.Face3(i, i + 1, i + 2); - faceTri.color.setRGB(colors[i / 3].r, colors[i / 3].g, colors[i / 3].b); - geometry.faces.push(faceTri); + // Use per-triangle color + var faceColors = new Float32Array(vertices.length); + for (i = 0; i < colors.length; i++) { + var color = new Color(colors[i].r, colors[i].g, colors[i].b); + for (j = 0; j < 9; j += 3) { + faceColors[i * 9 + j] = color.r; + faceColors[i * 9 + j + 1] = color.g; + faceColors[i * 9 + j + 2] = color.b; + } } - material.vertexColors = THREE.FaceColors; + geometry.setAttribute('color', new BufferAttribute(faceColors, 3)); + material.vertexColors = true; } else { - // use marker color + // Use marker color + var defaultColor = new Color(1, 1, 1); // Default color + var _faceColors = new Float32Array(vertices.length); for (i = 0; i < vertices.length; i += 3) { - var face = new THREE.Face3(i, i + 1, i + 2); - geometry.faces.push(face); + _faceColors[i * 3] = defaultColor.r; + _faceColors[i * 3 + 1] = defaultColor.g; + _faceColors[i * 3 + 2] = defaultColor.b; } + geometry.setAttribute('color', new BufferAttribute(_faceColors, 3)); } - geometry.computeBoundingBox(); geometry.computeBoundingSphere(); geometry.computeFaceNormals(); + _this.add(new Mesh(geometry, material)); + return _this; + } + _inherits(TriangleList, _THREE$Object3D); + return _createClass(TriangleList, [{ + key: "setColor", + value: + /** + * Set the color of this object to the given hex value. + * + * @param hex - the hex value of the color to set + */ + function setColor(hex) { + this.mesh.material.color.setHex(hex); + } + }]); + }(Object3D); - this.add(new THREE.Mesh(geometry, material)); - }; - - /** - * Set the color of this object to the given hex value. - * - * @param hex - the hex value of the color to set - */ - setColor(hex) { - this.mesh.material.color.setHex(hex); - }; - } + function _callSuper$u(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$u() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$u() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$u = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -52024,8 +42334,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Russell Toris - rctoris@wpi.edu */ - class Marker extends THREE.Object3D { - + var Marker = /*#__PURE__*/function (_THREE$Object3D) { /** * A Marker can convert a ROS marker message into a THREE object. * @@ -52035,9 +42344,10 @@ var ROS3D = (function (exports, ROSLIB) { * * path - the base path or URL for any mesh files that will be loaded for this marker * * message - the marker message */ - constructor(options) { - super(); - + function Marker(options) { + var _this; + _classCallCheck(this, Marker); + _this = _callSuper$u(this, Marker); options = options || {}; var path = options.path || '/'; var message = options.message; @@ -52046,20 +42356,17 @@ var ROS3D = (function (exports, ROSLIB) { if (path.substr(path.length - 1) !== '/') { path += '/'; } - - if(message.scale) { - this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; - } - else { - this.msgScale = [1,1,1]; + if (message.scale) { + _this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } else { + _this.msgScale = [1, 1, 1]; } - this.msgColor = message.color; - this.msgMesh = undefined; + _this.msgColor = message.color; + _this.msgMesh = undefined; // set the pose and get the color - this.setPose(message.pose); - var colorMaterial = makeColorMaterial(this.msgColor.r, - this.msgColor.g, this.msgColor.b, this.msgColor.a); + _this.setPose(message.pose); + var colorMaterial = makeColorMaterial(_this.msgColor.r, _this.msgColor.g, _this.msgColor.b, _this.msgColor.a); // create the object based on the type switch (message.type) { @@ -52071,64 +42378,64 @@ var ROS3D = (function (exports, ROSLIB) { var shaftDiameter = headDiameter * 0.5; // determine the points - var direction, p1 = null; + var direction, + p1 = null; if (message.points.length === 2) { - p1 = new THREE.Vector3(message.points[0].x, message.points[0].y, message.points[0].z); - var p2 = new THREE.Vector3(message.points[1].x, message.points[1].y, message.points[1].z); + p1 = new Vector3(message.points[0].x, message.points[0].y, message.points[0].z); + var p2 = new Vector3(message.points[1].x, message.points[1].y, message.points[1].z); direction = p1.clone().negate().add(p2); // direction = p2 - p1; len = direction.length(); headDiameter = message.scale.y; shaftDiameter = message.scale.x; - if (message.scale.z !== 0.0) { headLength = message.scale.z; } } // add the marker - this.add(new Arrow({ - direction : direction, - origin : p1, - length : len, - headLength : headLength, - shaftDiameter : shaftDiameter, - headDiameter : headDiameter, - material : colorMaterial + _this.add(new Arrow({ + direction: direction, + origin: p1, + length: len, + headLength: headLength, + shaftDiameter: shaftDiameter, + headDiameter: headDiameter, + material: colorMaterial })); break; case MARKER_CUBE: // set the cube dimensions - var cubeGeom = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); - this.add(new THREE.Mesh(cubeGeom, colorMaterial)); + var cubeGeom = new BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + _this.add(new Mesh(cubeGeom, colorMaterial)); break; case MARKER_SPHERE: // set the sphere dimensions - var sphereGeom = new THREE.SphereGeometry(0.5); - var sphereMesh = new THREE.Mesh(sphereGeom, colorMaterial); + var sphereGeom = new SphereGeometry(0.5); + var sphereMesh = new Mesh(sphereGeom, colorMaterial); sphereMesh.scale.x = message.scale.x; sphereMesh.scale.y = message.scale.y; sphereMesh.scale.z = message.scale.z; - this.add(sphereMesh); + _this.add(sphereMesh); break; case MARKER_CYLINDER: // set the cylinder dimensions - var cylinderGeom = new THREE.CylinderGeometry(0.5, 0.5, 1, 16, 1, false); - var cylinderMesh = new THREE.Mesh(cylinderGeom, colorMaterial); - cylinderMesh.quaternion.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI * 0.5); + var cylinderGeom = new CylinderGeometry(0.5, 0.5, 1, 16, 1, false); + var cylinderMesh = new Mesh(cylinderGeom, colorMaterial); + cylinderMesh.quaternion.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI * 0.5); cylinderMesh.scale.set(message.scale.x, message.scale.z, message.scale.y); - this.add(cylinderMesh); + _this.add(cylinderMesh); break; case MARKER_LINE_STRIP: - var lineStripGeom = new THREE.Geometry(); - var lineStripMaterial = new THREE.LineBasicMaterial({ - linewidth : message.scale.x + var lineStripGeom = new BufferGeometry(); + var lineStripMaterial = new LineBasicMaterial({ + linewidth: message.scale.x }); // add the points var j; - for ( j = 0; j < message.points.length; j++) { - var pt = new THREE.Vector3(); + for (j = 0; j < message.points.length; j++) { + var pt = new Vector3(); pt.x = message.points[j].x; pt.y = message.points[j].y; pt.z = message.points[j].z; @@ -52138,8 +42445,8 @@ var ROS3D = (function (exports, ROSLIB) { // determine the colors for each if (message.colors.length === message.points.length) { lineStripMaterial.vertexColors = true; - for ( j = 0; j < message.points.length; j++) { - var clr = new THREE.Color(); + for (j = 0; j < message.points.length; j++) { + var clr = new Color(); clr.setRGB(message.colors[j].r, message.colors[j].g, message.colors[j].b); lineStripGeom.colors.push(clr); } @@ -52148,18 +42455,18 @@ var ROS3D = (function (exports, ROSLIB) { } // add the line - this.add(new THREE.Line(lineStripGeom, lineStripMaterial)); + _this.add(new Line(lineStripGeom, lineStripMaterial)); break; case MARKER_LINE_LIST: - var lineListGeom = new THREE.Geometry(); - var lineListMaterial = new THREE.LineBasicMaterial({ - linewidth : message.scale.x + var lineListGeom = new BufferGeometry(); + var lineListMaterial = new LineBasicMaterial({ + linewidth: message.scale.x }); // add the points var k; - for ( k = 0; k < message.points.length; k++) { - var v = new THREE.Vector3(); + for (k = 0; k < message.points.length; k++) { + var v = new Vector3(); v.x = message.points[k].x; v.y = message.points[k].y; v.z = message.points[k].z; @@ -52169,8 +42476,8 @@ var ROS3D = (function (exports, ROSLIB) { // determine the colors for each if (message.colors.length === message.points.length) { lineListMaterial.vertexColors = true; - for ( k = 0; k < message.points.length; k++) { - var c = new THREE.Color(); + for (k = 0; k < message.points.length; k++) { + var c = new Color(); c.setRGB(message.colors[k].r, message.colors[k].g, message.colors[k].b); lineListGeom.colors.push(c); } @@ -52179,62 +42486,59 @@ var ROS3D = (function (exports, ROSLIB) { } // add the line - this.add(new THREE.LineSegments(lineListGeom, lineListMaterial)); + _this.add(new LineSegments(lineListGeom, lineListMaterial)); break; case MARKER_CUBE_LIST: // holds the main object - var object = new THREE.Object3D(); + var object = new Object3D(); // check if custom colors should be used var numPoints = message.points.length; - var createColors = (numPoints === message.colors.length); + var createColors = numPoints === message.colors.length; // do not render giant lists var stepSize = Math.ceil(numPoints / 1250); // add the points var p, cube, curColor, newMesh; - for (p = 0; p < numPoints; p+=stepSize) { - cube = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + for (p = 0; p < numPoints; p += stepSize) { + cube = new BoxGeometry(message.scale.x, message.scale.y, message.scale.z); // check the color - if(createColors) { + if (createColors) { curColor = makeColorMaterial(message.colors[p].r, message.colors[p].g, message.colors[p].b, message.colors[p].a); } else { curColor = colorMaterial; } - - newMesh = new THREE.Mesh(cube, curColor); + newMesh = new Mesh(cube, curColor); newMesh.position.x = message.points[p].x; newMesh.position.y = message.points[p].y; newMesh.position.z = message.points[p].z; object.add(newMesh); } - - this.add(object); + _this.add(object); break; case MARKER_SPHERE_LIST: // holds the main object - var sphereObject = new THREE.Object3D(); + var sphereObject = new Object3D(); // check if custom colors should be used var numSpherePoints = message.points.length; - var createSphereColors = (numSpherePoints === message.colors.length); + var createSphereColors = numSpherePoints === message.colors.length; // do not render giant lists var sphereStepSize = Math.ceil(numSpherePoints / 1250); // add the points var q, sphere, curSphereColor, newSphereMesh; - for (q = 0; q < numSpherePoints; q+=sphereStepSize) { - sphere = new THREE.SphereGeometry(0.5, 8, 8); + for (q = 0; q < numSpherePoints; q += sphereStepSize) { + sphere = new SphereGeometry(0.5, 8, 8); // check the color - if(createSphereColors) { + if (createSphereColors) { curSphereColor = makeColorMaterial(message.colors[q].r, message.colors[q].g, message.colors[q].b, message.colors[q].a); } else { curSphereColor = colorMaterial; } - - newSphereMesh = new THREE.Mesh(sphere, curSphereColor); + newSphereMesh = new Mesh(sphere, curSphereColor); newSphereMesh.scale.x = message.scale.x; newSphereMesh.scale.y = message.scale.y; newSphereMesh.scale.z = message.scale.z; @@ -52243,19 +42547,19 @@ var ROS3D = (function (exports, ROSLIB) { newSphereMesh.position.z = message.points[q].z; sphereObject.add(newSphereMesh); } - this.add(sphereObject); + _this.add(sphereObject); break; case MARKER_POINTS: // for now, use a particle system for the lists - var geometry = new THREE.Geometry(); - var material = new THREE.PointsMaterial({ - size : message.scale.x + var geometry = new BufferGeometry(); + var material = new PointsMaterial({ + size: message.scale.x }); // add the points var i; - for ( i = 0; i < message.points.length; i++) { - var vertex = new THREE.Vector3(); + for (i = 0; i < message.points.length; i++) { + var vertex = new Vector3(); vertex.x = message.points[i].x; vertex.y = message.points[i].y; vertex.z = message.points[i].z; @@ -52265,8 +42569,8 @@ var ROS3D = (function (exports, ROSLIB) { // determine the colors for each if (message.colors.length === message.points.length) { material.vertexColors = true; - for ( i = 0; i < message.points.length; i++) { - var color = new THREE.Color(); + for (i = 0; i < message.points.length; i++) { + var color = new Color(); color.setRGB(message.colors[i].r, message.colors[i].g, message.colors[i].b); geometry.colors.push(color); } @@ -52275,23 +42579,21 @@ var ROS3D = (function (exports, ROSLIB) { } // add the particle system - this.add(new THREE.Points(geometry, material)); + _this.add(new Points$1(geometry, material)); break; case MARKER_TEXT_VIEW_FACING: // only work on non-empty text if (message.text.length > 0) { // Use a THREE.Sprite to always be view-facing // ( code from http://stackoverflow.com/a/27348780 ) - var textColor = this.msgColor; - + var textColor = _this.msgColor; var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var textHeight = 100; var fontString = 'normal ' + textHeight + 'px sans-serif'; context.font = fontString; - var metrics = context.measureText( message.text ); + var metrics = context.measureText(message.text); var textWidth = metrics.width; - canvas.width = textWidth; // To account for overhang (like the letter 'g'), make the canvas bigger // The non-text portion is transparent anyway @@ -52299,223 +42601,214 @@ var ROS3D = (function (exports, ROSLIB) { // this does need to be set again context.font = fontString; - context.fillStyle = 'rgba(' - + Math.round(255 * textColor.r) + ', ' - + Math.round(255 * textColor.g) + ', ' - + Math.round(255 * textColor.b) + ', ' - + textColor.a + ')'; + context.fillStyle = 'rgba(' + Math.round(255 * textColor.r) + ', ' + Math.round(255 * textColor.g) + ', ' + Math.round(255 * textColor.b) + ', ' + textColor.a + ')'; context.textAlign = 'left'; context.textBaseline = 'middle'; - context.fillText( message.text, 0, canvas.height/2); - - var texture = new THREE.Texture(canvas); + context.fillText(message.text, 0, canvas.height / 2); + var texture = new Texture(canvas); texture.needsUpdate = true; - - var spriteMaterial = new THREE.SpriteMaterial({ + var spriteMaterial = new SpriteMaterial({ map: texture, // NOTE: This is needed for THREE.js r61, unused in r70 - useScreenCoordinates: false }); - var sprite = new THREE.Sprite( spriteMaterial ); + useScreenCoordinates: false + }); + var sprite = new Sprite(spriteMaterial); var textSize = message.scale.x; sprite.scale.set(textWidth / canvas.height * textSize, textSize, 1); - - this.add(sprite); } + _this.add(sprite); + } break; case MARKER_MESH_RESOURCE: // load and add the mesh var meshColorMaterial = null; - if(message.color.r !== 0 || message.color.g !== 0 || - message.color.b !== 0 || message.color.a !== 0) { + if (message.color.r !== 0 || message.color.g !== 0 || message.color.b !== 0 || message.color.a !== 0) { meshColorMaterial = colorMaterial; } - this.msgMesh = message.mesh_resource.substr(10); + _this.msgMesh = message.mesh_resource.substr(10); var meshResource = new MeshResource({ - path : path, - resource : this.msgMesh, - material : meshColorMaterial, + path: path, + resource: _this.msgMesh, + material: meshColorMaterial }); - this.add(meshResource); + _this.add(meshResource); break; case MARKER_TRIANGLE_LIST: // create the list of triangles var tri = new TriangleList({ - material : colorMaterial, - vertices : message.points, - colors : message.colors + material: colorMaterial, + vertices: message.points, + colors: message.colors }); tri.scale.set(message.scale.x, message.scale.y, message.scale.z); - this.add(tri); + _this.add(tri); break; default: console.error('Currently unsupported marker type: ' + message.type); break; } - }; - - /** - * Set the pose of this marker to the given values. - * - * @param pose - the pose to set for this marker - */ - setPose(pose) { - // set position information - this.position.x = pose.position.x; - this.position.y = pose.position.y; - this.position.z = pose.position.z; - - // set the rotation - this.quaternion.set(pose.orientation.x, pose.orientation.y, - pose.orientation.z, pose.orientation.w); - this.quaternion.normalize(); - - // update the world - this.updateMatrixWorld(); - }; + return _this; + } + _inherits(Marker, _THREE$Object3D); + return _createClass(Marker, [{ + key: "setPose", + value: + /** + * Set the pose of this marker to the given values. + * + * @param pose - the pose to set for this marker + */ + function setPose(pose) { + // set position information + this.position.x = pose.position.x; + this.position.y = pose.position.y; + this.position.z = pose.position.z; - /** - * Update this marker. - * - * @param message - the marker message - * @return true on success otherwhise false is returned - */ - update(message) { - // set the pose and get the color - this.setPose(message.pose); + // set the rotation + this.quaternion.set(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + this.quaternion.normalize(); - // Update color - if(message.color.r !== this.msgColor.r || - message.color.g !== this.msgColor.g || - message.color.b !== this.msgColor.b || - message.color.a !== this.msgColor.a) - { - var colorMaterial = makeColorMaterial( - message.color.r, message.color.g, - message.color.b, message.color.a); + // update the world + this.updateMatrixWorld(); + } + }, { + key: "update", + value: + /** + * Update this marker. + * + * @param message - the marker message + * @return true on success otherwhise false is returned + */ + function update(message) { + // set the pose and get the color + this.setPose(message.pose); + // Update color + if (message.color.r !== this.msgColor.r || message.color.g !== this.msgColor.g || message.color.b !== this.msgColor.b || message.color.a !== this.msgColor.a) { + var colorMaterial = makeColorMaterial(message.color.r, message.color.g, message.color.b, message.color.a); switch (message.type) { - case MARKER_LINE_STRIP: - case MARKER_LINE_LIST: - case MARKER_POINTS: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_POINTS: break; - case MARKER_ARROW: - case MARKER_CUBE: - case MARKER_SPHERE: - case MARKER_CYLINDER: - case MARKER_TRIANGLE_LIST: - case MARKER_TEXT_VIEW_FACING: - this.traverse (function (child){ - if (child instanceof THREE.Mesh) { - child.material = colorMaterial; - } + case MARKER_ARROW: + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + case MARKER_TRIANGLE_LIST: + case MARKER_TEXT_VIEW_FACING: + this.traverse(function (child) { + if (child instanceof Mesh) { + child.material = colorMaterial; + } }); break; - case MARKER_MESH_RESOURCE: + case MARKER_MESH_RESOURCE: var meshColorMaterial = null; - if(message.color.r !== 0 || message.color.g !== 0 || - message.color.b !== 0 || message.color.a !== 0) { - meshColorMaterial = this.colorMaterial; + if (message.color.r !== 0 || message.color.g !== 0 || message.color.b !== 0 || message.color.a !== 0) { + meshColorMaterial = this.colorMaterial; } - this.traverse (function (child){ - if (child instanceof THREE.Mesh) { - child.material = meshColorMaterial; - } + this.traverse(function (child) { + if (child instanceof Mesh) { + child.material = meshColorMaterial; + } }); break; - case MARKER_CUBE_LIST: - case MARKER_SPHERE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: // TODO Support to update color for MARKER_CUBE_LIST & MARKER_SPHERE_LIST return false; - default: + default: return false; } - this.msgColor = message.color; - } - - // Update geometry - var scaleChanged = - Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || - Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || - Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; - this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } - switch (message.type) { - case MARKER_CUBE: - case MARKER_SPHERE: - case MARKER_CYLINDER: - if(scaleChanged) { - return false; + // Update geometry + var scaleChanged = Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; + this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + switch (message.type) { + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + if (scaleChanged) { + return false; } break; - case MARKER_TEXT_VIEW_FACING: - if(scaleChanged || this.text !== message.text) { - return false; + case MARKER_TEXT_VIEW_FACING: + if (scaleChanged || this.text !== message.text) { + return false; } break; - case MARKER_MESH_RESOURCE: + case MARKER_MESH_RESOURCE: var meshResource = message.mesh_resource.substr(10); - if(meshResource !== this.msgMesh) { - return false; + if (meshResource !== this.msgMesh) { + return false; } - if(scaleChanged) { - return false; + if (scaleChanged) { + return false; } break; - case MARKER_ARROW: - case MARKER_LINE_STRIP: - case MARKER_LINE_LIST: - case MARKER_CUBE_LIST: - case MARKER_SPHERE_LIST: - case MARKER_POINTS: - case MARKER_TRIANGLE_LIST: + case MARKER_ARROW: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: + case MARKER_POINTS: + case MARKER_TRIANGLE_LIST: // TODO: Check if geometry changed return false; + } + return true; } - - return true; - }; - - /* - * Free memory of elements in this marker. - */ - dispose() { - this.children.forEach(function(element) { - if (element instanceof MeshResource) { - element.children.forEach(function(scene) { - if (scene.material !== undefined) { - scene.material.dispose(); - } - scene.children.forEach(function(mesh) { - if (mesh.geometry !== undefined) { - mesh.geometry.dispose(); - } - if (mesh.material !== undefined) { - mesh.material.dispose(); + }, { + key: "dispose", + value: + /* + * Free memory of elements in this marker. + */ + function dispose() { + this.children.forEach(function (element) { + if (element instanceof MeshResource) { + element.children.forEach(function (scene) { + if (scene.material !== undefined) { + scene.material.dispose(); } - scene.remove(mesh); + scene.children.forEach(function (mesh) { + if (mesh.geometry !== undefined) { + mesh.geometry.dispose(); + } + if (mesh.material !== undefined) { + mesh.material.dispose(); + } + scene.remove(mesh); + }); + element.remove(scene); }); - element.remove(scene); - }); - } else { - if (element.geometry !== undefined) { + } else { + if (element.geometry !== undefined) { element.geometry.dispose(); - } - if (element.material !== undefined) { + } + if (element.material !== undefined) { element.material.dispose(); + } } - } - element.parent.remove(element); - }); - }; - } + element.parent.remove(element); + }); + } + }]); + }(Object3D); + + function _callSuper$t(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$t() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$t() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$t = function _isNativeReflectConstruct() { return !!t; })(); } + function _superPropGet(t, e, r, o) { var p = _get(_getPrototypeOf(1 & o ? t.prototype : t), e, r); return 2 & o ? function (t) { return p.apply(r, t); } : p; } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class InteractiveMarkerControl extends THREE.Object3D { - + var InteractiveMarkerControl = /*#__PURE__*/function (_THREE$Object3D) { /** * The main marker control object for an interactive marker. * @@ -52528,55 +42821,51 @@ var ROS3D = (function (exports, ROSLIB) { * * path (optional) - the base path to any meshes that will be loaded * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) */ - constructor(options) { - super(); - var that = this; - + function InteractiveMarkerControl(options) { + var _this; + _classCallCheck(this, InteractiveMarkerControl); + _this = _callSuper$t(this, InteractiveMarkerControl); + var that = _this; options = options || {}; - this.parent = options.parent; + _this.parent = options.parent; var handle = options.handle; var message = options.message; - this.message = message; - this.name = message.name; - this.camera = options.camera; - this.path = options.path || '/'; - this.loader = options.loader; - this.dragging = false; - this.startMousePos = new THREE.Vector2(); - this.isShift = false; - + _this.message = message; + _this.name = message.name; + _this.camera = options.camera; + _this.path = options.path || '/'; + _this.loader = options.loader; + _this.dragging = false; + _this.startMousePos = new Vector2(); + _this.isShift = false; // orientation for the control - var controlOri = new THREE.Quaternion(message.orientation.x, message.orientation.y, - message.orientation.z, message.orientation.w); + var controlOri = new Quaternion(message.orientation.x, message.orientation.y, message.orientation.z, message.orientation.w); controlOri.normalize(); // transform x axis into local frame - var controlAxis = new THREE.Vector3(1, 0, 0); + var controlAxis = new Vector3(1, 0, 0); controlAxis.applyQuaternion(controlOri); - - this.currentControlOri = new THREE.Quaternion(); + _this.currentControlOri = new Quaternion(); // determine mouse interaction switch (message.interaction_mode) { case INTERACTIVE_MARKER_MOVE_ROTATE_3D: case INTERACTIVE_MARKER_MOVE_3D: - this.addEventListener('mousemove', this.parent.move3d.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.move3d.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_MOVE_AXIS: - this.addEventListener('mousemove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); - this.addEventListener('touchmove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.moveAxis.bind(_this.parent, _this, controlAxis)); + _this.addEventListener('touchmove', _this.parent.moveAxis.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_ROTATE_AXIS: - this - .addEventListener('mousemove', this.parent.rotateAxis.bind(this.parent, this, controlOri)); + _this.addEventListener('mousemove', _this.parent.rotateAxis.bind(_this.parent, _this, controlOri)); break; case INTERACTIVE_MARKER_MOVE_PLANE: - this - .addEventListener('mousemove', this.parent.movePlane.bind(this.parent, this, controlAxis)); + _this.addEventListener('mousemove', _this.parent.movePlane.bind(_this.parent, _this, controlAxis)); break; case INTERACTIVE_MARKER_BUTTON: - this.addEventListener('click', this.parent.buttonClick.bind(this.parent, this)); + _this.addEventListener('click', _this.parent.buttonClick.bind(_this.parent, _this)); break; } @@ -52591,38 +42880,38 @@ var ROS3D = (function (exports, ROSLIB) { // check the mode if (message.interaction_mode !== INTERACTIVE_MARKER_NONE) { - this.addEventListener('mousedown', this.parent.startDrag.bind(this.parent, this)); - this.addEventListener('mouseup', this.parent.stopDrag.bind(this.parent, this)); - this.addEventListener('contextmenu', this.parent.showMenu.bind(this.parent, this)); - this.addEventListener('mouseup', function(event3d) { + _this.addEventListener('mousedown', _this.parent.startDrag.bind(_this.parent, _this)); + _this.addEventListener('mouseup', _this.parent.stopDrag.bind(_this.parent, _this)); + _this.addEventListener('contextmenu', _this.parent.showMenu.bind(_this.parent, _this)); + _this.addEventListener('mouseup', function (event3d) { if (that.startMousePos.distanceToSquared(event3d.mousePos) === 0) { event3d.type = 'contextmenu'; that.dispatchEvent(event3d); } }); - this.addEventListener('mouseover', stopPropagation); - this.addEventListener('mouseout', stopPropagation); - this.addEventListener('click', stopPropagation); - this.addEventListener('mousedown', function(event3d) { + _this.addEventListener('mouseover', stopPropagation); + _this.addEventListener('mouseout', stopPropagation); + _this.addEventListener('click', stopPropagation); + _this.addEventListener('mousedown', function (event3d) { that.startMousePos = event3d.mousePos; }); // touch support - this.addEventListener('touchstart', function(event3d) { + _this.addEventListener('touchstart', function (event3d) { if (event3d.domEvent.touches.length === 1) { event3d.type = 'mousedown'; event3d.domEvent.button = 0; that.dispatchEvent(event3d); } }); - this.addEventListener('touchmove', function(event3d) { + _this.addEventListener('touchmove', function (event3d) { if (event3d.domEvent.touches.length === 1) { event3d.type = 'mousemove'; event3d.domEvent.button = 0; that.dispatchEvent(event3d); } }); - this.addEventListener('touchend', function(event3d) { + _this.addEventListener('touchend', function (event3d) { if (event3d.domEvent.touches.length === 0) { event3d.domEvent.button = 0; event3d.type = 'mouseup'; @@ -52631,25 +42920,24 @@ var ROS3D = (function (exports, ROSLIB) { that.dispatchEvent(event3d); } }); - - window.addEventListener('keydown', function(event){ - if(event.keyCode === 16){ + window.addEventListener('keydown', function (event) { + if (event.keyCode === 16) { that.isShift = true; } }); - window.addEventListener('keyup', function(event){ - if(event.keyCode === 16){ + window.addEventListener('keyup', function (event) { + if (event.keyCode === 16) { that.isShift = false; } }); } // rotation behavior - var rotInv = new THREE.Quaternion(); - var posInv = this.parent.position.clone().multiplyScalar(-1); + var rotInv = new Quaternion(); + var posInv = _this.parent.position.clone().multiplyScalar(-1); switch (message.orientation_mode) { case INTERACTIVE_MARKER_INHERIT: - rotInv = this.parent.quaternion.clone().inverse(); + rotInv = _this.parent.quaternion.clone().inverse(); break; case INTERACTIVE_MARKER_FIXED: break; @@ -52663,26 +42951,26 @@ var ROS3D = (function (exports, ROSLIB) { // temporary TFClient to get transformations from InteractiveMarker // frame to potential child Marker frames var localTfClient = new ROSLIB__namespace.TFClient({ - ros : handle.tfClient.ros, - fixedFrame : handle.message.header.frame_id, - serverName : handle.tfClient.serverName + ros: handle.tfClient.ros, + fixedFrame: handle.message.header.frame_id, + serverName: handle.tfClient.serverName }); // create visuals (markers) - message.markers.forEach(function(markerMsg) { - var addMarker = function(transformMsg) { + message.markers.forEach(function (markerMsg) { + var addMarker = function addMarker(transformMsg) { var markerHelper = new Marker({ - message : markerMsg, - path : that.path, - loader : that.loader + message: markerMsg, + path: that.path, + loader: that.loader }); // if transformMsg isn't null, this was called by TFClient if (transformMsg !== null) { // get the current pose as a ROSLIB.Pose... var newPose = new ROSLIB__namespace.Pose({ - position : markerHelper.position, - orientation : markerHelper.quaternion + position: markerHelper.position, + orientation: markerHelper.quaternion }); // so we can apply the transform provided by the TFClient newPose.applyTransform(new ROSLIB__namespace.Transform(transformMsg)); @@ -52691,24 +42979,22 @@ var ROS3D = (function (exports, ROSLIB) { // apply it to sub-marker position to get sub-marker position // relative to parent marker var transformMarker = new Marker({ - message : markerMsg, - path : that.path, - loader : that.loader + message: markerMsg, + path: that.path, + loader: that.loader }); transformMarker.position.add(posInv); transformMarker.position.applyQuaternion(rotInv); transformMarker.quaternion.multiplyQuaternions(rotInv, transformMarker.quaternion); - var translation = new THREE.Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); + var translation = new Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); var transform = new ROSLIB__namespace.Transform({ - translation : translation, - orientation : transformMarker.quaternion + translation: translation, + orientation: transformMarker.quaternion }); // apply that transform too newPose.applyTransform(transform); - markerHelper.setPose(newPose); - markerHelper.updateMatrixWorld(); // we only need to set the pose once - at least, this is what RViz seems to be doing, might change in the future localTfClient.unsubscribe(markerMsg.header.frame_id); @@ -52729,63 +43015,65 @@ var ROS3D = (function (exports, ROSLIB) { addMarker(null); } }); - }; - - updateMatrixWorld(force) { - var that = this; - var message = this.message; - switch (message.orientation_mode) { - case INTERACTIVE_MARKER_INHERIT: - super.updateMatrixWorld(force); - that.currentControlOri.copy(that.quaternion); - that.currentControlOri.normalize(); - break; - case INTERACTIVE_MARKER_FIXED: - that.quaternion.copy(that.parent.quaternion.clone().inverse()); - that.updateMatrix(); - that.matrixWorldNeedsUpdate = true; - super.updateMatrixWorld(force); - that.currentControlOri.copy(that.quaternion); - break; - case INTERACTIVE_MARKER_VIEW_FACING: - that.camera.updateMatrixWorld(); - var cameraRot = new THREE.Matrix4().extractRotation(that.camera.matrixWorld); - - var ros2Gl = new THREE.Matrix4(); - var r90 = Math.PI * 0.5; - var rv = new THREE.Euler(-r90, 0, r90); - ros2Gl.makeRotationFromEuler(rv); - - var worldToLocal = new THREE.Matrix4(); - worldToLocal.getInverse(that.parent.matrixWorld); - - cameraRot.multiplyMatrices(cameraRot, ros2Gl); - cameraRot.multiplyMatrices(worldToLocal, cameraRot); - - that.currentControlOri.setFromRotationMatrix(cameraRot); - - // check the orientation - if (!message.independent_marker_orientation) { - that.quaternion.copy(that.currentControlOri); + return _this; + } + _inherits(InteractiveMarkerControl, _THREE$Object3D); + return _createClass(InteractiveMarkerControl, [{ + key: "updateMatrixWorld", + value: function updateMatrixWorld(force) { + var that = this; + var message = this.message; + switch (message.orientation_mode) { + case INTERACTIVE_MARKER_INHERIT: + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + that.currentControlOri.copy(that.quaternion); + that.currentControlOri.normalize(); + break; + case INTERACTIVE_MARKER_FIXED: + that.quaternion.copy(that.parent.quaternion.clone().inverse()); that.updateMatrix(); that.matrixWorldNeedsUpdate = true; - } - super.updateMatrixWorld(force); - break; - default: - console.error('Unkown orientation mode: ' + message.orientation_mode); - break; + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + that.currentControlOri.copy(that.quaternion); + break; + case INTERACTIVE_MARKER_VIEW_FACING: + that.camera.updateMatrixWorld(); + var cameraRot = new Matrix4().extractRotation(that.camera.matrixWorld); + var ros2Gl = new Matrix4(); + var r90 = Math.PI * 0.5; + var rv = new Euler(-r90, 0, r90); + ros2Gl.makeRotationFromEuler(rv); + var worldToLocal = new Matrix4(); + worldToLocal.getInverse(that.parent.matrixWorld); + cameraRot.multiplyMatrices(cameraRot, ros2Gl); + cameraRot.multiplyMatrices(worldToLocal, cameraRot); + that.currentControlOri.setFromRotationMatrix(cameraRot); + + // check the orientation + if (!message.independent_marker_orientation) { + that.quaternion.copy(that.currentControlOri); + that.updateMatrix(); + that.matrixWorldNeedsUpdate = true; + } + _superPropGet(InteractiveMarkerControl, "updateMatrixWorld", this, 3)([force]); + break; + default: + console.error('Unkown orientation mode: ' + message.orientation_mode); + break; + } } - }; - } + }]); + }(Object3D); + + function _callSuper$s(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$s() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$s() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$s = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class InteractiveMarkerMenu extends THREE.EventDispatcher { - + var InteractiveMarkerMenu = /*#__PURE__*/function (_THREE$EventDispatche) { /** * A menu for an interactive marker. This will be overlayed on the canvas. * @@ -52798,9 +43086,11 @@ var ROS3D = (function (exports, ROSLIB) { * * overlayClassName (optional) - a custom CSS class for the menu overlay * * menuFontSize (optional) - the menu font size */ - constructor(options) { - super(); - var that = this; + function InteractiveMarkerMenu(options) { + var _this; + _classCallCheck(this, InteractiveMarkerMenu); + _this = _callSuper$s(this, InteractiveMarkerMenu); + var that = _this; options = options || {}; var menuEntries = options.menuEntries; var className = options.className || 'default-interactive-marker-menu'; @@ -52811,75 +43101,58 @@ var ROS3D = (function (exports, ROSLIB) { // holds the menu tree var allMenus = []; allMenus[0] = { - children : [] + children: [] }; - // create the CSS for this marker if it has not been created if (document.getElementById('default-interactive-marker-menu-css') === null) { var style = document.createElement('style'); style.id = 'default-interactive-marker-menu-css'; style.type = 'text/css'; - style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' - + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' - + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize +';' + 'z-index: 1002;' - + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' - + 'margin: 0px;' + 'list-style-type: none;' + '}' - + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' - + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' - + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' - + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' - + ' background-color: #666666;' + ' cursor: pointer;' + '}' - + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' - + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' - + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' - + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' - + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; + style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize + ';' + 'z-index: 1002;' + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' + 'margin: 0px;' + 'list-style-type: none;' + '}' + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' + ' background-color: #666666;' + ' cursor: pointer;' + '}' + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; document.getElementsByTagName('head')[0].appendChild(style); } // place the menu in a div - this.menuDomElem = document.createElement('div'); - this.menuDomElem.style.position = 'absolute'; - this.menuDomElem.className = className; - this.menuDomElem.addEventListener('contextmenu', function(event) { + _this.menuDomElem = document.createElement('div'); + _this.menuDomElem.style.position = 'absolute'; + _this.menuDomElem.className = className; + _this.menuDomElem.addEventListener('contextmenu', function (event) { event.preventDefault(); }); // create the overlay DOM - this.overlayDomElem = document.createElement('div'); - this.overlayDomElem.className = overlayClassName; - - this.hideListener = this.hide.bind(this); - this.overlayDomElem.addEventListener('contextmenu', this.hideListener); - this.overlayDomElem.addEventListener('click', this.hideListener); - this.overlayDomElem.addEventListener('touchstart', this.hideListener); + _this.overlayDomElem = document.createElement('div'); + _this.overlayDomElem.className = overlayClassName; + _this.hideListener = _this.hide.bind(_this); + _this.overlayDomElem.addEventListener('contextmenu', _this.hideListener); + _this.overlayDomElem.addEventListener('click', _this.hideListener); + _this.overlayDomElem.addEventListener('touchstart', _this.hideListener); // parse all entries and link children to parents var i, entry, id; - for ( i = 0; i < menuEntries.length; i++) { + for (i = 0; i < menuEntries.length; i++) { entry = menuEntries[i]; id = entry.id; allMenus[id] = { - title : entry.title, - id : id, - children : [] + title: entry.title, + id: id, + children: [] }; } - for ( i = 0; i < menuEntries.length; i++) { + for (i = 0; i < menuEntries.length; i++) { entry = menuEntries[i]; id = entry.id; var menu = allMenus[id]; var parent = allMenus[entry.parent_id]; parent.children.push(menu); } - function emitMenuSelect(menuEntry, domEvent) { this.dispatchEvent({ - type : 'menu-select', - domEvent : domEvent, - id : menuEntry.id, - controlName : this.controlName + type: 'menu-select', + domEvent: domEvent, + id: menuEntry.id, + controlName: this.controlName }); this.hide(domEvent); } @@ -52891,19 +43164,15 @@ var ROS3D = (function (exports, ROSLIB) { * @param parentMenu - the parent menu */ function makeUl(parentDomElem, parentMenu) { - var ulElem = document.createElement('ul'); parentDomElem.appendChild(ulElem); - var children = parentMenu.children; - - for ( var i = 0; i < children.length; i++) { + for (var i = 0; i < children.length; i++) { var liElem = document.createElement('li'); var divElem = document.createElement('div'); divElem.appendChild(document.createTextNode(children[i].title)); ulElem.appendChild(liElem); liElem.appendChild(divElem); - if (children[i].children.length > 0) { makeUl(liElem, children[i]); divElem.addEventListener('click', that.hide.bind(that)); @@ -52914,62 +43183,68 @@ var ROS3D = (function (exports, ROSLIB) { divElem.className = 'default-interactive-marker-menu-entry'; } } - } // construct DOM element - makeUl(this.menuDomElem, allMenus[0]); - }; - - /** - * Shoe the menu DOM element. - * - * @param control - the control for the menu - * @param event - the event that caused this - */ - show(control, event) { - if (event && event.preventDefault) { - event.preventDefault(); - } - - this.controlName = control.name; + makeUl(_this.menuDomElem, allMenus[0]); + return _this; + } + _inherits(InteractiveMarkerMenu, _THREE$EventDispatche); + return _createClass(InteractiveMarkerMenu, [{ + key: "show", + value: + /** + * Shoe the menu DOM element. + * + * @param control - the control for the menu + * @param event - the event that caused this + */ + function show(control, event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + this.controlName = control.name; - // position it on the click - if (event.domEvent.changedTouches !== undefined) { - // touch click - this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; - this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; - } else { - // mouse click - this.menuDomElem.style.left = event.domEvent.clientX + 'px'; - this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + // position it on the click + if (event.domEvent.changedTouches !== undefined) { + // touch click + this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; + this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; + } else { + // mouse click + this.menuDomElem.style.left = event.domEvent.clientX + 'px'; + this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + } + document.body.appendChild(this.overlayDomElem); + document.body.appendChild(this.menuDomElem); } - document.body.appendChild(this.overlayDomElem); - document.body.appendChild(this.menuDomElem); - }; - - /** - * Hide the menu DOM element. - * - * @param event (optional) - the event that caused this - */ - hide(event) { - if (event && event.preventDefault) { - event.preventDefault(); + }, { + key: "hide", + value: + /** + * Hide the menu DOM element. + * + * @param event (optional) - the event that caused this + */ + function hide(event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + document.body.removeChild(this.overlayDomElem); + document.body.removeChild(this.menuDomElem); } + }]); + }(EventDispatcher); - document.body.removeChild(this.overlayDomElem); - document.body.removeChild(this.menuDomElem); - }; - } + function _callSuper$r(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$r() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$r() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$r = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class InteractiveMarker extends THREE.Object3D { - + var InteractiveMarker = /*#__PURE__*/function (_THREE$Object3D) { /** * The main interactive marker object. * @@ -52981,346 +43256,2004 @@ var ROS3D = (function (exports, ROSLIB) { * * path (optional) - the base path to any meshes that will be loaded * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) */ - constructor(options) { - super(); + function InteractiveMarker(options) { + var _this; + _classCallCheck(this, InteractiveMarker); + _this = _callSuper$r(this, InteractiveMarker); options = options || {}; var handle = options.handle; - this.name = handle.name; + _this.name = handle.name; var camera = options.camera; var path = options.path || '/'; var loader = options.loader; - this.dragging = false; + _this.dragging = false; // set the initial pose - this.onServerSetPose({ - pose : handle.pose + _this.onServerSetPose({ + pose: handle.pose }); // information on where the drag started - this.dragStart = { - position : new THREE.Vector3(), - orientation : new THREE.Quaternion(), - positionWorld : new THREE.Vector3(), - orientationWorld : new THREE.Quaternion(), - event3d : {} + _this.dragStart = { + position: new Vector3(), + orientation: new Quaternion(), + positionWorld: new Vector3(), + orientationWorld: new Quaternion(), + event3d: {} }; // add each control message - handle.controls.forEach(function(controlMessage) { + handle.controls.forEach(function (controlMessage) { this.add(new InteractiveMarkerControl({ - parent : this, - handle : handle, - message : controlMessage, - camera : camera, - path : path, - loader : loader + parent: this, + handle: handle, + message: controlMessage, + camera: camera, + path: path, + loader: loader })); - }.bind(this)); + }.bind(_this)); // check for any menus if (handle.menuEntries.length > 0) { - this.menu = new InteractiveMarkerMenu({ - menuEntries : handle.menuEntries, - menuFontSize : handle.menuFontSize + _this.menu = new InteractiveMarkerMenu({ + menuEntries: handle.menuEntries, + menuFontSize: handle.menuFontSize }); // forward menu select events - this.menu.addEventListener('menu-select', function(event) { + _this.menu.addEventListener('menu-select', function (event) { this.dispatchEvent(event); - }.bind(this)); + }.bind(_this)); } - }; - - /** - * Show the interactive marker menu associated with this marker. - * - * @param control - the control to use - * @param event - the event that caused this - */ - showMenu(control, event) { - if (this.menu) { - this.menu.show(control, event); + return _this; + } + _inherits(InteractiveMarker, _THREE$Object3D); + return _createClass(InteractiveMarker, [{ + key: "showMenu", + value: + /** + * Show the interactive marker menu associated with this marker. + * + * @param control - the control to use + * @param event - the event that caused this + */ + function showMenu(control, event) { + if (this.menu) { + this.menu.show(control, event); + } } - }; - - /** - * Move the axis based on the given event information. - * - * @param control - the control to use - * @param origAxis - the origin of the axis - * @param event3d - the event that caused this - */ - moveAxis(control, origAxis, event3d) { - if (this.dragging) { - var currentControlOri = control.currentControlOri; - var axis = origAxis.clone().applyQuaternion(currentControlOri); - // get move axis in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); - - var axisRay = new THREE.Ray(originWorld, axisWorld); - - // find closest point to mouse on axis - var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); - - // offset from drag start position - var p = new THREE.Vector3(); - p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation) - .multiplyScalar(t)); - this.setPosition(control, p); - - - event3d.stopPropagation(); + }, { + key: "moveAxis", + value: + /** + * Move the axis based on the given event information. + * + * @param control - the control to use + * @param origAxis - the origin of the axis + * @param event3d - the event that caused this + */ + function moveAxis(control, origAxis, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var axis = origAxis.clone().applyQuaternion(currentControlOri); + // get move axis in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); + var axisRay = new Ray(originWorld, axisWorld); + + // find closest point to mouse on axis + var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); + + // offset from drag start position + var p = new Vector3(); + p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(t)); + this.setPosition(control, p); + event3d.stopPropagation(); + } } - }; - + }, { + key: "move3d", + value: + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + function move3d(control, origNormal, event3d) { + // by default, move in a plane + if (this.dragging) { + if (control.isShift) ; else { + // we want to use the origin plane that is closest to the camera + var cameraVector = control.camera.getWorldDirection(); + var x = Math.abs(cameraVector.x); + var y = Math.abs(cameraVector.y); + var z = Math.abs(cameraVector.z); + var controlOri = new Quaternion(1, 0, 0, 1); + if (y > x && y > z) { + // orientation for the control + controlOri = new Quaternion(0, 0, 1, 1); + } else if (z > x && z > y) { + // orientation for the control + controlOri = new Quaternion(0, 1, 0, 1); + } + controlOri.normalize(); - /** - * Move with respect to the plane based on the contorl and event. - * - * @param control - the control to use - * @param origNormal - the normal of the origin - * @param event3d - the event that caused this - */ - move3d(control, origNormal, event3d) { - // by default, move in a plane - if (this.dragging) { - - if(control.isShift);else { - // we want to use the origin plane that is closest to the camera - var cameraVector = control.camera.getWorldDirection(); - var x = Math.abs(cameraVector.x); - var y = Math.abs(cameraVector.y); - var z = Math.abs(cameraVector.z); - var controlOri = new THREE.Quaternion(1, 0, 0, 1); - if(y > x && y > z){ - // orientation for the control - controlOri = new THREE.Quaternion(0, 0, 1, 1); - }else if(z > x && z > y){ - // orientation for the control - controlOri = new THREE.Quaternion(0, 1, 0, 1); + // transform x axis into local frame + origNormal = new Vector3(1, 0, 0); + origNormal.applyQuaternion(controlOri); + this.movePlane(control, origNormal, event3d); } - controlOri.normalize(); - - // transform x axis into local frame - origNormal = new THREE.Vector3(1, 0, 0); - origNormal.applyQuaternion(controlOri); - this.movePlane(control, origNormal, event3d); } } - }; - - /** - * Move with respect to the plane based on the contorl and event. - * - * @param control - the control to use - * @param origNormal - the normal of the origin - * @param event3d - the event that caused this - */ - movePlane(control, origNormal, event3d) { - if (this.dragging) { - var currentControlOri = control.currentControlOri; - var normal = origNormal.clone().applyQuaternion(currentControlOri); - // get plane params in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); - - // intersect mouse ray with plane - var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); - - // offset from drag start position - var p = new THREE.Vector3(); - p.subVectors(intersection, originWorld); - p.add(this.dragStart.positionWorld); - this.setPosition(control, p); - event3d.stopPropagation(); - } - }; - - /** - * Rotate based on the control and event given. - * - * @param control - the control to use - * @param origOrientation - the orientation of the origin - * @param event3d - the event that caused this - */ - rotateAxis(control, origOrientation, event3d) { - if (this.dragging) { - control.updateMatrixWorld(); - - var currentControlOri = control.currentControlOri; - var orientation = currentControlOri.clone().multiply(origOrientation.clone()); - - var normal = (new THREE.Vector3(1, 0, 0)).applyQuaternion(orientation); - - // get plane params in world coords - var originWorld = this.dragStart.event3d.intersection.point; - var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); - - // intersect mouse ray with plane - var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); - - // offset local origin to lie on intersection plane - var normalRay = new THREE.Ray(this.dragStart.positionWorld, normalWorld); - var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); - - // rotates from world to plane coords - var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); - var orientationWorldInv = orientationWorld.clone().inverse(); - - // rotate original and current intersection into local coords - intersection.sub(rotOrigin); - intersection.applyQuaternion(orientationWorldInv); - - var origIntersection = this.dragStart.event3d.intersection.point.clone(); - origIntersection.sub(rotOrigin); - origIntersection.applyQuaternion(orientationWorldInv); - - // compute relative 2d angle - var a1 = Math.atan2(intersection.y, intersection.z); - var a2 = Math.atan2(origIntersection.y, origIntersection.z); - var a = a2 - a1; - - var rot = new THREE.Quaternion(); - rot.setFromAxisAngle(normal, a); - - // rotate - this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); - - // offset from drag start position - event3d.stopPropagation(); - } - }; - - /** - * Dispatch the given event type. - * - * @param type - the type of event - * @param control - the control to use - */ - feedbackEvent(type, control) { - this.dispatchEvent({ - type : type, - position : this.position.clone(), - orientation : this.quaternion.clone(), - controlName : control.name - }); - }; - - /** - * Start a drag action. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - startDrag(control, event3d) { - if (event3d.domEvent.button === 0) { - event3d.stopPropagation(); - this.dragging = true; - this.updateMatrixWorld(true); - var scale = new THREE.Vector3(); - this.matrixWorld - .decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); - this.dragStart.position = this.position.clone(); - this.dragStart.orientation = this.quaternion.clone(); - this.dragStart.event3d = event3d; - - this.feedbackEvent('user-mousedown', control); - } - }; - - /** - * Stop a drag action. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - stopDrag(control, event3d) { - if (event3d.domEvent.button === 0) { - event3d.stopPropagation(); - this.dragging = false; - this.dragStart.event3d = {}; - this.onServerSetPose(this.bufferedPoseEvent); - this.bufferedPoseEvent = undefined; - - this.feedbackEvent('user-mouseup', control); + }, { + key: "movePlane", + value: + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + function movePlane(control, origNormal, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var normal = origNormal.clone().applyQuaternion(currentControlOri); + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset from drag start position + var p = new Vector3(); + p.subVectors(intersection, originWorld); + p.add(this.dragStart.positionWorld); + this.setPosition(control, p); + event3d.stopPropagation(); + } } - }; - - /** - * Handle a button click. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - buttonClick(control, event3d) { - event3d.stopPropagation(); - this.feedbackEvent('user-button-click', control); - }; - - /** - * Handle a user pose change for the position. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - setPosition(control, position) { - this.position.copy(position); - this.feedbackEvent('user-pose-change', control); - }; - - /** - * Handle a user pose change for the orientation. - * - * @param control - the control to use - * @param event3d - the event that caused this - */ - setOrientation(control, orientation) { - orientation.normalize(); - this.quaternion.copy(orientation); - this.feedbackEvent('user-pose-change', control); - }; - - /** - * Update the marker based when the pose is set from the server. - * - * @param event - the event that caused this - */ - onServerSetPose(event) { - if (event !== undefined) { - // don't update while dragging + }, { + key: "rotateAxis", + value: + /** + * Rotate based on the control and event given. + * + * @param control - the control to use + * @param origOrientation - the orientation of the origin + * @param event3d - the event that caused this + */ + function rotateAxis(control, origOrientation, event3d) { if (this.dragging) { - this.bufferedPoseEvent = event; - } else { - var pose = event.pose; - this.position.copy(pose.position); - this.quaternion.copy(pose.orientation); + control.updateMatrixWorld(); + var currentControlOri = control.currentControlOri; + var orientation = currentControlOri.clone().multiply(origOrientation.clone()); + var normal = new Vector3(1, 0, 0).applyQuaternion(orientation); + + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset local origin to lie on intersection plane + var normalRay = new Ray(this.dragStart.positionWorld, normalWorld); + var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); + + // rotates from world to plane coords + var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); + var orientationWorldInv = orientationWorld.clone().inverse(); + + // rotate original and current intersection into local coords + intersection.sub(rotOrigin); + intersection.applyQuaternion(orientationWorldInv); + var origIntersection = this.dragStart.event3d.intersection.point.clone(); + origIntersection.sub(rotOrigin); + origIntersection.applyQuaternion(orientationWorldInv); + + // compute relative 2d angle + var a1 = Math.atan2(intersection.y, intersection.z); + var a2 = Math.atan2(origIntersection.y, origIntersection.z); + var a = a2 - a1; + var rot = new Quaternion(); + rot.setFromAxisAngle(normal, a); + + // rotate + this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); + + // offset from drag start position + event3d.stopPropagation(); + } + } + }, { + key: "feedbackEvent", + value: + /** + * Dispatch the given event type. + * + * @param type - the type of event + * @param control - the control to use + */ + function feedbackEvent(type, control) { + this.dispatchEvent({ + type: type, + position: this.position.clone(), + orientation: this.quaternion.clone(), + controlName: control.name + }); + } + }, { + key: "startDrag", + value: + /** + * Start a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function startDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = true; this.updateMatrixWorld(true); + var scale = new Vector3(); + this.matrixWorld.decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); + this.dragStart.position = this.position.clone(); + this.dragStart.orientation = this.quaternion.clone(); + this.dragStart.event3d = event3d; + this.feedbackEvent('user-mousedown', control); + } + } + }, { + key: "stopDrag", + value: + /** + * Stop a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function stopDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = false; + this.dragStart.event3d = {}; + this.onServerSetPose(this.bufferedPoseEvent); + this.bufferedPoseEvent = undefined; + this.feedbackEvent('user-mouseup', control); + } + } + }, { + key: "buttonClick", + value: + /** + * Handle a button click. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function buttonClick(control, event3d) { + event3d.stopPropagation(); + this.feedbackEvent('user-button-click', control); + } + }, { + key: "setPosition", + value: + /** + * Handle a user pose change for the position. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function setPosition(control, position) { + this.position.copy(position); + this.feedbackEvent('user-pose-change', control); + } + }, { + key: "setOrientation", + value: + /** + * Handle a user pose change for the orientation. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + function setOrientation(control, orientation) { + orientation.normalize(); + this.quaternion.copy(orientation); + this.feedbackEvent('user-pose-change', control); + } + }, { + key: "onServerSetPose", + value: + /** + * Update the marker based when the pose is set from the server. + * + * @param event - the event that caused this + */ + function onServerSetPose(event) { + if (event !== undefined) { + // don't update while dragging + if (this.dragging) { + this.bufferedPoseEvent = event; + } else { + var pose = event.pose; + this.position.copy(pose.position); + this.quaternion.copy(pose.orientation); + this.updateMatrixWorld(true); + } } } - }; + }, { + key: "dispose", + value: + /** + * Free memory of elements in this marker. + */ + function dispose() { + this.children.forEach(function (intMarkerControl) { + intMarkerControl.children.forEach(function (marker) { + marker.dispose(); + intMarkerControl.remove(marker); + }); + this.remove(intMarkerControl); + }.bind(this)); + } + }]); + }(Object3D); - /** - * Free memory of elements in this marker. - */ - dispose() { - this.children.forEach(function(intMarkerControl) { - intMarkerControl.children.forEach(function(marker) { - marker.dispose(); - intMarkerControl.remove(marker); - }); - this.remove(intMarkerControl); - }.bind(this)); - }; + function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } + var eventemitter2 = {exports: {}}; + + /*! + * EventEmitter2 + * https://github.com/hij1nx/EventEmitter2 + * + * Copyright (c) 2013 hij1nx + * Licensed under the MIT license. + */ + eventemitter2.exports; + + (function (module, exports) { + !function(undefined$1) { + var hasOwnProperty= Object.hasOwnProperty; + var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + var defaultMaxListeners = 10; + var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; + var symbolsSupported= typeof Symbol==='function'; + var reflectSupported= typeof Reflect === 'object'; + var setImmediateSupported= typeof setImmediate === 'function'; + var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; + var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ + var arr= Object.getOwnPropertyNames(obj); + arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); + return arr; + }) : Object.keys; + + function init() { + this._events = {}; + if (this._conf) { + configure.call(this, this._conf); + } + } + + function configure(conf) { + if (conf) { + this._conf = conf; + + conf.delimiter && (this.delimiter = conf.delimiter); + + if(conf.maxListeners!==undefined$1){ + this._maxListeners= conf.maxListeners; + } + + conf.wildcard && (this.wildcard = conf.wildcard); + conf.newListener && (this._newListener = conf.newListener); + conf.removeListener && (this._removeListener = conf.removeListener); + conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); + conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); + + if (this.wildcard) { + this.listenerTree = {}; + } + } + } + + function logPossibleMemoryLeak(count, eventName) { + var errorMsg = '(node) warning: possible EventEmitter memory ' + + 'leak detected. ' + count + ' listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.'; + + if(this.verboseMemoryLeak){ + errorMsg += ' Event name: ' + eventName + '.'; + } + + if(typeof process !== 'undefined' && process.emitWarning){ + var e = new Error(errorMsg); + e.name = 'MaxListenersExceededWarning'; + e.emitter = this; + e.count = count; + process.emitWarning(e); + } else { + console.error(errorMsg); + + if (console.trace){ + console.trace(); + } + } + } + + var toArray = function (a, b, c) { + var n = arguments.length; + switch (n) { + case 0: + return []; + case 1: + return [a]; + case 2: + return [a, b]; + case 3: + return [a, b, c]; + default: + var arr = new Array(n); + while (n--) { + arr[n] = arguments[n]; + } + return arr; + } + }; + + function toObject(keys, values) { + var obj = {}; + var key; + var len = keys.length; + var valuesCount = values ? value.length : 0; + for (var i = 0; i < len; i++) { + key = keys[i]; + obj[key] = i < valuesCount ? values[i] : undefined$1; + } + return obj; + } + + function TargetObserver(emitter, target, options) { + this._emitter = emitter; + this._target = target; + this._listeners = {}; + this._listenersCount = 0; + + var on, off; + + if (options.on || options.off) { + on = options.on; + off = options.off; + } + + if (target.addEventListener) { + on = target.addEventListener; + off = target.removeEventListener; + } else if (target.addListener) { + on = target.addListener; + off = target.removeListener; + } else if (target.on) { + on = target.on; + off = target.off; + } + + if (!on && !off) { + throw Error('target does not implement any known event API'); + } + + if (typeof on !== 'function') { + throw TypeError('on method must be a function'); + } + + if (typeof off !== 'function') { + throw TypeError('off method must be a function'); + } + + this._on = on; + this._off = off; + + var _observers= emitter._observers; + if(_observers){ + _observers.push(this); + }else { + emitter._observers= [this]; + } + } + + Object.assign(TargetObserver.prototype, { + subscribe: function(event, localEvent, reducer){ + var observer= this; + var target= this._target; + var emitter= this._emitter; + var listeners= this._listeners; + var handler= function(){ + var args= toArray.apply(null, arguments); + var eventObj= { + data: args, + name: localEvent, + original: event + }; + if(reducer){ + var result= reducer.call(target, eventObj); + if(result!==false){ + emitter.emit.apply(emitter, [eventObj.name].concat(args)); + } + return; + } + emitter.emit.apply(emitter, [localEvent].concat(args)); + }; + + + if(listeners[event]){ + throw Error('Event \'' + event + '\' is already listening'); + } + + this._listenersCount++; + + if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ + + this._onNewListener = function (_event) { + if (_event === localEvent && listeners[event] === null) { + listeners[event] = handler; + observer._on.call(target, event, handler); + } + }; + + emitter.on('newListener', this._onNewListener); + + this._onRemoveListener= function(_event){ + if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ + listeners[event]= null; + observer._off.call(target, event, handler); + } + }; + + listeners[event]= null; + + emitter.on('removeListener', this._onRemoveListener); + }else { + listeners[event]= handler; + observer._on.call(target, event, handler); + } + }, + + unsubscribe: function(event){ + var observer= this; + var listeners= this._listeners; + var emitter= this._emitter; + var handler; + var events; + var off= this._off; + var target= this._target; + var i; + + if(event && typeof event!=='string'){ + throw TypeError('event must be a string'); + } + + function clearRefs(){ + if(observer._onNewListener){ + emitter.off('newListener', observer._onNewListener); + emitter.off('removeListener', observer._onRemoveListener); + observer._onNewListener= null; + observer._onRemoveListener= null; + } + var index= findTargetIndex.call(emitter, observer); + emitter._observers.splice(index, 1); + } + + if(event){ + handler= listeners[event]; + if(!handler) return; + off.call(target, event, handler); + delete listeners[event]; + if(!--this._listenersCount){ + clearRefs(); + } + }else { + events= ownKeys(listeners); + i= events.length; + while(i-->0){ + event= events[i]; + off.call(target, event, listeners[event]); + } + this._listeners= {}; + this._listenersCount= 0; + clearRefs(); + } + } + }); + + function resolveOptions(options, schema, reducers, allowUnknown) { + var computedOptions = Object.assign({}, schema); + + if (!options) return computedOptions; + + if (typeof options !== 'object') { + throw TypeError('options must be an object') + } + + var keys = Object.keys(options); + var length = keys.length; + var option, value; + var reducer; + + function reject(reason) { + throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) + } + + for (var i = 0; i < length; i++) { + option = keys[i]; + if (!allowUnknown && !hasOwnProperty.call(schema, option)) { + throw Error('Unknown "' + option + '" option'); + } + value = options[option]; + if (value !== undefined$1) { + reducer = reducers[option]; + computedOptions[option] = reducer ? reducer(value, reject) : value; + } + } + return computedOptions; + } + + function constructorReducer(value, reject) { + if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { + reject('value must be a constructor'); + } + return value; + } + + function makeTypeReducer(types) { + var message= 'value must be type of ' + types.join('|'); + var len= types.length; + var firstType= types[0]; + var secondType= types[1]; + + if (len === 1) { + return function (v, reject) { + if (typeof v === firstType) { + return v; + } + reject(message); + } + } + + if (len === 2) { + return function (v, reject) { + var kind= typeof v; + if (kind === firstType || kind === secondType) return v; + reject(message); + } + } + + return function (v, reject) { + var kind = typeof v; + var i = len; + while (i-- > 0) { + if (kind === types[i]) return v; + } + reject(message); + } + } + + var functionReducer= makeTypeReducer(['function']); + + var objectFunctionReducer= makeTypeReducer(['object', 'function']); + + function makeCancelablePromise(Promise, executor, options) { + var isCancelable; + var callbacks; + var timer= 0; + var subscriptionClosed; + + var promise = new Promise(function (resolve, reject, onCancel) { + options= resolveOptions(options, { + timeout: 0, + overload: false + }, { + timeout: function(value, reject){ + value*= 1; + if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { + reject('timeout must be a positive number'); + } + return value; + } + }); + + isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; + + function cleanup() { + if (callbacks) { + callbacks = null; + } + if (timer) { + clearTimeout(timer); + timer = 0; + } + } + + var _resolve= function(value){ + cleanup(); + resolve(value); + }; + + var _reject= function(err){ + cleanup(); + reject(err); + }; + + if (isCancelable) { + executor(_resolve, _reject, onCancel); + } else { + callbacks = [function(reason){ + _reject(reason || Error('canceled')); + }]; + executor(_resolve, _reject, function (cb) { + if (subscriptionClosed) { + throw Error('Unable to subscribe on cancel event asynchronously') + } + if (typeof cb !== 'function') { + throw TypeError('onCancel callback must be a function'); + } + callbacks.push(cb); + }); + subscriptionClosed= true; + } + + if (options.timeout > 0) { + timer= setTimeout(function(){ + var reason= Error('timeout'); + reason.code = 'ETIMEDOUT'; + timer= 0; + promise.cancel(reason); + reject(reason); + }, options.timeout); + } + }); + + if (!isCancelable) { + promise.cancel = function (reason) { + if (!callbacks) { + return; + } + var length = callbacks.length; + for (var i = 1; i < length; i++) { + callbacks[i](reason); + } + // internal callback to reject the promise + callbacks[0](reason); + callbacks = null; + }; + } + + return promise; + } + + function findTargetIndex(observer) { + var observers = this._observers; + if(!observers){ + return -1; + } + var len = observers.length; + for (var i = 0; i < len; i++) { + if (observers[i]._target === observer) return i; + } + return -1; + } + + // Attention, function return type now is array, always ! + // It has zero elements if no any matches found and one or more + // elements (leafs) if there are matches + // + function searchListenerTree(handlers, type, tree, i, typeLength) { + if (!tree) { + return null; + } + + if (i === 0) { + var kind = typeof type; + if (kind === 'string') { + var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; + if ((n = type.indexOf(delimiter)) !== -1) { + ns = new Array(5); + do { + ns[l++] = type.slice(j, n); + j = n + dl; + } while ((n = type.indexOf(delimiter, j)) !== -1); + + ns[l++] = type.slice(j); + type = ns; + typeLength = l; + } else { + type = [type]; + typeLength = 1; + } + } else if (kind === 'object') { + typeLength = type.length; + } else { + type = [type]; + typeLength = 1; + } + } + + var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], + nextType = type[i + 1], branches, _listeners; + + if (i === typeLength) { + // + // If at the end of the event(s) list and the tree has listeners + // invoke those listeners. + // + + if(tree._listeners) { + if (typeof tree._listeners === 'function') { + handlers && handlers.push(tree._listeners); + listeners = [tree]; + } else { + handlers && handlers.push.apply(handlers, tree._listeners); + listeners = [tree]; + } + } + } else { + + if (currentType === '*') { + // + // If the event emitted is '*' at this part + // or there is a concrete match at this patch + // + branches = ownKeys(tree); + n = branches.length; + while (n-- > 0) { + branch = branches[n]; + if (branch !== '_listeners') { + _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + } + return listeners; + } else if (currentType === '**') { + endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); + if (endReached && tree._listeners) { + // The next element has a _listeners, add it to the handlers. + listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); + } + + branches = ownKeys(tree); + n = branches.length; + while (n-- > 0) { + branch = branches[n]; + if (branch !== '_listeners') { + if (branch === '*' || branch === '**') { + if (tree[branch]._listeners && !endReached) { + _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); + } else if (branch === nextType) { + _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); + } else { + // No match on this one, shift into the tree but not in the type array. + _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); + } + if (_listeners) { + if (listeners) { + listeners.push.apply(listeners, _listeners); + } else { + listeners = _listeners; + } + } + } + } + return listeners; + } else if (tree[currentType]) { + listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); + } + } + + xTree = tree['*']; + if (xTree) { + // + // If the listener tree will allow any match for this part, + // then recursively explore all branches of the tree + // + searchListenerTree(handlers, type, xTree, i + 1, typeLength); + } + + xxTree = tree['**']; + if (xxTree) { + if (i < typeLength) { + if (xxTree._listeners) { + // If we have a listener on a '**', it will catch all, so add its handler. + searchListenerTree(handlers, type, xxTree, typeLength, typeLength); + } + + // Build arrays of matching next branches and others. + branches= ownKeys(xxTree); + n= branches.length; + while(n-->0){ + branch= branches[n]; + if (branch !== '_listeners') { + if (branch === nextType) { + // We know the next element will match, so jump twice. + searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); + } else if (branch === currentType) { + // Current node matches, move into the tree. + searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); + } else { + isolatedBranch = {}; + isolatedBranch[branch] = xxTree[branch]; + searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); + } + } + } + } else if (xxTree._listeners) { + // We have reached the end and still on a '**' + searchListenerTree(handlers, type, xxTree, typeLength, typeLength); + } else if (xxTree['*'] && xxTree['*']._listeners) { + searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); + } + } + + return listeners; + } + + function growListenerTree(type, listener, prepend) { + var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; + + if(typeof type==='string') { + if ((i = type.indexOf(delimiter)) !== -1) { + ns = new Array(5); + do { + ns[len++] = type.slice(j, i); + j = i + dl; + } while ((i = type.indexOf(delimiter, j)) !== -1); + + ns[len++] = type.slice(j); + }else { + ns= [type]; + len= 1; + } + }else { + ns= type; + len= type.length; + } + + // + // Looks for two consecutive '**', if so, don't add the event at all. + // + if (len > 1) { + for (i = 0; i + 1 < len; i++) { + if (ns[i] === '**' && ns[i + 1] === '**') { + return; + } + } + } + + + + var tree = this.listenerTree, name; + + for (i = 0; i < len; i++) { + name = ns[i]; + + tree = tree[name] || (tree[name] = {}); + + if (i === len - 1) { + if (!tree._listeners) { + tree._listeners = listener; + } else { + if (typeof tree._listeners === 'function') { + tree._listeners = [tree._listeners]; + } + + if (prepend) { + tree._listeners.unshift(listener); + } else { + tree._listeners.push(listener); + } + + if ( + !tree._listeners.warned && + this._maxListeners > 0 && + tree._listeners.length > this._maxListeners + ) { + tree._listeners.warned = true; + logPossibleMemoryLeak.call(this, tree._listeners.length, name); + } + } + return true; + } + } + + return true; + } + + function collectTreeEvents(tree, events, root, asArray){ + var branches= ownKeys(tree); + var i= branches.length; + var branch, branchName, path; + var hasListeners= tree['_listeners']; + var isArrayPath; + + while(i-->0){ + branchName= branches[i]; + + branch= tree[branchName]; + + if(branchName==='_listeners'){ + path= root; + }else { + path = root ? root.concat(branchName) : [branchName]; + } + + isArrayPath= asArray || typeof branchName==='symbol'; + + hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); + + if(typeof branch==='object'){ + collectTreeEvents.call(this, branch, events, path, isArrayPath); + } + } + + return events; + } + + function recursivelyGarbageCollect(root) { + var keys = ownKeys(root); + var i= keys.length; + var obj, key, flag; + while(i-->0){ + key = keys[i]; + obj = root[key]; + + if(obj){ + flag= true; + if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ + delete root[key]; + } + } + } + + return flag; + } + + function Listener(emitter, event, listener){ + this.emitter= emitter; + this.event= event; + this.listener= listener; + } + + Listener.prototype.off= function(){ + this.emitter.off(this.event, this.listener); + return this; + }; + + function setupListener(event, listener, options){ + if (options === true) { + promisify = true; + } else if (options === false) { + async = true; + } else { + if (!options || typeof options !== 'object') { + throw TypeError('options should be an object or true'); + } + var async = options.async; + var promisify = options.promisify; + var nextTick = options.nextTick; + var objectify = options.objectify; + } + + if (async || nextTick || promisify) { + var _listener = listener; + var _origin = listener._origin || listener; + + if (nextTick && !nextTickSupported) { + throw Error('process.nextTick is not supported'); + } + + if (promisify === undefined$1) { + promisify = listener.constructor.name === 'AsyncFunction'; + } + + listener = function () { + var args = arguments; + var context = this; + var event = this.event; + + return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { + _setImmediate(resolve); + }).then(function () { + context.event = event; + return _listener.apply(context, args) + })) : (nextTick ? process.nextTick : _setImmediate)(function () { + context.event = event; + _listener.apply(context, args); + }); + }; + + listener._async = true; + listener._origin = _origin; + } + + return [listener, objectify? new Listener(this, event, listener): this]; + } + + function EventEmitter(conf) { + this._events = {}; + this._newListener = false; + this._removeListener = false; + this.verboseMemoryLeak = false; + configure.call(this, conf); + } + + EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property + + EventEmitter.prototype.listenTo= function(target, events, options){ + if(typeof target!=='object'){ + throw TypeError('target musts be an object'); + } + + var emitter= this; + + options = resolveOptions(options, { + on: undefined$1, + off: undefined$1, + reducers: undefined$1 + }, { + on: functionReducer, + off: functionReducer, + reducers: objectFunctionReducer + }); + + function listen(events){ + if(typeof events!=='object'){ + throw TypeError('events must be an object'); + } + + var reducers= options.reducers; + var index= findTargetIndex.call(emitter, target); + var observer; + + if(index===-1){ + observer= new TargetObserver(emitter, target, options); + }else { + observer= emitter._observers[index]; + } + + var keys= ownKeys(events); + var len= keys.length; + var event; + var isSingleReducer= typeof reducers==='function'; + + for(var i=0; i 0) { + observer = observers[i]; + if (!target || observer._target === target) { + observer.unsubscribe(event); + matched= true; + } + } + + return matched; + }; + + // By default EventEmitters will print a warning if more than + // 10 listeners are added to it. This is a useful default which + // helps finding memory leaks. + // + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + + EventEmitter.prototype.delimiter = '.'; + + EventEmitter.prototype.setMaxListeners = function(n) { + if (n !== undefined$1) { + this._maxListeners = n; + if (!this._conf) this._conf = {}; + this._conf.maxListeners = n; + } + }; + + EventEmitter.prototype.getMaxListeners = function() { + return this._maxListeners; + }; + + EventEmitter.prototype.event = ''; + + EventEmitter.prototype.once = function(event, fn, options) { + return this._once(event, fn, false, options); + }; + + EventEmitter.prototype.prependOnceListener = function(event, fn, options) { + return this._once(event, fn, true, options); + }; + + EventEmitter.prototype._once = function(event, fn, prepend, options) { + return this._many(event, 1, fn, prepend, options); + }; + + EventEmitter.prototype.many = function(event, ttl, fn, options) { + return this._many(event, ttl, fn, false, options); + }; + + EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { + return this._many(event, ttl, fn, true, options); + }; + + EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { + var self = this; + + if (typeof fn !== 'function') { + throw new Error('many only accepts instances of Function'); + } + + function listener() { + if (--ttl === 0) { + self.off(event, listener); + } + return fn.apply(this, arguments); + } + + listener._origin = fn; + + return this._on(event, listener, prepend, options); + }; + + EventEmitter.prototype.emit = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0], ns, wildcard= this.wildcard; + var args,l,i,j, containsSymbol; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { + return false; + } + } + + if (wildcard) { + ns= type; + if(type!=='newListener' && type!=='removeListener'){ + if (typeof type === 'object') { + l = type.length; + if (symbolsSupported) { + for (i = 0; i < l; i++) { + if (typeof type[i] === 'symbol') { + containsSymbol = true; + break; + } + } + } + if (!containsSymbol) { + type = type.join(this.delimiter); + } + } + } + } + + var al = arguments.length; + var handler; + + if (this._all && this._all.length) { + handler = this._all.slice(); + + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this, type); + break; + case 2: + handler[i].call(this, type, arguments[1]); + break; + case 3: + handler[i].call(this, type, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, arguments); + } + } + } + + if (wildcard) { + handler = []; + searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); + } else { + handler = this._events[type]; + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + handler.apply(this, args); + } + return true; + } else if (handler) { + // need to make copy of handlers because list can change in the middle + // of emit call + handler = handler.slice(); + } + } + + if (handler && handler.length) { + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this); + break; + case 2: + handler[i].call(this, arguments[1]); + break; + case 3: + handler[i].call(this, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, args); + } + } + return true; + } else if (!this.ignoreErrors && !this._all && type === 'error') { + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + } + + return !!this._all; + }; + + EventEmitter.prototype.emitAsync = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; + var args,l,i,j; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { return Promise.resolve([false]); } + } + + if (wildcard) { + ns= type; + if(type!=='newListener' && type!=='removeListener'){ + if (typeof type === 'object') { + l = type.length; + if (symbolsSupported) { + for (i = 0; i < l; i++) { + if (typeof type[i] === 'symbol') { + containsSymbol = true; + break; + } + } + } + if (!containsSymbol) { + type = type.join(this.delimiter); + } + } + } + } + + var promises= []; + + var al = arguments.length; + var handler; + + if (this._all) { + for (i = 0, l = this._all.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(this._all[i].call(this, type)); + break; + case 2: + promises.push(this._all[i].call(this, type, arguments[1])); + break; + case 3: + promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); + break; + default: + promises.push(this._all[i].apply(this, arguments)); + } + } + } + + if (wildcard) { + handler = []; + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } else { + handler = this._events[type]; + } + + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + promises.push(handler.call(this)); + break; + case 2: + promises.push(handler.call(this, arguments[1])); + break; + case 3: + promises.push(handler.call(this, arguments[1], arguments[2])); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + promises.push(handler.apply(this, args)); + } + } else if (handler && handler.length) { + handler = handler.slice(); + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(handler[i].call(this)); + break; + case 2: + promises.push(handler[i].call(this, arguments[1])); + break; + case 3: + promises.push(handler[i].call(this, arguments[1], arguments[2])); + break; + default: + promises.push(handler[i].apply(this, args)); + } + } + } else if (!this.ignoreErrors && !this._all && type === 'error') { + if (arguments[1] instanceof Error) { + return Promise.reject(arguments[1]); // Unhandled 'error' event + } else { + return Promise.reject("Uncaught, unspecified 'error' event."); + } + } + + return Promise.all(promises); + }; + + EventEmitter.prototype.on = function(type, listener, options) { + return this._on(type, listener, false, options); + }; + + EventEmitter.prototype.prependListener = function(type, listener, options) { + return this._on(type, listener, true, options); + }; + + EventEmitter.prototype.onAny = function(fn) { + return this._onAny(fn, false); + }; + + EventEmitter.prototype.prependAny = function(fn) { + return this._onAny(fn, true); + }; + + EventEmitter.prototype.addListener = EventEmitter.prototype.on; + + EventEmitter.prototype._onAny = function(fn, prepend){ + if (typeof fn !== 'function') { + throw new Error('onAny only accepts instances of Function'); + } + + if (!this._all) { + this._all = []; + } + + // Add the function to the event listener collection. + if(prepend){ + this._all.unshift(fn); + }else { + this._all.push(fn); + } + + return this; + }; + + EventEmitter.prototype._on = function(type, listener, prepend, options) { + if (typeof type === 'function') { + this._onAny(type, listener); + return this; + } + + if (typeof listener !== 'function') { + throw new Error('on only accepts instances of Function'); + } + this._events || init.call(this); + + var returnValue= this, temp; + + if (options !== undefined$1) { + temp = setupListener.call(this, type, listener, options); + listener = temp[0]; + returnValue = temp[1]; + } + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + if (this._newListener) { + this.emit('newListener', type, listener); + } + + if (this.wildcard) { + growListenerTree.call(this, type, listener, prepend); + return returnValue; + } + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } else { + if (typeof this._events[type] === 'function') { + // Change to array. + this._events[type] = [this._events[type]]; + } + + // If we've already got an array, just add + if(prepend){ + this._events[type].unshift(listener); + }else { + this._events[type].push(listener); + } + + // Check for listener leak + if ( + !this._events[type].warned && + this._maxListeners > 0 && + this._events[type].length > this._maxListeners + ) { + this._events[type].warned = true; + logPossibleMemoryLeak.call(this, this._events[type].length, type); + } + } + + return returnValue; + }; + + EventEmitter.prototype.off = function(type, listener) { + if (typeof listener !== 'function') { + throw new Error('removeListener only takes instances of Function'); + } + + var handlers,leafs=[]; + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + if(!leafs) return this; + } else { + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events[type]) return this; + handlers = this._events[type]; + leafs.push({_listeners:handlers}); + } + + for (var iLeaf=0; iLeaf 0) { + fns = this._all; + for(i = 0, l = fns.length; i < l; i++) { + if(fn === fns[i]) { + fns.splice(i, 1); + if (this._removeListener) + this.emit("removeListenerAny", fn); + return this; + } + } + } else { + fns = this._all; + if (this._removeListener) { + for(i = 0, l = fns.length; i < l; i++) + this.emit("removeListenerAny", fns[i]); + } + this._all = []; + } + return this; + }; + + EventEmitter.prototype.removeListener = EventEmitter.prototype.off; + + EventEmitter.prototype.removeAllListeners = function (type) { + if (type === undefined$1) { + !this._events || init.call(this); + return this; + } + + if (this.wildcard) { + var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; + if (!leafs) return this; + for (i = 0; i < leafs.length; i++) { + leaf = leafs[i]; + leaf._listeners = null; + } + this.listenerTree && recursivelyGarbageCollect(this.listenerTree); + } else if (this._events) { + this._events[type] = null; + } + return this; + }; + + EventEmitter.prototype.listeners = function (type) { + var _events = this._events; + var keys, listeners, allListeners; + var i; + var listenerTree; + + if (type === undefined$1) { + if (this.wildcard) { + throw Error('event name required for wildcard emitter'); + } + + if (!_events) { + return []; + } + + keys = ownKeys(_events); + i = keys.length; + allListeners = []; + while (i-- > 0) { + listeners = _events[keys[i]]; + if (typeof listeners === 'function') { + allListeners.push(listeners); + } else { + allListeners.push.apply(allListeners, listeners); + } + } + return allListeners; + } else { + if (this.wildcard) { + listenerTree= this.listenerTree; + if(!listenerTree) return []; + var handlers = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handlers, ns, listenerTree, 0); + return handlers; + } + + if (!_events) { + return []; + } + + listeners = _events[type]; + + if (!listeners) { + return []; + } + return typeof listeners === 'function' ? [listeners] : listeners; + } + }; + + EventEmitter.prototype.eventNames = function(nsAsArray){ + var _events= this._events; + return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); + }; + + EventEmitter.prototype.listenerCount = function(type) { + return this.listeners(type).length; + }; + + EventEmitter.prototype.hasListeners = function (type) { + if (this.wildcard) { + var handlers = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); + return handlers.length > 0; + } + + var _events = this._events; + var _all = this._all; + + return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); + }; + + EventEmitter.prototype.listenersAny = function() { + + if(this._all) { + return this._all; + } + else { + return []; + } + + }; + + EventEmitter.prototype.waitFor = function (event, options) { + var self = this; + var type = typeof options; + if (type === 'number') { + options = {timeout: options}; + } else if (type === 'function') { + options = {filter: options}; + } + + options= resolveOptions(options, { + timeout: 0, + filter: undefined$1, + handleError: false, + Promise: Promise, + overload: false + }, { + filter: functionReducer, + Promise: constructorReducer + }); + + return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { + function listener() { + var filter= options.filter; + if (filter && !filter.apply(self, arguments)) { + return; + } + self.off(event, listener); + if (options.handleError) { + var err = arguments[0]; + err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); + } else { + resolve(toArray.apply(null, arguments)); + } + } + + onCancel(function(){ + self.off(event, listener); + }); + + self._on(event, listener, false); + }, { + timeout: options.timeout, + overload: options.overload + }) + }; + + function once(emitter, name, options) { + options= resolveOptions(options, { + Promise: Promise, + timeout: 0, + overload: false + }, { + Promise: constructorReducer + }); + + var _Promise= options.Promise; + + return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ + var handler; + if (typeof emitter.addEventListener === 'function') { + handler= function () { + resolve(toArray.apply(null, arguments)); + }; + + onCancel(function(){ + emitter.removeEventListener(name, handler); + }); + + emitter.addEventListener( + name, + handler, + {once: true} + ); + return; + } + + var eventListener = function(){ + errorListener && emitter.removeListener('error', errorListener); + resolve(toArray.apply(null, arguments)); + }; + + var errorListener; + + if (name !== 'error') { + errorListener = function (err){ + emitter.removeListener(name, eventListener); + reject(err); + }; + + emitter.once('error', errorListener); + } + + onCancel(function(){ + errorListener && emitter.removeListener('error', errorListener); + emitter.removeListener(name, eventListener); + }); + + emitter.once(name, eventListener); + }, { + timeout: options.timeout, + overload: options.overload + }); + } + + var prototype= EventEmitter.prototype; + + Object.defineProperties(EventEmitter, { + defaultMaxListeners: { + get: function () { + return prototype._maxListeners; + }, + set: function (n) { + if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { + throw TypeError('n must be a non-negative number') + } + prototype._maxListeners = n; + }, + enumerable: true + }, + once: { + value: once, + writable: true, + configurable: true + } + }); + + Object.defineProperties(prototype, { + _maxListeners: { + value: defaultMaxListeners, + writable: true, + configurable: true + }, + _observers: {value: null, writable: true, configurable: true} + }); + + if (typeof undefined$1 === 'function' && undefined$1.amd) { + // AMD. Register as an anonymous module. + undefined$1(function() { + return EventEmitter; + }); + } else { + // CommonJS + module.exports = EventEmitter; + } + }(); + } (eventemitter2, eventemitter2.exports)); + + var eventemitter2Exports = eventemitter2.exports; + var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); + + function _callSuper$q(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$q() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$q() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$q = function _isNativeReflectConstruct() { return !!t; })(); } + /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class InteractiveMarkerHandle extends EventEmitter3 { - + var InteractiveMarkerHandle = /*#__PURE__*/function (_EventEmitter) { /** * Handle with signals for a single interactive marker. * @@ -53336,187 +45269,207 @@ var ROS3D = (function (exports, ROSLIB) { * * tfClient - a handle to the TF client to use * * menuFontSize (optional) - the menu font size */ - constructor(options) { - super(); + function InteractiveMarkerHandle(options) { + var _this; + _classCallCheck(this, InteractiveMarkerHandle); + _this = _callSuper$q(this, InteractiveMarkerHandle); options = options || {}; - this.message = options.message; - this.feedbackTopic = options.feedbackTopic; - this.tfClient = options.tfClient; - this.menuFontSize = options.menuFontSize || '0.8em'; - this.name = this.message.name; - this.header = this.message.header; - this.controls = this.message.controls; - this.menuEntries = this.message.menu_entries; - this.dragging = false; - this.timeoutHandle = null; - this.tfTransform = new ROSLIB__namespace.Transform(); - this.pose = new ROSLIB__namespace.Pose(); - - this.setPoseFromClientBound = this.setPoseFromClient.bind(this); - this.onMouseDownBound = this.onMouseDown.bind(this); - this.onMouseUpBound = this.onMouseUp.bind(this); - this.onButtonClickBound = this.onButtonClick.bind(this); - this.onMenuSelectBound = this.onMenuSelect.bind(this); + _this.message = options.message; + _this.feedbackTopic = options.feedbackTopic; + _this.tfClient = options.tfClient; + _this.menuFontSize = options.menuFontSize || '0.8em'; + _this.name = _this.message.name; + _this.header = _this.message.header; + _this.controls = _this.message.controls; + _this.menuEntries = _this.message.menu_entries; + _this.dragging = false; + _this.timeoutHandle = null; + _this.tfTransform = new ROSLIB__namespace.Transform(); + _this.pose = new ROSLIB__namespace.Pose(); + _this.setPoseFromClientBound = _this.setPoseFromClient.bind(_this); + _this.onMouseDownBound = _this.onMouseDown.bind(_this); + _this.onMouseUpBound = _this.onMouseUp.bind(_this); + _this.onButtonClickBound = _this.onButtonClick.bind(_this); + _this.onMenuSelectBound = _this.onMenuSelect.bind(_this); // start by setting the pose - this.setPoseFromServer(this.message.pose); - this.tfUpdateBound = this.tfUpdate.bind(this); - }; - - /** - * Subscribe to the TF associated with this interactive marker. - */ - subscribeTf() { - // subscribe to tf updates if frame-fixed - if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { - this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + _this.setPoseFromServer(_this.message.pose); + _this.tfUpdateBound = _this.tfUpdate.bind(_this); + return _this; + } + _inherits(InteractiveMarkerHandle, _EventEmitter); + return _createClass(InteractiveMarkerHandle, [{ + key: "subscribeTf", + value: + /** + * Subscribe to the TF associated with this interactive marker. + */ + function subscribeTf() { + // subscribe to tf updates if frame-fixed + if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { + this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + } } - }; - - unsubscribeTf() { - this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); - }; - - /** - * Emit the new pose that has come from the server. - */ - emitServerPoseUpdate() { - var poseTransformed = new ROSLIB__namespace.Pose(this.pose); - poseTransformed.applyTransform(this.tfTransform); - this.emit('pose', poseTransformed); - }; - - /** - * Update the pose based on the pose given by the server. - * - * @param poseMsg - the pose given by the server - */ - setPoseFromServer(poseMsg) { - this.pose = new ROSLIB__namespace.Pose(poseMsg); - this.emitServerPoseUpdate(); - }; - - /** - * Update the pose based on the TF given by the server. - * - * @param transformMsg - the TF given by the server - */ - tfUpdate(transformMsg) { - this.tfTransform = new ROSLIB__namespace.Transform(transformMsg); - this.emitServerPoseUpdate(); - }; - - /** - * Set the pose from the client based on the given event. - * - * @param event - the event to base the change off of - */ - setPoseFromClient(event) { - // apply the transform - this.pose = new ROSLIB__namespace.Pose(event); - var inv = this.tfTransform.clone(); - inv.rotation.invert(); - inv.translation.multiplyQuaternion(inv.rotation); - inv.translation.x *= -1; - inv.translation.y *= -1; - inv.translation.z *= -1; - this.pose.applyTransform(inv); - - // send feedback to the server - this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); - - // keep sending pose feedback until the mouse goes up - if (this.dragging) { + }, { + key: "unsubscribeTf", + value: function unsubscribeTf() { + this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); + } + }, { + key: "emitServerPoseUpdate", + value: + /** + * Emit the new pose that has come from the server. + */ + function emitServerPoseUpdate() { + var poseTransformed = new ROSLIB__namespace.Pose(this.pose); + poseTransformed.applyTransform(this.tfTransform); + this.emit('pose', poseTransformed); + } + }, { + key: "setPoseFromServer", + value: + /** + * Update the pose based on the pose given by the server. + * + * @param poseMsg - the pose given by the server + */ + function setPoseFromServer(poseMsg) { + this.pose = new ROSLIB__namespace.Pose(poseMsg); + this.emitServerPoseUpdate(); + } + }, { + key: "tfUpdate", + value: + /** + * Update the pose based on the TF given by the server. + * + * @param transformMsg - the TF given by the server + */ + function tfUpdate(transformMsg) { + this.tfTransform = new ROSLIB__namespace.Transform(transformMsg); + this.emitServerPoseUpdate(); + } + }, { + key: "setPoseFromClient", + value: + /** + * Set the pose from the client based on the given event. + * + * @param event - the event to base the change off of + */ + function setPoseFromClient(event) { + // apply the transform + this.pose = new ROSLIB__namespace.Pose(event); + var inv = this.tfTransform.clone(); + inv.rotation.invert(); + inv.translation.multiplyQuaternion(inv.rotation); + inv.translation.x *= -1; + inv.translation.y *= -1; + inv.translation.z *= -1; + this.pose.applyTransform(inv); + + // send feedback to the server + this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); + + // keep sending pose feedback until the mouse goes up + if (this.dragging) { + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); + } + this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); + } + } + }, { + key: "onButtonClick", + value: + /** + * Send the button click feedback to the server. + * + * @param event - the event associated with the button click + */ + function onButtonClick(event) { + this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, event.controlName); + } + }, { + key: "onMouseDown", + value: + /** + * Send the mousedown feedback to the server. + * + * @param event - the event associated with the mousedown + */ + function onMouseDown(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); + this.dragging = true; + } + }, { + key: "onMouseUp", + value: + /** + * Send the mouseup feedback to the server. + * + * @param event - the event associated with the mouseup + */ + function onMouseUp(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); + this.dragging = false; if (this.timeoutHandle) { clearTimeout(this.timeoutHandle); } - this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); } - }; - - /** - * Send the button click feedback to the server. - * - * @param event - the event associated with the button click - */ - onButtonClick(event) { - this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, - event.controlName); - }; - - /** - * Send the mousedown feedback to the server. - * - * @param event - the event associated with the mousedown - */ - onMouseDown(event) { - this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); - this.dragging = true; - }; - - /** - * Send the mouseup feedback to the server. - * - * @param event - the event associated with the mouseup - */ - onMouseUp(event) { - this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); - this.dragging = false; - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); + }, { + key: "onMenuSelect", + value: + /** + * Send the menu select feedback to the server. + * + * @param event - the event associated with the menu select + */ + function onMenuSelect(event) { + this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); } - }; - - /** - * Send the menu select feedback to the server. - * - * @param event - the event associated with the menu select - */ - onMenuSelect(event) { - this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); - }; - - /** - * Send feedback to the interactive marker server. - * - * @param eventType - the type of event that happened - * @param clickPosition (optional) - the position in ROS space the click happened - * @param menuEntryID (optional) - the menu entry ID that is associated - * @param controlName - the name of the control - */ - sendFeedback(eventType, clickPosition, - menuEntryID, controlName) { - - // check for the click position - var mousePointValid = clickPosition !== undefined; - clickPosition = clickPosition || { - x : 0, - y : 0, - z : 0 - }; - - var feedback = { - header : this.header, - client_id : this.clientID, - marker_name : this.name, - control_name : controlName, - event_type : eventType, - pose : this.pose, - mouse_point : clickPosition, - mouse_point_valid : mousePointValid, - menu_entry_id : menuEntryID - }; - this.feedbackTopic.publish(feedback); - }; - } + }, { + key: "sendFeedback", + value: + /** + * Send feedback to the interactive marker server. + * + * @param eventType - the type of event that happened + * @param clickPosition (optional) - the position in ROS space the click happened + * @param menuEntryID (optional) - the menu entry ID that is associated + * @param controlName - the name of the control + */ + function sendFeedback(eventType, clickPosition, menuEntryID, controlName) { + // check for the click position + var mousePointValid = clickPosition !== undefined; + clickPosition = clickPosition || { + x: 0, + y: 0, + z: 0 + }; + var feedback = { + header: this.header, + client_id: this.clientID, + marker_name: this.name, + control_name: controlName, + event_type: eventType, + pose: this.pose, + mouse_point: clickPosition, + mouse_point_valid: mousePointValid, + menu_entry_id: menuEntryID + }; + this.feedbackTopic.publish(feedback); + } + }]); + }(EventEmitter2); /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class InteractiveMarkerClient { - + var InteractiveMarkerClient = /*#__PURE__*/function () { /** * A client for an interactive marker topic. * @@ -53532,17 +45485,17 @@ var ROS3D = (function (exports, ROSLIB) { * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) * * menuFontSize (optional) - the menu font size */ - constructor(options) { + function InteractiveMarkerClient(options) { + _classCallCheck(this, InteractiveMarkerClient); options = options || {}; this.ros = options.ros; this.tfClient = options.tfClient; this.topicName = options.topic; this.path = options.path || '/'; this.camera = options.camera; - this.rootObject = options.rootObject || new THREE.Object3D(); + this.rootObject = options.rootObject || new Object3D(); this.loader = options.loader; this.menuFontSize = options.menuFontSize || '0.8em'; - this.interactiveMarkers = {}; this.updateTopic = null; this.feedbackTopic = null; @@ -53552,172 +45505,183 @@ var ROS3D = (function (exports, ROSLIB) { if (this.topicName) { this.subscribe(this.topicName); } - }; - - /** - * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. - * - * @param topic - the topic to subscribe to, like '/basic_controls' - */ - subscribe(topic) { - // unsubscribe to the other topics - this.unsubscribe(); - - this.updateTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : topic + '/tunneled/update', - messageType : 'visualization_msgs/InteractiveMarkerUpdate', - compression : 'png' - }); - this.updateTopic.subscribe(this.processUpdateBound); - - this.feedbackTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : topic + '/feedback', - messageType : 'visualization_msgs/InteractiveMarkerFeedback', - compression : 'png' - }); - this.feedbackTopic.advertise(); - - this.initService = new ROSLIB__namespace.Service({ - ros : this.ros, - name : topic + '/tunneled/get_init', - serviceType : 'demo_interactive_markers/GetInit' - }); - var request = new ROSLIB__namespace.ServiceRequest({}); - this.initService.callService(request, this.processInit.bind(this)); - }; - - /** - * Unsubscribe from the current interactive marker topic. - */ - unsubscribe() { - if (this.updateTopic) { - this.updateTopic.unsubscribe(this.processUpdateBound); - } - if (this.feedbackTopic) { - this.feedbackTopic.unadvertise(); + } + return _createClass(InteractiveMarkerClient, [{ + key: "subscribe", + value: + /** + * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. + * + * @param topic - the topic to subscribe to, like '/basic_controls' + */ + function subscribe(topic) { + // unsubscribe to the other topics + this.unsubscribe(); + this.updateTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: topic + '/tunneled/update', + messageType: 'visualization_msgs/InteractiveMarkerUpdate', + compression: 'png' + }); + this.updateTopic.subscribe(this.processUpdateBound); + this.feedbackTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: topic + '/feedback', + messageType: 'visualization_msgs/InteractiveMarkerFeedback', + compression: 'png' + }); + this.feedbackTopic.advertise(); + this.initService = new ROSLIB__namespace.Service({ + ros: this.ros, + name: topic + '/tunneled/get_init', + serviceType: 'demo_interactive_markers/GetInit' + }); + var request = new ROSLIB__namespace.ServiceRequest({}); + this.initService.callService(request, this.processInit.bind(this)); } - // erase all markers - for (var intMarkerName in this.interactiveMarkers) { - this.eraseIntMarker(intMarkerName); + }, { + key: "unsubscribe", + value: + /** + * Unsubscribe from the current interactive marker topic. + */ + function unsubscribe() { + if (this.updateTopic) { + this.updateTopic.unsubscribe(this.processUpdateBound); + } + if (this.feedbackTopic) { + this.feedbackTopic.unadvertise(); + } + // erase all markers + for (var intMarkerName in this.interactiveMarkers) { + this.eraseIntMarker(intMarkerName); + } + this.interactiveMarkers = {}; } - this.interactiveMarkers = {}; - }; + }, { + key: "processInit", + value: + /** + * Process the given interactive marker initialization message. + * + * @param initMessage - the interactive marker initialization message to process + */ + function processInit(initMessage) { + var message = initMessage.msg; - /** - * Process the given interactive marker initialization message. - * - * @param initMessage - the interactive marker initialization message to process - */ - processInit(initMessage) { - var message = initMessage.msg; + // erase any old markers + message.erases = []; + for (var intMarkerName in this.interactiveMarkers) { + message.erases.push(intMarkerName); + } + message.poses = []; - // erase any old markers - message.erases = []; - for (var intMarkerName in this.interactiveMarkers) { - message.erases.push(intMarkerName); + // treat it as an update + this.processUpdate(message); } - message.poses = []; - - // treat it as an update - this.processUpdate(message); - }; - - /** - * Process the given interactive marker update message. - * - * @param initMessage - the interactive marker update message to process - */ - processUpdate(message) { - // erase any markers - message.erases.forEach(function(name) { - this.eraseIntMarker(name); - }); + }, { + key: "processUpdate", + value: + /** + * Process the given interactive marker update message. + * + * @param initMessage - the interactive marker update message to process + */ + function processUpdate(message) { + // erase any markers + message.erases.forEach(function (name) { + this.eraseIntMarker(name); + }); - // updates marker poses - message.poses.forEach(function(poseMessage) { - var marker = this.interactiveMarkers[poseMessage.name]; - if (marker) { - marker.setPoseFromServer(poseMessage.pose); - } - }); + // updates marker poses + message.poses.forEach(function (poseMessage) { + var marker = this.interactiveMarkers[poseMessage.name]; + if (marker) { + marker.setPoseFromServer(poseMessage.pose); + } + }); - // add new markers - message.markers.forEach(function(msg) { - // get rid of anything with the same name - var oldhandle = this.interactiveMarkers[msg.name]; - if (oldhandle) { - this.eraseIntMarker(oldhandle.name); - } + // add new markers + message.markers.forEach(function (msg) { + // get rid of anything with the same name + var oldhandle = this.interactiveMarkers[msg.name]; + if (oldhandle) { + this.eraseIntMarker(oldhandle.name); + } - // create the handle - var handle = new InteractiveMarkerHandle({ - message : msg, - feedbackTopic : this.feedbackTopic, - tfClient : this.tfClient, - menuFontSize : this.menuFontSize - }); - this.interactiveMarkers[msg.name] = handle; - - // create the actual marker - var intMarker = new InteractiveMarker({ - handle : handle, - camera : this.camera, - path : this.path, - loader : this.loader - }); - // add it to the scene - intMarker.name = msg.name; - this.rootObject.add(intMarker); - - // listen for any pose updates from the server - handle.on('pose', function(pose) { - intMarker.onServerSetPose({ - pose : pose + // create the handle + var handle = new InteractiveMarkerHandle({ + message: msg, + feedbackTopic: this.feedbackTopic, + tfClient: this.tfClient, + menuFontSize: this.menuFontSize + }); + this.interactiveMarkers[msg.name] = handle; + + // create the actual marker + var intMarker = new InteractiveMarker({ + handle: handle, + camera: this.camera, + path: this.path, + loader: this.loader + }); + // add it to the scene + intMarker.name = msg.name; + this.rootObject.add(intMarker); + + // listen for any pose updates from the server + handle.on('pose', function (pose) { + intMarker.onServerSetPose({ + pose: pose + }); }); - }); - - // add bound versions of UI handlers - intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); - intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); - intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); - intMarker.addEventListener('user-button-click', handle.onButtonClickBound); - intMarker.addEventListener('menu-select', handle.onMenuSelectBound); - // now listen for any TF changes - handle.subscribeTf(); - }); - }; + // add bound versions of UI handlers + intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); + intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); + intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); + intMarker.addEventListener('user-button-click', handle.onButtonClickBound); + intMarker.addEventListener('menu-select', handle.onMenuSelectBound); - /** - * Erase the interactive marker with the given name. - * - * @param intMarkerName - the interactive marker name to delete - */ - eraseIntMarker(intMarkerName) { - if (this.interactiveMarkers[intMarkerName]) { - // remove the object - var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); - this.rootObject.remove(targetIntMarker); - // unsubscribe from TF topic! - var handle = this.interactiveMarkers[intMarkerName]; - handle.unsubscribeTf(); - - // remove all other listeners - - targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); - targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); - targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); - targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); - targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); - - // remove the handle from the map - after leaving this function's scope, there should be no references to the handle - delete this.interactiveMarkers[intMarkerName]; - targetIntMarker.dispose(); + // now listen for any TF changes + handle.subscribeTf(); + }); } - }; - } + }, { + key: "eraseIntMarker", + value: + /** + * Erase the interactive marker with the given name. + * + * @param intMarkerName - the interactive marker name to delete + */ + function eraseIntMarker(intMarkerName) { + if (this.interactiveMarkers[intMarkerName]) { + // remove the object + var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); + this.rootObject.remove(targetIntMarker); + // unsubscribe from TF topic! + var handle = this.interactiveMarkers[intMarkerName]; + handle.unsubscribeTf(); + + // remove all other listeners + + targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); + targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); + targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); + targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); + targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); + + // remove the handle from the map - after leaving this function's scope, there should be no references to the handle + delete this.interactiveMarkers[intMarkerName]; + targetIntMarker.dispose(); + } + } + }]); + }(); + + function _callSuper$p(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$p() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$p() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$p = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -53725,8 +45689,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Russell Toris - rctoris@wpi.edu */ - class SceneNode extends THREE.Object3D { - + var SceneNode = /*#__PURE__*/function (_THREE$Object3D) { /** * A SceneNode can be used to keep track of a 3D object with respect to a ROS frame within a scene. * @@ -53738,26 +45701,27 @@ var ROS3D = (function (exports, ROSLIB) { * * pose (optional) - the pose associated with this object * * object - the THREE 3D object to be rendered */ - constructor(options) { - super(); + function SceneNode(options) { + var _this; + _classCallCheck(this, SceneNode); + _this = _callSuper$p(this, SceneNode); options = options || {}; - this.tfClient = options.tfClient; - this.frameID = options.frameID; + _this.tfClient = options.tfClient; + _this.frameID = options.frameID; var object = options.object; - this.pose = options.pose || new ROSLIB__namespace.Pose(); + _this.pose = options.pose || new ROSLIB__namespace.Pose(); // Do not render this object until we receive a TF update - this.visible = false; + _this.visible = false; // add the model - this.add(object); + _this.add(object); // set the inital pose - this.updatePose(this.pose); + _this.updatePose(_this.pose); // save the TF handler so we can remove it later - this.tfUpdate = function(msg) { - + _this.tfUpdate = function (msg) { // apply the transform var tf = new ROSLIB__namespace.Transform(msg); var poseTransformed = new ROSLIB__namespace.Pose(this.pose); @@ -53769,26 +45733,34 @@ var ROS3D = (function (exports, ROSLIB) { }; // listen for TF updates - this.tfUpdateBound = this.tfUpdate.bind(this); - this.tfClient.subscribe(this.frameID, this.tfUpdateBound); - }; - - /** - * Set the pose of the associated model. - * - * @param pose - the pose to update with - */ - updatePose(pose) { - this.position.set( pose.position.x, pose.position.y, pose.position.z ); - this.quaternion.set(pose.orientation.x, pose.orientation.y, - pose.orientation.z, pose.orientation.w); - this.updateMatrixWorld(true); - }; + _this.tfUpdateBound = _this.tfUpdate.bind(_this); + _this.tfClient.subscribe(_this.frameID, _this.tfUpdateBound); + return _this; + } + _inherits(SceneNode, _THREE$Object3D); + return _createClass(SceneNode, [{ + key: "updatePose", + value: + /** + * Set the pose of the associated model. + * + * @param pose - the pose to update with + */ + function updatePose(pose) { + this.position.set(pose.position.x, pose.position.y, pose.position.z); + this.quaternion.set(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w); + this.updateMatrixWorld(true); + } + }, { + key: "unsubscribeTf", + value: function unsubscribeTf() { + this.tfClient.unsubscribe(this.frameID, this.tfUpdateBound); + } + }]); + }(Object3D); - unsubscribeTf() { - this.tfClient.unsubscribe(this.frameID, this.tfUpdateBound); - }; - } + function _callSuper$o(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$o() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$o() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$o = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -53796,8 +45768,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Nils Berg - berg.nils@gmail.com */ - class MarkerArrayClient extends EventEmitter3 { - + var MarkerArrayClient = /*#__PURE__*/function (_EventEmitter) { /** * A MarkerArray client that listens to a given topic. * @@ -53814,107 +45785,118 @@ var ROS3D = (function (exports, ROSLIB) { * * rootObject (optional) - the root object to add the markers to * * path (optional) - the base path to any meshes that will be loaded */ - constructor(options) { - super(); + function MarkerArrayClient(options) { + var _this; + _classCallCheck(this, MarkerArrayClient); + _this = _callSuper$o(this, MarkerArrayClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.path = options.path || '/'; + _this.ros = options.ros; + _this.topicName = options.topic; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.path = options.path || '/'; // Markers that are displayed (Map ns+id--Marker) - this.markers = {}; - this.rosTopic = undefined; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - subscribe(){ - this.unsubscribe(); - - // subscribe to MarkerArray topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'visualization_msgs/MarkerArray', - compression : 'png' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(arrayMessage){ - arrayMessage.markers.forEach(function(message) { - var key = message.ns + message.id; - if(message.action === 0) { - var updated = false; - if(key in this.markers) { // "MODIFY" - updated = this.markers[key].children[0].update(message); - if(!updated) { // "REMOVE" - this.removeMarker(key); + _this.markers = {}; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(MarkerArrayClient, _EventEmitter); + return _createClass(MarkerArrayClient, [{ + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to MarkerArray topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'visualization_msgs/MarkerArray', + compression: 'png' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(arrayMessage) { + arrayMessage.markers.forEach(function (message) { + var key = message.ns + message.id; + if (message.action === 0) { + var updated = false; + if (key in this.markers) { + // "MODIFY" + updated = this.markers[key].children[0].update(message); + if (!updated) { + // "REMOVE" + this.removeMarker(key); + } } + if (!updated) { + // "ADD" + var newMarker = new Marker({ + message: message, + path: this.path + }); + this.markers[key] = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newMarker + }); + this.rootObject.add(this.markers[key]); + } + } else if (message.action === 1) { + // "DEPRECATED" + console.warn('Received marker message with deprecated action identifier "1"'); + } else if (message.action === 2) { + // "DELETE" + this.removeMarker(key); + } else if (message.action === 3) { + // "DELETE ALL" + for (var m in this.markers) { + this.removeMarker(m); + } + this.markers = {}; + } else { + console.warn('Received marker message with unknown action identifier "' + message.action + '"'); } - if(!updated) { // "ADD" - var newMarker = new Marker({ - message : message, - path : this.path, - }); - this.markers[key] = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newMarker - }); - this.rootObject.add(this.markers[key]); - } - } - else if(message.action === 1) { // "DEPRECATED" - console.warn('Received marker message with deprecated action identifier "1"'); - } - else if(message.action === 2) { // "DELETE" - this.removeMarker(key); - } - else if(message.action === 3) { // "DELETE ALL" - for (var m in this.markers){ - this.removeMarker(m); - } - this.markers = {}; + }.bind(this)); + this.emit('change'); + } + }, { + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); } - else { - console.warn('Received marker message with unknown action identifier "'+message.action+'"'); + } + }, { + key: "removeMarker", + value: function removeMarker(key) { + var oldNode = this.markers[key]; + if (!oldNode) { + return; } - }.bind(this)); - - this.emit('change'); - }; - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(function (child) { + child.dispose(); + }); + delete this.markers[key]; } - }; + }]); + }(EventEmitter2); - removeMarker(key) { - var oldNode = this.markers[key]; - if(!oldNode) { - return; - } - oldNode.unsubscribeTf(); - this.rootObject.remove(oldNode); - oldNode.children.forEach(child => { - child.dispose(); - }); - delete(this.markers[key]); - }; - } + function _callSuper$n(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$n() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$n() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$n = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ - class MarkerClient extends EventEmitter3 { - + var MarkerClient = /*#__PURE__*/function (_EventEmitter) { /** * A marker client that listens to a given marker topic. * @@ -53932,106 +45914,115 @@ var ROS3D = (function (exports, ROSLIB) { * * path (optional) - the base path to any meshes that will be loaded * * lifetime - the lifetime of marker */ - constructor(options) { - super(); + function MarkerClient(options) { + var _this; + _classCallCheck(this, MarkerClient); + _this = _callSuper$n(this, MarkerClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.path = options.path || '/'; - this.lifetime = options.lifetime || 0; + _this.ros = options.ros; + _this.topicName = options.topic; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.path = options.path || '/'; + _this.lifetime = options.lifetime || 0; // Markers that are displayed (Map ns+id--Marker) - this.markers = {}; - this.rosTopic = undefined; - this.updatedTime = {}; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _this.markers = {}; + _this.rosTopic = undefined; + _this.updatedTime = {}; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(MarkerClient, _EventEmitter); + return _createClass(MarkerClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - - checkTime(name){ + }, { + key: "checkTime", + value: function checkTime(name) { var curTime = new Date().getTime(); if (curTime - this.updatedTime[name] > this.lifetime) { - this.removeMarker(name); - this.emit('change'); + this.removeMarker(name); + this.emit('change'); } else { - var that = this; - setTimeout(function() {that.checkTime(name);}, - 100); + var that = this; + setTimeout(function () { + that.checkTime(name); + }, 100); } - }; - - subscribe(){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'visualization_msgs/Marker', - compression : 'png' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(message){ - // remove old marker from Three.Object3D children buffer - var key = message.ns + message.id; - var oldNode = this.markers[key]; - this.updatedTime[key] = new Date().getTime(); - if (oldNode) { - this.removeMarker(key); - - } else if (this.lifetime) { - this.checkTime(message.ns + message.id); } - - if (message.action === 0) { // "ADD" or "MODIFY" - var newMarker = new Marker({ - message : message, - path : this.path, + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'visualization_msgs/Marker', + compression: 'png' }); - - this.markers[key] = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newMarker + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + // remove old marker from Three.Object3D children buffer + var key = message.ns + message.id; + var oldNode = this.markers[key]; + this.updatedTime[key] = new Date().getTime(); + if (oldNode) { + this.removeMarker(key); + } else if (this.lifetime) { + this.checkTime(message.ns + message.id); + } + if (message.action === 0) { + // "ADD" or "MODIFY" + var newMarker = new Marker({ + message: message, + path: this.path + }); + this.markers[key] = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newMarker + }); + this.rootObject.add(this.markers[key]); + } + this.emit('change'); + } + }, { + key: "removeMarker", + value: function removeMarker(key) { + var oldNode = this.markers[key]; + if (!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(function (child) { + child.dispose(); }); - this.rootObject.add(this.markers[key]); + delete this.markers[key]; } + }]); + }(EventEmitter2); - this.emit('change'); - }; - - removeMarker(key) { - var oldNode = this.markers[key]; - if(!oldNode) { - return; - } - oldNode.unsubscribeTf(); - this.rootObject.remove(oldNode); - oldNode.children.forEach(child => { - child.dispose(); - }); - delete(this.markers[key]); - }; - } + function _callSuper$m(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$m() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$m() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$m = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Jihoon Lee - lee@magazino.eu */ - class Arrow2 extends THREE.ArrowHelper { - + var Arrow2 = /*#__PURE__*/function (_THREE$ArrowHelper) { /** * A Arrow is a THREE object that can be used to display an arrow model using ArrowHelper * @@ -54046,62 +46037,47 @@ var ROS3D = (function (exports, ROSLIB) { * * headDiameter (optional) - the head diameter of the arrow * * material (optional) - the material to use for this arrow */ - constructor(options) { + function Arrow2(options) { + _classCallCheck(this, Arrow2); options = options || {}; - var origin = options.origin || new THREE.Vector3(0, 0, 0); - var direction = options.direction || new THREE.Vector3(1, 0, 0); + var origin = options.origin || new Vector3(0, 0, 0); + var direction = options.direction || new Vector3(1, 0, 0); var length = options.length || 1; options.headLength || 0.2; options.shaftDiameter || 0.05; options.headDiameter || 0.1; - options.material || new THREE.MeshBasicMaterial(); - - super(direction, origin, length, 0xff0000); - - }; - - - /* - * Free memory of elements in this object. - */ - dispose() { - if (this.line !== undefined) { + options.material || new MeshBasicMaterial(); + return _callSuper$m(this, Arrow2, [direction, origin, length, 0xff0000]); + } + _inherits(Arrow2, _THREE$ArrowHelper); + return _createClass(Arrow2, [{ + key: "dispose", + value: + /* + * Free memory of elements in this object. + */ + function dispose() { + if (this.line !== undefined) { this.line.material.dispose(); this.line.geometry.dispose(); - } - if (this.cone!== undefined) { + } + if (this.cone !== undefined) { this.cone.material.dispose(); this.cone.geometry.dispose(); + } } - }; - - /* - setLength( length, headLength, headWidth ) { - if ( headLength === undefined ) { - headLength = 0.2 * length; - } - if ( headWidth === undefined ) { - headWidth = 0.2 * headLength; - } - - this.line.scale.set( 1, Math.max( 0, length), 1 ); - this.line.updateMatrix(); - - this.cone.scale.set( headWidth, headLength, headWidth ); - this.cone.position.y = length; - this.cone.updateMatrix(); + }]); + }(ArrowHelper); - }; - */ - } + function _callSuper$l(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$l() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$l() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$l = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ - class Axes extends THREE.Object3D { - + var Axes = /*#__PURE__*/function (_THREE$Object3D) { /** * An Axes object can be used to display the axis of a particular coordinate frame. * @@ -54119,9 +46095,11 @@ var ROS3D = (function (exports, ROSLIB) { * equal to the length of the axis. Parameter only applies when * lineType is set to dashed. */ - constructor(options) { - super(); - var that = this; + function Axes(options) { + var _this; + _classCallCheck(this, Axes); + _this = _callSuper$l(this, Axes); + var that = _this; options = options || {}; var shaftRadius = options.shaftRadius || 0.008; var headRadius = options.headRadius || 0.023; @@ -54129,13 +46107,11 @@ var ROS3D = (function (exports, ROSLIB) { var scaleArg = options.scale || 1.0; var lineType = options.lineType || 'full'; var lineDashLength = options.lineDashLength || 0.1; - - - this.scale.set(scaleArg, scaleArg, scaleArg); + _this.scale.set(scaleArg, scaleArg, scaleArg); // create the cylinders for the objects - this.lineGeom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); - this.headGeom = new THREE.CylinderGeometry(0, headRadius, headLength); + _this.lineGeom = new CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); + _this.headGeom = new CylinderGeometry(0, headRadius, headLength); /** * Adds an axis marker to this axes object. @@ -54144,20 +46120,20 @@ var ROS3D = (function (exports, ROSLIB) { */ function addAxis(axis) { // set the color of the axis - var color = new THREE.Color(); + var color = new Color(); color.setRGB(axis.x, axis.y, axis.z); - var material = new THREE.MeshBasicMaterial({ - color : color.getHex() + var material = new MeshBasicMaterial({ + color: color.getHex() }); // setup the rotation information - var rotAxis = new THREE.Vector3(); - rotAxis.crossVectors(axis, new THREE.Vector3(0, -1, 0)); - var rot = new THREE.Quaternion(); + var rotAxis = new Vector3(); + rotAxis.crossVectors(axis, new Vector3(0, -1, 0)); + var rot = new Quaternion(); rot.setFromAxisAngle(rotAxis, 0.5 * Math.PI); // create the arrow - var arrow = new THREE.Mesh(that.headGeom, material); + var arrow = new Mesh(that.headGeom, material); arrow.position.copy(axis); arrow.position.multiplyScalar(0.95); arrow.quaternion.copy(rot); @@ -54168,9 +46144,9 @@ var ROS3D = (function (exports, ROSLIB) { var line; if (lineType === 'dashed') { var l = lineDashLength; - for (var i = 0; (l / 2 + 3 * l * i + l / 2) <= 1; ++i) { - var geom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, l); - line = new THREE.Mesh(geom, material); + for (var i = 0; l / 2 + 3 * l * i + l / 2 <= 1; ++i) { + var geom = new CylinderGeometry(shaftRadius, shaftRadius, l); + line = new Mesh(geom, material); line.position.copy(axis); // Make spacing between dashes equal to 1.5 times the dash length. line.position.multiplyScalar(l / 2 + 3 * l * i); @@ -54179,7 +46155,7 @@ var ROS3D = (function (exports, ROSLIB) { that.add(line); } } else if (lineType === 'full') { - line = new THREE.Mesh(that.lineGeom, material); + line = new Mesh(that.lineGeom, material); line.position.copy(axis); line.position.multiplyScalar(0.45); line.quaternion.copy(rot); @@ -54191,19 +46167,24 @@ var ROS3D = (function (exports, ROSLIB) { } // add the three markers to the axes - addAxis(new THREE.Vector3(1, 0, 0)); - addAxis(new THREE.Vector3(0, 1, 0)); - addAxis(new THREE.Vector3(0, 0, 1)); - }; - } + addAxis(new Vector3(1, 0, 0)); + addAxis(new Vector3(0, 1, 0)); + addAxis(new Vector3(0, 0, 1)); + return _this; + } + _inherits(Axes, _THREE$Object3D); + return _createClass(Axes); + }(Object3D); + + function _callSuper$k(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$k() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$k() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$k = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ - class Grid extends THREE.Object3D { - + var Grid = /*#__PURE__*/function (_THREE$Object3D) { /** * Create a grid object. * @@ -54215,46 +46196,51 @@ var ROS3D = (function (exports, ROSLIB) { * * lineWidth (optional) - the width of the lines in the grid * * cellSize (optional) - The length, in meters, of the side of each cell */ - constructor(options) { + + function Grid(options) { + var _this; + _classCallCheck(this, Grid); options = options || {}; var num_cells = options.num_cells || 10; var color = options.color || '#cccccc'; var lineWidth = options.lineWidth || 1; var cellSize = options.cellSize || 1; - - super(); - - var material = new THREE.LineBasicMaterial({ + _this = _callSuper$k(this, Grid); + var material = new LineBasicMaterial({ color: color, linewidth: lineWidth }); - + var edges = []; for (var i = 0; i <= num_cells; ++i) { var edge = cellSize * num_cells / 2; - var position = edge - (i * cellSize); - var geometryH = new THREE.Geometry(); - geometryH.vertices.push( - new THREE.Vector3( -edge, position, 0 ), - new THREE.Vector3( edge, position, 0 ) - ); - var geometryV = new THREE.Geometry(); - geometryV.vertices.push( - new THREE.Vector3( position, -edge, 0 ), - new THREE.Vector3( position, edge, 0 ) - ); - this.add(new THREE.Line(geometryH, material)); - this.add(new THREE.Line(geometryV, material)); + var position = edge - i * cellSize; + + // Horizontal lines + edges.push(new Vector3(-edge, position, 0), new Vector3(edge, position, 0)); + + // Vertical lines + edges.push(new Vector3(position, -edge, 0), new Vector3(position, edge, 0)); } - }; - } + var geometry = new BufferGeometry().setFromPoints(edges); + + // Define lines with the geometry + var lineSegments = new LineSegments(geometry, material); + _this.add(lineSegments); + return _this; + } + _inherits(Grid, _THREE$Object3D); + return _createClass(Grid); + }(Object3D); + + function _callSuper$j(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$j() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$j() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$j = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ - class OccupancyGrid extends THREE.Mesh { - + var OccupancyGrid = /*#__PURE__*/function (_THREE$Mesh) { /** * An OccupancyGrid can convert a ROS occupancy grid message into a THREE object. * @@ -54265,126 +46251,126 @@ var ROS3D = (function (exports, ROSLIB) { * * color (optional) - color of the visualized grid * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) */ - constructor(options) { + function OccupancyGrid(options) { + var _this; + _classCallCheck(this, OccupancyGrid); options = options || {}; var message = options.message; var opacity = options.opacity || 1.0; - var color = options.color || {r:255,g:255,b:255,a:255}; + var color = options.color || { + r: 255, + g: 255, + b: 255, + a: 255 + }; // create the geometry var info = message.info; var origin = info.origin; var width = info.width; var height = info.height; - var geom = new THREE.PlaneBufferGeometry(width, height); + var geom = new PlaneGeometry(width, height); // create the color material var imageData = new Uint8Array(width * height * 4); - var texture = new THREE.DataTexture(imageData, width, height, THREE.RGBAFormat); + var texture = new DataTexture(imageData, width, height, RGBAFormat); texture.flipY = true; - texture.minFilter = THREE.NearestFilter; - texture.magFilter = THREE.NearestFilter; + texture.minFilter = NearestFilter; + texture.magFilter = NearestFilter; texture.needsUpdate = true; - - var material = new THREE.MeshBasicMaterial({ - map : texture, - transparent : opacity < 1.0, - opacity : opacity + var material = new MeshBasicMaterial({ + map: texture, + transparent: opacity < 1.0, + opacity: opacity }); - material.side = THREE.DoubleSide; + material.side = DoubleSide; // create the mesh - super(geom, material); + _this = _callSuper$j(this, OccupancyGrid, [geom, material]); // move the map so the corner is at X, Y and correct orientation (informations from message.info) // assign options to this for subclasses - Object.assign(this, options); - - this.quaternion.copy(new THREE.Quaternion( - origin.orientation.x, - origin.orientation.y, - origin.orientation.z, - origin.orientation.w - )); - this.position.x = (width * info.resolution) / 2 + origin.position.x; - this.position.y = (height * info.resolution) / 2 + origin.position.y; - this.position.z = origin.position.z; - this.scale.x = info.resolution; - this.scale.y = info.resolution; - + Object.assign(_this, options); + _this.quaternion.copy(new Quaternion(origin.orientation.x, origin.orientation.y, origin.orientation.z, origin.orientation.w)); + _this.position.x = width * info.resolution / 2 + origin.position.x; + _this.position.y = height * info.resolution / 2 + origin.position.y; + _this.position.z = origin.position.z; + _this.scale.x = info.resolution; + _this.scale.y = info.resolution; var data = message.data; // update the texture (after the the super call and this are accessible) - this.color = color; - this.material = material; - this.texture = texture; - - for ( var row = 0; row < height; row++) { - for ( var col = 0; col < width; col++) { - + _this.color = color; + _this.material = material; + _this.texture = texture; + for (var row = 0; row < height; row++) { + for (var col = 0; col < width; col++) { // determine the index into the map data - var invRow = (height - row - 1); - var mapI = col + (invRow * width); + var invRow = height - row - 1; + var mapI = col + invRow * width; // determine the value - var val = this.getValue(mapI, invRow, col, data); + var val = _this.getValue(mapI, invRow, col, data); // determine the color - var color = this.getColor(mapI, invRow, col, val); + var color = _this.getColor(mapI, invRow, col, val); // determine the index into the image data array - var i = (col + (row * width)) * 4; + var i = (col + row * width) * 4; // copy the color imageData.set(color, i); } } - texture.needsUpdate = true; + return _this; + } + _inherits(OccupancyGrid, _THREE$Mesh); + return _createClass(OccupancyGrid, [{ + key: "dispose", + value: function dispose() { + this.material.dispose(); + this.texture.dispose(); + } + }, { + key: "getValue", + value: + /** + * Returns the value for a given grid cell + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {object} data the data buffer + */ + function getValue(index, row, col, data) { + return data[index]; + } + }, { + key: "getColor", + value: + /** + * Returns a color value given parameters of the position in the grid; the default implementation + * scales the default color value by the grid value. Subclasses can extend this functionality + * (e.g. lookup a color in a color map). + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {float} value the value of the cell + * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel + */ + function getColor(index, row, col, value) { + return [value * this.color.r / 255, value * this.color.g / 255, value * this.color.b / 255, 255]; + } + }]); + }(Mesh); - }; - - dispose() { - this.material.dispose(); - this.texture.dispose(); - }; - - /** - * Returns the value for a given grid cell - * @param {int} index the current index of the cell - * @param {int} row the row of the cell - * @param {int} col the column of the cell - * @param {object} data the data buffer - */ - getValue(index, row, col, data) { - return data[index]; - }; - - /** - * Returns a color value given parameters of the position in the grid; the default implementation - * scales the default color value by the grid value. Subclasses can extend this functionality - * (e.g. lookup a color in a color map). - * @param {int} index the current index of the cell - * @param {int} row the row of the cell - * @param {int} col the column of the cell - * @param {float} value the value of the cell - * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel - */ - getColor(index, row, col, value) { - return [ - (value * this.color.r) / 255, - (value * this.color.g) / 255, - (value * this.color.b) / 255, - 255 - ]; - }; - } + function _callSuper$i(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$i() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$i() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$i = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Russell Toris - rctoris@wpi.edu */ - class OccupancyGridClient extends EventEmitter3 { - + var OccupancyGridClient = /*#__PURE__*/function (_EventEmitter) { /** * An occupancy grid client that listens to a given map topic. * @@ -54405,95 +46391,135 @@ var ROS3D = (function (exports, ROSLIB) { * * color (optional) - color of the visualized grid * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) */ - constructor(options) { - super(); + function OccupancyGridClient(options) { + var _this; + _classCallCheck(this, OccupancyGridClient); + _this = _callSuper$i(this, OccupancyGridClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/map'; - this.compression = options.compression || 'cbor'; - this.continuous = options.continuous; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); - this.color = options.color || {r:255,g:255,b:255}; - this.opacity = options.opacity || 1.0; + _this.ros = options.ros; + _this.topicName = options.topic || '/map'; + _this.compression = options.compression || 'cbor'; + _this.continuous = options.continuous; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); + _this.color = options.color || { + r: 255, + g: 255, + b: 255 + }; + _this.opacity = options.opacity || 1.0; // current grid that is displayed - this.currentGrid = null; + _this.currentGrid = null; // subscribe to the topic - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(OccupancyGridClient, _EventEmitter); + return _createClass(OccupancyGridClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - - subscribe(){ - this.unsubscribe(); + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'nav_msgs/OccupancyGrid', + queue_length: 1, + compression: this.compression + }); + this.sceneNode = null; + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + // check for an old map + if (this.currentGrid) { + // check if it there is a tf client + if (this.tfClient) { + // grid is of type ROS3D.SceneNode + this.sceneNode.unsubscribeTf(); + this.sceneNode.remove(this.currentGrid); + } else { + this.rootObject.remove(this.currentGrid); + } + this.currentGrid.dispose(); + } + var newGrid = new OccupancyGrid({ + message: message, + color: this.color, + opacity: this.opacity + }); - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'nav_msgs/OccupancyGrid', - queue_length : 1, - compression : this.compression - }); - this.sceneNode = null; - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(message){ - // check for an old map - if (this.currentGrid) { - // check if it there is a tf client + // check if we care about the scene if (this.tfClient) { - // grid is of type ROS3D.SceneNode - this.sceneNode.unsubscribeTf(); - this.sceneNode.remove(this.currentGrid); + this.currentGrid = newGrid; + if (this.sceneNode === null) { + this.sceneNode = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newGrid, + pose: this.offsetPose + }); + this.rootObject.add(this.sceneNode); + } else { + this.sceneNode.add(this.currentGrid); + } } else { - this.rootObject.remove(this.currentGrid); + this.sceneNode = this.currentGrid = newGrid; + this.rootObject.add(this.currentGrid); } - this.currentGrid.dispose(); - } - - var newGrid = new OccupancyGrid({ - message : message, - color : this.color, - opacity : this.opacity - }); + this.emit('change'); - // check if we care about the scene - if (this.tfClient) { - this.currentGrid = newGrid; - if (this.sceneNode === null) { - this.sceneNode = new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : newGrid, - pose : this.offsetPose - }); - this.rootObject.add(this.sceneNode); - } else { - this.sceneNode.add(this.currentGrid); + // check if we should unsubscribe + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessageBound); } - } else { - this.sceneNode = this.currentGrid = newGrid; - this.rootObject.add(this.currentGrid); } + }]); + }(EventEmitter2); - this.emit('change'); + function _arrayLikeToArray(r, a) { + (null == a || a > r.length) && (a = r.length); + for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; + return n; + } - // check if we should unsubscribe - if (!this.continuous) { - this.rosTopic.unsubscribe(this.processMessageBound); - } - }; + function _arrayWithoutHoles(r) { + if (Array.isArray(r)) return _arrayLikeToArray(r); + } + + function _iterableToArray(r) { + if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); + } + + function _unsupportedIterableToArray(r, a) { + if (r) { + if ("string" == typeof r) return _arrayLikeToArray(r, a); + var t = {}.toString.call(r).slice(8, -1); + return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; + } + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _toConsumableArray(r) { + return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } /** @@ -54501,43 +46527,53 @@ var ROS3D = (function (exports, ROSLIB) { * @author Peter Sari - sari@photoneo.com */ - class OcTreeBaseNode { - + var OcTreeBaseNode = /*#__PURE__*/function () { /** * Base node type that represents one voxel as a node of the tree */ - - constructor() { + + function OcTreeBaseNode() { + _classCallCheck(this, OcTreeBaseNode); this._children = [null, null, null, null, null, null, null, null]; this.value = null; - }; - - createChildNodeAt(newNode, index) { - this._children[index % 8] = newNode; - }; - - hasChildAt(index) { - return this._children[index % 8] !== null; - }; - - getChildAt(index) { - return this._children[index % 8]; - }; - - isLeafNode() { - for (let i = 0; i < 8; ++i) { - if (this._children[i] !== null) { return false; } + } + return _createClass(OcTreeBaseNode, [{ + key: "createChildNodeAt", + value: function createChildNodeAt(newNode, index) { + this._children[index % 8] = newNode; } - return true; - }; - - hasChildren() { - for (let i = 0; i < 8; ++i) { - if (this._children[i] !== null) { return true; } + }, { + key: "hasChildAt", + value: function hasChildAt(index) { + return this._children[index % 8] !== null; } - return false; - }; - } + }, { + key: "getChildAt", + value: function getChildAt(index) { + return this._children[index % 8]; + } + }, { + key: "isLeafNode", + value: function isLeafNode() { + for (var i = 0; i < 8; ++i) { + if (this._children[i] !== null) { + return false; + } + } + return true; + } + }, { + key: "hasChildren", + value: function hasChildren() { + for (var i = 0; i < 8; ++i) { + if (this._children[i] !== null) { + return true; + } + } + return false; + } + }]); + }(); /** * @fileOverview @@ -54554,7 +46590,7 @@ var ROS3D = (function (exports, ROSLIB) { var OcTreeVoxelRenderMode = { OCCUPIED: 'occupied', FREE: 'free', - ALL: 'all', + ALL: 'all' }; /** @@ -54577,45 +46613,69 @@ var ROS3D = (function (exports, ROSLIB) { to read ArrayBuffer in a streamed data-like fashion with mixed types in it */ function InStream(data, isLittleEndian) { + var _this = this; this.buffer = data.buffer; this.length = data.length; - this.isLittleEndian = (typeof isLittleEndian !== 'undefined') ? !!isLittleEndian : true; + this.isLittleEndian = typeof isLittleEndian !== 'undefined' ? !!isLittleEndian : true; this._dataView = new DataView(this.buffer); this._cursor = 0; // Creates a set of wrapper functions for DataView // also flattens all dependencies - [ - { kind: 'Int8', width: 1 }, - { kind: 'Uint8', width: 1 }, - { kind: 'Int16', width: 2 }, - { kind: 'Uint16', width: 2 }, - { kind: 'Int32', width: 4 }, - { kind: 'Uint32', width: 4 }, - { kind: 'BigInt64', width: 8 }, - { kind: 'BigUint64', width: 8 }, - { kind: 'Float32', width: 4 }, - { kind: 'Float64', width: 8 }, - ] - .forEach(wrap => { - const interfaceFunction = 'read' + wrap.kind; - const wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView - - this[interfaceFunction] = () => { - if (this._cursor + wrap.width > this.length) { throw new Error('Cannot read data stream. Overflow. Len=' + this.length + ' crsr=' + this._cursor); } - const returningValue = this._dataView[wrappedFunction](this._cursor, this.isLittleEndian); - this._cursor += wrap.width; - return returningValue; - }; - }); - - Object.defineProperty(this, 'isEnd', { get: () => this.cursor >= this.data.length }); + [{ + kind: 'Int8', + width: 1 + }, { + kind: 'Uint8', + width: 1 + }, { + kind: 'Int16', + width: 2 + }, { + kind: 'Uint16', + width: 2 + }, { + kind: 'Int32', + width: 4 + }, { + kind: 'Uint32', + width: 4 + }, { + kind: 'BigInt64', + width: 8 + }, { + kind: 'BigUint64', + width: 8 + }, { + kind: 'Float32', + width: 4 + }, { + kind: 'Float64', + width: 8 + }].forEach(function (wrap) { + var interfaceFunction = 'read' + wrap.kind; + var wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView + + _this[interfaceFunction] = function () { + if (_this._cursor + wrap.width > _this.length) { + throw new Error('Cannot read data stream. Overflow. Len=' + _this.length + ' crsr=' + _this._cursor); + } + var returningValue = _this._dataView[wrappedFunction](_this._cursor, _this.isLittleEndian); + _this._cursor += wrap.width; + return returningValue; + }; + }); + Object.defineProperty(this, 'isEnd', { + get: function get() { + return _this.cursor >= _this.data.length; + } + }); return this; } - // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- - class OcTreeBase { + // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + var OcTreeBase = /*#__PURE__*/function () { /** * Represensta a BaseTree that can be build from ros message and create a THREE node from it. * Due a tree can be represented different ways in a message, this class is also a base class to @@ -54628,33 +46688,26 @@ var ROS3D = (function (exports, ROSLIB) { * * color - color of the visualized map (if solid coloring option was set) * * voxelRenderMode - toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode */ - constructor(options) { - - this.resolution = (typeof options.resolution !== 'undefined') ? options.resolution : 1.; - this.color = new THREE.Color((typeof options.color !== 'undefined') ? options.color : 'green'); - this.opacity = (typeof options.opacity !== 'undefined') ? options.opacity : 1.; - - this.voxelRenderMode = (typeof options.voxelRenderMode !== 'undefined') ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; - + function OcTreeBase(options) { + _classCallCheck(this, OcTreeBase); + this.resolution = typeof options.resolution !== 'undefined' ? options.resolution : 1.; + this.color = new Color(typeof options.color !== 'undefined' ? options.color : 'green'); + this.opacity = typeof options.opacity !== 'undefined' ? options.opacity : 1.; + this.voxelRenderMode = typeof options.voxelRenderMode !== 'undefined' ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; this._rootNode = null; this._treeDepth = 16; this._treeMaxKeyVal = 32768; - - this._BINARY_UNALLOCATED = 0b00; - this._BINARY_LEAF_FREE = 0b01; - this._BINARY_LEAF_OCCUPIED = 0b10; - this._BINARY_HAS_CHILDREN = 0b11; - + this._BINARY_UNALLOCATED = 0; + this._BINARY_LEAF_FREE = 1; + this._BINARY_LEAF_OCCUPIED = 2; + this._BINARY_HAS_CHILDREN = 3; this._BINARY_CHILD_BUILD_TABLE = {}; - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE] = function (child) { child.value = this._defaultFreeValue; }; - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED] = function (child) { child.value = this._defaultOccupiedValue; }; - this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN] = function (child) { child.value = null; }; @@ -54662,451 +46715,393 @@ var ROS3D = (function (exports, ROSLIB) { /** * Table which we are building the geometry data from. */ - this._FACES = [ - { // 0. left (x=0) - normal: [-1, 0, 0,], - vertices: [ - [0, 1, 0], - [0, 0, 0], - [0, 1, 1], - [0, 0, 1], - ], - childIndex: [ - 0b001, - 0b011, - 0b101, - 0b111 - ] - }, - { // 1. right (x=1) - normal: [1, 0, 0,], - vertices: [ - [1, 1, 1], - [1, 0, 1], - [1, 1, 0], - [1, 0, 0], - ], - - childIndex: [ - 0b000, - 0b010, - 0b100, - 0b110 - ] - }, - { // 2. bottom (y=0) - normal: [0, -1, 0,], - vertices: [ - [1, 0, 1], - [0, 0, 1], - [1, 0, 0], - [0, 0, 0], - ], - childIndex: [ - 0b010, - 0b011, - 0b110, - 0b111 - ] - }, - { // 3. top (y=1) - normal: [0, 1, 0,], - vertices: [ - [0, 1, 1], - [1, 1, 1], - [0, 1, 0], - [1, 1, 0], - ], - childIndex: [ - 0b000, - 0b001, - 0b100, - 0b101 - ] - }, - { // 4. back (z=0) - normal: [0, 0, -1,], - vertices: [ - [1, 0, 0], - [0, 0, 0], - [1, 1, 0], - [0, 1, 0], - ], - childIndex: [ - 0b100, - 0b101, - 0b110, - 0b111 - ] - }, - { // 5.front (z=1) - normal: [0, 0, 1,], - vertices: [ - [0, 0, 1], - [1, 0, 1], - [0, 1, 1], - [1, 1, 1], - ], - childIndex: [ - 0b000, - 0b001, - 0b010, - 0b011 - ] - }, - ]; + this._FACES = [{ + // 0. left (x=0) + normal: [-1, 0, 0], + vertices: [[0, 1, 0], [0, 0, 0], [0, 1, 1], [0, 0, 1]], + childIndex: [1, 3, 5, 7] + }, { + // 1. right (x=1) + normal: [1, 0, 0], + vertices: [[1, 1, 1], [1, 0, 1], [1, 1, 0], [1, 0, 0]], + childIndex: [0, 2, 4, 6] + }, { + // 2. bottom (y=0) + normal: [0, -1, 0], + vertices: [[1, 0, 1], [0, 0, 1], [1, 0, 0], [0, 0, 0]], + childIndex: [2, 3, 6, 7] + }, { + // 3. top (y=1) + normal: [0, 1, 0], + vertices: [[0, 1, 1], [1, 1, 1], [0, 1, 0], [1, 1, 0]], + childIndex: [0, 1, 4, 5] + }, { + // 4. back (z=0) + normal: [0, 0, -1], + vertices: [[1, 0, 0], [0, 0, 0], [1, 1, 0], [0, 1, 0]], + childIndex: [4, 5, 6, 7] + }, { + // 5.front (z=1) + normal: [0, 0, 1], + vertices: [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]], + childIndex: [0, 1, 2, 3] + }]; // Table of voxel size for each level of the tree this.nodeSizeTable = new Array(this._treeDepth); - let _val = this.resolution; - for (let i = this._treeDepth - 1; i >= 0; --i) { + var _val = this.resolution; + for (var i = this._treeDepth - 1; i >= 0; --i) { this.nodeSizeTable[i] = _val; _val = 2. * _val; } - this._defaultOccupiedValue = true; this._defaultFreeValue = false; - this.object = null; - }; - - - /* - * Finds a key in a given depth. Search is performed on the lowest level by default. - * @return the node at given position, null if not found - */ - searchAtDepth(key, depth) { - depth = (typeof depth !== 'undefined') ? (depth > 0 ? depth : this._treeDepth) : this._treeDepth; - - const keyAtDepth = this._adjustKeyAtDepth(key, depth); - const diff = this._treeDepth - depth; - let currentNode = this._rootNode; - - // follow nodes down to requested level (for diff = 0 it's the last level) - // Return the closest node, or null if not any - - for (let i = (this._treeDepth - 1); i >= diff; --i) { - const pos = this._computeChildIdx(keyAtDepth, i); - if (currentNode.hasChildAt(pos)) { - currentNode = currentNode.getChildAt(pos); - } else { - // we expected a child but did not get it - // is the current node a leaf already? - if (!currentNode.hasChildren()) { return currentNode; } - // it is not, search failed - return null; + } + return _createClass(OcTreeBase, [{ + key: "searchAtDepth", + value: + /* + * Finds a key in a given depth. Search is performed on the lowest level by default. + * @return the node at given position, null if not found + */ + function searchAtDepth(key, depth) { + depth = typeof depth !== 'undefined' ? depth > 0 ? depth : this._treeDepth : this._treeDepth; + var keyAtDepth = this._adjustKeyAtDepth(key, depth); + var diff = this._treeDepth - depth; + var currentNode = this._rootNode; + + // follow nodes down to requested level (for diff = 0 it's the last level) + // Return the closest node, or null if not any + + for (var i = this._treeDepth - 1; i >= diff; --i) { + var pos = this._computeChildIdx(keyAtDepth, i); + if (currentNode.hasChildAt(pos)) { + currentNode = currentNode.getChildAt(pos); + } else { + // we expected a child but did not get it + // is the current node a leaf already? + if (!currentNode.hasChildren()) { + return currentNode; + } + // it is not, search failed + return null; + } } + return currentNode; } - - return currentNode; - - }; - - /** - * - */ - _computeCoordFromKey(key) { - return key.map(keyVal => this.resolution * (keyVal - this._treeMaxKeyVal)); - }; - - _computeChildIdx(key, depth) { - let pos = 0; - if (key[0] & (1 << depth)) { pos += 1; } - if (key[1] & (1 << depth)) { pos += 2; } - if (key[2] & (1 << depth)) { pos += 4; } - - return pos; - }; - - _computeKeyFromChildIdx(index, offset, depth) { - const diff = this._treeDepth - depth - 1; - - return [ - offset[0] + (!!(index & 1) << diff), - offset[1] + (!!(index & 2) << diff), - offset[2] + (!!(index & 4) << diff), - ]; - - }; - - _adjustKeyAtDepth(key, depth) { - // generate appropriate key_at_depth for queried depth - let diff = this._treeDepth - depth; - if (diff === 0) { return key; } - - return key.map(keyVal => (((keyVal - this._treeMaxKeyVal) >> diff) << diff) + (1 << (diff - 1)) + this._treeMaxKeyVal); - }; - - _newNode() { return new OcTreeBaseNode(); }; - - /* - * Reads and builds a tree which was represented in a binary form from a message - * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, - * occupation is represented as a binary value. - * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) - * starting with the root node. - */ - - readBinary(data) { - if (this._rootNode !== null) { - delete this._rootNode; + }, { + key: "_computeCoordFromKey", + value: + /** + * + */ + function _computeCoordFromKey(key) { + var _this2 = this; + return key.map(function (keyVal) { + return _this2.resolution * (keyVal - _this2._treeMaxKeyVal); + }); } - this._rootNode = this._newNode(); - - let dataStream = new InStream(data, true); - - let stack = new Array(); - stack.push(this._rootNode); - - while (stack.length > 0) { - let node = stack.pop(); - - // 2 bits per children, 16 bit total - const childAllocationMap = dataStream.readUint16(); - - // Insert all children and leaves - let index = 8; - while (index !== 0) { - --index; - const allocation = (childAllocationMap & (0b11 << (2 * index))) >> (2 * index); - - if (allocation !== this._BINARY_UNALLOCATED) { - let child = this._newNode(); - - const fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); - fn(child); - - node.createChildNodeAt(child, index); - if (allocation === this._BINARY_HAS_CHILDREN) { stack.push(child); } - } + }, { + key: "_computeChildIdx", + value: function _computeChildIdx(key, depth) { + var pos = 0; + if (key[0] & 1 << depth) { + pos += 1; + } + if (key[1] & 1 << depth) { + pos += 2; + } + if (key[2] & 1 << depth) { + pos += 4; } + return pos; } - - }; - - /** - * Reads a full tree (with node data) from a message. - * A pacjet starts with the node data, followed by the allocation map of their children. - * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData - */ - read(data) { - if (this._rootNode !== null) { - delete this._rootNode; + }, { + key: "_computeKeyFromChildIdx", + value: function _computeKeyFromChildIdx(index, offset, depth) { + var diff = this._treeDepth - depth - 1; + return [offset[0] + (!!(index & 1) << diff), offset[1] + (!!(index & 2) << diff), offset[2] + (!!(index & 4) << diff)]; } + }, { + key: "_adjustKeyAtDepth", + value: function _adjustKeyAtDepth(key, depth) { + var _this3 = this; + // generate appropriate key_at_depth for queried depth + var diff = this._treeDepth - depth; + if (diff === 0) { + return key; + } + return key.map(function (keyVal) { + return (keyVal - _this3._treeMaxKeyVal >> diff << diff) + (1 << diff - 1) + _this3._treeMaxKeyVal; + }); + } + }, { + key: "_newNode", + value: function _newNode() { + return new OcTreeBaseNode(); + } + }, { + key: "readBinary", + value: + /* + * Reads and builds a tree which was represented in a binary form from a message + * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, + * occupation is represented as a binary value. + * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) + * starting with the root node. + */ - this._rootNode = this._newNode(); - - let dataStream = new InStream(data, true); - - let stack = new Array(); - stack.push(this._rootNode); - - while (stack.length > 0) { - let node = stack.pop(); - - // Data comes first - this._readNodeData(dataStream, node); - - const childAllocationMap = dataStream.readUint8(); - - // Insert all children and leaves - let index = 8; - while (index !== 0) { - --index; - const hasChild = childAllocationMap & (1 << index); - if (hasChild) { - let child = this._newNode(); - child.value = null; - node.createChildNodeAt(child, index); - stack.push(child); + function readBinary(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + var dataStream = new InStream(data, true); + var stack = new Array(); + stack.push(this._rootNode); + while (stack.length > 0) { + var node = stack.pop(); + + // 2 bits per children, 16 bit total + var childAllocationMap = dataStream.readUint16(); + + // Insert all children and leaves + var index = 8; + while (index !== 0) { + --index; + var allocation = (childAllocationMap & 3 << 2 * index) >> 2 * index; + if (allocation !== this._BINARY_UNALLOCATED) { + var child = this._newNode(); + var fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); + fn(child); + node.createChildNodeAt(child, index); + if (allocation === this._BINARY_HAS_CHILDREN) { + stack.push(child); + } + } } } } - - }; - - /** - * Abstract function; Reads and sets data of a node - */ - _readNodeData(dataStream, node) { - // This needs to be implemented by specialized tree - console.error('Not implemented'); - }; - - /** - * Builds up THREE.js geometry from tree data. - */ - buildGeometry() { - console.assert(this._rootNode !== null, 'No tree data'); - const { vertices, normals, colors, indices } = this._buildFaces(); - - const geometry = new THREE.BufferGeometry(); - - const material = new THREE.MeshBasicMaterial({ - color: 'white', - flatShading: true, - vertexColors: THREE.VertexColors, - transparent: this.opacity < 1.0, - opacity: this.opacity - }); - - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); - - geometry.setIndex(indices); - - const mesh = new THREE.Mesh(geometry, material); - this.object = new THREE.Object3D(); - this.object.add(mesh); - }; - - _traverseLeaves(callback) { - let stack = new Array(); - stack.push({ node: this._rootNode, depth: 0, key: [0, 0, 0] }); - - while (stack.length > 0) { - let current = stack.pop(); - if (current.node.isLeafNode()) { - callback(current.node, current.key, current.depth - 1); - } else { - for (let index = 0; index < 8; ++index) { - if (current.node.hasChildAt(index)) { - const key = this._computeKeyFromChildIdx(index, current.key, current.depth); - stack.push({ - node: current.node.getChildAt(index), - depth: current.depth + 1, - key - }); + }, { + key: "read", + value: + /** + * Reads a full tree (with node data) from a message. + * A pacjet starts with the node data, followed by the allocation map of their children. + * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData + */ + function read(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + var dataStream = new InStream(data, true); + var stack = new Array(); + stack.push(this._rootNode); + while (stack.length > 0) { + var node = stack.pop(); + + // Data comes first + this._readNodeData(dataStream, node); + var childAllocationMap = dataStream.readUint8(); + + // Insert all children and leaves + var index = 8; + while (index !== 0) { + --index; + var hasChild = childAllocationMap & 1 << index; + if (hasChild) { + var child = this._newNode(); + child.value = null; + node.createChildNodeAt(child, index); + stack.push(child); } } } } - }; - - /** - * Abstract function; to implement different coloring schemes - */ - _obtainColor(node) { - return this.color; - }; - - _checkOccupied(node) { - return node.value !== false; - }; - - _buildFaces() { - let geometry = { - vertices: [], - indices: [], - normals: [], - colors: [], - - _insertFace: function (face, pos, size, color) { - const indexCount = this.vertices.length / 3; - - face.vertices.forEach(function(vertex) { - this.vertices.push( - pos[0] + vertex[0] * size, - pos[1] + vertex[1] * size, - pos[2] + vertex[2] * size - ); - }); - - const colorArr = [color.r, color.g, color.b]; - - this.colors.push(...colorArr, ...colorArr, ...colorArr, ...colorArr); - this.normals.push(...face.normal, ...face.normal, ...face.normal, ...face.normal); - - this.indices.push( - indexCount, indexCount + 1, indexCount + 2, - indexCount + 2, indexCount + 1, indexCount + 3 - ); - }, - - _checkNeighborsTouchingFace: function (face, neighborNode, voxelRenderMode) { - // Finds if there's not a node at a given position, aka a 'hole' - let stack = new Array(); - stack.push(neighborNode); - while (stack.length !== 0) { - const node = stack.pop(); - if (node.hasChildren()) { - face.childIndex.forEach(function(childIndex) { - if (node.hasChildAt(childIndex)) { - const child = node.getChildAt(childIndex); - - // filter occupancy - const isOccupied = this._checkOccupied(node); - const isNeedsToRender = (isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED) || (!isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE); - - if (isNeedsToRender) { stack.push(child); } - } - else { - return true; - } - }); + }, { + key: "_readNodeData", + value: + /** + * Abstract function; Reads and sets data of a node + */ + function _readNodeData(dataStream, node) { + // This needs to be implemented by specialized tree + console.error('Not implemented'); + } + }, { + key: "buildGeometry", + value: + /** + * Builds up THREE.js geometry from tree data. + */ + function buildGeometry() { + console.assert(this._rootNode !== null, 'No tree data'); + var _this$_buildFaces = this._buildFaces(), + vertices = _this$_buildFaces.vertices, + normals = _this$_buildFaces.normals, + colors = _this$_buildFaces.colors, + indices = _this$_buildFaces.indices; + var geometry = new BufferGeometry(); + var material = new MeshBasicMaterial({ + color: 'white', + flatShading: true, + vertexColors: true, + transparent: this.opacity < 1.0, + opacity: this.opacity + }); + geometry.addAttribute('position', new BufferAttribute(new Float32Array(vertices), 3)); + geometry.addAttribute('normal', new BufferAttribute(new Float32Array(normals), 3)); + geometry.addAttribute('color', new BufferAttribute(new Float32Array(colors), 3)); + geometry.setIndex(indices); + var mesh = new Mesh(geometry, material); + this.object = new Object3D(); + this.object.add(mesh); + } + }, { + key: "_traverseLeaves", + value: function _traverseLeaves(callback) { + var stack = new Array(); + stack.push({ + node: this._rootNode, + depth: 0, + key: [0, 0, 0] + }); + while (stack.length > 0) { + var current = stack.pop(); + if (current.node.isLeafNode()) { + callback(current.node, current.key, current.depth - 1); + } else { + for (var index = 0; index < 8; ++index) { + if (current.node.hasChildAt(index)) { + var key = this._computeKeyFromChildIdx(index, current.key, current.depth); + stack.push({ + node: current.node.getChildAt(index), + depth: current.depth + 1, + key: key + }); + } } } - return false; } - - }; - - this._traverseLeaves((node, key, depth) => { - const pos = this._computeCoordFromKey(key); - const size = this.nodeSizeTable[depth]; - const diff = this._treeDepth - depth; - - const isOccupied = this._checkOccupied(node); - - // By default it will show ALL - // Hide free voxels if set - if (!isOccupied && this.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { return; } - - // Hide occuped voxels if set. - if (isOccupied && this.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { return; } - - this._FACES.forEach(function(face) { - // Add geometry where there is no neighbor voxel - const neighborKey = [ - key[0] + face.normal[0] * diff * diff, - key[1] + face.normal[1] * diff * diff, - key[2] + face.normal[2] * diff * diff, - ]; - const neighborNode = this.searchAtDepth(neighborKey); - if (neighborNode === null) { - // 1. Simply add geometry where there is no neighbors - geometry._insertFace(face, pos, size, this._obtainColor(node)); - } else if (depth < this._treeDepth) { - // 2. Special case, when a node (voxel) is not on the lowest level - // of the tree, but also need to add a geometry, because might - // not be "fully covered" by neighboring voxels on the lowest level - - if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) ; + } + }, { + key: "_obtainColor", + value: + /** + * Abstract function; to implement different coloring schemes + */ + function _obtainColor(node) { + return this.color; + } + }, { + key: "_checkOccupied", + value: function _checkOccupied(node) { + return node.value !== false; + } + }, { + key: "_buildFaces", + value: function _buildFaces() { + var _this4 = this; + var geometry = { + vertices: [], + indices: [], + normals: [], + colors: [], + _insertFace: function _insertFace(face, pos, size, color) { + var _this$colors, _this$normals; + var indexCount = this.vertices.length / 3; + face.vertices.forEach(function (vertex) { + this.vertices.push(pos[0] + vertex[0] * size, pos[1] + vertex[1] * size, pos[2] + vertex[2] * size); + }); + var colorArr = [color.r, color.g, color.b]; + (_this$colors = this.colors).push.apply(_this$colors, colorArr.concat(colorArr, colorArr, colorArr)); + (_this$normals = this.normals).push.apply(_this$normals, _toConsumableArray(face.normal).concat(_toConsumableArray(face.normal), _toConsumableArray(face.normal), _toConsumableArray(face.normal))); + this.indices.push(indexCount, indexCount + 1, indexCount + 2, indexCount + 2, indexCount + 1, indexCount + 3); + }, + _checkNeighborsTouchingFace: function _checkNeighborsTouchingFace(face, neighborNode, voxelRenderMode) { + // Finds if there's not a node at a given position, aka a 'hole' + var stack = new Array(); + stack.push(neighborNode); + var _loop = function _loop() { + var node = stack.pop(); + if (node.hasChildren()) { + face.childIndex.forEach(function (childIndex) { + if (node.hasChildAt(childIndex)) { + var child = node.getChildAt(childIndex); + + // filter occupancy + var isOccupied = this._checkOccupied(node); + var isNeedsToRender = isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED || !isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE; + if (isNeedsToRender) { + stack.push(child); + } + } else { + return true; + } + }); + } + }; + while (stack.length !== 0) { + _loop(); + } + return false; + } + }; + this._traverseLeaves(function (node, key, depth) { + var pos = _this4._computeCoordFromKey(key); + var size = _this4.nodeSizeTable[depth]; + var diff = _this4._treeDepth - depth; + var isOccupied = _this4._checkOccupied(node); + + // By default it will show ALL + // Hide free voxels if set + if (!isOccupied && _this4.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { + return; } + // Hide occuped voxels if set. + if (isOccupied && _this4.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { + return; + } + _this4._FACES.forEach(function (face) { + // Add geometry where there is no neighbor voxel + var neighborKey = [key[0] + face.normal[0] * diff * diff, key[1] + face.normal[1] * diff * diff, key[2] + face.normal[2] * diff * diff]; + var neighborNode = this.searchAtDepth(neighborKey); + if (neighborNode === null) { + // 1. Simply add geometry where there is no neighbors + geometry._insertFace(face, pos, size, this._obtainColor(node)); + } else if (depth < this._treeDepth) { + // 2. Special case, when a node (voxel) is not on the lowest level + // of the tree, but also need to add a geometry, because might + // not be "fully covered" by neighboring voxels on the lowest level + + if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) ; + } + }); }); - }); - - // return geometry; - return { - vertices: geometry.vertices, - normals: geometry.normals, - colors: geometry.colors, - indices: geometry.indices - }; + // return geometry; + return { + vertices: geometry.vertices, + normals: geometry.normals, + colors: geometry.colors, + indices: geometry.indices + }; + } + }]); + }(); - }; - } + function _callSuper$h(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$h() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$h() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$h = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ - class OcTree extends OcTreeBase { - + var OcTree = /*#__PURE__*/function (_OcTreeBase) { /** * Specilaization of BaseOcTree * @@ -55118,98 +47113,138 @@ var ROS3D = (function (exports, ROSLIB) { * * palette (optional) - Palette used for false-coloring (default: predefined palette) * * paletteSclae (optional) - Scale of palette to represent a wider range of values (default: 1.) */ - - constructor(options) { - super(options); - - this._defaultOccupiedValue = 1.; - this._defaultFreeValue = -1.; - - this.occupancyThreshold = (typeof options.occupancyThreshold !== 'undefined') ? options.occupancyThreshold : 0.0000001; - - this.useFlatColoring = (typeof options.colorMode !== 'undefined') && options.colorMode === OcTreeColorMode.SOLID; - this.palette = (typeof options.palette !== 'undefined') ? options.palette.map(color => new THREE.Color(color)) : - [ - { r: 0, g: 0, b: 128, }, // dark blue (low) - { r: 0, g: 255, b: 0, }, // green - { r: 255, g: 255, b: 0, }, // yellow (mid) - { r: 255, g: 128, b: 0, }, // orange - { r: 255, g: 0, b: 0, } // red (high) - ]; - - this.paletteScale = (typeof options.paletteScale !== 'undefined') ? options.paletteScale : 1.; - }; - - - _readNodeData(dataStream, node) { - node.value = dataStream.readFloat32(); - }; - - _obtainColor(node) { - if (this.useFlatColoring) { - return this.color; + function OcTree(options) { + var _this; + _classCallCheck(this, OcTree); + _this = _callSuper$h(this, OcTree, [options]); + _this._defaultOccupiedValue = 1.; + _this._defaultFreeValue = -1.; + _this.occupancyThreshold = typeof options.occupancyThreshold !== 'undefined' ? options.occupancyThreshold : 0.0000001; + _this.useFlatColoring = typeof options.colorMode !== 'undefined' && options.colorMode === OcTreeColorMode.SOLID; + _this.palette = typeof options.palette !== 'undefined' ? options.palette.map(function (color) { + return new Color(color); + }) : [{ + r: 0, + g: 0, + b: 128 + }, + // dark blue (low) + { + r: 0, + g: 255, + b: 0 + }, + // green + { + r: 255, + g: 255, + b: 0 + }, + // yellow (mid) + { + r: 255, + g: 128, + b: 0 + }, + // orange + { + r: 255, + g: 0, + b: 0 + } // red (high) + ]; + _this.paletteScale = typeof options.paletteScale !== 'undefined' ? options.paletteScale : 1.; + return _this; + } + _inherits(OcTree, _OcTreeBase); + return _createClass(OcTree, [{ + key: "_readNodeData", + value: function _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); } + }, { + key: "_obtainColor", + value: function _obtainColor(node) { + if (this.useFlatColoring) { + return this.color; + } - // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range - const value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize - - const intVal = Math.trunc(value); - const fracVal = value - intVal; - - if (intVal < 0) { return this.palette[0]; } - if (intVal >= this.palette.length - 1) { return this.palette[this.palette.length - 1]; } - - // Simple lerp - return { - r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, - g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, - b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b, - }; - - }; + // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range + var value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize - _checkOccupied(node) { - return node.value >= this.occupancyThreshold; - }; - } + var intVal = Math.trunc(value); + var fracVal = value - intVal; + if (intVal < 0) { + return this.palette[0]; + } + if (intVal >= this.palette.length - 1) { + return this.palette[this.palette.length - 1]; + } - class ColorOcTree extends OcTree { + // Simple lerp + return { + r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, + g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, + b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b + }; + } + }, { + key: "_checkOccupied", + value: function _checkOccupied(node) { + return node.value >= this.occupancyThreshold; + } + }]); + }(OcTreeBase); + function _callSuper$g(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$g() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$g() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$g = function _isNativeReflectConstruct() { return !!t; })(); } + var ColorOcTree = /*#__PURE__*/function (_OcTree) { /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ - - constructor(options) { - super(options); - this.useOwnColor = (typeof options.palette !== 'undefined') && options.colorMode === OcTreeColorMode.COLOR; - }; - - - _readNodeData(dataStream, node) { - node.value = dataStream.readFloat32(); // occupancy - node.color = { - r: dataStream.readUint8(), // red - g: dataStream.readUint8(), // green - b: dataStream.readUint8(), // blue - }; - }; + function ColorOcTree(options) { + var _this; + _classCallCheck(this, ColorOcTree); + _this = _callSuper$g(this, ColorOcTree, [options]); + _this.useOwnColor = typeof options.palette !== 'undefined' && options.colorMode === OcTreeColorMode.COLOR; + return _this; + } + _inherits(ColorOcTree, _OcTree); + return _createClass(ColorOcTree, [{ + key: "_readNodeData", + value: function _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); // occupancy + node.color = { + r: dataStream.readUint8(), + // red + g: dataStream.readUint8(), + // green + b: dataStream.readUint8() // blue + }; + } + }, { + key: "_obtainColor", + value: function _obtainColor(node) { + if (!this.useOwnColor) { + return OcTree.prototype._obtainColor.call(this, node); + } + return node.color; + } + }]); + }(OcTree); - _obtainColor(node) { - if (!this.useOwnColor) { return OcTree.prototype._obtainColor.call(this, node); } - return node.color; - }; - } + function _callSuper$f(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$f() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$f() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$f = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Peter Sari - sari@photoneo.com */ - class OcTreeClient extends EventEmitter3 { - + var OcTreeClient = /*#__PURE__*/function (_EventEmitter) { /** * An OcTree client that listens to a given OcTree topic. * @@ -55235,128 +47270,128 @@ var ROS3D = (function (exports, ROSLIB) { * * voxelRenderMode (optional)- toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode. (default `occupid`) * */ - - constructor(options) { - super(); + + function OcTreeClient(options) { + var _this; + _classCallCheck(this, OcTreeClient); + _this = _callSuper$f(this, OcTreeClient); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/octomap'; - this.compression = options.compression || 'cbor'; - this.continuous = options.continuous; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); + _this.ros = options.ros; + _this.topicName = options.topic || '/octomap'; + _this.compression = options.compression || 'cbor'; + _this.continuous = options.continuous; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.offsetPose = options.offsetPose || new ROSLIB__namespace.Pose(); // Options passed to converter - this.options = {}; + _this.options = {}; // Append only when it was set, otherwise defaults are provided by the underlying layer - if (typeof options.color !== 'undefined') { this.options['color'] = options.color; } - if (typeof options.opacity !== 'undefined') { this.options['opacity'] = options.opacity; } - if (typeof options.colorMode !== 'undefined') { this.options['colorMode'] = options.colorMode; } - if (typeof options.palette !== 'undefined') { this.options['palette'] = options.palette; } - if (typeof options.paletteScale !== 'undefined') { this.options['paletteScale'] = options.palette; } - if (typeof options.voxelRenderMode !== 'undefined') { this.options['voxelRenderMode'] = options.voxelRenderMode; } + if (typeof options.color !== 'undefined') { + _this.options['color'] = options.color; + } + if (typeof options.opacity !== 'undefined') { + _this.options['opacity'] = options.opacity; + } + if (typeof options.colorMode !== 'undefined') { + _this.options['colorMode'] = options.colorMode; + } + if (typeof options.palette !== 'undefined') { + _this.options['palette'] = options.palette; + } + if (typeof options.paletteScale !== 'undefined') { + _this.options['paletteScale'] = options.palette; + } + if (typeof options.voxelRenderMode !== 'undefined') { + _this.options['voxelRenderMode'] = options.voxelRenderMode; + } // current grid that is displayed - this.currentMap = null; - - // subscribe to the topic - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - + _this.currentMap = null; - unsubscribe() { - if (this.rosTopic) { - this.rosTopic.unsubscribe(this.processMessageBound); - } - }; - - subscribe() { - this.unsubscribe(); // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros: this.ros, - name: this.topicName, - messageType: 'octomap_msgs/Octomap', - queue_length: 1, - compression: this.compression - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(message) { - // check for an old map - if (this.currentMap) { - if (this.currentMap.tfClient) { - this.currentMap.unsubscribeTf(); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(OcTreeClient, _EventEmitter); + return _createClass(OcTreeClient, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); } } - - this._processMessagePrivate(message); - - if (!this.continuous) { - this.rosTopic.unsubscribe(this.processMessageBound); + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'octomap_msgs/Octomap', + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessageBound); } - }; - - - _loadOcTree(message) { - - return new Promise( - function (resolve, reject) { - + }, { + key: "processMessage", + value: function processMessage(message) { + // check for an old map + if (this.currentMap) { + if (this.currentMap.tfClient) { + this.currentMap.unsubscribeTf(); + } + } + this._processMessagePrivate(message); + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessageBound); + } + } + }, { + key: "_loadOcTree", + value: function _loadOcTree(message) { + return new Promise(function (resolve, reject) { // 1. Create the corresponding octree object from message - const options = Object.assign({ - resolution: message.resolution, + var options = Object.assign({ + resolution: message.resolution }, this.options); - - let newOcTree = null; + var newOcTree = null; { if (message.binary) { - newOcTree = new OcTreeBase( - options - ); + newOcTree = new OcTreeBase(options); newOcTree.readBinary(message.data); } else { - - const ctorTable = { + var ctorTable = { 'OcTree': OcTree, - 'ColorOcTree': ColorOcTree, + 'ColorOcTree': ColorOcTree }; - if (message.id in ctorTable) { console.log(message.id, ctorTable); - - newOcTree = new ctorTable[message.id]( - options - ); - + newOcTree = new ctorTable[message.id](options); newOcTree.read(message.data); } - } } - { newOcTree.buildGeometry(); } - resolve(newOcTree); }.bind(this)); - - }; - - _processMessagePrivate(message) { - let promise = this._loadOcTree(message); - - promise.then( + } + }, { + key: "_processMessagePrivate", + value: function _processMessagePrivate(message) { + var promise = this._loadOcTree(message); + promise.then( // 3. Replace geometry function (newOcTree) { // check if we care about the scene - const oldNode = this.sceneNode; + var oldNode = this.sceneNode; if (this.tfClient) { this.currentMap = newOcTree; this.sceneNode = new SceneNode({ @@ -55369,23 +47404,23 @@ var ROS3D = (function (exports, ROSLIB) { this.sceneNode = newOcTree.object; this.currentMap = newOcTree; } - this.rootObject.remove(oldNode); this.rootObject.add(this.sceneNode); - this.emit('change'); - }.bind(this) - ); - }; - } + }.bind(this)); + } + }]); + }(EventEmitter2); + + function _callSuper$e(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$e() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$e() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$e = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David V. Lu!! - davidvlu@gmail.com */ - class Odometry extends THREE.Object3D { - + var Odometry = /*#__PURE__*/function (_THREE$Object3D) { /** * An Odometry client * @@ -55403,78 +47438,81 @@ var ROS3D = (function (exports, ROSLIB) { * * shaftDiameter (optional) - the shaft diameter of the arrow (default: 0.05) * * headDiameter (optional) - the head diameter of the arrow (default: 0.1) */ - constructor(options) { - super(); - this.options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/particlecloud'; - this.tfClient = options.tfClient; - this.color = options.color || 0xcc00ff; - this.length = options.length || 1.0; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.keep = options.keep || 1; - - this.sns = []; - - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + function Odometry(options) { + var _this; + _classCallCheck(this, Odometry); + _this = _callSuper$e(this, Odometry); + _this.options = options || {}; + _this.ros = options.ros; + _this.topicName = options.topic || '/particlecloud'; + _this.tfClient = options.tfClient; + _this.color = options.color || 0xcc00ff; + _this.length = options.length || 1.0; + _this.rootObject = options.rootObject || new Object3D(); + _this.keep = options.keep || 1; + _this.sns = []; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(Odometry, _THREE$Object3D); + return _createClass(Odometry, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - - subscribe(){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'nav_msgs/Odometry' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(message){ - if(this.sns.length >= this.keep) { + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'nav_msgs/Odometry' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + if (this.sns.length >= this.keep) { this.sns[0].unsubscribeTf(); this.rootObject.remove(this.sns[0]); this.sns.shift(); + } + this.options.origin = new Vector3(message.pose.pose.position.x, message.pose.pose.position.y, message.pose.pose.position.z); + var rot = new Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, message.pose.pose.orientation.z, message.pose.pose.orientation.w); + this.options.direction = new Vector3(1, 0, 0); + this.options.direction.applyQuaternion(rot); + this.options.material = new MeshBasicMaterial({ + color: this.color + }); + var arrow = new Arrow(this.options); + this.sns.push(new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: arrow + })); + this.rootObject.add(this.sns[this.sns.length - 1]); } + }]); + }(Object3D); - this.options.origin = new THREE.Vector3( message.pose.pose.position.x, message.pose.pose.position.y, - message.pose.pose.position.z); - - var rot = new THREE.Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, - message.pose.pose.orientation.z, message.pose.pose.orientation.w); - this.options.direction = new THREE.Vector3(1,0,0); - this.options.direction.applyQuaternion(rot); - this.options.material = new THREE.MeshBasicMaterial({color: this.color}); - var arrow = new Arrow(this.options); - - this.sns.push(new SceneNode({ - frameID : message.header.frame_id, - tfClient : this.tfClient, - object : arrow - })); - - this.rootObject.add(this.sns[ this.sns.length - 1]); - }; - } + function _callSuper$d(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$d() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$d() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$d = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author David V. Lu!! - davidvlu@gmail.com */ - class Path extends THREE.Object3D { - + var Path = /*#__PURE__*/function (_THREE$Object3D) { /** * A Path client that listens to a given topic and displays a line connecting the poses. * @@ -55487,77 +47525,81 @@ var ROS3D = (function (exports, ROSLIB) { * * rootObject (optional) - the root object to add this marker to * * color (optional) - color for line (default: 0xcc00ff) */ - constructor(options) { - super(); + function Path(options) { + var _this; + _classCallCheck(this, Path); + _this = _callSuper$d(this, Path); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/path'; - this.tfClient = options.tfClient; - this.color = options.color || 0xcc00ff; - this.rootObject = options.rootObject || new THREE.Object3D(); - - this.sn = null; - this.line = null; - - this.rosTopic = undefined; - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _this.ros = options.ros; + _this.topicName = options.topic || '/path'; + _this.tfClient = options.tfClient; + _this.color = options.color || 0xcc00ff; + _this.rootObject = options.rootObject || new Object3D(); + _this.sn = null; + _this.line = null; + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(Path, _THREE$Object3D); + return _createClass(Path, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - - subscribe(){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'nav_msgs/Path' - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(message){ - if(this.sn!==null){ + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'nav_msgs/Path' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + if (this.sn !== null) { this.sn.unsubscribeTf(); this.rootObject.remove(this.sn); - } - - var lineGeometry = new THREE.Geometry(); - for(var i=0; i= message.range_min && range <= message.range_max){ + }, { + key: "processMessage", + value: function processMessage(message) { + if (!this.points.setup(message.header.frame_id)) { + return; + } + var n = message.ranges.length; + var j = 0; + for (var i = 0; i < n; i += this.points.pointRatio) { + var range = message.ranges[i]; + if (range >= message.range_min && range <= message.range_max) { var angle = message.angle_min + i * message.angle_increment; this.points.positions.array[j++] = range * Math.cos(angle); this.points.positions.array[j++] = range * Math.sin(angle); this.points.positions.array[j++] = 0.0; + } } + this.points.update(j / 3); } - this.points.update(j/3); - }; - } + }]); + }(Object3D); + + function _callSuper$5(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$5() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$5() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$5 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Mathieu Bredif - mathieu.bredif@ign.fr */ - class NavSatFix extends THREE.Object3D { - + var NavSatFix = /*#__PURE__*/function (_THREE$Object3D) { /** * A NavSatFix client that listens to a given topic and displays a line connecting the gps fixes. * @@ -56206,82 +48274,88 @@ var ROS3D = (function (exports, ROSLIB) { * * keep (optional) - number of gps fix points to keep (default: 100) * * convert (optional) - conversion function from lon/lat/alt to THREE.Vector3 (default: passthrough) */ - - constructor(options) { - - super(); + + function NavSatFix(options) { + var _this; + _classCallCheck(this, NavSatFix); + _this = _callSuper$5(this, NavSatFix); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/gps/fix'; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.object3d = options.object3d || new THREE.Object3D(); + _this.ros = options.ros; + _this.topicName = options.topic || '/gps/fix'; + _this.rootObject = options.rootObject || new Object3D(); + _this.object3d = options.object3d || new Object3D(); var material = options.material || {}; - this.altitudeNaN = options.altitudeNaN || 0; - this.keep = options.keep || 100; - this.convert = options.convert || function(lon,lat,alt) { return new THREE.Vector3(lon,lat,alt); }; - this.count = 0; - this.next1 = 0; - this.next2 = this.keep; - - this.geom = new THREE.BufferGeometry(); - this.vertices = new THREE.BufferAttribute(new Float32Array( 6 * this.keep ), 3 ); - this.geom.addAttribute( 'position', this.vertices); - this.material = material.isMaterial ? material : new THREE.LineBasicMaterial( material ); - this.line = new THREE.Line( this.geom, this.material ); - this.rootObject.add(this.object3d); - this.rootObject.add(this.line); - - this.rosTopic = undefined; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _this.altitudeNaN = options.altitudeNaN || 0; + _this.keep = options.keep || 100; + _this.convert = options.convert || function (lon, lat, alt) { + return new Vector3(lon, lat, alt); + }; + _this.count = 0; + _this.next1 = 0; + _this.next2 = _this.keep; + _this.geom = new BufferGeometry(); + _this.vertices = new BufferAttribute(new Float32Array(6 * _this.keep), 3); + _this.geom.addAttribute('position', _this.vertices); + _this.material = material.isMaterial ? material : new LineBasicMaterial(material); + _this.line = new Line(_this.geom, _this.material); + _this.rootObject.add(_this.object3d); + _this.rootObject.add(_this.line); + _this.rosTopic = undefined; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(NavSatFix, _THREE$Object3D); + return _createClass(NavSatFix, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - - subscribe(){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - queue_length : 1, - messageType : 'sensor_msgs/NavSatFix' - }); - - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(message){ - var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; - var p = this.convert(message.longitude, message.latitude, altitude); - - // move the object3d to the gps position - this.object3d.position.copy(p); - this.object3d.updateMatrixWorld(true); - - // copy the position twice in the circular buffer - // the second half replicates the first to allow a single drawRange - this.vertices.array[3*this.next1 ] = p.x; - this.vertices.array[3*this.next1+1] = p.y; - this.vertices.array[3*this.next1+2] = p.z; - this.vertices.array[3*this.next2 ] = p.x; - this.vertices.array[3*this.next2+1] = p.y; - this.vertices.array[3*this.next2+2] = p.z; - this.vertices.needsUpdate = true; + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + queue_length: 1, + messageType: 'sensor_msgs/NavSatFix' + }); + this.rosTopic.subscribe(this.processMessageBound); + } + }, { + key: "processMessage", + value: function processMessage(message) { + var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; + var p = this.convert(message.longitude, message.latitude, altitude); + + // move the object3d to the gps position + this.object3d.position.copy(p); + this.object3d.updateMatrixWorld(true); + + // copy the position twice in the circular buffer + // the second half replicates the first to allow a single drawRange + this.vertices.array[3 * this.next1] = p.x; + this.vertices.array[3 * this.next1 + 1] = p.y; + this.vertices.array[3 * this.next1 + 2] = p.z; + this.vertices.array[3 * this.next2] = p.x; + this.vertices.array[3 * this.next2 + 1] = p.y; + this.vertices.array[3 * this.next2 + 2] = p.z; + this.vertices.needsUpdate = true; + this.next1 = (this.next1 + 1) % this.keep; + this.next2 = this.next1 + this.keep; + this.count = Math.min(this.count + 1, this.keep); + this.geom.setDrawRange(this.next2 - this.count, this.count); + } + }]); + }(Object3D); - this.next1 = (this.next1+1) % this.keep; - this.next2 = this.next1 + this.keep; - this.count = Math.min(this.count+1, this.keep); - this.geom.setDrawRange(this.next2-this.count, this.count ); - }; - } + function _callSuper$4(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$4() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$4() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$4 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -56297,36 +48371,42 @@ var ROS3D = (function (exports, ROSLIB) { * returns the number of decoded records */ function decode64(inbytes, outbytes, record_size, pointRatio) { - var x,b=0,l=0,j=0,L=inbytes.length,A=outbytes.length; - record_size = record_size || A; // default copies everything (no skipping) - pointRatio = pointRatio || 1; // default copies everything (no skipping) - var bitskip = (pointRatio-1) * record_size * 8; - for(x=0;x=8){ - l-=8; - outbytes[j++]=(b>>>l)&0xff; - if((j % record_size) === 0) { // skip records - // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} - // first optimization: for(;l0){b=decode64.e[inbytes.charAt(x)];} - } + var x, + b = 0, + l = 0, + j = 0, + L = inbytes.length, + A = outbytes.length; + record_size = record_size || A; // default copies everything (no skipping) + pointRatio = pointRatio || 1; // default copies everything (no skipping) + var bitskip = (pointRatio - 1) * record_size * 8; + for (x = 0; x < L && j < A; x++) { + b = (b << 6) + decode64.e[inbytes.charAt(x)]; + l += 6; + if (l >= 8) { + l -= 8; + outbytes[j++] = b >>> l & 0xff; + if (j % record_size === 0) { + // skip records + // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} + // first optimization: for(;l 0) { + b = decode64.e[inbytes.charAt(x)]; } + } } - return Math.floor(j/record_size); + } + return Math.floor(j / record_size); } // initialize decoder with static lookup table 'e' - decode64.S='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - decode64.e={}; - for(var i=0;i<64;i++){decode64.e[decode64.S.charAt(i)]=i;} - - - class PointCloud2 extends THREE.Object3D { - + decode64.S = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + decode64.e = {}; + for (var i = 0; i < 64; i++) { + decode64.e[decode64.S.charAt(i)] = i; + } + var PointCloud2 = /*#__PURE__*/function (_THREE$Object3D) { /** * A PointCloud2 client that listens to a given topic and displays the points. * @@ -56345,92 +48425,97 @@ var ROS3D = (function (exports, ROSLIB) { * * colorsrc (optional) - the field to be used for coloring (default: 'rgb') * * colormap (optional) - function that turns the colorsrc field value to a color */ - constructor(options) { - super(); + function PointCloud2(options) { + var _this; + _classCallCheck(this, PointCloud2); + _this = _callSuper$4(this, PointCloud2); options = options || {}; - this.ros = options.ros; - this.topicName = options.topic || '/points'; - this.throttle_rate = options.throttle_rate || null; - this.compression = options.compression || 'cbor'; - this.max_pts = options.max_pts || 10000; - this.points = new Points(options); - this.rosTopic = undefined; - this.buffer = null; - - this.processMessageBound = this.processMessage.bind(this); - this.subscribe(); - }; - - - unsubscribe(){ - if(this.rosTopic){ - this.rosTopic.unsubscribe(this.processMessageBound); + _this.ros = options.ros; + _this.topicName = options.topic || '/points'; + _this.throttle_rate = options.throttle_rate || null; + _this.compression = options.compression || 'cbor'; + _this.max_pts = options.max_pts || 10000; + _this.points = new Points(options); + _this.rosTopic = undefined; + _this.buffer = null; + _this.processMessageBound = _this.processMessage.bind(_this); + _this.subscribe(); + return _this; + } + _inherits(PointCloud2, _THREE$Object3D); + return _createClass(PointCloud2, [{ + key: "unsubscribe", + value: function unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessageBound); + } } - }; - - subscribe(){ - this.unsubscribe(); - - // subscribe to the topic - this.rosTopic = new ROSLIB__namespace.Topic({ - ros : this.ros, - name : this.topicName, - messageType : 'sensor_msgs/PointCloud2', - throttle_rate : this.throttle_rate, - queue_length : 1, - compression: this.compression - }); - this.rosTopic.subscribe(this.processMessageBound); - }; - - processMessage(msg){ - if(!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { - return; + }, { + key: "subscribe", + value: function subscribe() { + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB__namespace.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'sensor_msgs/PointCloud2', + throttle_rate: this.throttle_rate, + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessageBound); } - - var n, pointRatio = this.points.pointRatio; - var bufSz = this.max_pts * msg.point_step; - - if (msg.data.buffer) { - this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); - n = Math.min(msg.height*msg.width / pointRatio, this.points.positions.array.length / 3); - } else { - if (!this.buffer || this.buffer.byteLength < bufSz) { - this.buffer = new Uint8Array(bufSz); + }, { + key: "processMessage", + value: function processMessage(msg) { + if (!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { + return; } - n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); - pointRatio = 1; - } - - var dv = new DataView(this.buffer.buffer); - var littleEndian = !msg.is_bigendian; - var x = this.points.fields.x.offset; - var y = this.points.fields.y.offset; - var z = this.points.fields.z.offset; - var base, color; - for(var i = 0; i < n; i++){ - base = i * pointRatio * msg.point_step; - this.points.positions.array[3*i ] = dv.getFloat32(base+x, littleEndian); - this.points.positions.array[3*i + 1] = dv.getFloat32(base+y, littleEndian); - this.points.positions.array[3*i + 2] = dv.getFloat32(base+z, littleEndian); - - if(this.points.colors){ - color = this.points.colormap(this.points.getColor(dv,base,littleEndian)); - this.points.colors.array[3*i ] = color.r; - this.points.colors.array[3*i + 1] = color.g; - this.points.colors.array[3*i + 2] = color.b; + var n, + pointRatio = this.points.pointRatio; + var bufSz = this.max_pts * msg.point_step; + if (msg.data.buffer) { + this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); + n = Math.min(msg.height * msg.width / pointRatio, this.points.positions.array.length / 3); + } else { + if (!this.buffer || this.buffer.byteLength < bufSz) { + this.buffer = new Uint8Array(bufSz); + } + n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); + pointRatio = 1; + } + var dv = new DataView(this.buffer.buffer); + var littleEndian = !msg.is_bigendian; + var x = this.points.fields.x.offset; + var y = this.points.fields.y.offset; + var z = this.points.fields.z.offset; + var base, color; + for (var i = 0; i < n; i++) { + base = i * pointRatio * msg.point_step; + this.points.positions.array[3 * i] = dv.getFloat32(base + x, littleEndian); + this.points.positions.array[3 * i + 1] = dv.getFloat32(base + y, littleEndian); + this.points.positions.array[3 * i + 2] = dv.getFloat32(base + z, littleEndian); + if (this.points.colors) { + color = this.points.colormap(this.points.getColor(dv, base, littleEndian)); + this.points.colors.array[3 * i] = color.r; + this.points.colors.array[3 * i + 1] = color.g; + this.points.colors.array[3 * i + 2] = color.b; + } } + this.points.update(n); } - this.points.update(n); - }; - } + }]); + }(Object3D); + + function _callSuper$3(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$3() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$3() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$3 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview * @author Jihoon Lee - jihoon.lee@kakaobrain.com */ - class TFAxes extends THREE.Object3D { - + var TFAxes = /*#__PURE__*/function (_THREE$Object3D) { /** * An Axes node can be used to display the axis of a particular coordinate frame. * @@ -56450,33 +48535,36 @@ var ROS3D = (function (exports, ROSLIB) { * equal to the length of the axis. Parameter only applies when * lineType is set to dashed. */ - constructor(options) { - super(); + function TFAxes(options) { + var _this; + _classCallCheck(this, TFAxes); + _this = _callSuper$3(this, TFAxes); options = options || {}; - - this.frame_id = options.frame_id; - this.tfClient = options.tfClient; - this.rootObject = options.rootObject || new THREE.Object3D(); - this.axes = new Axes( - { - shaftRadius: options.shaftRadius || 0.025, - headRadius: options.headRaidus || 0.07, - headLength: options.headLength || 0.2, - scale: options.scale || 1.0, - lineType: options.lineType || 'full', - lineDashLength: options.lineDashLength || 0.1 - }); - - this.sn = new SceneNode({ - frameID: this.frame_id, - tfClient : this.tfClient, - object : this.axes + _this.frame_id = options.frame_id; + _this.tfClient = options.tfClient; + _this.rootObject = options.rootObject || new Object3D(); + _this.axes = new Axes({ + shaftRadius: options.shaftRadius || 0.025, + headRadius: options.headRaidus || 0.07, + headLength: options.headLength || 0.2, + scale: options.scale || 1.0, + lineType: options.lineType || 'full', + lineDashLength: options.lineDashLength || 0.1 }); + _this.sn = new SceneNode({ + frameID: _this.frame_id, + tfClient: _this.tfClient, + object: _this.axes + }); + _this.rootObject.add(_this.sn); + return _this; + } + _inherits(TFAxes, _THREE$Object3D); + return _createClass(TFAxes); + }(Object3D); - this.rootObject.add(this.sn); - - }; - } + function _callSuper$2(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$2() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct$2() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$2 = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -56484,8 +48572,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Russell Toris - rctoris@wpi.edu */ - class Urdf extends THREE.Object3D { - + var Urdf = /*#__PURE__*/function (_THREE$Object3D) { /** * A URDF can be used to load a ROSLIB.UrdfModel and its associated models into a 3D object. * @@ -56498,21 +48585,23 @@ var ROS3D = (function (exports, ROSLIB) { * * tfPrefix (optional) - the TF prefix to used for multi-robots * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) */ - constructor(options) { + function Urdf(options) { + var _this; + _classCallCheck(this, Urdf); options = options || {}; var urdfModel = options.urdfModel; var path = options.path || '/'; var tfClient = options.tfClient; var tfPrefix = options.tfPrefix || ''; var loader = options.loader; - - super(); + console.log('Path ' + path); + _this = _callSuper$2(this, Urdf); // load all models var links = urdfModel.links; - for ( var l in links) { + for (var l in links) { var link = links[l]; - for( var i=0; i 0) { - target = intersections[0].object; - event3D.intersection = this.lastIntersection = intersections[0]; - } else { - target = this.fallbackTarget; - } - // if the mouse moves from one object to another (or from/to the 'null' object), notify both - if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { - - // Event Status. TODO: Make it as enum - // 0: Accepted - // 1: Failed - // 2: Continued - var eventStatus = this.notify(target, 'mouseover', event3D); - if (eventStatus === 0) { - this.notify(this.lastTarget, 'mouseout', event3D); - } else if(eventStatus === 1) { - // if target was null or no target has caught our event, fall back + // in the normal case, we need to check what is under the mouse + target = this.lastTarget; + var intersections = []; + intersections = mouseRaycaster.intersectObject(this.rootObject, true); + if (intersections.length > 0) { + target = intersections[0].object; + event3D.intersection = this.lastIntersection = intersections[0]; + } else { target = this.fallbackTarget; - if (target !== this.lastTarget) { - this.notify(target, 'mouseover', event3D); + } + + // if the mouse moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { + // Event Status. TODO: Make it as enum + // 0: Accepted + // 1: Failed + // 2: Continued + var eventStatus = this.notify(target, 'mouseover', event3D); + if (eventStatus === 0) { this.notify(this.lastTarget, 'mouseout', event3D); + } else if (eventStatus === 1) { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(target, 'mouseover', event3D); + this.notify(this.lastTarget, 'mouseout', event3D); + } } } - } - // if the finger moves from one object to another (or from/to the 'null' object), notify both - if (target !== this.lastTarget && domEvent.type.match(/touch/)) { - var toucheventAccepted = this.notify(target, domEvent.type, event3D); - if (toucheventAccepted) { - this.notify(this.lastTarget, 'touchleave', event3D); - this.notify(this.lastTarget, 'touchend', event3D); - } else { - // if target was null or no target has caught our event, fall back - target = this.fallbackTarget; - if (target !== this.lastTarget) { - this.notify(this.lastTarget, 'touchmove', event3D); + // if the finger moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/touch/)) { + var toucheventAccepted = this.notify(target, domEvent.type, event3D); + if (toucheventAccepted) { + this.notify(this.lastTarget, 'touchleave', event3D); this.notify(this.lastTarget, 'touchend', event3D); + } else { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(this.lastTarget, 'touchmove', event3D); + this.notify(this.lastTarget, 'touchend', event3D); + } } } - } - // pass through event - this.notify(target, domEvent.type, event3D); - if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { - this.dragging = true; + // pass through event + this.notify(target, domEvent.type, event3D); + if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { + this.dragging = true; + } + this.lastTarget = target; } - this.lastTarget = target; - }; - - /** - * Notify the listener of the type of event that occurred. - * - * @param target - the target of the event - * @param type - the type of event that occurred - * @param event3D - the 3D mouse even information - * @returns if an event was canceled - */ - notify(target, type, event3D) { - // ensure the type is set - // - event3D.type = type; - - // make the event cancelable - event3D.cancelBubble = false; - event3D.continueBubble = false; - event3D.stopPropagation = function() { - event3D.cancelBubble = true; - }; + }, { + key: "notify", + value: + /** + * Notify the listener of the type of event that occurred. + * + * @param target - the target of the event + * @param type - the type of event that occurred + * @param event3D - the 3D mouse even information + * @returns if an event was canceled + */ + function notify(target, type, event3D) { + // ensure the type is set + // + event3D.type = type; + + // make the event cancelable + event3D.cancelBubble = false; + event3D.continueBubble = false; + event3D.stopPropagation = function () { + event3D.cancelBubble = true; + }; - // it hit the selectable object but don't highlight - event3D.continuePropagation = function () { - event3D.continueBubble = true; - }; + // it hit the selectable object but don't highlight + event3D.continuePropagation = function () { + event3D.continueBubble = true; + }; - // walk up graph until event is canceled or root node has been reached - event3D.currentTarget = target; - - while (event3D.currentTarget) { - // try to fire event on object - if (event3D.currentTarget.dispatchEvent - && event3D.currentTarget.dispatchEvent instanceof Function) { - event3D.currentTarget.dispatchEvent(event3D); - if (event3D.cancelBubble) { - this.dispatchEvent(event3D); - return 0; // Event Accepted - } - else if(event3D.continueBubble) { - return 2; // Event Continued + // walk up graph until event is canceled or root node has been reached + event3D.currentTarget = target; + while (event3D.currentTarget) { + // try to fire event on object + if (event3D.currentTarget.dispatchEvent && event3D.currentTarget.dispatchEvent instanceof Function) { + event3D.currentTarget.dispatchEvent(event3D); + if (event3D.cancelBubble) { + this.dispatchEvent(event3D); + return 0; // Event Accepted + } else if (event3D.continueBubble) { + return 2; // Event Continued + } } + // walk up + event3D.currentTarget = event3D.currentTarget.parent; } - // walk up - event3D.currentTarget = event3D.currentTarget.parent; + return 1; // Event Failed } + }]); + }(EventDispatcher); - return 1; // Event Failed - }; - } + function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } + function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /** * @fileOverview @@ -57049,8 +49152,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author AlteredQualia - http://alteredqualia.com */ - class OrbitControls extends THREE.EventDispatcher { - + var OrbitControls = /*#__PURE__*/function (_THREE$EventDispatche) { /** * Behaves like THREE.OrbitControls, but uses right-handed coordinates and z as up vector. * @@ -57067,64 +49169,63 @@ var ROS3D = (function (exports, ROSLIB) { * panning/zooming. Only has effect when * displayPanAndZoomFrame is set to true. */ - constructor(options) { - super(); - var that = this; + function OrbitControls(options) { + var _this; + _classCallCheck(this, OrbitControls); + _this = _callSuper(this, OrbitControls); + var that = _this; options = options || {}; var scene = options.scene; - this.camera = options.camera; - this.center = new THREE.Vector3(); - this.userZoom = true; - this.userZoomSpeed = options.userZoomSpeed || 1.0; - this.userRotate = true; - this.userRotateSpeed = options.userRotateSpeed || 1.0; - this.autoRotate = options.autoRotate; - this.autoRotateSpeed = options.autoRotateSpeed || 2.0; - this.displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? - true : - !!options.displayPanAndZoomFrame; - this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; + _this.camera = options.camera; + _this.center = new Vector3(); + _this.userZoom = true; + _this.userZoomSpeed = options.userZoomSpeed || 1.0; + _this.userRotate = true; + _this.userRotateSpeed = options.userRotateSpeed || 1.0; + _this.autoRotate = options.autoRotate; + _this.autoRotateSpeed = options.autoRotateSpeed || 2.0; + _this.displayPanAndZoomFrame = options.displayPanAndZoomFrame === undefined ? true : !!options.displayPanAndZoomFrame; + _this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; // In ROS, z is pointing upwards - this.camera.up = new THREE.Vector3(0, 0, 1); + _this.camera.up = new Vector3(0, 0, 1); // internals var pixelsPerRound = 1800; var touchMoveThreshold = 10; - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); - var zoomStart = new THREE.Vector2(); - var zoomEnd = new THREE.Vector2(); - var zoomDelta = new THREE.Vector2(); - var moveStartCenter = new THREE.Vector3(); - var moveStartNormal = new THREE.Vector3(); - var moveStartPosition = new THREE.Vector3(); - var moveStartIntersection = new THREE.Vector3(); + var rotateStart = new Vector2(); + var rotateEnd = new Vector2(); + var rotateDelta = new Vector2(); + var zoomStart = new Vector2(); + var zoomEnd = new Vector2(); + var zoomDelta = new Vector2(); + var moveStartCenter = new Vector3(); + var moveStartNormal = new Vector3(); + var moveStartPosition = new Vector3(); + var moveStartIntersection = new Vector3(); var touchStartPosition = new Array(2); var touchMoveVector = new Array(2); - this.phiDelta = 0; - this.thetaDelta = 0; - this.scale = 1; - this.lastPosition = new THREE.Vector3(); + _this.phiDelta = 0; + _this.thetaDelta = 0; + _this.scale = 1; + _this.lastPosition = new Vector3(); // internal states var STATE = { - NONE : -1, - ROTATE : 0, - ZOOM : 1, - MOVE : 2 + NONE: -1, + ROTATE: 0, + ZOOM: 1, + MOVE: 2 }; var state = STATE.NONE; - - this.axes = new Axes({ - shaftRadius : 0.025, - headRadius : 0.07, - headLength : 0.2, - lineType: this.lineTypePanAndZoomFrame + _this.axes = new Axes({ + shaftRadius: 0.025, + headRadius: 0.07, + headLength: 0.2, + lineType: _this.lineTypePanAndZoomFrame }); - if (this.displayPanAndZoomFrame) { + if (_this.displayPanAndZoomFrame) { // initially not visible - scene.add(this.axes); - this.axes.traverse(function(obj) { + scene.add(_this.axes); + _this.axes.traverse(function (obj) { obj.visible = false; }); } @@ -57137,7 +49238,6 @@ var ROS3D = (function (exports, ROSLIB) { function onMouseDown(event3D) { var event = event3D.domEvent; event.preventDefault(); - switch (event.button) { case 0: state = STATE.ROTATE; @@ -57145,23 +49245,18 @@ var ROS3D = (function (exports, ROSLIB) { break; case 1: state = STATE.MOVE; - - moveStartNormal = new THREE.Vector3(0, 0, 1); - var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal = new Vector3(0, 0, 1); + var rMat = new Matrix4().extractRotation(this.camera.matrix); moveStartNormal.applyMatrix4(rMat); - moveStartCenter = that.center.clone(); moveStartPosition = that.camera.position.clone(); - moveStartIntersection = intersectViewPlane(event3D.mouseRay, - moveStartCenter, - moveStartNormal); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, moveStartCenter, moveStartNormal); break; case 2: state = STATE.ZOOM; zoomStart.set(event.clientX, event.clientY); break; } - this.showAxes(); } @@ -57173,38 +49268,28 @@ var ROS3D = (function (exports, ROSLIB) { function onMouseMove(event3D) { var event = event3D.domEvent; if (state === STATE.ROTATE) { - rotateEnd.set(event.clientX, event.clientY); rotateDelta.subVectors(rotateEnd, rotateStart); - that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); - rotateStart.copy(rotateEnd); this.showAxes(); } else if (state === STATE.ZOOM) { zoomEnd.set(event.clientX, event.clientY); zoomDelta.subVectors(zoomEnd, zoomStart); - if (zoomDelta.y > 0) { that.zoomIn(); } else { that.zoomOut(); } - zoomStart.copy(zoomEnd); this.showAxes(); - } else if (state === STATE.MOVE) { var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); - if (!intersection) { return; } - - var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), intersection - .clone()); - + var delta = new Vector3().subVectors(moveStartIntersection.clone(), intersection.clone()); that.center.addVectors(moveStartCenter.clone(), delta.clone()); that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); that.update(); @@ -57222,10 +49307,8 @@ var ROS3D = (function (exports, ROSLIB) { * @returns the intersection */ function intersectViewPlane(mouseRay, planeOrigin, planeNormal) { - - var vector = new THREE.Vector3(); - var intersection = new THREE.Vector3(); - + var vector = new Vector3(); + var intersection = new Vector3(); vector.subVectors(planeOrigin, mouseRay.origin); var dot = mouseRay.direction.dot(planeNormal); @@ -57236,7 +49319,6 @@ var ROS3D = (function (exports, ROSLIB) { // calc distance to plane var scalar = planeNormal.dot(vector) / dot; - intersection = mouseRay.direction.clone().multiplyScalar(scalar); return intersection; } @@ -57250,7 +49332,6 @@ var ROS3D = (function (exports, ROSLIB) { if (!that.userRotate) { return; } - state = STATE.NONE; } @@ -57263,11 +49344,10 @@ var ROS3D = (function (exports, ROSLIB) { if (!that.userZoom) { return; } - var event = event3D.domEvent; // wheelDelta --> Chrome, detail --> Firefox var delta; - if (typeof (event.wheelDelta) !== 'undefined') { + if (typeof event.wheelDelta !== 'undefined') { delta = event.wheelDelta; } else { delta = -event.detail; @@ -57277,7 +49357,6 @@ var ROS3D = (function (exports, ROSLIB) { } else { that.zoomOut(); } - this.showAxes(); } @@ -57291,31 +49370,24 @@ var ROS3D = (function (exports, ROSLIB) { switch (event.touches.length) { case 1: state = STATE.ROTATE; - rotateStart.set(event.touches[0].pageX - window.scrollX, - event.touches[0].pageY - window.scrollY); + rotateStart.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); break; case 2: state = STATE.NONE; /* ready for move */ - moveStartNormal = new THREE.Vector3(0, 0, 1); - var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal = new Vector3(0, 0, 1); + var rMat = new Matrix4().extractRotation(this.camera.matrix); moveStartNormal.applyMatrix4(rMat); moveStartCenter = that.center.clone(); moveStartPosition = that.camera.position.clone(); - moveStartIntersection = intersectViewPlane(event3D.mouseRay, - moveStartCenter, - moveStartNormal); - touchStartPosition[0] = new THREE.Vector2(event.touches[0].pageX, - event.touches[0].pageY); - touchStartPosition[1] = new THREE.Vector2(event.touches[1].pageX, - event.touches[1].pageY); - touchMoveVector[0] = new THREE.Vector2(0, 0); - touchMoveVector[1] = new THREE.Vector2(0, 0); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, moveStartCenter, moveStartNormal); + touchStartPosition[0] = new Vector2(event.touches[0].pageX, event.touches[0].pageY); + touchStartPosition[1] = new Vector2(event.touches[1].pageX, event.touches[1].pageY); + touchMoveVector[0] = new Vector2(0, 0); + touchMoveVector[1] = new Vector2(0, 0); break; } - this.showAxes(); - event.preventDefault(); } @@ -57327,238 +49399,222 @@ var ROS3D = (function (exports, ROSLIB) { function onTouchMove(event3D) { var event = event3D.domEvent; if (state === STATE.ROTATE) { - rotateEnd.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); rotateDelta.subVectors(rotateEnd, rotateStart); - that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); - rotateStart.copy(rotateEnd); this.showAxes(); } else { - touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, - touchStartPosition[0].y - event.touches[0].pageY); - touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, - touchStartPosition[1].y - event.touches[1].pageY); - if (touchMoveVector[0].lengthSq() > touchMoveThreshold && - touchMoveVector[1].lengthSq() > touchMoveThreshold) { - touchStartPosition[0].set(event.touches[0].pageX, - event.touches[0].pageY); - touchStartPosition[1].set(event.touches[1].pageX, - event.touches[1].pageY); - if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && - state !== STATE.ZOOM) { + touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, touchStartPosition[0].y - event.touches[0].pageY); + touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, touchStartPosition[1].y - event.touches[1].pageY); + if (touchMoveVector[0].lengthSq() > touchMoveThreshold && touchMoveVector[1].lengthSq() > touchMoveThreshold) { + touchStartPosition[0].set(event.touches[0].pageX, event.touches[0].pageY); + touchStartPosition[1].set(event.touches[1].pageX, event.touches[1].pageY); + if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && state !== STATE.ZOOM) { state = STATE.MOVE; - } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && - state !== STATE.MOVE) { + } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && state !== STATE.MOVE) { state = STATE.ZOOM; } if (state === STATE.ZOOM) { - var tmpVector = new THREE.Vector2(); - tmpVector.subVectors(touchStartPosition[0], - touchStartPosition[1]); - if (touchMoveVector[0].dot(tmpVector) < 0 && - touchMoveVector[1].dot(tmpVector) > 0) { + var tmpVector = new Vector2(); + tmpVector.subVectors(touchStartPosition[0], touchStartPosition[1]); + if (touchMoveVector[0].dot(tmpVector) < 0 && touchMoveVector[1].dot(tmpVector) > 0) { that.zoomOut(); - } else if (touchMoveVector[0].dot(tmpVector) > 0 && - touchMoveVector[1].dot(tmpVector) < 0) { + } else if (touchMoveVector[0].dot(tmpVector) > 0 && touchMoveVector[1].dot(tmpVector) < 0) { that.zoomIn(); } } } if (state === STATE.MOVE) { - var intersection = intersectViewPlane(event3D.mouseRay, - that.center, - moveStartNormal); + var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); if (!intersection) { return; } - var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), - intersection.clone()); + var delta = new Vector3().subVectors(moveStartIntersection.clone(), intersection.clone()); that.center.addVectors(moveStartCenter.clone(), delta.clone()); that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); that.update(); that.camera.updateMatrixWorld(); } - this.showAxes(); - event.preventDefault(); } } - function onTouchEnd(event3D) { var event = event3D.domEvent; - if (event.touches.length === 1 && - state !== STATE.ROTATE) { + if (event.touches.length === 1 && state !== STATE.ROTATE) { state = STATE.ROTATE; - rotateStart.set(event.touches[0].pageX - window.scrollX, - event.touches[0].pageY - window.scrollY); - } - else { - state = STATE.NONE; + rotateStart.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); + } else { + state = STATE.NONE; } } // add event listeners - this.addEventListener('mousedown', onMouseDown); - this.addEventListener('mouseup', onMouseUp); - this.addEventListener('mousemove', onMouseMove); - this.addEventListener('touchstart', onTouchDown); - this.addEventListener('touchmove', onTouchMove); - this.addEventListener('touchend', onTouchEnd); + _this.addEventListener('mousedown', onMouseDown); + _this.addEventListener('mouseup', onMouseUp); + _this.addEventListener('mousemove', onMouseMove); + _this.addEventListener('touchstart', onTouchDown); + _this.addEventListener('touchmove', onTouchMove); + _this.addEventListener('touchend', onTouchEnd); // Chrome/Firefox have different events here - this.addEventListener('mousewheel', onMouseWheel); - this.addEventListener('DOMMouseScroll', onMouseWheel); - }; - - /** - * Display the main axes for 1 second. - */ - showAxes() { - var that = this; - - this.axes.traverse(function(obj) { - obj.visible = true; - }); - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - } - this.hideTimeout = setTimeout(function() { - that.axes.traverse(function(obj) { - obj.visible = false; + _this.addEventListener('mousewheel', onMouseWheel); + _this.addEventListener('DOMMouseScroll', onMouseWheel); + return _this; + } + _inherits(OrbitControls, _THREE$EventDispatche); + return _createClass(OrbitControls, [{ + key: "showAxes", + value: + /** + * Display the main axes for 1 second. + */ + function showAxes() { + var that = this; + this.axes.traverse(function (obj) { + obj.visible = true; }); - that.hideTimeout = false; - }, 1000); - }; - - /** - * Rotate the camera to the left by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - rotateLeft(angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + if (this.hideTimeout) { + clearTimeout(this.hideTimeout); + } + this.hideTimeout = setTimeout(function () { + that.axes.traverse(function (obj) { + obj.visible = false; + }); + that.hideTimeout = false; + }, 1000); } - this.thetaDelta -= angle; - }; - - /** - * Rotate the camera to the right by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - rotateRight(angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateLeft", + value: + /** + * Rotate the camera to the left by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateLeft(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta -= angle; } - this.thetaDelta += angle; - }; - - /** - * Rotate the camera up by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - rotateUp(angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateRight", + value: + /** + * Rotate the camera to the right by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateRight(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta += angle; } - this.phiDelta -= angle; - }; - - /** - * Rotate the camera down by the given angle. - * - * @param angle (optional) - the angle to rotate by - */ - rotateDown(angle) { - if (angle === undefined) { - angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }, { + key: "rotateUp", + value: + /** + * Rotate the camera up by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateUp(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta -= angle; } - this.phiDelta += angle; - }; - - /** - * Zoom in by the given scale. - * - * @param zoomScale (optional) - the scale to zoom in by - */ - zoomIn(zoomScale) { - if (zoomScale === undefined) { - zoomScale = Math.pow(0.95, this.userZoomSpeed); + }, { + key: "rotateDown", + value: + /** + * Rotate the camera down by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + function rotateDown(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta += angle; } - this.scale /= zoomScale; - }; - - /** - * Zoom out by the given scale. - * - * @param zoomScale (optional) - the scale to zoom in by - */ - zoomOut(zoomScale) { - if (zoomScale === undefined) { - zoomScale = Math.pow(0.95, this.userZoomSpeed); + }, { + key: "zoomIn", + value: + /** + * Zoom in by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + function zoomIn(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale /= zoomScale; } - this.scale *= zoomScale; - }; - - /** - * Update the camera to the current settings. - */ - update() { - // x->y, y->z, z->x - var position = this.camera.position; - var offset = position.clone().sub(this.center); - - // angle from z-axis around y-axis - var theta = Math.atan2(offset.y, offset.x); - - // angle from y-axis - var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); - - if (this.autoRotate) { - this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + }, { + key: "zoomOut", + value: + /** + * Zoom out by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + function zoomOut(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale *= zoomScale; } - - theta += this.thetaDelta; - phi += this.phiDelta; - - // restrict phi to be between EPS and PI-EPS - var eps = 0.000001; - phi = Math.max(eps, Math.min(Math.PI - eps, phi)); - - var radius = offset.length(); - offset.set( - radius * Math.sin(phi) * Math.cos(theta), - radius * Math.sin(phi) * Math.sin(theta), - radius * Math.cos(phi) - ); - offset.multiplyScalar(this.scale); - - position.copy(this.center).add(offset); - - this.camera.lookAt(this.center); - - radius = offset.length(); - this.axes.position.copy(this.center); - this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); - this.axes.updateMatrixWorld(true); - - this.thetaDelta = 0; - this.phiDelta = 0; - this.scale = 1; - - if (this.lastPosition.distanceTo(this.camera.position) > 0) { - this.dispatchEvent({ - type : 'change' - }); - this.lastPosition.copy(this.camera.position); + }, { + key: "update", + value: + /** + * Update the camera to the current settings. + */ + function update() { + // x->y, y->z, z->x + var position = this.camera.position; + var offset = position.clone().sub(this.center); + + // angle from z-axis around y-axis + var theta = Math.atan2(offset.y, offset.x); + + // angle from y-axis + var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); + if (this.autoRotate) { + this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + } + theta += this.thetaDelta; + phi += this.phiDelta; + + // restrict phi to be between EPS and PI-EPS + var eps = 0.000001; + phi = Math.max(eps, Math.min(Math.PI - eps, phi)); + var radius = offset.length(); + offset.set(radius * Math.sin(phi) * Math.cos(theta), radius * Math.sin(phi) * Math.sin(theta), radius * Math.cos(phi)); + offset.multiplyScalar(this.scale); + position.copy(this.center).add(offset); + this.camera.lookAt(this.center); + radius = offset.length(); + this.axes.position.copy(this.center); + this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); + this.axes.updateMatrixWorld(true); + this.thetaDelta = 0; + this.phiDelta = 0; + this.scale = 1; + if (this.lastPosition.distanceTo(this.camera.position) > 0) { + this.dispatchEvent({ + type: 'change' + }); + this.lastPosition.copy(this.camera.position); + } } - }; - } + }]); + }(EventDispatcher); /** * @fileOverview @@ -57567,8 +49623,7 @@ var ROS3D = (function (exports, ROSLIB) { * @author Jihoon Lee - jihoonlee.in@gmail.com */ - class Viewer { - + var Viewer = /*#__PURE__*/function () { /** * A Viewer can be used to render an interactive 3D scene to a HTML5 canvas. * @@ -57590,7 +49645,10 @@ var ROS3D = (function (exports, ROSLIB) { * * panning/zooming. Only has effect when * * displayPanAndZoomFrame is set to true. */ - constructor(options) { + + function Viewer(options) { + _classCallCheck(this, Viewer); + console.log('Here 1'); options = options || {}; var divID = options.divID; var elem = options.elem; @@ -57603,17 +49661,17 @@ var ROS3D = (function (exports, ROSLIB) { var far = options.far || 1000; var alpha = options.alpha || 1.0; var cameraPosition = options.cameraPose || { - x : 3, - y : 3, - z : 3 + x: 3, + y: 3, + z: 3 }; var cameraZoomSpeed = options.cameraZoomSpeed || 0.5; - var displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? true : !!options.displayPanAndZoomFrame; + var displayPanAndZoomFrame = options.displayPanAndZoomFrame === undefined ? true : !!options.displayPanAndZoomFrame; var lineTypePanAndZoomFrame = options.lineTypePanAndZoomFrame || 'full'; // create the canvas to render to - this.renderer = new THREE.WebGLRenderer({ - antialias : antialias, + this.renderer = new WebGLRenderer({ + antialias: antialias, alpha: true }); this.renderer.setClearColor(parseInt(background.replace('#', '0x'), 16), alpha); @@ -57623,42 +49681,42 @@ var ROS3D = (function (exports, ROSLIB) { this.renderer.autoClear = false; // create the global scene - this.scene = new THREE.Scene(); + this.scene = new Scene(); // create the global camera - this.camera = new THREE.PerspectiveCamera(40, width / height, near, far); + this.camera = new PerspectiveCamera(40, width / height, near, far); this.camera.position.x = cameraPosition.x; this.camera.position.y = cameraPosition.y; this.camera.position.z = cameraPosition.z; // add controls to the camera this.cameraControls = new OrbitControls({ - scene : this.scene, - camera : this.camera, - displayPanAndZoomFrame : displayPanAndZoomFrame, + scene: this.scene, + camera: this.camera, + displayPanAndZoomFrame: displayPanAndZoomFrame, lineTypePanAndZoomFrame: lineTypePanAndZoomFrame }); this.cameraControls.userZoomSpeed = cameraZoomSpeed; // lights - this.scene.add(new THREE.AmbientLight(0x555555)); - this.directionalLight = new THREE.DirectionalLight(0xffffff, intensity); + this.scene.add(new AmbientLight(0x555555)); + this.directionalLight = new DirectionalLight(0xffffff, intensity); this.scene.add(this.directionalLight); + console.log('Here 2'); // propagates mouse events to three.js objects - this.selectableObjects = new THREE.Group(); + this.selectableObjects = new Group(); this.scene.add(this.selectableObjects); var mouseHandler = new MouseHandler({ - renderer : this.renderer, - camera : this.camera, - rootObject : this.selectableObjects, - fallbackTarget : this.cameraControls + renderer: this.renderer, + camera: this.camera, + rootObject: this.selectableObjects, + fallbackTarget: this.cameraControls }); // highlights the receiver of mouse events this.highlighter = new Highlighter({ - mouseHandler : mouseHandler + mouseHandler: mouseHandler }); - this.stopped = true; this.animationRequestId = undefined; @@ -57668,80 +49726,93 @@ var ROS3D = (function (exports, ROSLIB) { // begin the render loop this.start(); - }; - - /** - * Start the render loop - */ - start(){ - this.stopped = false; - this.draw(); - }; - - /** - * Renders the associated scene to the viewer. - */ - draw(){ - if(this.stopped){ - // Do nothing if stopped - return; + console.log('Here 3'); + } + return _createClass(Viewer, [{ + key: "start", + value: + /** + * Start the render loop + */ + function start() { + this.stopped = false; + this.draw(); } + }, { + key: "draw", + value: + /** + * Renders the associated scene to the viewer. + */ + function draw() { + if (this.stopped) { + // Do nothing if stopped + return; + } - // update the controls - this.cameraControls.update(); - - // put light to the top-left of the camera - // BUG: position is a read-only property of DirectionalLight, - // attempting to assign to it either does nothing or throws an error. - //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); - this.directionalLight.position.normalize(); + // update the controls + this.cameraControls.update(); + console.log('Here 5'); - // set the scene - this.renderer.clear(true, true, true); - this.renderer.render(this.scene, this.camera); - this.highlighter.renderHighlights(this.scene, this.renderer, this.camera); + // put light to the top-left of the camera + // BUG: position is a read-only property of DirectionalLight, + // attempting to assign to it either does nothing or throws an error. + //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); + this.directionalLight.position.normalize(); - // draw the frame - this.animationRequestId = requestAnimationFrame(this.draw.bind(this)); - }; + // set the scene + this.renderer.clear(true, true, true); + this.renderer.render(this.scene, this.camera); + this.highlighter.renderHighlights(this.scene, this.renderer, this.camera); - /** - * Stop the render loop - */ - stop(){ - if(!this.stopped){ - // Stop animation render loop - cancelAnimationFrame(this.animationRequestId); + // draw the frame + this.animationRequestId = requestAnimationFrame(this.draw.bind(this)); } - this.stopped = true; - }; - - /** - * Add the given THREE Object3D to the global scene in the viewer. - * - * @param object - the THREE Object3D to add - * @param selectable (optional) - if the object should be added to the selectable list - */ - addObject(object, selectable) { - if (selectable) { - this.selectableObjects.add(object); - } else { - this.scene.add(object); + }, { + key: "stop", + value: + /** + * Stop the render loop + */ + function stop() { + if (!this.stopped) { + // Stop animation render loop + cancelAnimationFrame(this.animationRequestId); + } + this.stopped = true; } - }; - - /** - * Resize 3D viewer - * - * @param width - new width value - * @param height - new height value - */ - resize(width, height) { - this.camera.aspect = width / height; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(width, height); - }; - } + }, { + key: "addObject", + value: + /** + * Add the given THREE Object3D to the global scene in the viewer. + * + * @param object - the THREE Object3D to add + * @param selectable (optional) - if the object should be added to the selectable list + */ + function addObject(object, selectable) { + if (selectable) { + this.selectableObjects.add(object); + } else { + this.scene.add(object); + } + } + }, { + key: "resize", + value: + /** + * Resize 3D viewer + * + * @param width - new width value + * @param height - new height value + */ + function resize(width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + } + }]); + }(); exports.Arrow = Arrow; exports.Arrow2 = Arrow2; diff --git a/build/ros3d.min.js b/build/ros3d.min.js index 35bd91a2..bf13095f 100644 --- a/build/ros3d.min.js +++ b/build/ros3d.min.js @@ -1,5 +1,13 @@ -var ROS3D=function(e,t){"use strict";function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(i){if("default"!==i){var r=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,r.get?r:{enumerable:!0,get:function(){return e[i]}})}})),t.default=e,Object.freeze(t)}var r=i(t);function n(){}void 0===Number.EPSILON&&(Number.EPSILON=Math.pow(2,-52)),void 0===Number.isInteger&&(Number.isInteger=function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}),void 0===Math.sign&&(Math.sign=function(e){return e<0?-1:e>0?1:+e}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),i=1;i>8&255]+e[t>>16&255]+e[t>>24&255]+"-"+e[255&i]+e[i>>8&255]+"-"+e[i>>16&15|64]+e[i>>24&255]+"-"+e[63&r|128]+e[r>>8&255]+"-"+e[r>>16&255]+e[r>>24&255]+e[255&n]+e[n>>8&255]+e[n>>16&255]+e[n>>24&255]}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,r,n){return r+(e-t)*(n-r)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*te.DEG2RAD},radToDeg:function(e){return e*te.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))}};function ie(e,t){this.x=e||0,this.y=t||0}function re(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}function ne(e,t,i,r){this._x=e||0,this._y=t||0,this._z=i||0,this._w=void 0!==r?r:1}function oe(e,t,i){this.x=e||0,this.y=t||0,this.z=i||0}function ae(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(ie.prototype,{width:{get:function(){return this.x},set:function(e){this.x=e}},height:{get:function(){return this.y},set:function(e){this.y=e}}}),Object.assign(ie.prototype,{isVector2:!0,set:function(e,t){return this.x=e,this.y=t,this},setScalar:function(e){return this.x=e,this.y=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(e){return this.x=e.x,this.y=e.y,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this)},addScalar:function(e){return this.x+=e,this.y+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this)},subScalar:function(e){return this.x-=e,this.y-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this},multiply:function(e){return this.x*=e.x,this.y*=e.y,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this},divide:function(e){return this.x/=e.x,this.y/=e.y,this},divideScalar:function(e){return this.multiplyScalar(1/e)},applyMatrix3:function(e){var t=this.x,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[7],this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this},clampScalar:(o=new ie,a=new ie,function(e,t){return o.set(e,e),a.set(t,t),this.clamp(o,a)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return 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},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(e){return this.x*e.x+this.y*e.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var e=Math.atan2(this.y,this.x);return e<0&&(e+=2*Math.PI),e},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y;return t*t+i*i},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},equals:function(e){return e.x===this.x&&e.y===this.y},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this},rotateAround:function(e,t){var i=Math.cos(t),r=Math.sin(t),n=this.x-e.x,o=this.y-e.y;return this.x=n*i-o*r+e.x,this.y=n*r+o*i+e.y,this}}),Object.assign(re.prototype,{isMatrix4:!0,set:function(e,t,i,r,n,o,a,s,c,h,l,u,p,d,f,m){var v=this.elements;return v[0]=e,v[4]=t,v[8]=i,v[12]=r,v[1]=n,v[5]=o,v[9]=a,v[13]=s,v[2]=c,v[6]=h,v[10]=l,v[14]=u,v[3]=p,v[7]=d,v[11]=f,v[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new re).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this},copyPosition:function(e){var t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this},extractBasis:function(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this},extractRotation:(p=new oe,function(e){var t=this.elements,i=e.elements,r=1/p.setFromMatrixColumn(e,0).length(),n=1/p.setFromMatrixColumn(e,1).length(),o=1/p.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[4]=i[4]*n,t[5]=i[5]*n,t[6]=i[6]*n,t[8]=i[8]*o,t[9]=i[9]*o,t[10]=i[10]*o,this}),makeRotationFromEuler:function(e){e&&e.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var t=this.elements,i=e.x,r=e.y,n=e.z,o=Math.cos(i),a=Math.sin(i),s=Math.cos(r),c=Math.sin(r),h=Math.cos(n),l=Math.sin(n);if("XYZ"===e.order){var u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=-s*l,t[8]=c,t[1]=p+d*c,t[5]=u-f*c,t[9]=-a*s,t[2]=f-u*c,t[6]=d+p*c,t[10]=o*s}else if("YXZ"===e.order){var m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m+y*a,t[4]=g*a-v,t[8]=o*c,t[1]=o*l,t[5]=o*h,t[9]=-a,t[2]=v*a-g,t[6]=y+m*a,t[10]=o*s}else if("ZXY"===e.order){m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m-y*a,t[4]=-o*l,t[8]=g+v*a,t[1]=v+g*a,t[5]=o*h,t[9]=y-m*a,t[2]=-o*c,t[6]=a,t[10]=o*s}else if("ZYX"===e.order){u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=d*c-p,t[8]=u*c+f,t[1]=s*l,t[5]=f*c+u,t[9]=p*c-d,t[2]=-c,t[6]=a*s,t[10]=o*s}else if("YZX"===e.order){var x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=_-x*l,t[8]=w*l+b,t[1]=l,t[5]=o*h,t[9]=-a*h,t[2]=-c*h,t[6]=b*l+w,t[10]=x-_*l}else if("XZY"===e.order){x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=-l,t[8]=c*h,t[1]=x*l+_,t[5]=o*h,t[9]=b*l-w,t[2]=w*l-b,t[6]=a*h,t[10]=_*l+x}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromQuaternion:function(e){var t=this.elements,i=e._x,r=e._y,n=e._z,o=e._w,a=i+i,s=r+r,c=n+n,h=i*a,l=i*s,u=i*c,p=r*s,d=r*c,f=n*c,m=o*a,v=o*s,g=o*c;return t[0]=1-(p+f),t[4]=l-g,t[8]=u+v,t[1]=l+g,t[5]=1-(h+f),t[9]=d-m,t[2]=u-v,t[6]=d+m,t[10]=1-(h+p),t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},lookAt:(h=new oe,l=new oe,u=new oe,function(e,t,i){var r=this.elements;return u.subVectors(e,t),0===u.lengthSq()&&(u.z=1),u.normalize(),h.crossVectors(i,u),0===h.lengthSq()&&(1===Math.abs(i.z)?u.x+=1e-4:u.z+=1e-4,u.normalize(),h.crossVectors(i,u)),h.normalize(),l.crossVectors(u,h),r[0]=h.x,r[4]=l.x,r[8]=u.x,r[1]=h.y,r[5]=l.y,r[9]=u.y,r[2]=h.z,r[6]=l.z,r[10]=u.z,this}),multiply:function(e,t){return void 0!==t?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(e,t)):this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var i=e.elements,r=t.elements,n=this.elements,o=i[0],a=i[4],s=i[8],c=i[12],h=i[1],l=i[5],u=i[9],p=i[13],d=i[2],f=i[6],m=i[10],v=i[14],g=i[3],y=i[7],x=i[11],b=i[15],w=r[0],_=r[4],M=r[8],E=r[12],T=r[1],S=r[5],A=r[9],R=r[13],L=r[2],C=r[6],P=r[10],N=r[14],O=r[3],I=r[7],D=r[11],U=r[15];return n[0]=o*w+a*T+s*L+c*O,n[4]=o*_+a*S+s*C+c*I,n[8]=o*M+a*A+s*P+c*D,n[12]=o*E+a*R+s*N+c*U,n[1]=h*w+l*T+u*L+p*O,n[5]=h*_+l*S+u*C+p*I,n[9]=h*M+l*A+u*P+p*D,n[13]=h*E+l*R+u*N+p*U,n[2]=d*w+f*T+m*L+v*O,n[6]=d*_+f*S+m*C+v*I,n[10]=d*M+f*A+m*P+v*D,n[14]=d*E+f*R+m*N+v*U,n[3]=g*w+y*T+x*L+b*O,n[7]=g*_+y*S+x*C+b*I,n[11]=g*M+y*A+x*P+b*D,n[15]=g*E+y*R+x*N+b*U,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i=0?1:-1,y=1-v*v;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,v*g);m=Math.sin(m*b)/x,a=Math.sin(a*b)/x}var w=a*g;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-a){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}e[t]=s,e[t+1]=c,e[t+2]=h,e[t+3]=l}}),Object.defineProperties(ne.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this.onChangeCallback()}}}),Object.assign(ne.prototype,{set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this.onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var i=e._x,r=e._y,n=e._z,o=e.order,a=Math.cos,s=Math.sin,c=a(i/2),h=a(r/2),l=a(n/2),u=s(i/2),p=s(r/2),d=s(n/2);return"XYZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===o&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],s=i[5],c=i[9],h=i[2],l=i[6],u=i[10],p=r+s+u;return p>0?(t=.5/Math.sqrt(p+1),this._w=.25/t,this._x=(l-c)*t,this._y=(o-h)*t,this._z=(a-n)*t):r>s&&r>u?(t=2*Math.sqrt(1+r-s-u),this._w=(l-c)/t,this._x=.25*t,this._y=(n+a)/t,this._z=(o+h)/t):s>u?(t=2*Math.sqrt(1+s-r-u),this._w=(o-h)/t,this._x=(n+a)/t,this._y=.25*t,this._z=(c+l)/t):(t=2*Math.sqrt(1+u-r-s),this._w=(a-n)/t,this._x=(o+h)/t,this._y=(c+l)/t,this._z=.25*t),this.onChangeCallback(),this},setFromUnitVectors:function(){var e,t=new oe;return function(i,r){return void 0===t&&(t=new oe),(e=i.dot(r)+1)<1e-6?(e=0,Math.abs(i.x)>Math.abs(i.z)?t.set(-i.y,i.x,0):t.set(0,-i.z,i.y)):t.crossVectors(i,r),this._x=t.x,this._y=t.y,this._z=t.z,this._w=e,this.normalize()}}(),inverse:function(){return this.conjugate().normalize()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this.onChangeCallback(),this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var i=e._x,r=e._y,n=e._z,o=e._w,a=t._x,s=t._y,c=t._z,h=t._w;return this._x=i*h+o*a+r*c-n*s,this._y=r*h+o*s+n*a-i*c,this._z=n*h+o*c+i*s-r*a,this._w=o*h-i*a-r*s-n*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,r=this._y,n=this._z,o=this._w,a=o*e._w+i*e._x+r*e._y+n*e._z;if(a<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,a=-a):this.copy(e),a>=1)return this._w=o,this._x=i,this._y=r,this._z=n,this;var s=Math.sqrt(1-a*a);if(Math.abs(s)<.001)return this._w=.5*(o+this._w),this._x=.5*(i+this._x),this._y=.5*(r+this._y),this._z=.5*(n+this._z),this;var c=Math.atan2(s,a),h=Math.sin((1-t)*c)/s,l=Math.sin(t*c)/s;return this._w=o*h+this._w*l,this._x=i*h+this._x*l,this._y=r*h+this._y*l,this._z=n*h+this._z*l,this.onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return void 0===t&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(oe.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:(d=new ne,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(d.setFromEuler(e))}),applyAxisAngle:function(){var e=new ne;return function(t,i){return this.applyQuaternion(e.setFromAxisAngle(t,i))}}(),applyMatrix3:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[3]*i+n[6]*r,this.y=n[1]*t+n[4]*i+n[7]*r,this.z=n[2]*t+n[5]*i+n[8]*r,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements,o=1/(n[3]*t+n[7]*i+n[11]*r+n[15]);return this.x=(n[0]*t+n[4]*i+n[8]*r+n[12])*o,this.y=(n[1]*t+n[5]*i+n[9]*r+n[13])*o,this.z=(n[2]*t+n[6]*i+n[10]*r+n[14])*o,this},applyQuaternion:function(e){var t=this.x,i=this.y,r=this.z,n=e.x,o=e.y,a=e.z,s=e.w,c=s*t+o*r-a*i,h=s*i+a*t-n*r,l=s*r+n*i-o*t,u=-n*t-o*i-a*r;return this.x=c*s+u*-n+h*-a-l*-o,this.y=h*s+u*-o+l*-n-c*-a,this.z=l*s+u*-a+c*-o-h*-n,this},project:function(){var e=new re;return function(t){return e.multiplyMatrices(t.projectionMatrix,e.getInverse(t.matrixWorld)),this.applyMatrix4(e)}}(),unproject:function(){var e=new re;return function(t){return e.multiplyMatrices(t.matrixWorld,e.getInverse(t.projectionMatrix)),this.applyMatrix4(e)}}(),transformDirection:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r,this.y=n[1]*t+n[5]*i+n[9]*r,this.z=n[2]*t+n[6]*i+n[10]*r,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:function(){var e=new oe,t=new oe;return function(i,r){return e.set(i,i,i),t.set(r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return 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},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},cross:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var i=e.x,r=e.y,n=e.z,o=t.x,a=t.y,s=t.z;return this.x=r*s-n*a,this.y=n*o-i*s,this.z=i*a-r*o,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:function(){var e=new oe;return function(t){return e.copy(this).projectOnVector(t),this.sub(e)}}(),reflect:function(){var e=new oe;return function(t){return this.sub(e.copy(t).multiplyScalar(2*this.dot(t)))}}(),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(te.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}}),Object.assign(ae.prototype,{isMatrix3:!0,set:function(e,t,i,r,n,o,a,s,c){var h=this.elements;return h[0]=e,h[1]=r,h[2]=a,h[3]=t,h[4]=n,h[5]=s,h[6]=i,h[7]=o,h[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")}(r)}),i.image=r.uuid}return t||(e.textures[this.uuid]=i),i},dispose:function(){this.dispatchEvent({type:"dispose"})},transformUv:function(e){if(this.mapping===f){if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case b:e.x=e.x-Math.floor(e.x);break;case w:e.x=e.x<0?0:1;break;case _:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case b:e.y=e.y-Math.floor(e.y);break;case w:e.y=e.y<0?0:1;break;case _:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}this.flipY&&(e.y=1-e.y)}}}),Object.defineProperty(ce.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(he.prototype,{isVector4:!0,set:function(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this.w=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setW:function(e){return this.w=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){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: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=this.w,o=e.elements;return this.x=o[0]*t+o[4]*i+o[8]*r+o[12]*n,this.y=o[1]*t+o[5]*i+o[9]*r+o[13]*n,this.z=o[2]*t+o[6]*i+o[10]*r+o[14]*n,this.w=o[3]*t+o[7]*i+o[11]*r+o[15]*n,this},divideScalar:function(e){return this.multiplyScalar(1/e)},setAxisAngleFromQuaternion:function(e){this.w=2*Math.acos(e.w);var t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this},setAxisAngleFromRotationMatrix:function(e){var t,i,r,n,o=.01,a=.1,s=e.elements,c=s[0],h=s[4],l=s[8],u=s[1],p=s[5],d=s[9],f=s[2],m=s[6],v=s[10];if(Math.abs(h-u)y&&g>x?gx?y0)return e;var n=t*i,o=ge[n];if(void 0===o&&(o=new Float32Array(n),ge[n]=o),0!==t){r.toArray(o,0);for(var a=1,s=0;a!==t;++a)s+=i,e[a].toArray(o,s)}return o}function _e(e,t){var i=ye[t];void 0===i&&(i=new Int32Array(t),ye[t]=i);for(var r=0;r!==t;++r)i[r]=e.allocTextureUnit();return i}function Me(e,t){e.uniform1f(this.addr,t)}function Ee(e,t){e.uniform1i(this.addr,t)}function Te(e,t){void 0===t.x?e.uniform2fv(this.addr,t):e.uniform2f(this.addr,t.x,t.y)}function Se(e,t){void 0!==t.x?e.uniform3f(this.addr,t.x,t.y,t.z):void 0!==t.r?e.uniform3f(this.addr,t.r,t.g,t.b):e.uniform3fv(this.addr,t)}function Ae(e,t){void 0===t.x?e.uniform4fv(this.addr,t):e.uniform4f(this.addr,t.x,t.y,t.z,t.w)}function Re(e,t){e.uniformMatrix2fv(this.addr,!1,t.elements||t)}function Le(e,t){void 0===t.elements?e.uniformMatrix3fv(this.addr,!1,t):(be.set(t.elements),e.uniformMatrix3fv(this.addr,!1,be))}function Ce(e,t){void 0===t.elements?e.uniformMatrix4fv(this.addr,!1,t):(xe.set(t.elements),e.uniformMatrix4fv(this.addr,!1,xe))}function Pe(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTexture2D(t||fe,r)}function Ne(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTextureCube(t||me,r)}function Oe(e,t){e.uniform2iv(this.addr,t)}function Ie(e,t){e.uniform3iv(this.addr,t)}function De(e,t){e.uniform4iv(this.addr,t)}function Ue(e,t){e.uniform1fv(this.addr,t)}function Be(e,t){e.uniform1iv(this.addr,t)}function Fe(e,t){e.uniform2fv(this.addr,we(t,this.size,2))}function ze(e,t){e.uniform3fv(this.addr,we(t,this.size,3))}function ke(e,t){e.uniform4fv(this.addr,we(t,this.size,4))}function Ge(e,t){e.uniformMatrix2fv(this.addr,!1,we(t,this.size,4))}function Ve(e,t){e.uniformMatrix3fv(this.addr,!1,we(t,this.size,9))}function je(e,t){e.uniformMatrix4fv(this.addr,!1,we(t,this.size,16))}function He(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTexture2D(t[o]||fe,n[o])}function We(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTextureCube(t[o]||me,n[o])}function Xe(e,t,i){this.id=e,this.addr=i,this.setValue=function(e){switch(e){case 5126:return Me;case 35664:return Te;case 35665:return Se;case 35666:return Ae;case 35674:return Re;case 35675:return Le;case 35676:return Ce;case 35678:case 36198:return Pe;case 35680:return Ne;case 5124:case 35670:return Ee;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function qe(e,t,i){this.id=e,this.addr=i,this.size=t.size,this.setValue=function(e){switch(e){case 5126:return Ue;case 35664:return Fe;case 35665:return ze;case 35666:return ke;case 35674:return Ge;case 35675:return Ve;case 35676:return je;case 35678:return He;case 35680:return We;case 5124:case 35670:return Be;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function Ye(e){this.id=e,ve.call(this)}Ye.prototype.setValue=function(e,t){for(var i=this.seq,r=0,n=i.length;r!==n;++r){var o=i[r];o.setValue(e,t[o.id])}};var Ze=/([\w\d_]+)(\])?(\[|\.)?/g;function Je(e,t){e.seq.push(t),e.map[t.id]=t}function Ke(e,t,i){var r=e.name,n=r.length;for(Ze.lastIndex=0;;){var o=Ze.exec(r),a=Ze.lastIndex,s=o[1],c="]"===o[2],h=o[3];if(c&&(s|=0),void 0===h||"["===h&&a+2===n){Je(i,void 0===h?new Xe(s,e,t):new qe(s,e,t));break}var l=i.map[s];void 0===l&&Je(i,l=new Ye(s)),i=l}}function Qe(e,t,i){ve.call(this),this.renderer=i;for(var r=e.getProgramParameter(t,e.ACTIVE_UNIFORMS),n=0;n>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function e(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+6*(t-e)*(2/3-i):e}return function(t,i,r){if(t=te.euclideanModulo(t,1),i=te.clamp(i,0,1),r=te.clamp(r,0,1),0===i)this.r=this.g=this.b=r;else{var n=r<=.5?r*(1+i):r+i-r*i,o=2*r-n;this.r=e(o,n,t+1/3),this.g=e(o,n,t),this.b=e(o,n,t-1/3)}return this}}(),setStyle:function(e){function t(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}var i;if(i=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var r,n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(255,parseInt(r[1],10))/255,this.g=Math.min(255,parseInt(r[2],10))/255,this.b=Math.min(255,parseInt(r[3],10))/255,t(r[5]),this;if(r=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(100,parseInt(r[1],10))/100,this.g=Math.min(100,parseInt(r[2],10))/100,this.b=Math.min(100,parseInt(r[3],10))/100,t(r[5]),this;break;case"hsl":case"hsla":if(r=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o)){var a=parseFloat(r[1])/360,s=parseInt(r[2],10)/100,c=parseInt(r[3],10)/100;return t(r[5]),this.setHSL(a,s,c)}}}else if(i=/^\#([A-Fa-f0-9]+)$/.exec(e)){var h,l=(h=i[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}e&&e.length>0&&(void 0!==(h=$e[e])?this.setHex(h):console.warn("THREE.Color: Unknown color "+e));return this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(e){return this.r=e.r,this.g=e.g,this.b=e.b,this},copyGammaToLinear:function(e,t){return void 0===t&&(t=2),this.r=Math.pow(e.r,t),this.g=Math.pow(e.g,t),this.b=Math.pow(e.b,t),this},copyLinearToGamma:function(e,t){void 0===t&&(t=2);var i=t>0?1/t:1;return this.r=Math.pow(e.r,i),this.g=Math.pow(e.g,i),this.b=Math.pow(e.b,i),this},convertGammaToLinear:function(){var e=this.r,t=this.g,i=this.b;return this.r=e*e,this.g=t*t,this.b=i*i,this},convertLinearToGamma:function(){return this.r=Math.sqrt(this.r),this.g=Math.sqrt(this.g),this.b=Math.sqrt(this.b),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(e){var t,i,r=e||{h:0,s:0,l:0},n=this.r,o=this.g,a=this.b,s=Math.max(n,o,a),c=Math.min(n,o,a),h=(c+s)/2;if(c===s)t=0,i=0;else{var l=s-c;switch(i=h<=.5?l/(s+c):l/(2-s-c),s){case n:t=(o-a)/l+(o 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n",lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 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\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",distanceRGBA_frag:"#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n",linedashed_frag:"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\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_frag:"#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 \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"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\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},nt={basic:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.fog]),vertexShader:rt.meshbasic_vert,fragmentShader:rt.meshbasic_frag},lambert:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.fog,tt.lights,{emissive:{value:new et(0)}}]),vertexShader:rt.meshlambert_vert,fragmentShader:rt.meshlambert_frag},phong:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.gradientmap,tt.fog,tt.lights,{emissive:{value:new et(0)},specular:{value:new et(1118481)},shininess:{value:30}}]),vertexShader:rt.meshphong_vert,fragmentShader:rt.meshphong_frag},standard:{uniforms:it.merge([tt.common,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.roughnessmap,tt.metalnessmap,tt.fog,tt.lights,{emissive:{value:new et(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},points:{uniforms:it.merge([tt.points,tt.fog]),vertexShader:rt.points_vert,fragmentShader:rt.points_frag},dashed:{uniforms:it.merge([tt.common,tt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rt.linedashed_vert,fragmentShader:rt.linedashed_frag},depth:{uniforms:it.merge([tt.common,tt.displacementmap]),vertexShader:rt.depth_vert,fragmentShader:rt.depth_frag},normal:{uniforms:it.merge([tt.common,tt.bumpmap,tt.normalmap,tt.displacementmap,{opacity:{value:1}}]),vertexShader:rt.normal_vert,fragmentShader:rt.normal_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:rt.cube_vert,fragmentShader:rt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rt.equirect_vert,fragmentShader:rt.equirect_frag},distanceRGBA:{uniforms:it.merge([tt.common,tt.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rt.distanceRGBA_vert,fragmentShader:rt.distanceRGBA_frag},shadow:{uniforms:it.merge([tt.lights,tt.fog,{color:{value:new et(0)},opacity:{value:1}}]),vertexShader:rt.shadow_vert,fragmentShader:rt.shadow_frag}};function ot(e,t){this.min=void 0!==e?e:new ie(1/0,1/0),this.max=void 0!==t?t:new ie(-1/0,-1/0)}function at(e,t,i,r,n){var o,a,s,c,h,l,u,p;function d(){var e=new Float32Array([-1,-1,0,0,1,-1,1,0,1,1,1,1,-1,1,0,1]),r=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,r,t.STATIC_DRAW),u=t.createTexture(),p=t.createTexture(),i.bindTexture(t.TEXTURE_2D,u),t.texImage2D(t.TEXTURE_2D,0,t.RGB,16,16,0,t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),i.bindTexture(t.TEXTURE_2D,p),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,16,16,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),s={vertexShader:["uniform lowp int renderType;","uniform vec3 screenPosition;","uniform vec2 scale;","uniform float rotation;","uniform sampler2D occlusionMap;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tvUV = uv;","\tvec2 pos = position;","\tif ( renderType == 2 ) {","\t\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );","\t\tvVisibility = visibility.r / 9.0;","\t\tvVisibility *= 1.0 - visibility.g / 9.0;","\t\tvVisibility *= visibility.b / 9.0;","\t\tvVisibility *= 1.0 - visibility.a / 9.0;","\t\tpos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;","\t\tpos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;","\t}","\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["uniform lowp int renderType;","uniform sampler2D map;","uniform float opacity;","uniform vec3 color;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tif ( renderType == 0 ) {","\t\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );","\t} else if ( renderType == 1 ) {","\t\tgl_FragColor = texture2D( map, vUV );","\t} else {","\t\tvec4 texture = texture2D( map, vUV );","\t\ttexture.a *= opacity * vVisibility;","\t\tgl_FragColor = texture;","\t\tgl_FragColor.rgb *= color;","\t}","}"].join("\n")},c=function(e){var i=t.createProgram(),r=t.createShader(t.FRAGMENT_SHADER),o=t.createShader(t.VERTEX_SHADER),a="precision "+n.precision+" float;\n";return t.shaderSource(r,a+e.fragmentShader),t.shaderSource(o,a+e.vertexShader),t.compileShader(r),t.compileShader(o),t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),i}(s),h={vertex:t.getAttribLocation(c,"position"),uv:t.getAttribLocation(c,"uv")},l={renderType:t.getUniformLocation(c,"renderType"),map:t.getUniformLocation(c,"map"),occlusionMap:t.getUniformLocation(c,"occlusionMap"),opacity:t.getUniformLocation(c,"opacity"),color:t.getUniformLocation(c,"color"),scale:t.getUniformLocation(c,"scale"),rotation:t.getUniformLocation(c,"rotation"),screenPosition:t.getUniformLocation(c,"screenPosition")}}this.render=function(e,n,s,f){if(0!==e.length){var m=new oe,v=f.w/f.z,g=.5*f.z,y=.5*f.w,x=16/f.w,b=new ie(x*v,x),w=new oe(1,1,0),_=new ie(1,1),M=new ot;M.min.set(f.x,f.y),M.max.set(f.x+(f.z-16),f.y+(f.w-16)),void 0===c&&d(),i.useProgram(c),i.initAttributes(),i.enableAttribute(h.vertex),i.enableAttribute(h.uv),i.disableUnusedAttributes(),t.uniform1i(l.occlusionMap,0),t.uniform1i(l.map,1),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(h.vertex,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(h.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),i.disable(t.CULL_FACE),i.buffers.depth.setMask(!1);for(var E=0,T=e.length;E.001&&L.scale>.001&&(w.x=L.x,w.y=L.y,w.z=L.z,x=L.size*L.scale/f.w,b.x=x*v,b.y=x,t.uniform3f(l.screenPosition,w.x,w.y,w.z),t.uniform2f(l.scale,b.x,b.y),t.uniform1f(l.rotation,L.rotation),t.uniform1f(l.opacity,L.opacity),t.uniform3f(l.color,L.color.r,L.color.g,L.color.b),i.setBlending(L.blending,L.blendEquation,L.blendSrc,L.blendDst),r.setTexture2D(L.texture,1),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0))}}}i.enable(t.CULL_FACE),i.enable(t.DEPTH_TEST),i.buffers.depth.setMask(!0),i.reset()}}}function st(e,t,i,r,n,o,a,s,c){ce.call(this,e,t,i,r,n,o,a,s,c),this.needsUpdate=!0}function ct(e,t,i,r,n){var o,a,s,c,h,l,u=new oe,p=new ne,d=new oe;function f(){var e=new Float32Array([-.5,-.5,0,0,.5,-.5,1,0,.5,.5,1,1,-.5,.5,0,1]),i=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s=function(){var e=t.createProgram(),i=t.createShader(t.VERTEX_SHADER),r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float rotation;","uniform vec2 scale;","uniform vec2 uvOffset;","uniform vec2 uvScale;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvUV = uvOffset + uv * uvScale;","\tvec2 alignedPosition = position * scale;","\tvec2 rotatedPosition;","\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;","\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;","\tvec4 mvPosition;","\tmvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );","\tmvPosition.xy += rotatedPosition;","\tgl_Position = projectionMatrix * mvPosition;","\tfogDepth = - mvPosition.z;","}"].join("\n")),t.shaderSource(r,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform vec3 color;","uniform sampler2D map;","uniform float opacity;","uniform int fogType;","uniform vec3 fogColor;","uniform float fogDensity;","uniform float fogNear;","uniform float fogFar;","uniform float alphaTest;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvec4 texture = texture2D( map, vUV );","\tgl_FragColor = vec4( color * texture.xyz, texture.a * opacity );","\tif ( gl_FragColor.a < alphaTest ) discard;","\tif ( fogType > 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),t.compileShader(i),t.compileShader(r),t.attachShader(e,i),t.attachShader(e,r),t.linkProgram(e),e}(),c={position:t.getAttribLocation(s,"position"),uv:t.getAttribLocation(s,"uv")},h={uvOffset:t.getUniformLocation(s,"uvOffset"),uvScale:t.getUniformLocation(s,"uvScale"),rotation:t.getUniformLocation(s,"rotation"),scale:t.getUniformLocation(s,"scale"),color:t.getUniformLocation(s,"color"),map:t.getUniformLocation(s,"map"),opacity:t.getUniformLocation(s,"opacity"),modelViewMatrix:t.getUniformLocation(s,"modelViewMatrix"),projectionMatrix:t.getUniformLocation(s,"projectionMatrix"),fogType:t.getUniformLocation(s,"fogType"),fogDensity:t.getUniformLocation(s,"fogDensity"),fogNear:t.getUniformLocation(s,"fogNear"),fogFar:t.getUniformLocation(s,"fogFar"),fogColor:t.getUniformLocation(s,"fogColor"),fogDepth:t.getUniformLocation(s,"fogDepth"),alphaTest:t.getUniformLocation(s,"alphaTest")};var r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");r.width=8,r.height=8;var u=r.getContext("2d");u.fillStyle="white",u.fillRect(0,0,8,8),l=new st(r)}function m(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(n,v,g){if(0!==n.length){void 0===s&&f(),i.useProgram(s),i.initAttributes(),i.enableAttribute(c.position),i.enableAttribute(c.uv),i.disableUnusedAttributes(),i.disable(t.CULL_FACE),i.enable(t.BLEND),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(c.position,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(c.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.uniformMatrix4fv(h.projectionMatrix,!1,g.projectionMatrix.elements),i.activeTexture(t.TEXTURE0),t.uniform1i(h.map,0);var y=0,x=0,b=v.fog;b?(t.uniform3f(h.fogColor,b.color.r,b.color.g,b.color.b),b.isFog?(t.uniform1f(h.fogNear,b.near),t.uniform1f(h.fogFar,b.far),t.uniform1i(h.fogType,1),y=1,x=1):b.isFogExp2&&(t.uniform1f(h.fogDensity,b.density),t.uniform1i(h.fogType,2),y=2,x=2)):(t.uniform1i(h.fogType,0),y=0,x=0);for(var w=0,_=n.length;w<_;w++){(E=n[w]).modelViewMatrix.multiplyMatrices(g.matrixWorldInverse,E.matrixWorld),E.z=-E.modelViewMatrix.elements[14]}n.sort(m);var M=[];for(w=0,_=n.length;w<_;w++){var E,T=(E=n[w]).material;if(!1!==T.visible){E.onBeforeRender(e,v,g,void 0,T,void 0),t.uniform1f(h.alphaTest,T.alphaTest),t.uniformMatrix4fv(h.modelViewMatrix,!1,E.modelViewMatrix.elements),E.matrixWorld.decompose(u,p,d),M[0]=d.x,M[1]=d.y;var S=0;v.fog&&T.fog&&(S=x),y!==S&&(t.uniform1i(h.fogType,S),y=S),null!==T.map?(t.uniform2f(h.uvOffset,T.map.offset.x,T.map.offset.y),t.uniform2f(h.uvScale,T.map.repeat.x,T.map.repeat.y)):(t.uniform2f(h.uvOffset,0,0),t.uniform2f(h.uvScale,1,1)),t.uniform1f(h.opacity,T.opacity),t.uniform3f(h.color,T.color.r,T.color.g,T.color.b),t.uniform1f(h.rotation,T.rotation),t.uniform2fv(h.scale,M),i.setBlending(T.blending,T.blendEquation,T.blendSrc,T.blendDst,T.blendEquationAlpha,T.blendSrcAlpha,T.blendDstAlpha,T.premultipliedAlpha),i.buffers.depth.setTest(T.depthTest),i.buffers.depth.setMask(T.depthWrite),i.buffers.color.setMask(T.colorWrite),r.setTexture2D(T.map||l,0),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0),E.onAfterRender(e,v,g,void 0,T,void 0)}}i.enable(t.CULL_FACE),i.reset()}}}nt.physical={uniforms:it.merge([nt.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},Object.assign(ot.prototype,{set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y},getParameter:function(e,t){return(t||new ie).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return(t||new ie).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new ie;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),st.prototype=Object.create(ce.prototype),st.prototype.constructor=st;var ht,lt,ut,pt,dt,ft,mt,vt=0;function gt(){Object.defineProperty(this,"id",{value:vt++}),this.uuid=te.generateUUID(),this.name="",this.type="Material",this.fog=!0,this.lights=!0,this.blending=1,this.side=0,this.flatShading=!1,this.vertexColors=0,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=100,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaTest=0,this.premultipliedAlpha=!1,this.overdraw=0,this.visible=!0,this.userData={},this.needsUpdate=!0}function yt(e){gt.call(this),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.setValues(e)}function xt(e){gt.call(this),this.type="MeshDistanceMaterial",this.referencePosition=new oe,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.lights=!1,this.setValues(e)}function bt(e,t){this.min=void 0!==e?e:new oe(1/0,1/0,1/0),this.max=void 0!==t?t:new oe(-1/0,-1/0,-1/0)}function wt(e,t){this.center=void 0!==e?e:new oe,this.radius=void 0!==t?t:0}function _t(e,t){this.normal=void 0!==e?e:new oe(1,0,0),this.constant=void 0!==t?t:0}function Mt(e,t,i,r,n,o){this.planes=[void 0!==e?e:new _t,void 0!==t?t:new _t,void 0!==i?i:new _t,void 0!==r?r:new _t,void 0!==n?n:new _t,void 0!==o?o:new _t]}function Et(e,t,i){for(var r=new Mt,n=new re,o=new ie,a=new ie(i,i),s=new oe,c=new oe,h=new Array(4),l=new Array(4),u={},p=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],d=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)],f=[new he,new he,new he,new he,new he,new he],m=0;4!==m;++m){var v=0!=(1&m),g=0!=(2&m),y=new yt({depthPacking:3201,morphTargets:v,skinning:g});h[m]=y;var x=new xt({morphTargets:v,skinning:g});l[m]=x}var b=this;function w(t,i,r,n,o,a){var s=t.geometry,c=null,p=h,d=t.customDepthMaterial;if(r&&(p=l,d=t.customDistanceMaterial),d)c=d;else{var f=!1;i.morphTargets&&(s&&s.isBufferGeometry?f=s.morphAttributes&&s.morphAttributes.position&&s.morphAttributes.position.length>0:s&&s.isGeometry&&(f=s.morphTargets&&s.morphTargets.length>0)),t.isSkinnedMesh&&!1===i.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t);var m=0;f&&(m|=1),t.isSkinnedMesh&&i.skinning&&(m|=2),c=p[m]}if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var v=c.uuid,g=i.uuid,y=u[v];void 0===y&&(y={},u[v]=y);var x=y[g];void 0===x&&(x=c.clone(),y[g]=x),c=x}c.visible=i.visible,c.wireframe=i.wireframe;var w=i.side;return b.renderSingleSided&&2==w&&(w=0),b.renderReverseSided&&(0===w?w=1:1===w&&(w=0)),c.side=w,c.clipShadows=i.clipShadows,c.clippingPlanes=i.clippingPlanes,c.clipIntersection=i.clipIntersection,c.wireframeLinewidth=i.wireframeLinewidth,c.linewidth=i.linewidth,r&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(n),c.nearDistance=o,c.farDistance=a),c}function _(i,n,o,a){if(!1!==i.visible){if(i.layers.test(n.layers)&&(i.isMesh||i.isLine||i.isPoints)&&i.castShadow&&(!i.frustumCulled||r.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(o.matrixWorldInverse,i.matrixWorld);var s=t.update(i),h=i.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u0&&(i.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(i.morphTargets=!0),!0===this.skinning&&(i.skinning=!0),!1===this.visible&&(i.visible=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),t){var n=r(e.textures),o=r(e.images);n.length>0&&(i.textures=n),o.length>0&&(i.images=o)}return i},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.lights=e.lights,this.blending=e.blending,this.side=e.side,this.flatShading=e.flatShading,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.premultipliedAlpha=e.premultipliedAlpha,this.overdraw=e.overdraw,this.visible=e.visible,this.userData=JSON.parse(JSON.stringify(e.userData)),this.clipShadows=e.clipShadows,this.clipIntersection=e.clipIntersection;var t=e.clippingPlanes,i=null;if(null!==t){var r=t.length;i=new Array(r);for(var n=0;n!==r;++n)i[n]=t[n].clone()}return this.clippingPlanes=i,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),yt.prototype=Object.create(gt.prototype),yt.prototype.constructor=yt,yt.prototype.isMeshDepthMaterial=!0,yt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.depthPacking=e.depthPacking,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this},xt.prototype=Object.create(gt.prototype),xt.prototype.constructor=xt,xt.prototype.isMeshDistanceMaterial=!0,xt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.referencePosition.copy(e.referencePosition),this.nearDistance=e.nearDistance,this.farDistance=e.farDistance,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this},Object.assign(bt.prototype,{isBox3:!0,set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromArray:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.length;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromBufferAttribute:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.count;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return(t||new oe).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:(lt=new oe,function(e){return this.clampPoint(e.center,lt),lt.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=e.constant&&i>=e.constant},clampPoint:function(e,t){return(t||new oe).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new oe;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),getBoundingSphere:function(){var e=new oe;return function(t){var i=t||new wt;return this.getCenter(i.center),i.radius=.5*this.getSize(e).length(),i}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:(ht=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],function(e){return this.isEmpty()||(ht[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),ht[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),ht[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),ht[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),ht[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),ht[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),ht[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),ht[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(ht)),this}),translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),Object.assign(wt.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(ut=new bt,function(e,t){var i=this.center;void 0!==t?i.copy(t):ut.setFromPoints(e).getCenter(i);for(var r=0,n=0,o=e.length;nthis.radius*this.radius&&(r.sub(this.center).normalize(),r.multiplyScalar(this.radius).add(this.center)),r},getBoundingBox:function(e){var t=e||new bt;return t.set(this.center,this.center),t.expandByScalar(this.radius),t},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}}),Object.assign(_t.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(){var e=new oe,t=new oe;return function(i,r,n){var o=e.subVectors(n,r).cross(t.subVectors(i,r)).normalize();return this.setFromNormalAndCoplanarPoint(o,i),this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return(t||new oe).copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(){var e=new oe;return function(t,i){var r=i||new oe,n=t.delta(e),o=this.normal.dot(n);if(0===o)return 0===this.distanceToPoint(t.start)?r.copy(t.start):void 0;var a=-(t.start.dot(this.normal)+this.constant)/o;return a<0||a>1?void 0:r.copy(n).multiplyScalar(a).add(t.start)}}(),intersectsLine:function(e){var t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return(e||new oe).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var e=new oe,t=new ae;return function(i,r){var n=r||t.getNormalMatrix(i),o=this.coplanarPoint(e).applyMatrix4(i),a=this.normal.applyMatrix3(n).normalize();return this.constant=-o.dot(a),this}}(),translate:function(e){return this.constant-=e.dot(this.normal),this},equals:function(e){return e.normal.equals(this.normal)&&e.constant===this.constant}}),Object.assign(Mt.prototype,{set:function(e,t,i,r,n,o){var a=this.planes;return a[0].copy(e),a[1].copy(t),a[2].copy(i),a[3].copy(r),a[4].copy(n),a[5].copy(o),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,i=0;i<6;i++)t[i].copy(e.planes[i]);return this},setFromMatrix:function(e){var t=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],s=i[4],c=i[5],h=i[6],l=i[7],u=i[8],p=i[9],d=i[10],f=i[11],m=i[12],v=i[13],g=i[14],y=i[15];return t[0].setComponents(a-r,l-s,f-u,y-m).normalize(),t[1].setComponents(a+r,l+s,f+u,y+m).normalize(),t[2].setComponents(a+n,l+c,f+p,y+v).normalize(),t[3].setComponents(a-n,l-c,f-p,y-v).normalize(),t[4].setComponents(a-o,l-h,f-d,y-g).normalize(),t[5].setComponents(a+o,l+h,f+d,y+g).normalize(),this},intersectsObject:(ft=new wt,function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),ft.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(ft)}),intersectsSprite:function(){var e=new wt;return function(t){return e.center.set(0,0,0),e.radius=.7071067811865476,e.applyMatrix4(t.matrixWorld),this.intersectsSphere(e)}}(),intersectsSphere:function(e){for(var t=this.planes,i=e.center,r=-e.radius,n=0;n<6;n++){if(t[n].distanceToPoint(i)0?e.min.x:e.max.x,dt.x=r.normal.x>0?e.max.x:e.min.x,pt.y=r.normal.y>0?e.min.y:e.max.y,dt.y=r.normal.y>0?e.max.y:e.min.y,pt.z=r.normal.z>0?e.min.z:e.max.z,dt.z=r.normal.z>0?e.max.z:e.min.z;var n=r.distanceToPoint(pt),o=r.distanceToPoint(dt);if(n<0&&o<0)return!1}return!0}),containsPoint:function(e){for(var t=this.planes,i=0;i<6;i++)if(t[i].distanceToPoint(e)<0)return!1;return!0}}),St.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],St.DefaultOrder="XYZ",Object.defineProperties(St.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},order:{get:function(){return this._order},set:function(e){this._order=e,this.onChangeCallback()}}}),Object.assign(St.prototype,{isEuler:!0,set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._order=r||this._order,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)},copy:function(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this.onChangeCallback(),this},setFromRotationMatrix:function(e,t,i){var r=te.clamp,n=e.elements,o=n[0],a=n[4],s=n[8],c=n[1],h=n[5],l=n[9],u=n[2],p=n[6],d=n[10];return"XYZ"===(t=t||this._order)?(this._y=Math.asin(r(s,-1,1)),Math.abs(s)<.99999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-a,o)):(this._x=Math.atan2(p,h),this._z=0)):"YXZ"===t?(this._x=Math.asin(-r(l,-1,1)),Math.abs(l)<.99999?(this._y=Math.atan2(s,d),this._z=Math.atan2(c,h)):(this._y=Math.atan2(-u,o),this._z=0)):"ZXY"===t?(this._x=Math.asin(r(p,-1,1)),Math.abs(p)<.99999?(this._y=Math.atan2(-u,d),this._z=Math.atan2(-a,h)):(this._y=0,this._z=Math.atan2(c,o))):"ZYX"===t?(this._y=Math.asin(-r(u,-1,1)),Math.abs(u)<.99999?(this._x=Math.atan2(p,d),this._z=Math.atan2(c,o)):(this._x=0,this._z=Math.atan2(-a,h))):"YZX"===t?(this._z=Math.asin(r(c,-1,1)),Math.abs(c)<.99999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-u,o)):(this._x=0,this._y=Math.atan2(s,d))):"XZY"===t?(this._z=Math.asin(-r(a,-1,1)),Math.abs(a)<.99999?(this._x=Math.atan2(p,h),this._y=Math.atan2(s,o)):(this._x=Math.atan2(-l,d),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+t),this._order=t,!1!==i&&this.onChangeCallback(),this},setFromQuaternion:function(){var e=new re;return function(t,i,r){return e.makeRotationFromQuaternion(t),this.setFromRotationMatrix(e,i,r)}}(),setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:(mt=new ne,function(e){return mt.setFromEuler(this),this.setFromQuaternion(mt,e)}),equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order},fromArray:function(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e},toVector3:function(e){return e?e.set(this._x,this._y,this._z):new oe(this._x,this._y,this._z)},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(At.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){r.children=[];for(s=0;s0&&(i.geometries=u),p.length>0&&(i.materials=p),d.length>0&&(i.textures=d),f.length>0&&(i.images=f),a.length>0&&(i.shapes=a)}return i.object=r,i;function m(e){var t=[];for(var i in e){var r=e[i];delete r.metadata,t.push(r)}return t}},clone:function(e){return(new this.constructor).copy(this,e)},copy:function(e,t){if(void 0===t&&(t=!0),this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(var i=0;it&&(t=e[i]);return t}zt.prototype=Object.assign(Object.create(n.prototype),{constructor:zt,isGeometry:!0,applyMatrix:function(e){for(var t=(new ae).getNormalMatrix(e),i=0,r=this.vertices.length;i0)for(p=0;p0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,i;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,i,r,n;for(i=0,r=this.faces.length;i0&&(e+=t[i].distanceTo(t[i-1])),this.lineDistances[i]=e},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt),this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new wt),this.boundingSphere.setFromPoints(this.vertices)},merge:function(e,t,i){if(e&&e.isGeometry){var r,n=this.vertices.length,o=this.vertices,a=e.vertices,s=this.faces,c=e.faces,h=this.faceVertexUvs[0],l=e.faceVertexUvs[0],u=this.colors,p=e.colors;void 0===i&&(i=0),void 0!==t&&(r=(new ae).getNormalMatrix(t));for(var d=0,f=a.length;d=0;i--){var f=p[i];for(this.faces.splice(f,1),a=0,s=this.faceVertexUvs.length;a0,v=d.vertexNormals.length>0,g=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,v),x=M(x,6,g),x=M(x,7,y),a.push(x),a.push(d.a,d.b,d.c),a.push(d.materialIndex),f){var b=this.faceVertexUvs[0][n];a.push(S(b[0]),S(b[1]),S(b[2]))}if(m&&a.push(E(d.normal)),v){var w=d.vertexNormals;a.push(E(w[0]),E(w[1]),E(w[2]))}if(g&&a.push(T(d.color)),y){var _=d.vertexColors;a.push(T(_[0]),T(_[1]),T(_[2]))}}function M(e,t,i){return i?e|1<0&&(e.data.colors=h),u.length>0&&(e.data.uvs=[u]),e.data.faces=a,e},clone:function(){return(new zt).copy(this)},copy:function(e){var t,i,r,n,o,a;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var s=e.vertices;for(t=0,i=s.length;t0,a=n[1]&&n[1].length>0,s=e.morphTargets,c=s.length;if(c>0){t=[];for(var h=0;h0){l=[];for(h=0;h0?1:-1,h.push(L.x,L.y,L.z),l.push(y/m),l.push(1-x/v),A+=1}}for(x=0;x1&&i.sort(yi),r.length>1&&r.sort(xi)}}}function wi(){var e={};return{get:function(t,i){var r=t.id+","+i.id,n=e[r];return void 0===n&&(n=new bi,e[r]=n),n},dispose:function(){e={}}}}function _i(e,t){return Math.abs(t[1])-Math.abs(e[1])}function Mi(e){var t={},i=new Float32Array(8);return{update:function(r,n,o,a){var s=r.morphTargetInfluences,c=s.length,h=t[n.id];if(void 0===h){h=[];for(var l=0;l65535?qt:Wt)(a,1),t.update(r,e.ELEMENT_ARRAY_BUFFER),n[i.id]=r,r}}}function Ai(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var i;switch(t.type){case"DirectionalLight":i={direction:new oe,color:new et,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"SpotLight":i={position:new oe,direction:new oe,color:new et,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"PointLight":i={position:new oe,color:new et,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":i={direction:new oe,skyColor:new et,groundColor:new et};break;case"RectAreaLight":i={color:new et,position:new oe,halfWidth:new oe,halfHeight:new oe}}return e[t.id]=i,i}}}function Ri(){var e=new Ai,t={hash:"",ambient:[0,0,0],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},i=new oe,r=new re,n=new re;return{setup:function(o,a,s){for(var c=0,h=0,l=0,u=0,p=0,d=0,f=0,m=0,v=s.matrixWorldInverse,g=0,y=o.length;g65535?qt:Wt)(e,1):this.index=e},addAttribute:function(e,t){return t&&t.isBufferAttribute||t&&t.isInterleavedBufferAttribute?"index"===e?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),void this.setIndex(t)):(this.attributes[e]=t,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),void this.addAttribute(e,new kt(arguments[1],arguments[2])))},getAttribute:function(e){return this.attributes[e]},removeAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,i){this.groups.push({start:e,count:t,materialIndex:void 0!==i?i:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix:function(e){var t=this.attributes.position;void 0!==t&&(e.applyToBufferAttribute(t),t.needsUpdate=!0);var i=this.attributes.normal;void 0!==i&&((new ae).getNormalMatrix(e).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var e=new re;return function(t){return e.makeRotationX(t),this.applyMatrix(e),this}}(),rotateY:function(){var e=new re;return function(t){return e.makeRotationY(t),this.applyMatrix(e),this}}(),rotateZ:function(){var e=new re;return function(t){return e.makeRotationZ(t),this.applyMatrix(e),this}}(),translate:function(){var e=new re;return function(t,i,r){return e.makeTranslation(t,i,r),this.applyMatrix(e),this}}(),scale:function(){var e=new re;return function(t,i,r){return e.makeScale(t,i,r),this.applyMatrix(e),this}}(),lookAt:function(){var e=new Ot;return function(t){e.lookAt(t),e.updateMatrix(),this.applyMatrix(e.matrix)}}(),center:function(){this.computeBoundingBox();var e=this.boundingBox.getCenter().negate();return this.translate(e.x,e.y,e.z),e},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var i=new Yt(3*t.vertices.length,3),r=new Yt(3*t.colors.length,3);if(this.addAttribute("position",i.copyVector3sArray(t.vertices)),this.addAttribute("color",r.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var n=new Yt(t.lineDistances.length,1);this.addAttribute("lineDistance",n.copyArray(t.lineDistances))}null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone())}else e.isMesh&&t&&t.isGeometry&&this.fromGeometry(t);return this},setFromPoints:function(e){for(var t=[],i=0,r=e.length;i0){var i=new Float32Array(3*e.normals.length);this.addAttribute("normal",new kt(i,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var r=new Float32Array(3*e.colors.length);this.addAttribute("color",new kt(r,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var n=new Float32Array(2*e.uvs.length);this.addAttribute("uv",new kt(n,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var o=new Float32Array(2*e.uvs2.length);this.addAttribute("uv2",new kt(o,2).copyVector2sArray(e.uvs2))}if(e.indices.length>0){var a=new(Kt(e.indices)>65535?Uint32Array:Uint16Array)(3*e.indices.length);this.setIndex(new kt(a,1).copyIndicesArray(e.indices))}for(var s in this.groups=e.groups,e.morphTargets){for(var c=[],h=e.morphTargets[s],l=0,u=h.length;l0){var f=new Yt(4*e.skinIndices.length,4);this.addAttribute("skinIndex",f.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var m=new Yt(4*e.skinWeights.length,4);this.addAttribute("skinWeight",m.copyVector4sArray(e.skinWeights))}return null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone()),this},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt);var e=this.attributes.position;void 0!==e?this.boundingBox.setFromBufferAttribute(e):this.boundingBox.makeEmpty(),(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:function(){var e=new bt,t=new oe;return function(){null===this.boundingSphere&&(this.boundingSphere=new wt);var i=this.attributes.position;if(i){var r=this.boundingSphere.center;e.setFromBufferAttribute(i),e.getCenter(r);for(var n=0,o=0,a=i.count;o0&&(e.data.groups=JSON.parse(JSON.stringify(s)));var c=this.boundingSphere;return null!==c&&(e.data.boundingSphere={center:c.center.toArray(),radius:c.radius}),e},clone:function(){return(new ai).copy(this)},copy:function(e){var t,i,r;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var n=e.index;null!==n&&this.setIndex(n.clone());var o=e.attributes;for(t in o){var a=o[t];this.addAttribute(t,a.clone())}var s=e.morphAttributes;for(t in s){var c=[],h=s[t];for(i=0,r=h.length;i0)if(o=h*l-u,s=c*d,(n=h*u-l)>=0)if(o>=-s)if(o<=s){var f=1/d;a=(n*=f)*(n+h*(o*=f)+2*l)+o*(h*n+o+2*u)+p}else o=c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o=-c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o<=-s?a=-(n=Math.max(0,-(-h*c+l)))*n+(o=n>0?-c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p:o<=s?(n=0,a=(o=Math.min(Math.max(-c,-u),c))*(o+2*u)+p):a=-(n=Math.max(0,-(h*c+l)))*n+(o=n>0?c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p;else o=h>0?-c:c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;return i&&i.copy(this.direction).multiplyScalar(n).add(this.origin),r&&r.copy(ei).multiplyScalar(o).add($t),a}),intersectSphere:function(){var e=new oe;return function(t,i){e.subVectors(t.center,this.origin);var r=e.dot(this.direction),n=e.dot(e)-r*r,o=t.radius*t.radius;if(n>o)return null;var a=Math.sqrt(o-n),s=r-a,c=r+a;return s<0&&c<0?null:s<0?this.at(c,i):this.at(s,i)}}(),intersectsSphere:function(e){return this.distanceToPoint(e.center)<=e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null},intersectPlane:function(e,t){var i=this.distanceToPlane(e);return null===i?null:this.at(i,t)},intersectsPlane:function(e){var t=e.distanceToPoint(this.origin);return 0===t||e.normal.dot(this.direction)*t<0},intersectBox:function(e,t){var i,r,n,o,a,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(i=(e.min.x-u.x)*c,r=(e.max.x-u.x)*c):(i=(e.max.x-u.x)*c,r=(e.min.x-u.x)*c),h>=0?(n=(e.min.y-u.y)*h,o=(e.max.y-u.y)*h):(n=(e.max.y-u.y)*h,o=(e.min.y-u.y)*h),i>o||n>r?null:((n>i||i!=i)&&(i=n),(o=0?(a=(e.min.z-u.z)*l,s=(e.max.z-u.z)*l):(a=(e.max.z-u.z)*l,s=(e.min.z-u.z)*l),i>s||a>r?null:((a>i||i!=i)&&(i=a),(s=0?i:r,t)))},intersectsBox:(Qt=new oe,function(e){return null!==this.intersectBox(e,Qt)}),intersectTriangle:function(){var e=new oe,t=new oe,i=new oe,r=new oe;return function(n,o,a,s,c){t.subVectors(o,n),i.subVectors(a,n),r.crossVectors(t,i);var h,l=this.direction.dot(r);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}e.subVectors(this.origin,n);var u=h*this.direction.dot(i.crossVectors(e,i));if(u<0)return null;var p=h*this.direction.dot(t.cross(e));if(p<0)return null;if(u+p>l)return null;var d=-h*e.dot(r);return d<0?null:this.at(d/l,c)}}(),applyMatrix4:function(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this},equals:function(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}}),Object.assign(fi.prototype,{set:function(e,t){return this.start.copy(e),this.end.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.start.copy(e.start),this.end.copy(e.end),this},getCenter:function(e){return(e||new oe).addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(e){return(e||new oe).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(e,t){var i=t||new oe;return this.delta(i).multiplyScalar(e).add(this.start)},closestPointToPointParameter:(ii=new oe,ri=new oe,function(e,t){ii.subVectors(e,this.start),ri.subVectors(this.end,this.start);var i=ri.dot(ri),r=ri.dot(ii)/i;return t&&(r=te.clamp(r,0,1)),r}),closestPointToPoint:function(e,t,i){var r=this.closestPointToPointParameter(e,t),n=i||new oe;return this.delta(n).multiplyScalar(r).add(this.start)},applyMatrix4:function(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this},equals:function(e){return e.start.equals(this.start)&&e.end.equals(this.end)}}),Object.assign(mi,{normal:(ni=new oe,function(e,t,i,r){var n=r||new oe;n.subVectors(i,t),ni.subVectors(e,t),n.cross(ni);var o=n.lengthSq();return o>0?n.multiplyScalar(1/Math.sqrt(o)):n.set(0,0,0)}),barycoordFromPoint:function(){var e=new oe,t=new oe,i=new oe;return function(r,n,o,a,s){e.subVectors(a,n),t.subVectors(o,n),i.subVectors(r,n);var c=e.dot(e),h=e.dot(t),l=e.dot(i),u=t.dot(t),p=t.dot(i),d=c*u-h*h,f=s||new oe;if(0===d)return f.set(-2,-1,-1);var m=1/d,v=(u*l-h*p)*m,g=(c*p-h*l)*m;return f.set(1-v-g,g,v)}}(),containsPoint:function(){var e=new oe;return function(t,i,r,n){var o=mi.barycoordFromPoint(t,i,r,n,e);return o.x>=0&&o.y>=0&&o.x+o.y<=1}}()}),Object.assign(mi.prototype,{set:function(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this},setFromPointsAndIndices:function(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this},area:function(){var e=new oe,t=new oe;return function(){return e.subVectors(this.c,this.b),t.subVectors(this.a,this.b),.5*e.cross(t).length()}}(),midpoint:function(e){return(e||new oe).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(e){return mi.normal(this.a,this.b,this.c,e)},plane:function(e){return(e||new _t).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(e,t){return mi.barycoordFromPoint(e,this.a,this.b,this.c,t)},containsPoint:function(e){return mi.containsPoint(e,this.a,this.b,this.c)},closestPointToPoint:function(){var e=new _t,t=[new fi,new fi,new fi],i=new oe,r=new oe;return function(n,o){var a=o||new oe,s=1/0;if(e.setFromCoplanarPoints(this.a,this.b,this.c),e.projectPoint(n,i),!0===this.containsPoint(i))a.copy(i);else{t[0].set(this.a,this.b),t[1].set(this.b,this.c),t[2].set(this.c,this.a);for(var c=0;c0){var a=n[o[0]];if(void 0!==a)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=a.length;e0)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=s.length;ei.far?null:{distance:c,point:f.clone(),object:e}}function g(e,t,i,a,s,c,p,f){r.fromBufferAttribute(a,c),n.fromBufferAttribute(a,p),o.fromBufferAttribute(a,f);var g=v(e,e.material,t,i,r,n,o,d);return g&&(s&&(h.fromBufferAttribute(s,c),l.fromBufferAttribute(s,p),u.fromBufferAttribute(s,f),g.uv=m(d,r,n,o,h,l,u)),g.face=new Ut(c,p,f,mi.normal(r,n,o)),g.faceIndex=c),g}return function(p,f){var y,x=this.geometry,b=this.material,w=this.matrixWorld;if(void 0!==b&&(null===x.boundingSphere&&x.computeBoundingSphere(),i.copy(x.boundingSphere),i.applyMatrix4(w),!1!==p.ray.intersectsSphere(i)&&(e.getInverse(w),t.copy(p.ray).applyMatrix4(e),null===x.boundingBox||!1!==t.intersectsBox(x.boundingBox))))if(x.isBufferGeometry){var _,M,E,T,S,A=x.index,R=x.attributes.position,L=x.attributes.uv;if(null!==A)for(T=0,S=A.count;T0&&(O=B);for(var F=0,z=U.length;F/gm,(function(e,t){var i=rt[t];if(void 0===i)throw new Error("Can not resolve #include <"+t+">");return ji(i)}))}function Hi(e){return e.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,(function(e,t,i,r){for(var n="",o=parseInt(t);o0?e.gammaFactor:1,T=function(e,t,i){return[(e=e||{}).derivatives||t.envMapCubeUV||t.bumpMap||t.normalMap||t.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(e.fragDepth||t.logarithmicDepthBuffer)&&i.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",e.drawBuffers&&i.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(e.shaderTextureLOD||t.envMap)&&i.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Gi).join("\n")}(r.extensions,o,t),S=function(e){var t=[];for(var i in e){var r=e[i];!1!==r&&t.push("#define "+i+" "+r)}return t.join("\n")}(s),A=a.createProgram();r.isRawShaderMaterial?((f=[S].filter(Gi).join("\n")).length>0&&(f+="\n"),(b=[T,S].filter(Gi).join("\n")).length>0&&(b+="\n")):(f=["precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+E,"#define MAX_BONES "+o.maxBones,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+p:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.displacementMap&&o.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.flatShading?"#define FLAT_SHADED":"",o.skinning?"#define USE_SKINNING":"",o.useVertexTexture?"#define BONE_TEXTURE":"",o.morphTargets?"#define USE_MORPHTARGETS":"",o.morphNormals&&!1===o.flatShading?"#define USE_MORPHNORMALS":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.sizeAttenuation?"#define USE_SIZEATTENUATION":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Gi).join("\n"),b=[T,"precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.alphaTest?"#define ALPHATEST "+o.alphaTest:"","#define GAMMA_FACTOR "+E,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+u:"",o.envMap?"#define "+p:"",o.envMap?"#define "+d:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.gradientMap?"#define USE_GRADIENTMAP":"",o.flatShading?"#define FLAT_SHADED":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,"#define UNION_CLIPPING_PLANES "+(o.numClippingPlanes-o.numClipIntersection),o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",o.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"",o.envMap&&t.get("EXT_shader_texture_lod")?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",0!==o.toneMapping?"#define TONE_MAPPING":"",0!==o.toneMapping?rt.tonemapping_pars_fragment:"",0!==o.toneMapping?ki("toneMapping",o.toneMapping):"",o.dithering?"#define DITHERING":"",o.outputEncoding||o.mapEncoding||o.envMapEncoding||o.emissiveMapEncoding?rt.encodings_pars_fragment:"",o.mapEncoding?zi("mapTexelToLinear",o.mapEncoding):"",o.envMapEncoding?zi("envMapTexelToLinear",o.envMapEncoding):"",o.emissiveMapEncoding?zi("emissiveMapTexelToLinear",o.emissiveMapEncoding):"",o.outputEncoding?(w="linearToOutputTexel",_=o.outputEncoding,M=Fi(_),"vec4 "+w+"( vec4 value ) { return LinearTo"+M[0]+M[1]+"; }"):"",o.depthPacking?"#define DEPTH_PACKING "+r.depthPacking:"","\n"].filter(Gi).join("\n")),c=Vi(c=ji(c),o),h=Vi(h=ji(h),o),r.isShaderMaterial||(c=Hi(c),h=Hi(h));var R=f+c,L=b+h,C=Ci(a,a.VERTEX_SHADER,R),P=Ci(a,a.FRAGMENT_SHADER,L);a.attachShader(A,C),a.attachShader(A,P),void 0!==r.index0AttributeName?a.bindAttribLocation(A,0,r.index0AttributeName):!0===o.morphTargets&&a.bindAttribLocation(A,0,"position"),a.linkProgram(A);var N,O,I=a.getProgramInfoLog(A),D=a.getShaderInfoLog(C),U=a.getShaderInfoLog(P),B=!0,F=!0;return!1===a.getProgramParameter(A,a.LINK_STATUS)?(B=!1,console.error("THREE.WebGLProgram: shader error: ",a.getError(),"gl.VALIDATE_STATUS",a.getProgramParameter(A,a.VALIDATE_STATUS),"gl.getProgramInfoLog",I,D,U)):""!==I?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",I):""!==D&&""!==U||(F=!1),F&&(this.diagnostics={runnable:B,material:r,programLog:I,vertexShader:{log:D,prefix:f},fragmentShader:{log:U,prefix:b}}),a.deleteShader(C),a.deleteShader(P),this.getUniforms=function(){return void 0===N&&(N=new Qe(a,A,e)),N},this.getAttributes=function(){return void 0===O&&(O=function(e,t){for(var i={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;n0,maxBones:p,useVertexTexture:i.floatVertexTextures,morphTargets:t.morphTargets,morphNormals:t.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:r.directional.length,numPointLights:r.point.length,numSpotLights:r.spot.length,numRectAreaLights:r.rectArea.length,numHemiLights:r.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:t.dithering,shadowMapEnabled:e.shadowMap.enabled&&l.receiveShadow&&o.length>0,shadowMapType:e.shadowMap.type,toneMapping:e.toneMapping,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:t.premultipliedAlpha,alphaTest:t.alphaTest,doubleSided:2===t.side,flipSided:1===t.side,depthPacking:void 0!==t.depthPacking&&t.depthPacking}},this.getProgramCode=function(t,i){var r=[];if(i.shaderID?r.push(i.shaderID):(r.push(t.fragmentShader),r.push(t.vertexShader)),void 0!==t.defines)for(var n in t.defines)r.push(n),r.push(t.defines[n]);for(var a=0;at||e.height>t){var i=t/Math.max(e.width,e.height),r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return r.width=Math.floor(e.width*i),r.height=Math.floor(e.height*i),r.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,r.width,r.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+r.width+"x"+r.height,e),r}return e}function l(e){return te.isPowerOfTwo(e.width)&&te.isPowerOfTwo(e.height)}function u(e,t){return e.generateMipmaps&&t&&e.minFilter!==M&&e.minFilter!==S}function p(t){return t===M||t===E||t===T?e.NEAREST:e.LINEAR}function d(t){var i=t.target;i.removeEventListener("dispose",d),function(t){var i=r.get(t);if(t.image&&i.__image__webglTextureCube)e.deleteTexture(i.__image__webglTextureCube);else{if(void 0===i.__webglInit)return;e.deleteTexture(i.__webglTexture)}r.remove(t)}(i),i.isVideoTexture&&delete c[i.id],a.textures--}function f(t){var i=t.target;i.removeEventListener("dispose",f),function(t){var i=r.get(t),n=r.get(t.texture);if(!t)return;void 0!==n.__webglTexture&&e.deleteTexture(n.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLRenderTargetCube)for(var o=0;o<6;o++)e.deleteFramebuffer(i.__webglFramebuffer[o]),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer[o]);else e.deleteFramebuffer(i.__webglFramebuffer),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer);r.remove(t.texture),r.remove(t)}(i),a.textures--}function m(t,p){var f=r.get(t);if(t.version>0&&f.__version!==t.version){var m=t.image;if(void 0===m)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined",t);else{if(!1!==m.complete)return void function(t,r,p){void 0===t.__webglInit&&(t.__webglInit=!0,r.addEventListener("dispose",d),t.__webglTexture=e.createTexture(),r.isVideoTexture&&(c[r.id]=r),a.textures++);i.activeTexture(e.TEXTURE0+p),i.bindTexture(e.TEXTURE_2D,t.__webglTexture),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,r.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,r.unpackAlignment);var f=h(r.image,n.maxTextureSize);(function(e){return e.wrapS!==w||e.wrapT!==w||e.minFilter!==M&&e.minFilter!==S})(r)&&!1===l(f)&&(f=function(e){if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement||e instanceof ImageBitmap){var t=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return t.width=te.floorPowerOfTwo(e.width),t.height=te.floorPowerOfTwo(e.height),t.getContext("2d").drawImage(e,0,0,t.width,t.height),console.warn("THREE.WebGLRenderer: image is not power of two ("+e.width+"x"+e.height+"). Resized to "+t.width+"x"+t.height,e),t}return e}(f));var m=l(f),g=o.convert(r.format),y=o.convert(r.type);v(e.TEXTURE_2D,r,m);var x,b=r.mipmaps;if(r.isDepthTexture){var _=e.DEPTH_COMPONENT;if(r.type===N){if(!s)throw new Error("Float Depth Texture only supported in WebGL2.0");_=e.DEPTH_COMPONENT32F}else s&&(_=e.DEPTH_COMPONENT16);r.format===B&&_===e.DEPTH_COMPONENT&&r.type!==C&&r.type!==P&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=C,y=o.convert(r.type)),r.format===F&&(_=e.DEPTH_STENCIL,r.type!==I&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=I,y=o.convert(r.type))),i.texImage2D(e.TEXTURE_2D,0,_,f.width,f.height,0,g,y,null)}else if(r.isDataTexture)if(b.length>0&&m){for(var E=0,T=b.length;E-1?i.compressedTexImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):i.texImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,g,y,x.data);else if(b.length>0&&m){for(E=0,T=b.length;E1||r.get(a).__currentAnisotropy)&&(e.texParameterf(i,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,n.getMaxAnisotropy())),r.get(a).__currentAnisotropy=a.anisotropy)}}function g(t,n,a,s){var c=o.convert(n.texture.format),h=o.convert(n.texture.type);i.texImage2D(s,0,c,n.width,n.height,0,c,h,null),e.bindFramebuffer(e.FRAMEBUFFER,t),e.framebufferTexture2D(e.FRAMEBUFFER,a,s,r.get(n.texture).__webglTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}function y(t,i){e.bindRenderbuffer(e.RENDERBUFFER,t),i.depthBuffer&&!i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t)):i.depthBuffer&&i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t)):e.renderbufferStorage(e.RENDERBUFFER,e.RGBA4,i.width,i.height),e.bindRenderbuffer(e.RENDERBUFFER,null)}function x(t){var i=r.get(t),n=!0===t.isWebGLRenderTargetCube;if(t.depthTexture){if(n)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,i){if(i&&i.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(e.bindFramebuffer(e.FRAMEBUFFER,t),!i.depthTexture||!i.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");r.get(i.depthTexture).__webglTexture&&i.depthTexture.image.width===i.width&&i.depthTexture.image.height===i.height||(i.depthTexture.image.width=i.width,i.depthTexture.image.height=i.height,i.depthTexture.needsUpdate=!0),m(i.depthTexture,0);var n=r.get(i.depthTexture).__webglTexture;if(i.depthTexture.format===B)e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,n,0);else{if(i.depthTexture.format!==F)throw new Error("Unknown depthTexture format");e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,n,0)}}(i.__webglFramebuffer,t)}else if(n){i.__webglDepthbuffer=[];for(var o=0;o<6;o++)e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[o]),i.__webglDepthbuffer[o]=e.createRenderbuffer(),y(i.__webglDepthbuffer[o],t)}else e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer=e.createRenderbuffer(),y(i.__webglDepthbuffer,t);e.bindFramebuffer(e.FRAMEBUFFER,null)}this.setTexture2D=m,this.setTextureCube=function(t,s){var c=r.get(t);if(6===t.image.length)if(t.version>0&&c.__version!==t.version){c.__image__webglTextureCube||(t.addEventListener("dispose",d),c.__image__webglTextureCube=e.createTexture(),a.textures++),i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,t.flipY);for(var p=t&&t.isCompressedTexture,f=t.image[0]&&t.image[0].isDataTexture,m=[],g=0;g<6;g++)m[g]=p||f?f?t.image[g].image:t.image[g]:h(t.image[g],n.maxCubemapSize);var y=l(m[0]),x=o.convert(t.format),b=o.convert(t.type);v(e.TEXTURE_CUBE_MAP,t,y);for(g=0;g<6;g++)if(p)for(var w,_=m[g].mipmaps,M=0,E=_.length;M-1?i.compressedTexImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,w.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,x,b,w.data);else f?i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,m[g].width,m[g].height,0,x,b,m[g].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,x,b,m[g]);u(t,y)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),c.__version=t.version,t.onUpdate&&t.onUpdate(t)}else i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube)},this.setTextureCubeDynamic=function(t,n){i.activeTexture(e.TEXTURE0+n),i.bindTexture(e.TEXTURE_CUBE_MAP,r.get(t).__webglTexture)},this.setupRenderTarget=function(t){var n=r.get(t),o=r.get(t.texture);t.addEventListener("dispose",f),o.__webglTexture=e.createTexture(),a.textures++;var s=!0===t.isWebGLRenderTargetCube,c=l(t);if(s){n.__webglFramebuffer=[];for(var h=0;h<6;h++)n.__webglFramebuffer[h]=e.createFramebuffer()}else n.__webglFramebuffer=e.createFramebuffer();if(s){i.bindTexture(e.TEXTURE_CUBE_MAP,o.__webglTexture),v(e.TEXTURE_CUBE_MAP,t.texture,c);for(h=0;h<6;h++)g(n.__webglFramebuffer[h],t,e.COLOR_ATTACHMENT0,e.TEXTURE_CUBE_MAP_POSITIVE_X+h);u(t.texture,c)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),i.bindTexture(e.TEXTURE_CUBE_MAP,null)}else i.bindTexture(e.TEXTURE_2D,o.__webglTexture),v(e.TEXTURE_2D,t.texture,c),g(n.__webglFramebuffer,t,e.COLOR_ATTACHMENT0,e.TEXTURE_2D),u(t.texture,c)&&e.generateMipmap(e.TEXTURE_2D),i.bindTexture(e.TEXTURE_2D,null);t.depthBuffer&&x(t)},this.updateRenderTargetMipmap=function(t){var n=t.texture;if(u(n,l(t))){var o=t.isWebGLRenderTargetCube?e.TEXTURE_CUBE_MAP:e.TEXTURE_2D,a=r.get(n).__webglTexture;i.bindTexture(o,a),e.generateMipmap(o),i.bindTexture(o,null)}},this.updateVideoTextures=function(){for(var e in c)c[e].update()}}function Yi(){var e={};return{get:function(t){var i=t.uuid,r=e[i];return void 0===r&&(r={},e[i]=r),r},remove:function(t){delete e[t.uuid]},clear:function(){e={}}}}function Zi(e,t,i){var r=new function(){var t=!1,i=new he,r=null,n=new he(0,0,0,0);return{setMask:function(i){r===i||t||(e.colorMask(i,i,i,i),r=i)},setLocked:function(e){t=e},setClear:function(t,r,o,a,s){!0===s&&(t*=a,r*=a,o*=a),i.set(t,r,o,a),!1===n.equals(i)&&(e.clearColor(t,r,o,a),n.copy(i))},reset:function(){t=!1,r=null,n.set(-1,0,0,0)}}},n=new function(){var t=!1,i=null,r=null,n=null;return{setTest:function(t){t?D(e.DEPTH_TEST):U(e.DEPTH_TEST)},setMask:function(r){i===r||t||(e.depthMask(r),i=r)},setFunc:function(t){if(r!==t){if(t)switch(t){case 0:e.depthFunc(e.NEVER);break;case 1:e.depthFunc(e.ALWAYS);break;case 2:e.depthFunc(e.LESS);break;case 3:default:e.depthFunc(e.LEQUAL);break;case 4:e.depthFunc(e.EQUAL);break;case 5:e.depthFunc(e.GEQUAL);break;case 6:e.depthFunc(e.GREATER);break;case 7:e.depthFunc(e.NOTEQUAL)}else e.depthFunc(e.LEQUAL);r=t}},setLocked:function(e){t=e},setClear:function(t){n!==t&&(e.clearDepth(t),n=t)},reset:function(){t=!1,i=null,r=null,n=null}}},o=new function(){var t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null;return{setTest:function(t){t?D(e.STENCIL_TEST):U(e.STENCIL_TEST)},setMask:function(r){i===r||t||(e.stencilMask(r),i=r)},setFunc:function(t,i,a){r===t&&n===i&&o===a||(e.stencilFunc(t,i,a),r=t,n=i,o=a)},setOp:function(t,i,r){a===t&&s===i&&c===r||(e.stencilOp(t,i,r),a=t,s=i,c=r)},setLocked:function(e){t=e},setClear:function(t){h!==t&&(e.clearStencil(t),h=t)},reset:function(){t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null}}},a=e.getParameter(e.MAX_VERTEX_ATTRIBS),s=new Uint8Array(a),c=new Uint8Array(a),h=new Uint8Array(a),l={},u=null,p=null,d=null,f=null,m=null,v=null,g=null,y=null,x=null,b=!1,w=null,_=null,M=null,E=null,T=null,S=e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),A=parseFloat(/^WebGL\ ([0-9])/.exec(e.getParameter(e.VERSION))[1]),R=parseFloat(A)>=1,L=null,C={},P=new he,N=new he;function O(t,i,r){var n=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(var a=0;a0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}var o=void 0!==i.precision?i.precision:"highp",a=n(o);a!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",a,"instead."),o=a);var s=!0===i.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),l=e.getParameter(e.MAX_TEXTURE_SIZE),u=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),p=e.getParameter(e.MAX_VERTEX_ATTRIBS),d=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),f=e.getParameter(e.MAX_VARYING_VECTORS),m=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),v=h>0,g=!!t.get("OES_texture_float");return{getMaxAnisotropy:function(){if(void 0!==r)return r;var i=t.get("EXT_texture_filter_anisotropic");return r=null!==i?e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:n,precision:o,logarithmicDepthBuffer:s,maxTextures:c,maxVertexTextures:h,maxTextureSize:l,maxCubemapSize:u,maxAttributes:p,maxVertexUniforms:d,maxVaryings:f,maxFragmentUniforms:m,vertexTextures:v,floatFragmentTextures:g,floatVertexTextures:v&&g}}function Ki(e,t,i,r){It.call(this),this.type="PerspectiveCamera",this.fov=void 0!==e?e:50,this.zoom=1,this.near=void 0!==i?i:.1,this.far=void 0!==r?r:2e3,this.focus=10,this.aspect=void 0!==t?t:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qi(e){Ki.call(this),this.cameras=e||[]}function $i(e){var t=this,i=null,r=null,n=null;"undefined"!=typeof window&&"VRFrameData"in window&&(r=new window.VRFrameData);var o=new re,a=new Ki;a.bounds=new he(0,0,.5,1),a.layers.enable(1);var s=new Ki;s.bounds=new he(.5,0,.5,1),s.layers.enable(2);var c,h,l=new Qi([a,s]);function u(){if(null!==i&&i.isPresenting){var r=i.getEyeParameters("left"),n=r.renderWidth,o=r.renderHeight;h=e.getPixelRatio(),c=e.getSize(),e.setDrawingBufferSize(2*n,o,1)}else t.enabled&&e.setDrawingBufferSize(c.width,c.height,h)}l.layers.enable(1),l.layers.enable(2),"undefined"!=typeof window&&window.addEventListener("vrdisplaypresentchange",u,!1),this.enabled=!1,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e)},this.setPoseTarget=function(e){void 0!==e&&(n=e)},this.getCamera=function(e){if(null===i)return e;i.depthNear=e.near,i.depthFar=e.far,i.getFrameData(r);var t=r.pose,c=null!==n?n:e;if(null!==t.position?c.position.fromArray(t.position):c.position.set(0,0,0),null!==t.orientation&&c.quaternion.fromArray(t.orientation),c.updateMatrixWorld(),!1===i.isPresenting)return e;a.near=e.near,s.near=e.near,a.far=e.far,s.far=e.far,l.matrixWorld.copy(e.matrixWorld),l.matrixWorldInverse.copy(e.matrixWorldInverse),a.matrixWorldInverse.fromArray(r.leftViewMatrix),s.matrixWorldInverse.fromArray(r.rightViewMatrix);var h=c.parent;null!==h&&(o.getInverse(h.matrixWorld),a.matrixWorldInverse.multiply(o),s.matrixWorldInverse.multiply(o)),a.matrixWorld.getInverse(a.matrixWorldInverse),s.matrixWorld.getInverse(s.matrixWorldInverse),a.projectionMatrix.fromArray(r.leftProjectionMatrix),s.projectionMatrix.fromArray(r.rightProjectionMatrix),l.projectionMatrix.copy(a.projectionMatrix);var u=i.getLayers();if(u.length){var p=u[0];null!==p.leftBounds&&4===p.leftBounds.length&&a.bounds.fromArray(p.leftBounds),null!==p.rightBounds&&4===p.rightBounds.length&&s.bounds.fromArray(p.rightBounds)}return l},this.submitFrame=function(){i&&i.isPresenting&&i.submitFrame()},this.dispose=function(){"undefined"!=typeof window&&window.removeEventListener("vrdisplaypresentchange",u)}}function er(e){var t={};return{get:function(i){if(void 0!==t[i])return t[i];var r;switch(i){case"WEBGL_depth_texture":r=e.getExtension("WEBGL_depth_texture")||e.getExtension("MOZ_WEBGL_depth_texture")||e.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":r=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":r=e.getExtension("WEBGL_compressed_texture_s3tc")||e.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":r=e.getExtension("WEBGL_compressed_texture_pvrtc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;case"WEBGL_compressed_texture_etc1":r=e.getExtension("WEBGL_compressed_texture_etc1");break;default:r=e.getExtension(i)}return null===r&&console.warn("THREE.WebGLRenderer: "+i+" extension not supported."),t[i]=r,r}}}function tr(){var e=this,t=null,i=0,r=!1,n=!1,o=new _t,a=new ae,s={value:null,needsUpdate:!1};function c(){s.value!==t&&(s.value=t,s.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,i,r,n){var c=null!==t?t.length:0,h=null;if(0!==c){if(h=s.value,!0!==n||null===h){var l=r+4*c,u=i.matrixWorldInverse;a.getNormalMatrix(u),(null===h||h.length=0){var h=n[s];if(void 0!==h){var l=h.normalized,u=h.itemSize,p=w.get(h);if(void 0===p)continue;var d=p.buffer,f=p.type,g=p.bytesPerElement;if(h.isInterleavedBufferAttribute){var x=h.data,b=x.stride,_=h.offset;x&&x.isInstancedInterleavedBuffer?(y.enableAttributeAndDivisor(c,x.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=x.meshPerAttribute*x.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,b*g,(r*b+_)*g)}else h.isInstancedBufferAttribute?(y.enableAttributeAndDivisor(c,h.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=h.meshPerAttribute*h.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,0,r*u*g)}else if(void 0!==a){var M=a[s];if(void 0!==M)switch(M.length){case 2:m.vertexAttrib2fv(c,M);break;case 3:m.vertexAttrib3fv(c,M);break;case 4:m.vertexAttrib4fv(c,M);break;default:m.vertexAttrib1fv(c,M)}}}}y.disableUnusedAttributes()}(r,s,i),null!==u&&m.bindBuffer(m.ELEMENT_ARRAY_BUFFER,l.buffer));var g=0;null!==u?g=u.count:void 0!==p&&(g=p.count);var x=i.drawRange.start*d,b=i.drawRange.count*d,M=null!==o?o.start*d:0,E=null!==o?o.count*d:1/0,T=Math.max(x,M),S=Math.min(g,x+b,M+E)-1,A=Math.max(0,S-T+1);if(0!==A){if(n.isMesh)if(!0===r.wireframe)y.setLineWidth(r.wireframeLinewidth*me()),f.setMode(m.LINES);else switch(n.drawMode){case 0:f.setMode(m.TRIANGLES);break;case 1:f.setMode(m.TRIANGLE_STRIP);break;case 2:f.setMode(m.TRIANGLE_FAN)}else if(n.isLine){var L=r.linewidth;void 0===L&&(L=1),y.setLineWidth(L*me()),n.isLineSegments?f.setMode(m.LINES):n.isLineLoop?f.setMode(m.LINE_LOOP):f.setMode(m.LINE_STRIP)}else n.isPoints&&f.setMode(m.POINTS);i&&i.isInstancedBufferGeometry?i.maxInstancedCount>0&&f.renderInstances(i,T,A):f.render(T,A)}},this.compile=function(e,t){l.length=0,u.length=0,e.traverse((function(e){e.isLight&&(l.push(e),e.castShadow&&u.push(e))})),E.setup(l,u,t),e.traverse((function(t){if(t.material)if(Array.isArray(t.material))for(var i=0;i=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(l=0;l=0&&e.numSupportedMorphNormals++}var p=r.shader.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(r.numClippingPlanes=ae.numPlanes,r.numIntersection=ae.numIntersection,p.clippingPlanes=ae.uniform),r.fog=t,r.lightsHash=E.state.hash,e.lights&&(p.ambientLightColor.value=E.state.ambient,p.directionalLights.value=E.state.directional,p.spotLights.value=E.state.spot,p.rectAreaLights.value=E.state.rectArea,p.pointLights.value=E.state.point,p.hemisphereLights.value=E.state.hemi,p.directionalShadowMap.value=E.state.directionalShadowMap,p.directionalShadowMatrix.value=E.state.directionalShadowMatrix,p.spotShadowMap.value=E.state.spotShadowMap,p.spotShadowMatrix.value=E.state.spotShadowMatrix,p.pointShadowMap.value=E.state.pointShadowMap,p.pointShadowMatrix.value=E.state.pointShadowMatrix);var d=r.program.getUniforms(),f=Qe.seqWithValue(d.seq,p);r.uniformsList=f}function Ne(e,t,i,r){Z=0;var n=x.get(i);if(se&&(ce||e!==H)){var o=e===H&&i.id===V;ae.setState(i.clippingPlanes,i.clipIntersection,i.clipShadows,e,n,o)}!1===i.needsUpdate&&(void 0===n.program||i.fog&&n.fog!==t||i.lights&&n.lightsHash!==E.state.hash?i.needsUpdate=!0:void 0===n.numClippingPlanes||n.numClippingPlanes===ae.numPlanes&&n.numIntersection===ae.numIntersection||(i.needsUpdate=!0)),i.needsUpdate&&(Pe(i,t,r),i.needsUpdate=!1);var a,s,c=!1,h=!1,l=!1,u=n.program,p=u.getUniforms(),d=n.shader.uniforms;if(y.useProgram(u.program)&&(c=!0,h=!0,l=!0),i.id!==V&&(V=i.id,h=!0),c||e!==H){if(p.setValue(m,"projectionMatrix",e.projectionMatrix),g.logarithmicDepthBuffer&&p.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),H!==(W||e)&&(H=W||e,h=!0,l=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshStandardMaterial||i.envMap){var f=p.map.cameraPosition;void 0!==f&&f.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.skinning)&&p.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(i.skinning){p.setOptional(m,r,"bindMatrix"),p.setOptional(m,r,"bindMatrixInverse");var v=r.skeleton;if(v){var b=v.bones;if(g.floatVertexTextures){if(void 0===v.boneTexture){var w=Math.sqrt(4*b.length);w=te.ceilPowerOfTwo(w),w=Math.max(w,4);var _=new Float32Array(w*w*4);_.set(v.boneMatrices);var M=new pe(_,w,w,U,N);v.boneMatrices=_,v.boneTexture=M,v.boneTextureSize=w}p.setValue(m,"boneTexture",v.boneTexture),p.setValue(m,"boneTextureSize",v.boneTextureSize)}else p.setOptional(m,v,"boneMatrices")}}return h&&(p.setValue(m,"toneMappingExposure",F.toneMappingExposure),p.setValue(m,"toneMappingWhitePoint",F.toneMappingWhitePoint),i.lights&&(s=l,(a=d).ambientLightColor.needsUpdate=s,a.directionalLights.needsUpdate=s,a.pointLights.needsUpdate=s,a.spotLights.needsUpdate=s,a.rectAreaLights.needsUpdate=s,a.hemisphereLights.needsUpdate=s),t&&i.fog&&function(e,t){e.fogColor.value=t.color,t.isFog?(e.fogNear.value=t.near,e.fogFar.value=t.far):t.isFogExp2&&(e.fogDensity.value=t.density)}(d,t),i.isMeshBasicMaterial?Oe(d,i):i.isMeshLambertMaterial?(Oe(d,i),function(e,t){t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap)}(d,i)):i.isMeshPhongMaterial?(Oe(d,i),i.isMeshToonMaterial?function(e,t){Ie(e,t),t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(d,i):Ie(d,i)):i.isMeshStandardMaterial?(Oe(d,i),i.isMeshPhysicalMaterial?function(e,t){e.clearCoat.value=t.clearCoat,e.clearCoatRoughness.value=t.clearCoatRoughness,De(e,t)}(d,i):De(d,i)):i.isMeshDepthMaterial?(Oe(d,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(d,i)):i.isMeshDistanceMaterial?(Oe(d,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias);e.referencePosition.value.copy(t.referencePosition),e.nearDistance.value=t.nearDistance,e.farDistance.value=t.farDistance}(d,i)):i.isMeshNormalMaterial?(Oe(d,i),function(e,t){t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale);t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale));t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(d,i)):i.isLineBasicMaterial?(function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity}(d,i),i.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(d,i)):i.isPointsMaterial?function(e,t){if(e.diffuse.value=t.color,e.opacity.value=t.opacity,e.size.value=t.size*Q,e.scale.value=.5*K,e.map.value=t.map,null!==t.map){if(!0===t.map.matrixAutoUpdate){var i=t.map.offset,r=t.map.repeat,n=t.map.rotation,o=t.map.center;t.map.matrix.setUvTransform(i.x,i.y,r.x,r.y,n,o.x,o.y)}e.uvTransform.value.copy(t.map.matrix)}}(d,i):i.isShadowMaterial&&(d.color.value=i.color,d.opacity.value=i.opacity),void 0!==d.ltcMat&&(d.ltcMat.value=tt.LTC_MAT_TEXTURE),void 0!==d.ltcMag&&(d.ltcMag.value=tt.LTC_MAG_TEXTURE),Qe.upload(m,n.uniformsList,d,F)),p.setValue(m,"modelViewMatrix",r.modelViewMatrix),p.setValue(m,"normalMatrix",r.normalMatrix),p.setValue(m,"modelMatrix",r.matrixWorld),u}function Oe(e,t){var i;if(e.opacity.value=t.opacity,t.color&&(e.diffuse.value=t.color),t.emissive&&e.emissive.value.copy(t.emissive).multiplyScalar(t.emissiveIntensity),t.map&&(e.map.value=t.map),t.alphaMap&&(e.alphaMap.value=t.alphaMap),t.specularMap&&(e.specularMap.value=t.specularMap),t.envMap&&(e.envMap.value=t.envMap,e.flipEnvMap.value=t.envMap&&t.envMap.isCubeTexture?-1:1,e.reflectivity.value=t.reflectivity,e.refractionRatio.value=t.refractionRatio),t.lightMap&&(e.lightMap.value=t.lightMap,e.lightMapIntensity.value=t.lightMapIntensity),t.aoMap&&(e.aoMap.value=t.aoMap,e.aoMapIntensity.value=t.aoMapIntensity),t.map?i=t.map:t.specularMap?i=t.specularMap:t.displacementMap?i=t.displacementMap:t.normalMap?i=t.normalMap:t.bumpMap?i=t.bumpMap:t.roughnessMap?i=t.roughnessMap:t.metalnessMap?i=t.metalnessMap:t.alphaMap?i=t.alphaMap:t.emissiveMap&&(i=t.emissiveMap),void 0!==i){if(i.isWebGLRenderTarget&&(i=i.texture),!0===i.matrixAutoUpdate){var r=i.offset,n=i.repeat,o=i.rotation,a=i.center;i.matrix.setUvTransform(r.x,r.y,n.x,n.y,o,a.x,a.y)}e.uvTransform.value.copy(i.matrix)}}function Ie(e,t){e.specular.value=t.specular,e.shininess.value=Math.max(t.shininess,1e-4),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}function De(e,t){e.roughness.value=t.roughness,e.metalness.value=t.metalness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap),t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}this.animate=function(e){Se=e,function(){if(!Te){var e=ye.getDevice();e&&e.isPresenting?e.requestAnimationFrame(Ae):window.requestAnimationFrame(Ae),Te=!0}}()},this.render=function(e,t,i,r){if(t&&t.isCamera){if(!z){j="",V=-1,H=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),ye.enabled&&(t=ye.getCamera(t)),le.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),ne.setFromMatrix(le),l.length=0,u.length=0,d.length=0,f.length=0,ce=this.localClippingEnabled,se=ae.init(this.clippingPlanes,ce,t),(p=S.get(e,t)).init(),Re(e,t,F.sortObjects),!0===F.sortObjects&&p.sort(),b.updateVideoTextures(),se&&ae.beginShadows(),xe.render(u,e,t),E.setup(l,u,t),se&&ae.endShadows(),fe.frame++,fe.calls=0,fe.vertices=0,fe.faces=0,fe.points=0,void 0===i&&(i=null),this.setRenderTarget(i),A.render(p,e,t,r);var n=p.opaque,o=p.transparent;if(e.overrideMaterial){var a=e.overrideMaterial;n.length&&Le(n,e,t,a),o.length&&Le(o,e,t,a)}else n.length&&Le(n,e,t),o.length&&Le(o,e,t);D.render(d,e,t),I.render(f,e,t,X),i&&b.updateRenderTargetMipmap(i),y.buffers.depth.setTest(!0),y.buffers.depth.setMask(!0),y.buffers.color.setMask(!0),y.setPolygonOffset(!1),ye.enabled&&ye.submitFrame()}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFaceCulling=function(e,t){y.setCullFace(e),y.setFlipSided(0===t)},this.allocTextureUnit=function(){var e=Z;return e>=g.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+g.maxTextures),Z+=1,e},this.setTexture2D=(Ee=!1,function(e,t){e&&e.isWebGLRenderTarget&&(Ee||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Ee=!0),e=e.texture),b.setTexture2D(e,t)}),this.setTexture=function(){var e=!1;return function(t,i){e||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),e=!0),b.setTexture2D(t,i)}}(),this.setTextureCube=function(){var e=!1;return function(t,i){t&&t.isWebGLRenderTargetCube&&(e||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),e=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?b.setTextureCube(t,i):b.setTextureCubeDynamic(t,i)}}(),this.getRenderTarget=function(){return k},this.setRenderTarget=function(e){k=e,e&&void 0===x.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var t=null,i=!1;if(e){var r=x.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=r[e.activeCubeFace],i=!0):t=r,X.copy(e.viewport),q.copy(e.scissor),Y=e.scissorTest}else X.copy($).multiplyScalar(Q),q.copy(ee).multiplyScalar(Q),Y=ie;if(G!==t&&(m.bindFramebuffer(m.FRAMEBUFFER,t),G=t),y.viewport(X),y.scissor(q),y.setScissorTest(Y),i){var n=x.get(e.texture);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,n.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,r,n,o){if(e&&e.isWebGLRenderTarget){var a=x.get(e).__webglFramebuffer;if(a){var s=!1;a!==G&&(m.bindFramebuffer(m.FRAMEBUFFER,a),s=!0);try{var c=e.texture,h=c.format,l=c.type;if(h!==U&&B.convert(h)!==m.getParameter(m.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(l===L||B.convert(l)===m.getParameter(m.IMPLEMENTATION_COLOR_READ_TYPE)||l===N&&(v.get("OES_texture_float")||v.get("WEBGL_color_buffer_float"))||l===O&&v.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?t>=0&&t<=e.width-r&&i>=0&&i<=e.height-n&&m.readPixels(t,i,r,n,B.convert(h),B.convert(l),o):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&m.bindFramebuffer(m.FRAMEBUFFER,G)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")}}function nr(e,t){this.name="",this.color=new et(e),this.density=void 0!==t?t:25e-5}function or(e,t,i){this.name="",this.color=new et(e),this.near=void 0!==t?t:1,this.far=void 0!==i?i:1e3}function ar(){Ot.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function sr(e,t,i,r,n){Ot.call(this),this.lensFlares=[],this.positionScreen=new oe,this.customUpdateCallback=void 0,void 0!==e&&this.add(e,t,i,r,n)}function cr(e){gt.call(this),this.type="SpriteMaterial",this.color=new et(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function hr(e){Ot.call(this),this.type="Sprite",this.material=void 0!==e?e:new cr}function lr(){Ot.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ur(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===t)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,r=this.bones.length;i=0?(p=e(g-h,v,p),d.subVectors(u,p)):(p=e(g+h,v,p),d.subVectors(p,u)),v-h>=0?(p=e(g,v-h,p),f.subVectors(u,p)):(p=e(g,v+h,p),f.subVectors(p,u)),l.crossVectors(d,f).normalize(),s.push(l.x,l.y,l.z),c.push(g,v)}}for(r=0;r.9&&a<.1&&(t<.2&&(o[e+0]+=1),i<.2&&(o[e+2]+=1),r<.2&&(o[e+4]+=1))}}()}(),this.addAttribute("position",new Yt(n,3)),this.addAttribute("normal",new Yt(n.slice(),3)),this.addAttribute("uv",new Yt(o,2)),0===r?this.computeVertexNormals():this.normalizeNormals()}function Lr(e,t){zt.call(this),this.type="TetrahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Cr(e,t)),this.mergeVertices()}function Cr(e,t){Rr.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],e,t),this.type="TetrahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Pr(e,t){zt.call(this),this.type="OctahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Nr(e,t)),this.mergeVertices()}function Nr(e,t){Rr.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],e,t),this.type="OctahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Or(e,t){zt.call(this),this.type="IcosahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ir(e,t)),this.mergeVertices()}function Ir(e,t){var i=(1+Math.sqrt(5))/2,r=[-1,i,0,1,i,0,-1,-i,0,1,-i,0,0,-1,i,0,1,i,0,-1,-i,0,1,-i,i,0,-1,i,0,1,-i,0,-1,-i,0,1];Rr.call(this,r,[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],e,t),this.type="IcosahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Dr(e,t){zt.call(this),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ur(e,t)),this.mergeVertices()}function Ur(e,t){var i=(1+Math.sqrt(5))/2,r=1/i,n=[-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,-i,0,-r,i,0,r,-i,0,r,i,-r,-i,0,-r,i,0,r,-i,0,r,i,0,-i,0,-r,i,0,-r,-i,0,r,i,0,r];Rr.call(this,n,[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],e,t),this.type="DodecahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Br(e,t,i,r,n,o){zt.call(this),this.type="TubeGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},void 0!==o&&console.warn("THREE.TubeGeometry: taper has been removed.");var a=new Fr(e,t,i,r,n);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals,this.fromBufferGeometry(a),this.mergeVertices()}function Fr(e,t,i,r,n){ai.call(this),this.type="TubeBufferGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},t=t||64,i=i||1,r=r||8,n=n||!1;var o=e.computeFrenetFrames(t,n);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals;var a,s,c=new oe,h=new oe,l=new ie,u=new oe,p=[],d=[],f=[],m=[];function v(n){u=e.getPointAt(n/t,u);var a=o.normals[n],l=o.binormals[n];for(s=0;s<=r;s++){var f=s/r*Math.PI*2,m=Math.sin(f),v=-Math.cos(f);h.x=v*a.x+m*l.x,h.y=v*a.y+m*l.y,h.z=v*a.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+i*h.x,c.y=u.y+i*h.y,c.z=u.z+i*h.z,p.push(c.x,c.y,c.z)}}!function(){for(a=0;ai)){var r=e.ray.origin.distanceTo(Pi);re.far||t.push({distance:r,point:Pi.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)}}),lr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:lr,copy:function(e){Ot.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,r=t.length;i1){e.setFromMatrixPosition(i.matrixWorld),t.setFromMatrixPosition(this.matrixWorld);var n=e.distanceTo(t);r[0].object.visible=!0;for(var o=1,a=r.length;o=r[o].distance;o++)r[o-1].object.visible=!1,r[o].object.visible=!0;for(;oa))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}else for(g=0,y=m.length/3-1;ga))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}else if(s.isGeometry){var w=s.vertices,_=w.length;for(g=0;g<_-1;g+=d){var M;if(!(t.distanceSqToSegment(w[g],w[g+1],p,u)>a))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),vr.prototype=Object.assign(Object.create(mr.prototype),{constructor:vr,isLineSegments:!0}),gr.prototype=Object.assign(Object.create(mr.prototype),{constructor:gr,isLineLoop:!0}),yr.prototype=Object.create(gt.prototype),yr.prototype.constructor=yr,yr.prototype.isPointsMaterial=!0,yr.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.size=e.size,this.sizeAttenuation=e.sizeAttenuation,this},xr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:xr,isPoints:!0,raycast:function(){var e=new re,t=new di,i=new wt;return function(r,n){var o=this,a=this.geometry,s=this.matrixWorld,c=r.params.Points.threshold;if(null===a.boundingSphere&&a.computeBoundingSphere(),i.copy(a.boundingSphere),i.applyMatrix4(s),i.radius+=c,!1!==r.ray.intersectsSphere(i)){e.getInverse(s),t.copy(r.ray).applyMatrix4(e);var h=c/((this.scale.x+this.scale.y+this.scale.z)/3),l=h*h,u=new oe;if(a.isBufferGeometry){var p=a.index,d=a.attributes.position.array;if(null!==p)for(var f=p.array,m=0,v=f.length;mr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:c.clone(),index:i,face:null,object:o})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),br.prototype=Object.assign(Object.create(Ot.prototype),{constructor:br,isGroup:!0}),wr.prototype=Object.assign(Object.create(ce.prototype),{constructor:wr,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),_r.prototype=Object.create(ce.prototype),_r.prototype.constructor=_r,_r.prototype.isCompressedTexture=!0,Mr.prototype=Object.create(ce.prototype),Mr.prototype.constructor=Mr,Mr.prototype.isDepthTexture=!0,Er.prototype=Object.create(ai.prototype),Er.prototype.constructor=Er,Tr.prototype=Object.create(zt.prototype),Tr.prototype.constructor=Tr,Sr.prototype=Object.create(ai.prototype),Sr.prototype.constructor=Sr,Ar.prototype=Object.create(zt.prototype),Ar.prototype.constructor=Ar,Rr.prototype=Object.create(ai.prototype),Rr.prototype.constructor=Rr,Lr.prototype=Object.create(zt.prototype),Lr.prototype.constructor=Lr,Cr.prototype=Object.create(Rr.prototype),Cr.prototype.constructor=Cr,Pr.prototype=Object.create(zt.prototype),Pr.prototype.constructor=Pr,Nr.prototype=Object.create(Rr.prototype),Nr.prototype.constructor=Nr,Or.prototype=Object.create(zt.prototype),Or.prototype.constructor=Or,Ir.prototype=Object.create(Rr.prototype),Ir.prototype.constructor=Ir,Dr.prototype=Object.create(zt.prototype),Dr.prototype.constructor=Dr,Ur.prototype=Object.create(Rr.prototype),Ur.prototype.constructor=Ur,Br.prototype=Object.create(zt.prototype),Br.prototype.constructor=Br,Fr.prototype=Object.create(ai.prototype),Fr.prototype.constructor=Fr,zr.prototype=Object.create(zt.prototype),zr.prototype.constructor=zr,kr.prototype=Object.create(ai.prototype),kr.prototype.constructor=kr,Gr.prototype=Object.create(zt.prototype),Gr.prototype.constructor=Gr,Vr.prototype=Object.create(ai.prototype),Vr.prototype.constructor=Vr;var jr=function(e,t,i){i=i||2;var r,n,o,a,s,c,h,l=t&&t.length,u=l?t[0]*i:e.length,p=Hr(e,0,u,i,!0),d=[];if(!p)return d;if(l&&(p=function(e,t,i,r){var n,o,a,s=[];for(n=0,o=t.length;n80*i){r=o=e[0],n=a=e[1];for(var f=i;fo&&(o=s),c>a&&(a=c);h=0!==(h=Math.max(o-r,a-n))?1/h:0}return Xr(p,d,i,r,n,h),d};function Hr(e,t,i,r,n){var o,a;if(n===function(e,t,i,r){for(var n=0,o=t,a=i-r;o0)for(o=t;o=t;o-=r)a=hn(o,e[o],e[o+1],a);return a&&on(a,a.next)&&(ln(a),a=a.next),a}function Wr(e,t){if(!e)return e;t||(t=e);var i,r=e;do{if(i=!1,r.steiner||!on(r,r.next)&&0!==nn(r.prev,r,r.next))r=r.next;else{if(ln(r),(r=t=r.prev)===r.next)break;i=!0}}while(i||r!==t);return t}function Xr(e,t,i,r,n,o,a){if(e){!a&&o&&function(e,t,i,r){var n=e;do{null===n.z&&(n.z=$r(n.x,n.y,t,i,r)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==e);n.prevZ.nextZ=null,n.prevZ=null,function(e){var t,i,r,n,o,a,s,c,h=1;do{for(i=e,e=null,o=null,a=0;i;){for(a++,r=i,s=0,t=0;t0||c>0&&r;)0!==s&&(0===c||!r||i.z<=r.z)?(n=i,i=i.nextZ,s--):(n=r,r=r.nextZ,c--),o?o.nextZ=n:e=n,n.prevZ=o,o=n;i=r}o.nextZ=null,h*=2}while(a>1)}(n)}(e,r,n,o);for(var s,c,h=e;e.prev!==e.next;)if(s=e.prev,c=e.next,o?Yr(e,r,n,o):qr(e))t.push(s.i/i),t.push(e.i/i),t.push(c.i/i),ln(e),e=c.next,h=c.next;else if((e=c)===h){a?1===a?Xr(e=Zr(e,t,i),t,i,r,n,o,2):2===a&&Jr(e,t,i,r,n,o):Xr(Wr(e),t,i,r,n,o,1);break}}}function qr(e){var t=e.prev,i=e,r=e.next;if(nn(t,i,r)>=0)return!1;for(var n=e.next.next;n!==e.prev;){if(tn(t.x,t.y,i.x,i.y,r.x,r.y,n.x,n.y)&&nn(n.prev,n,n.next)>=0)return!1;n=n.next}return!0}function Yr(e,t,i,r){var n=e.prev,o=e,a=e.next;if(nn(n,o,a)>=0)return!1;for(var s=n.xo.x?n.x>a.x?n.x:a.x:o.x>a.x?o.x:a.x,l=n.y>o.y?n.y>a.y?n.y:a.y:o.y>a.y?o.y:a.y,u=$r(s,c,t,i,r),p=$r(h,l,t,i,r),d=e.nextZ;d&&d.z<=p;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=e.prevZ;d&&d.z>=u;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function Zr(e,t,i){var r=e;do{var n=r.prev,o=r.next.next;!on(n,o)&&an(n,r,r.next,o)&&sn(n,o)&&sn(o,n)&&(t.push(n.i/i),t.push(r.i/i),t.push(o.i/i),ln(r),ln(r.next),r=e=o),r=r.next}while(r!==e);return r}function Jr(e,t,i,r,n,o){var a=e;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&rn(a,s)){var c=cn(a,s);return a=Wr(a,a.next),c=Wr(c,c.next),Xr(a,t,i,r,n,o),void Xr(c,t,i,r,n,o)}s=s.next}a=a.next}while(a!==e)}function Kr(e,t){return e.x-t.x}function Qr(e,t){if(t=function(e,t){var i,r=t,n=e.x,o=e.y,a=-1/0;do{if(o<=r.y&&o>=r.next.y&&r.next.y!==r.y){var s=r.x+(o-r.y)*(r.next.x-r.x)/(r.next.y-r.y);if(s<=n&&s>a){if(a=s,s===n){if(o===r.y)return r;if(o===r.next.y)return r.next}i=r.x=r.x&&r.x>=l&&n!==r.x&&tn(oi.x)&&sn(r,e)&&(i=r,p=c),r=r.next;return i}(e,t),t){var i=cn(t,e);Wr(i,i.next)}}function $r(e,t,i,r,n){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*n)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*n)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function en(e){var t=e,i=e;do{t.x=0&&(e-a)*(r-s)-(i-a)*(t-s)>=0&&(i-a)*(o-s)-(n-a)*(r-s)>=0}function rn(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&an(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(e,t)&&sn(e,t)&&sn(t,e)&&function(e,t){var i=e,r=!1,n=(e.x+t.x)/2,o=(e.y+t.y)/2;do{i.y>o!=i.next.y>o&&i.next.y!==i.y&&n<(i.next.x-i.x)*(o-i.y)/(i.next.y-i.y)+i.x&&(r=!r),i=i.next}while(i!==e);return r}(e,t)}function nn(e,t,i){return(t.y-e.y)*(i.x-t.x)-(t.x-e.x)*(i.y-t.y)}function on(e,t){return e.x===t.x&&e.y===t.y}function an(e,t,i,r){return!!(on(e,t)&&on(i,r)||on(e,r)&&on(i,t))||nn(e,t,i)>0!=nn(e,t,r)>0&&nn(i,r,e)>0!=nn(i,r,t)>0}function sn(e,t){return nn(e.prev,e,e.next)<0?nn(e,t,e.next)>=0&&nn(e,e.prev,t)>=0:nn(e,t,e.prev)<0||nn(e,e.next,t)<0}function cn(e,t){var i=new un(e.i,e.x,e.y),r=new un(t.i,t.x,t.y),n=e.next,o=t.prev;return e.next=t,t.prev=e,i.next=n,n.prev=i,r.next=i,i.prev=r,o.next=r,r.prev=o,r}function hn(e,t,i,r){var n=new un(e,t,i);return r?(n.next=r.next,n.prev=r,r.next.prev=n,r.next=n):(n.prev=n,n.next=n),n}function ln(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function un(e,t,i){this.i=e,this.x=t,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var pn={area:function(e){for(var t=e.length,i=0,r=t-1,n=0;n2&&e[t-1].equals(e[0])&&e.pop()}function r(e,t){for(var i=0;i0)&&f.push(w,_,E),(c!==i-1||h0&&g(!0),t>0&&g(!1)),this.setIndex(h),this.addAttribute("position",new Yt(l,3)),this.addAttribute("normal",new Yt(u,3)),this.addAttribute("uv",new Yt(p,2))}function Ln(e,t,i,r,n,o,a){An.call(this,0,e,t,i,r,n,o,a),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Cn(e,t,i,r,n,o,a){Rn.call(this,0,e,t,i,r,n,o,a),this.type="ConeBufferGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Pn(e,t,i,r){zt.call(this),this.type="CircleGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},this.fromBufferGeometry(new Nn(e,t,i,r)),this.mergeVertices()}function Nn(e,t,i,r){ai.call(this),this.type="CircleBufferGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},e=e||1,t=void 0!==t?Math.max(3,t):8,i=void 0!==i?i:0,r=void 0!==r?r:2*Math.PI;var n,o,a=[],s=[],c=[],h=[],l=new oe,u=new ie;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),o=0,n=3;o<=t;o++,n+=3){var p=i+o/t*r;l.x=e*Math.cos(p),l.y=e*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[n]/e+1)/2,u.y=(s[n+1]/e+1)/2,h.push(u.x,u.y)}for(n=1;n<=t;n++)a.push(n,n+1,0);this.setIndex(a),this.addAttribute("position",new Yt(s,3)),this.addAttribute("normal",new Yt(c,3)),this.addAttribute("uv",new Yt(h,2))}dn.prototype=Object.create(zt.prototype),dn.prototype.constructor=dn,fn.prototype=Object.create(ai.prototype),fn.prototype.constructor=fn,fn.prototype.getArrays=function(){var e=this.getAttribute("position"),t=e?Array.prototype.slice.call(e.array):[],i=this.getAttribute("uv"),r=i?Array.prototype.slice.call(i.array):[],n=this.index;return{position:t,uv:r,index:n?Array.prototype.slice.call(n.array):[]}},fn.prototype.addShapeList=function(e,t){var i=e.length;t.arrays=this.getArrays();for(var r=0;rNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=t.x-s/p,m=t.y+a/p,v=((i.x-h/d-f)*h-(i.y+c/d-m)*c)/(a*h-s*c),g=(r=f+a*v-e.x)*r+(n=m+s*v-e.y)*n;if(g<=2)return new ie(r,n);o=Math.sqrt(g/2)}else{var y=!1;a>Number.EPSILON?c>Number.EPSILON&&(y=!0):a<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(r=-s,n=a,o=Math.sqrt(l)):(r=a,n=s,o=Math.sqrt(l/2))}return new ie(r/o,n/o)}for(var G=[],V=0,j=C.length,H=j-1,W=V+1;V=0;N--){for(I=N/y,D=v*Math.cos(I*Math.PI/2),O=g*Math.sin(I*Math.PI/2),V=0,j=C.length;V=0;){i=V,(r=V-1)<0&&(r=e.length-1);var n=0,o=w+2*y;for(n=0;n0||0===e.search(/^data\:image\/jpeg/);n.format=r?D:U,n.needsUpdate=!0,void 0!==t&&t(n)}),i,r),n},setCrossOrigin:function(e){return this.crossOrigin=e,this},setPath:function(e){return this.path=e,this}}),Object.assign(eo.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(e,t){var i=this.getUtoTmapping(e);return this.getPoint(i,t)},getPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPoint(i/e));return t},getSpacedPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPointAt(i/e));return t},getLength:function(){var e=this.getLengths();return e[e.length-1]},getLengths:function(e){if(void 0===e&&(e=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var t,i,r=[],n=this.getPoint(0),o=0;for(r.push(0),i=1;i<=e;i++)o+=(t=this.getPoint(i/e)).distanceTo(n),r.push(o),n=t;return this.cacheArcLengths=r,r},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(e,t){var i,r=this.getLengths(),n=0,o=r.length;i=t||e*r[o-1];for(var a,s=0,c=o-1;s<=c;)if((a=r[n=Math.floor(s+(c-s)/2)]-i)<0)s=n+1;else{if(!(a>0)){c=n;break}c=n-1}if(r[n=c]===i)return n/(o-1);var h=r[n];return(n+(i-h)/(r[n+1]-h))/(o-1)},getTangent:function(e){var t=1e-4,i=e-t,r=e+t;i<0&&(i=0),r>1&&(r=1);var n=this.getPoint(i);return this.getPoint(r).clone().sub(n).normalize()},getTangentAt:function(e){var t=this.getUtoTmapping(e);return this.getTangent(t)},computeFrenetFrames:function(e,t){var i,r,n,o=new oe,a=[],s=[],c=[],h=new oe,l=new re;for(i=0;i<=e;i++)r=i/e,a[i]=this.getTangentAt(r),a[i].normalize();s[0]=new oe,c[0]=new oe;var u=Number.MAX_VALUE,p=Math.abs(a[0].x),d=Math.abs(a[0].y),f=Math.abs(a[0].z);for(p<=u&&(u=p,o.set(1,0,0)),d<=u&&(u=d,o.set(0,1,0)),f<=u&&o.set(0,0,1),h.crossVectors(a[0],o).normalize(),s[0].crossVectors(a[0],h),c[0].crossVectors(a[0],s[0]),i=1;i<=e;i++)s[i]=s[i-1].clone(),c[i]=c[i-1].clone(),h.crossVectors(a[i-1],a[i]),h.length()>Number.EPSILON&&(h.normalize(),n=Math.acos(te.clamp(a[i-1].dot(a[i]),-1,1)),s[i].applyMatrix4(l.makeRotationAxis(h,n))),c[i].crossVectors(a[i],s[i]);if(!0===t)for(n=Math.acos(te.clamp(s[0].dot(s[e]),-1,1)),n/=e,a[0].dot(h.crossVectors(s[0],s[e]))>0&&(n=-n),i=1;i<=e;i++)s[i].applyMatrix4(l.makeRotationAxis(a[i],n*i)),c[i].crossVectors(a[i],s[i]);return{tangents:a,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this},toJSON:function(){var e={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e},fromJSON:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}),to.prototype=Object.create(eo.prototype),to.prototype.constructor=to,to.prototype.isEllipseCurve=!0,to.prototype.getPoint=function(e,t){for(var i=t||new ie,r=2*Math.PI,n=this.aEndAngle-this.aStartAngle,o=Math.abs(n)r;)n-=r;n0?0:(Math.floor(Math.abs(l)/s.length)+1)*s.length:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?i=s[(l-1)%c]:(no.subVectors(s[0],s[1]).add(s[0]),i=no),r=s[l%c],n=s[(l+1)%c],this.closed||l+2r.length-2?r.length-1:o+1],l=r[o>r.length-3?r.length-1:o+2];return i.set(ho(a,s.x,c.x,h.x,l.x),ho(a,s.y,c.y,h.y,l.y)),i},xo.prototype.copy=function(e){eo.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var n=i[r]-t,o=this.curves[r],a=o.getLength(),s=0===a?0:1-n/a;return o.getPointAt(s)}r++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,r=this.curves.length;i1&&!i[i.length-1].equals(i[0])&&i.push(i[0]),i},copy:function(e){eo.prototype.copy.call(this,e),this.curves=[];for(var t=0,i=e.curves.length;t0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(e){return wo.prototype.copy.call(this,e),this.currentPoint.copy(e.currentPoint),this},toJSON:function(){var e=wo.prototype.toJSON.call(this);return e.currentPoint=this.currentPoint.toArray(),e},fromJSON:function(e){return wo.prototype.fromJSON.call(this,e),this.currentPoint.fromArray(e.currentPoint),this}}),Mo.prototype=Object.assign(Object.create(_o.prototype),{constructor:Mo,getPointsHoles:function(e){for(var t=[],i=0,r=this.holes.length;i=n)break e;var s=t[1];e=(n=t[--i-1]))break t}o=i,i=0}for(;i>>1;et;)--o;if(++o,0!==n||o!==r){n>=o&&(n=(o=Math.max(o,1))-1);var a=this.getValueSize();this.times=Ho.arraySlice(i,n,o),this.values=Ho.arraySlice(this.values,n*a,o*a)}return this},validate:function(){var e=!0,t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);var i=this.times,r=this.values,n=i.length;0===n&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);for(var o=null,a=0;a!==n;a++){var s=i[a];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,a,s),e=!1;break}if(null!==o&&o>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,a,s,o),e=!1;break}o=s}if(void 0!==r&&Ho.isTypedArray(r)){a=0;for(var c=r.length;a!==c;++a){var h=r[a];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,a,h),e=!1;break}}}return e},optimize:function(){for(var e=this.times,t=this.values,i=this.getValueSize(),r=this.getInterpolation()===Z,n=1,o=e.length-1,a=1;a0){e[n]=e[o];for(f=o*i,m=n*i,p=0;p!==i;++p)t[m+p]=t[f+p];++n}return n!==e.length&&(this.times=Ho.arraySlice(e,0,n),this.values=Ho.arraySlice(t,0,n*i)),this}}),Xo.prototype=Object.assign(Object.create(Wo.prototype),{constructor:Xo,ValueTypeName:"vector"}),Object.assign(qo,{parse:function(e){for(var t=[],i=e.tracks,r=1/(e.fps||1),n=0,o=i.length;n!==o;++n)t.push(Wo.parse(i[n]).scale(r));return new qo(e.name,e.duration,t)},toJSON:function(e){for(var t=[],i=e.tracks,r={name:e.name,duration:e.duration,tracks:t},n=0,o=i.length;n!==o;++n)t.push(Wo.toJSON(i[n]));return r},CreateFromMorphTargetSequence:function(e,t,i,r){for(var n=t.length,o=[],a=0;a1){var h=r[u=c[1]];h||(r[u]=h=[]),h.push(s)}}var l=[];for(var u in r)l.push(qo.CreateFromMorphTargetSequence(u,r[u],t,i));return l},parseAnimation:function(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var i=function(e,t,i,r,n){if(0!==i.length){var o=[],a=[];Ho.flattenJSON(i,o,a,r),0!==o.length&&n.push(new e(t,o,a))}},r=[],n=e.name||"default",o=e.length||-1,a=e.fps||30,s=e.hierarchy||[],c=0;c1?e.skinWeights[r+1]:0,s=i>2?e.skinWeights[r+2]:0,c=i>3?e.skinWeights[r+3]:0;t.skinWeights.push(new he(o,a,s,c))}if(e.skinIndices)for(r=0,n=e.skinIndices.length;r1?e.skinIndices[r+1]:0,u=i>2?e.skinIndices[r+2]:0,p=i>3?e.skinIndices[r+3]:0;t.skinIndices.push(new he(h,l,u,p))}t.bones=e.bones,t.bones&&t.bones.length>0&&(t.skinWeights.length!==t.skinIndices.length||t.skinIndices.length!==t.vertices.length)&&console.warn("When skinning, number of vertices ("+t.vertices.length+"), skinIndices ("+t.skinIndices.length+"), and skinWeights ("+t.skinWeights.length+") should match.")}(e,i),function(e,t){var i=e.scale;if(void 0!==e.morphTargets)for(var r=0,n=e.morphTargets.length;r0){console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');var l=t.faces,u=e.morphColors[0].colors;for(r=0,n=l.length;r0&&(t.animations=i)}(e,i),i.computeFaceNormals(),i.computeBoundingSphere(),void 0===e.materials||0===e.materials.length?{geometry:i}:{geometry:i,materials:ta.prototype.initMaterials(e.materials,t,this.crossOrigin)}}}),Object.assign(na.prototype,{load:function(e,t,i,r){""===this.texturePath&&(this.texturePath=e.substring(0,e.lastIndexOf("/")+1));var n=this;new Yn(n.manager).load(e,(function(i){var o=null;try{o=JSON.parse(i)}catch(t){return void 0!==r&&r(t),void console.error("THREE:ObjectLoader: Can't parse "+e+".",t.message)}var a=o.metadata;void 0!==a&&void 0!==a.type&&"geometry"!==a.type.toLowerCase()?n.parse(o,t):console.error("THREE.ObjectLoader: Can't load "+e+". Use THREE.JSONLoader instead.")}),i,r)},setTexturePath:function(e){this.texturePath=e},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){var i=this.parseShape(e.shapes),r=this.parseGeometries(e.geometries,i),n=this.parseImages(e.images,(function(){void 0!==t&&t(s)})),o=this.parseTextures(e.textures,n),a=this.parseMaterials(e.materials,o),s=this.parseObject(e.object,r,a);return e.animations&&(s.animations=this.parseAnimations(e.animations)),void 0!==e.images&&0!==e.images.length||void 0!==t&&t(s),s},parseShape:function(e){var t={};if(void 0!==e)for(var i=0,r=e.length;i0){var o=new Kn(new Wn(t));o.setCrossOrigin(this.crossOrigin);for(var a=0,s=e.length;a0?new dr(s,c):new vi(s,c);break;case"LOD":n=new lr;break;case"Line":n=new mr(o(t.geometry),a(t.material),t.mode);break;case"LineLoop":n=new gr(o(t.geometry),a(t.material));break;case"LineSegments":n=new vr(o(t.geometry),a(t.material));break;case"PointCloud":case"Points":n=new xr(o(t.geometry),a(t.material));break;case"Sprite":n=new hr(a(t.material));break;case"Group":n=new br;break;default:n=new Ot}if(n.uuid=t.uuid,void 0!==t.name&&(n.name=t.name),void 0!==t.matrix?(e.fromArray(t.matrix),e.decompose(n.position,n.quaternion,n.scale)):(void 0!==t.position&&n.position.fromArray(t.position),void 0!==t.rotation&&n.rotation.fromArray(t.rotation),void 0!==t.quaternion&&n.quaternion.fromArray(t.quaternion),void 0!==t.scale&&n.scale.fromArray(t.scale)),void 0!==t.castShadow&&(n.castShadow=t.castShadow),void 0!==t.receiveShadow&&(n.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.bias&&(n.shadow.bias=t.shadow.bias),void 0!==t.shadow.radius&&(n.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&n.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(n.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.children)for(var h=t.children,l=0;lNumber.EPSILON){if(h<0&&(a=t[o],c=-c,s=t[n],h=-h),e.ys.y)continue;if(e.y===a.y){if(e.x===a.x)return!0}else{var l=h*(e.x-a.x)-c*(e.y-a.y);if(0===l)return!0;if(l<0)continue;r=!r}}else{if(e.y!==a.y)continue;if(s.x<=e.x&&e.x<=a.x||a.x<=e.x&&e.x<=s.x)return!0}}return r}var n=pn.isClockWise,o=this.subPaths;if(0===o.length)return[];if(!0===t)return i(o);var a,s,c,h=[];if(1===o.length)return s=o[0],(c=new Mo).curves=s.curves,h.push(c),h;var l=!n(o[0].getPoints());l=e?!l:l;var u,p,d=[],f=[],m=[],v=0;f[v]=void 0,m[v]=[];for(var g=0,y=o.length;g1){for(var x=!1,b=[],w=0,_=f.length;w<_;w++)d[w]=[];for(w=0,_=f.length;w<_;w++)for(var M=m[w],E=0;E0&&(x||(m=d))}g=0;for(var R=f.length;g0){this.source.connect(this.filters[0]);for(var e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(var e=1,t=this.filters.length;e=.5)for(var o=0;o!==n;++o)e[t+o]=e[i+o]},_slerp:function(e,t,i,r){ne.slerpFlat(e,t,e,t,e,i,r)},_lerp:function(e,t,i,r,n){for(var o=1-r,a=0;a!==n;++a){var s=t+a;e[s]=e[s]*o+e[i+a]*r}}}),Object.assign(Fa.prototype,{getValue:function(e,t){this.bind();var i=this._targetGroup.nCachedObjects_,r=this._bindings[i];void 0!==r&&r.getValue(e,t)},setValue:function(e,t){for(var i=this._bindings,r=this._targetGroup.nCachedObjects_,n=i.length;r!==n;++r)i[r].setValue(e,t)},bind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].bind()},unbind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].unbind()}}),Object.assign(za,{Composite:Fa,create:function(e,t,i){return e&&e.isAnimationObjectGroup?new za.Composite(e,t,i):new za(e,t,i)},sanitizeNodeName:function(e){return e.replace(/\s/g,"_").replace(/[^\w-]/g,"")},parseTrackName:(Ma=new RegExp("^"+/((?:[\w-]+[\/:])*)/.source+/([\w-\.]+)?/.source+/(?:\.([\w-]+)(?:\[(.+)\])?)?/.source+/\.([\w-]+)(?:\[(.+)\])?/.source+"$"),Ea=["material","materials","bones"],function(e){var t=Ma.exec(e);if(!t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);var i={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},r=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==r&&-1!==r){var n=i.nodeName.substring(r+1);-1!==Ea.indexOf(n)&&(i.nodeName=i.nodeName.substring(0,r),i.objectName=n)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return i}),findNode:function(e,t){if(!t||""===t||"root"===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){var i=function(e){for(var i=0;i=t){var l=t++,u=e[l];i[u.uuid]=h,e[h]=u,i[c]=l,e[l]=s;for(var p=0,d=n;p!==d;++p){var f=r[p],m=f[l],v=f[h];f[h]=m,f[l]=v}}}this.nCachedObjects_=t},uncache:function(){for(var e=this._objects,t=e.length,i=this.nCachedObjects_,r=this._indicesByUUID,n=this._bindings,o=n.length,a=0,s=arguments.length;a!==s;++a){var c=arguments[a],h=c.uuid,l=r[h];if(void 0!==l)if(delete r[h],l0)for(var c=this._interpolants,h=this._propertyBindings,l=0,u=c.length;l!==u;++l)c[l].evaluate(a),h[l].accumulate(r,s)}else this._updateWeight(e)},_updateWeight:function(e){var t=0;if(this.enabled){t=this.weight;var i=this._weightInterpolant;if(null!==i){var r=i.evaluate(e)[0];t*=r,e>i.parameterPositions[1]&&(this.stopFading(),0===r&&(this.enabled=!1))}}return this._effectiveWeight=t,t},_updateTimeScale:function(e){var t=0;if(!this.paused){t=this.timeScale;var i=this._timeScaleInterpolant;if(null!==i)t*=i.evaluate(e)[0],e>i.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}return this._effectiveTimeScale=t,t},_updateTime:function(e){var t=this.time+e;if(0===e)return t;var i=this._clip.duration,r=this.loop,n=this._loopCount;if(2200===r){-1===n&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(t>=i)t=i;else{if(!(t<0))break e;t=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{var o=2202===r;if(-1===n&&(e>=0?(n=0,this._setEndings(!0,0===this.repetitions,o)):this._setEndings(0===this.repetitions,!0,o)),t>=i||t<0){var a=Math.floor(t/i);t-=i*a,n+=Math.abs(a);var s=this.repetitions-n;if(s<0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,t=e>0?i:0,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(0===s){var c=e<0;this._setEndings(c,!c,o)}else this._setEndings(!1,!1,o);this._loopCount=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:a})}}if(o&&1==(1&n))return this.time=t,i-t}return this.time=t,t},_setEndings:function(e,t,i){var r=this._interpolantSettings;i?(r.endingStart=K,r.endingEnd=K):(r.endingStart=e?this.zeroSlopeAtStart?K:J:Q,r.endingEnd=t?this.zeroSlopeAtEnd?K:J:Q)},_scheduleFading:function(e,t,i){var r=this._mixer,n=r.time,o=this._weightInterpolant;null===o&&(o=r._lendControlInterpolant(),this._weightInterpolant=o);var a=o.parameterPositions,s=o.sampleValues;return a[0]=n,s[0]=t,a[1]=n+e,s[1]=i,this}}),Va.prototype=Object.assign(Object.create(n.prototype),{constructor:Va,_bindAction:function(e,t){var i=e._localRoot||this._root,r=e._clip.tracks,n=r.length,o=e._propertyBindings,a=e._interpolants,s=i.uuid,c=this._bindingsByRootAndName,h=c[s];void 0===h&&(h={},c[s]=h);for(var l=0;l!==n;++l){var u=r[l],p=u.name,d=h[p];if(void 0!==d)o[l]=d;else{if(void 0!==(d=o[l])){null===d._cacheIndex&&(++d.referenceCount,this._addInactiveBinding(d,s,p));continue}var f=t&&t._propertyBindings[l].binding.parsedPath;++(d=new Ba(za.create(i,p,f),u.ValueTypeName,u.getValueSize())).referenceCount,this._addInactiveBinding(d,s,p),o[l]=d}a[l].resultBuffer=d.buffer}},_activateAction:function(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){var t=(e._localRoot||this._root).uuid,i=e._clip.uuid,r=this._actionsByClip[i];this._bindAction(e,r&&r.knownActions[0]),this._addInactiveAction(e,i,t)}for(var n=e._propertyBindings,o=0,a=n.length;o!==a;++o){var s=n[o];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}},_deactivateAction:function(e){if(this._isActiveAction(e)){for(var t=e._propertyBindings,i=0,r=t.length;i!==r;++i){var n=t[i];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(e)}},_initMemoryManager:function(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;var e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}},_isActiveAction:function(e){var t=e._cacheIndex;return null!==t&&t.99999?this.quaternion.set(0,0,0,1):e.y<-.99999?this.quaternion.set(1,0,0,0):(Ra.set(e.z,0,-e.x).normalize(),Aa=Math.acos(e.y),this.quaternion.setFromAxisAngle(Ra,Aa))}),gs.prototype.setLength=function(e,t,i){void 0===t&&(t=.2*e),void 0===i&&(i=.2*t),this.line.scale.set(1,Math.max(0,e-t),1),this.line.updateMatrix(),this.cone.scale.set(i,t,i),this.cone.position.y=e,this.cone.updateMatrix()},gs.prototype.setColor=function(e){this.line.material.color.copy(e),this.cone.material.color.copy(e)},ys.prototype=Object.create(vr.prototype),ys.prototype.constructor=ys;var xs={createMultiMaterialObject:function(e,t){for(var i=new br,r=0,n=t.length;r0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),"," (- z + zOffset / 1000.0) * maxDepthPerTile,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),this.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n")}metaLoaded(){this.metaLoaded=!0,this.initStreamer()}initStreamer(){if(this.metaLoaded){this.texture=new Ss.Texture(this.video),this.geometry=new Ss.Geometry;for(var e=0,t=this.width*this.height;e{(this.isMjpeg||this.video.readyState===this.video.HAVE_ENOUGH_DATA)&&(this.texture.needsUpdate=!0)}),1e3/30)}}startStream(){this.isMjpeg||this.video.play()}stopStream(){this.isMjpeg||this.video.pause()}}class Ns extends Ss.Mesh{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1,n=e.headLength||.2,o=e.shaftDiameter||.05,a=e.headDiameter||.1,s=e.material||new Ss.MeshBasicMaterial,c=r-n,h=new Ss.CylinderGeometry(.5*o,.5*o,c,12,1),l=new Ss.Matrix4;l.setPosition(new Ss.Vector3(0,.5*c,0)),h.applyMatrix(l);var u=new Ss.CylinderGeometry(0,.5*a,n,12,1);l.setPosition(new Ss.Vector3(0,c+.5*n,0)),u.applyMatrix(l),h.merge(u),super(h,s),this.position.copy(t),this.setDirection(i)}setDirection(e){var t=new Ss.Vector3;0===e.x&&0===e.z?t.set(1,0,0):t.set(0,1,0).cross(e);var i=Math.acos(new Ss.Vector3(0,1,0).dot(e.clone().normalize()));this.matrix=(new Ss.Matrix4).makeRotationAxis(t.normalize(),i),this.rotation.setFromRotationMatrix(this.matrix,this.rotation.order)}setLength(e){this.scale.set(e,e,e)}setColor(e){this.material.color.setHex(e)}dispose(){void 0!==this.geometry&&this.geometry.dispose(),void 0!==this.material&&this.material.dispose()}}Ss.STLLoader=function(e){this.manager=void 0!==e?e:Ss.DefaultLoadingManager},Ss.STLLoader.prototype={constructor:Ss.STLLoader,load:function(e,t,i,r){var n=this,o=new Ss.FileLoader(n.manager);o.setResponseType("arraybuffer"),o.load(e,(function(e){t(n.parse(e))}),i,r)},parse:function(e){var t=function(e){if("string"==typeof e){for(var t=new Uint8Array(e.length),i=0;i>5&31)/31,r=(w>>10&31)/31):(t=o,i=a,r=s)}for(var _=1;_<=3;_++){var M=g+12*_;f.push(h.getFloat32(M,!0)),f.push(h.getFloat32(M+4,!0)),f.push(h.getFloat32(M+8,!0)),m.push(y,x,b),u&&n.push(t,i,r)}}return d.addAttribute("position",new Ss.BufferAttribute(new Float32Array(f),3)),d.addAttribute("normal",new Ss.BufferAttribute(new Float32Array(m),3)),u&&(d.addAttribute("color",new Ss.BufferAttribute(new Float32Array(n),3)),d.hasColors=!0,d.alpha=c),d}(t):function(e){for(var t,i=new Ss.BufferGeometry,r=/facet([\s\S]*?)endfacet/g,n=0,o=/[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source,a=new RegExp("vertex"+o+o+o,"g"),s=new RegExp("normal"+o+o+o,"g"),c=[],h=[],l=new Ss.Vector3;null!==(t=r.exec(e));){for(var u=0,p=0,d=t[0];null!==(t=s.exec(d));)l.x=parseFloat(t[1]),l.y=parseFloat(t[2]),l.z=parseFloat(t[3]),p++;for(;null!==(t=a.exec(d));)c.push(parseFloat(t[1]),parseFloat(t[2]),parseFloat(t[3])),h.push(l.x,l.y,l.z),u++;1!==p&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+n),3!==u&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+n),n++}return i.addAttribute("position",new Ss.Float32BufferAttribute(c,3)),i.addAttribute("normal",new Ss.Float32BufferAttribute(h,3)),i}(function(e){if("string"!=typeof e){var t=new Uint8Array(e);if(void 0!==window.TextDecoder)return(new TextDecoder).decode(t);for(var i="",r=0,n=e.byteLength;r0?t[t.length-1]:"",smooth:void 0!==i?i.smooth:this.smooth,groupStart:void 0!==i?i.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(e){var t={index:"number"==typeof e?e:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return t.clone=this.clone.bind(t),t}};return this.materials.push(r),r},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(e){var t=this.currentMaterial();if(t&&-1===t.groupEnd&&(t.groupEnd=this.geometry.vertices.length/3,t.groupCount=t.groupEnd-t.groupStart,t.inherited=!1),e&&this.materials.length>1)for(var i=this.materials.length-1;i>=0;i--)this.materials[i].groupCount<=0&&this.materials.splice(i,1);return e&&0===this.materials.length&&this.materials.push({name:"",smooth:this.smooth}),t}},i&&i.name&&"function"==typeof i.clone){var r=i.clone(0);r.inherited=!0,this.object.materials.push(r)}this.objects.push(this.object)},finalize:function(){this.object&&"function"==typeof this.object._finalize&&this.object._finalize(!0)},parseVertexIndex:function(e,t){var i=parseInt(e,10);return 3*(i>=0?i-1:i+t/3)},parseNormalIndex:function(e,t){var i=parseInt(e,10);return 3*(i>=0?i-1:i+t/3)},parseUVIndex:function(e,t){var i=parseInt(e,10);return 2*(i>=0?i-1:i+t/2)},addVertex:function(e,t,i){var r=this.vertices,n=this.object.geometry.vertices;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addVertexPoint:function(e){var t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){var t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,i){var r=this.normals,n=this.object.geometry.normals;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addColor:function(e,t,i){var r=this.colors,n=this.object.geometry.colors;n.push(r[e+0],r[e+1],r[e+2]),n.push(r[t+0],r[t+1],r[t+2]),n.push(r[i+0],r[i+1],r[i+2])},addUV:function(e,t,i){var r=this.uvs,n=this.object.geometry.uvs;n.push(r[e+0],r[e+1]),n.push(r[t+0],r[t+1]),n.push(r[i+0],r[i+1])},addUVLine:function(e){var t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,i,r,n,o,a,s,c){var h=this.vertices.length,l=this.parseVertexIndex(e,h),u=this.parseVertexIndex(t,h),p=this.parseVertexIndex(i,h);if(this.addVertex(l,u,p),void 0!==r&&""!==r){var d=this.uvs.length;l=this.parseUVIndex(r,d),u=this.parseUVIndex(n,d),p=this.parseUVIndex(o,d),this.addUV(l,u,p)}if(void 0!==a&&""!==a){var f=this.normals.length;l=this.parseNormalIndex(a,f),u=a===s?l:this.parseNormalIndex(s,f),p=a===c?l:this.parseNormalIndex(c,f),this.addNormal(l,u,p)}this.colors.length>0&&this.addColor(l,u,p)},addPointGeometry:function(e){this.object.geometry.type="Points";for(var t=this.vertices.length,i=0,r=e.length;i0){var m=f.split("/");u.push(m)}}var v=u[0];for(p=1,d=u.length-1;p1){var A=o[1].trim().toLowerCase();t.object.smooth="0"!==A&&"off"!==A}else t.object.smooth=!0;(G=t.object.currentMaterial())&&(G.smooth=t.object.smooth)}t.finalize();var R=new Ss.Object3D;R.materialLibraries=[].concat(t.materialLibraries);for(s=0,c=t.objects.length;s0?D.addAttribute("normal",new Ss.Float32BufferAttribute(C.normals,3)):D.computeVertexNormals(),C.colors.length>0&&(I=!0,D.addAttribute("color",new Ss.Float32BufferAttribute(C.colors,3))),C.uvs.length>0&&D.addAttribute("uv",new Ss.Float32BufferAttribute(C.uvs,2));for(var U,B=[],F=0,z=P.length;F1){for(F=0,z=P.length;F=0?s.substring(0,c):s;h=h.toLowerCase();var l=c>=0?s.substring(c+1):"";if(l=l.trim(),"newmtl"===h)r={name:l},o[l]=r;else if("ka"===h||"kd"===h||"ks"===h||"ke"===h){var u=l.split(n,3);r[h]=[parseFloat(u[0]),parseFloat(u[1]),parseFloat(u[2])]}else r[h]=l}}var p=new Ss.MTLLoader.MaterialCreator(this.resourcePath||t,this.materialOptions);return p.setCrossOrigin(this.crossOrigin),p.setManager(this.manager),p.setMaterials(o),p}},Ss.MTLLoader.MaterialCreator=function(e,t){this.baseUrl=e||"",this.options=t,this.materialsInfo={},this.materials={},this.materialsArray=[],this.nameLookup={},this.side=this.options&&this.options.side?this.options.side:Ss.FrontSide,this.wrap=this.options&&this.options.wrap?this.options.wrap:Ss.RepeatWrapping},Ss.MTLLoader.MaterialCreator.prototype={constructor:Ss.MTLLoader.MaterialCreator,crossOrigin:"anonymous",setCrossOrigin:function(e){return this.crossOrigin=e,this},setManager:function(e){this.manager=e},setMaterials:function(e){this.materialsInfo=this.convert(e),this.materials={},this.materialsArray=[],this.nameLookup={}},convert:function(e){if(!this.options)return e;var t={};for(var i in e){var r=e[i],n={};for(var o in t[i]=n,r){var a=!0,s=r[o],c=o.toLowerCase();switch(c){case"kd":case"ka":case"ks":this.options&&this.options.normalizeRGB&&(s=[s[0]/255,s[1]/255,s[2]/255]),this.options&&this.options.ignoreZeroRGBs&&0===s[0]&&0===s[1]&&0===s[2]&&(a=!1)}a&&(n[c]=s)}}return t},preload:function(){for(var e in this.materialsInfo)this.create(e)},getIndex:function(e){return this.nameLookup[e]},getAsArray:function(){var e=0;for(var t in this.materialsInfo)this.materialsArray[e]=this.create(t),this.nameLookup[t]=e,e++;return this.materialsArray},create:function(e){return void 0===this.materials[e]&&this.createMaterial_(e),this.materials[e]},createMaterial_:function(e){var t=this,i=this.materialsInfo[e],r={name:e,side:this.side};function n(e,i){if(!r[e]){var n,o,a=t.getTextureParams(i,r),s=t.loadTexture((n=t.baseUrl,"string"!=typeof(o=a.url)||""===o?"":/^https?:\/\//i.test(o)?o:n+o));s.repeat.copy(a.scale),s.offset.copy(a.offset),s.wrapS=t.wrap,s.wrapT=t.wrap,r[e]=s}}for(var o in i){var a,s=i[o];if(""!==s)switch(o.toLowerCase()){case"kd":r.color=(new Ss.Color).fromArray(s);break;case"ks":r.specular=(new Ss.Color).fromArray(s);break;case"ke":r.emissive=(new Ss.Color).fromArray(s);break;case"map_kd":n("map",s);break;case"map_ks":n("specularMap",s);break;case"map_ke":n("emissiveMap",s);break;case"norm":n("normalMap",s);break;case"map_bump":case"bump":n("bumpMap",s);break;case"map_d":n("alphaMap",s),r.transparent=!0;break;case"ns":r.shininess=parseFloat(s);break;case"d":(a=parseFloat(s))<1&&(r.opacity=a,r.transparent=!0);break;case"tr":a=parseFloat(s),this.options&&this.options.invertTrProperty&&(a=1-a),a>0&&(r.opacity=1-a,r.transparent=!0)}}return this.materials[e]=new Ss.MeshPhongMaterial(r),this.materials[e]},getTextureParams:function(e,t){var i,r={scale:new Ss.Vector2(1,1),offset:new Ss.Vector2(0,0)},n=e.split(/\s+/);return(i=n.indexOf("-bm"))>=0&&(t.bumpScale=parseFloat(n[i+1]),n.splice(i,2)),(i=n.indexOf("-s"))>=0&&(r.scale.set(parseFloat(n[i+1]),parseFloat(n[i+2])),n.splice(i,4)),(i=n.indexOf("-o"))>=0&&(r.offset.set(parseFloat(n[i+1]),parseFloat(n[i+2])),n.splice(i,4)),r.url=n.join(" ").trim(),r},loadTexture:function(e,t,i,r,n){var o,a=Ss.Loader.Handlers.get(e),s=void 0!==this.manager?this.manager:Ss.DefaultLoadingManager;return null===a&&(a=new Ss.TextureLoader(s)),a.setCrossOrigin&&a.setCrossOrigin(this.crossOrigin),o=a.load(e,i,r,n),void 0!==t&&(o.mapping=t),o}},Ss.ColladaLoader=function(e){this.manager=void 0!==e?e:Ss.DefaultLoadingManager},Ss.ColladaLoader.prototype={constructor:Ss.ColladaLoader,crossOrigin:"Anonymous",load:function(e,t,i,r){var n=this,o=Ss.Loader.prototype.extractUrlBase(e);new Ss.FileLoader(n.manager).load(e,(function(e){t(n.parse(e,o))}),i,r)},options:{set convertUpAxis(e){console.warn("THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.")}},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){function i(e,t){for(var i=[],r=e.childNodes,n=0,o=r.length;n0&&t.push(new Ss.VectorKeyframeTrack(r+".position",n,o)),a.length>0&&t.push(new Ss.QuaternionKeyframeTrack(r+".quaternion",n,a)),s.length>0&&t.push(new Ss.VectorKeyframeTrack(r+".scale",n,s)),t}function _(e,t,i){var r,n,o,a=!0;for(n=0,o=e.length;n=0;){var r=e[t];if(null!==r.value[i])return r;t--}return null}function E(e,t,i){for(;t0&&p.addAttribute("position",new Ss.Float32BufferAttribute(n.array,n.stride)),o.array.length>0&&p.addAttribute("normal",new Ss.Float32BufferAttribute(o.array,o.stride)),s.array.length>0&&p.addAttribute("color",new Ss.Float32BufferAttribute(s.array,s.stride)),a.array.length>0&&p.addAttribute("uv",new Ss.Float32BufferAttribute(a.array,a.stride)),c.length>0&&p.addAttribute("skinIndex",new Ss.Float32BufferAttribute(c,h)),l.length>0&&p.addAttribute("skinWeight",new Ss.Float32BufferAttribute(l,u)),r.data=p,r.type=e[0].type,r.materialKeys=d,r}function ne(e,t,i,r){var n=e.p,o=e.stride,a=e.vcount;function s(e){for(var t=n[e+i]*l,o=t+l;t0&&console.log("THREE.ColladaLoader: Geometry has faces with more than 4 vertices.")}else for(p=0,d=n.length;p=t.limits.max&&(t.static=!0),t.middlePosition=(t.limits.min+t.limits.max)/2,t}function le(e){for(var t={sid:e.getAttribute("sid"),name:e.getAttribute("name")||"",attachments:[],transforms:[]},i=0;ir.limits.max||t0){var q=this.msgColor,Y=document.createElement("canvas"),Z=Y.getContext("2d"),J="normal 100px sans-serif";Z.font=J;var K=Z.measureText(i.text).width;Y.width=K,Y.height=150,Z.font=J,Z.fillStyle="rgba("+Math.round(255*q.r)+", "+Math.round(255*q.g)+", "+Math.round(255*q.b)+", "+q.a+")",Z.textAlign="left",Z.textBaseline="middle",Z.fillText(i.text,0,Y.height/2);var Q=new Ss.Texture(Y);Q.needsUpdate=!0;var $=new Ss.SpriteMaterial({map:Q,useScreenCoordinates:!1}),ee=new Ss.Sprite($),te=i.scale.x;ee.scale.set(K/Y.height*te,te,1),this.add(ee)}break;case 10:var ie=null;0===i.color.r&&0===i.color.g&&0===i.color.b&&0===i.color.a||(ie=r),this.msgMesh=i.mesh_resource.substr(10);var re=new Fs({path:t,resource:this.msgMesh,material:ie});this.add(re);break;case 11:var ne=new zs({material:r,vertices:i.points,colors:i.colors});ne.scale.set(i.scale.x,i.scale.y,i.scale.z),this.add(ne);break;default:console.error("Currently unsupported marker type: "+i.type)}}setPose(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()}update(e){if(this.setPose(e.pose),e.color.r!==this.msgColor.r||e.color.g!==this.msgColor.g||e.color.b!==this.msgColor.b||e.color.a!==this.msgColor.a){var t=As(e.color.r,e.color.g,e.color.b,e.color.a);switch(e.type){case 4:case 5:case 8:break;case 0:case 1:case 2:case 3:case 11:case 9:this.traverse((function(e){e instanceof Ss.Mesh&&(e.material=t)}));break;case 10:var i=null;0===e.color.r&&0===e.color.g&&0===e.color.b&&0===e.color.a||(i=this.colorMaterial),this.traverse((function(e){e instanceof Ss.Mesh&&(e.material=i)}));break;default:return!1}this.msgColor=e.color}var r=Math.abs(this.msgScale[0]-e.scale.x)>1e-6||Math.abs(this.msgScale[1]-e.scale.y)>1e-6||Math.abs(this.msgScale[2]-e.scale.z)>1e-6;switch(this.msgScale=[e.scale.x,e.scale.y,e.scale.z],e.type){case 1:case 2:case 3:if(r)return!1;break;case 9:if(r||this.text!==e.text)return!1;break;case 10:if(e.mesh_resource.substr(10)!==this.msgMesh)return!1;if(r)return!1;break;case 0:case 4:case 5:case 6:case 7:case 8:case 11:return!1}return!0}dispose(){this.children.forEach((function(e){e instanceof Fs?e.children.forEach((function(t){void 0!==t.material&&t.material.dispose(),t.children.forEach((function(e){void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose(),t.remove(e)})),e.remove(t)})):(void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose()),e.parent.remove(e)}))}}class Gs extends Ss.Object3D{constructor(e){super();var t=this;e=e||{},this.parent=e.parent;var i=e.handle,n=e.message;this.message=n,this.name=n.name,this.camera=e.camera,this.path=e.path||"/",this.loader=e.loader,this.dragging=!1,this.startMousePos=new Ss.Vector2,this.isShift=!1;var o=new Ss.Quaternion(n.orientation.x,n.orientation.y,n.orientation.z,n.orientation.w);o.normalize();var a=new Ss.Vector3(1,0,0);switch(a.applyQuaternion(o),this.currentControlOri=new Ss.Quaternion,n.interaction_mode){case 9:case 7:this.addEventListener("mousemove",this.parent.move3d.bind(this.parent,this,a));break;case 3:this.addEventListener("mousemove",this.parent.moveAxis.bind(this.parent,this,a)),this.addEventListener("touchmove",this.parent.moveAxis.bind(this.parent,this,a));break;case 5:this.addEventListener("mousemove",this.parent.rotateAxis.bind(this.parent,this,o));break;case 4:this.addEventListener("mousemove",this.parent.movePlane.bind(this.parent,this,a));break;case 2:this.addEventListener("click",this.parent.buttonClick.bind(this.parent,this))}function s(e){e.stopPropagation()}0!==n.interaction_mode&&(this.addEventListener("mousedown",this.parent.startDrag.bind(this.parent,this)),this.addEventListener("mouseup",this.parent.stopDrag.bind(this.parent,this)),this.addEventListener("contextmenu",this.parent.showMenu.bind(this.parent,this)),this.addEventListener("mouseup",(function(e){0===t.startMousePos.distanceToSquared(e.mousePos)&&(e.type="contextmenu",t.dispatchEvent(e))})),this.addEventListener("mouseover",s),this.addEventListener("mouseout",s),this.addEventListener("click",s),this.addEventListener("mousedown",(function(e){t.startMousePos=e.mousePos})),this.addEventListener("touchstart",(function(e){1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,t.dispatchEvent(e))})),this.addEventListener("touchmove",(function(e){1===e.domEvent.touches.length&&(e.type="mousemove",e.domEvent.button=0,t.dispatchEvent(e))})),this.addEventListener("touchend",(function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",t.dispatchEvent(e),e.type="click",t.dispatchEvent(e))})),window.addEventListener("keydown",(function(e){16===e.keyCode&&(t.isShift=!0)})),window.addEventListener("keyup",(function(e){16===e.keyCode&&(t.isShift=!1)})));var c=new Ss.Quaternion,h=this.parent.position.clone().multiplyScalar(-1);switch(n.orientation_mode){case 0:c=this.parent.quaternion.clone().inverse();break;case 1:case 2:break;default:console.error("Unkown orientation mode: "+n.orientation_mode)}var l=new r.TFClient({ros:i.tfClient.ros,fixedFrame:i.message.header.frame_id,serverName:i.tfClient.serverName});n.markers.forEach((function(e){var i=function(i){var n=new ks({message:e,path:t.path,loader:t.loader});if(null!==i){var o=new r.Pose({position:n.position,orientation:n.quaternion});o.applyTransform(new r.Transform(i));var a=new ks({message:e,path:t.path,loader:t.loader});a.position.add(h),a.position.applyQuaternion(c),a.quaternion.multiplyQuaternions(c,a.quaternion);var s=new Ss.Vector3(a.position.x,a.position.y,a.position.z),u=new r.Transform({translation:s,orientation:a.quaternion});o.applyTransform(u),n.setPose(o),n.updateMatrixWorld(),l.unsubscribe(e.header.frame_id)}t.add(n)};""!==e.header.frame_id?l.subscribe(e.header.frame_id,i):i(null)}))}updateMatrixWorld(e){var t=this,i=this.message;switch(i.orientation_mode){case 0:super.updateMatrixWorld(e),t.currentControlOri.copy(t.quaternion),t.currentControlOri.normalize();break;case 1:t.quaternion.copy(t.parent.quaternion.clone().inverse()),t.updateMatrix(),t.matrixWorldNeedsUpdate=!0,super.updateMatrixWorld(e),t.currentControlOri.copy(t.quaternion);break;case 2:t.camera.updateMatrixWorld();var r=(new Ss.Matrix4).extractRotation(t.camera.matrixWorld),n=new Ss.Matrix4,o=.5*Math.PI,a=new Ss.Euler(-o,0,o);n.makeRotationFromEuler(a);var s=new Ss.Matrix4;s.getInverse(t.parent.matrixWorld),r.multiplyMatrices(r,n),r.multiplyMatrices(s,r),t.currentControlOri.setFromRotationMatrix(r),i.independent_marker_orientation||(t.quaternion.copy(t.currentControlOri),t.updateMatrix(),t.matrixWorldNeedsUpdate=!0),super.updateMatrixWorld(e);break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}}}class Vs extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).menuEntries,r=e.className||"default-interactive-marker-menu";e.entryClassName;var n,o,a,s=e.overlayClassName||"default-interactive-marker-overlay",c=e.menuFontSize||"0.8em",h=[];if(h[0]={children:[]},null===document.getElementById("default-interactive-marker-menu-css")){var l=document.createElement("style");l.id="default-interactive-marker-menu-css",l.type="text/css",l.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: "+c+";z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(l)}for(this.menuDomElem=document.createElement("div"),this.menuDomElem.style.position="absolute",this.menuDomElem.className=r,this.menuDomElem.addEventListener("contextmenu",(function(e){e.preventDefault()})),this.overlayDomElem=document.createElement("div"),this.overlayDomElem.className=s,this.hideListener=this.hide.bind(this),this.overlayDomElem.addEventListener("contextmenu",this.hideListener),this.overlayDomElem.addEventListener("click",this.hideListener),this.overlayDomElem.addEventListener("touchstart",this.hideListener),n=0;n0?(e(s,o[a]),c.addEventListener("click",t.hide.bind(t)),c.addEventListener("touchstart",t.hide.bind(t))):(c.addEventListener("click",p.bind(t,o[a])),c.addEventListener("touchstart",p.bind(t,o[a])),c.className="default-interactive-marker-menu-entry")}}(this.menuDomElem,h[0])}show(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,void 0!==t.domEvent.changedTouches?(this.menuDomElem.style.left=t.domEvent.changedTouches[0].pageX+"px",this.menuDomElem.style.top=t.domEvent.changedTouches[0].pageY+"px"):(this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px"),document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)}hide(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)}}class js extends Ss.Object3D{constructor(e){super();var t=(e=e||{}).handle;this.name=t.name;var i=e.camera,r=e.path||"/",n=e.loader;this.dragging=!1,this.onServerSetPose({pose:t.pose}),this.dragStart={position:new Ss.Vector3,orientation:new Ss.Quaternion,positionWorld:new Ss.Vector3,orientationWorld:new Ss.Quaternion,event3d:{}},t.controls.forEach(function(e){this.add(new Gs({parent:this,handle:t,message:e,camera:i,path:r,loader:n}))}.bind(this)),t.menuEntries.length>0&&(this.menu=new Vs({menuEntries:t.menuEntries,menuFontSize:t.menuFontSize}),this.menu.addEventListener("menu-select",function(e){this.dispatchEvent(e)}.bind(this)))}showMenu(e,t){this.menu&&this.menu.show(e,t)}moveAxis(e,t,i){if(this.dragging){var r=e.currentControlOri,n=t.clone().applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),s=new Ss.Ray(o,a),c=Cs(s,i.camera,i.mousePos),h=new Ss.Vector3;h.addVectors(this.dragStart.position,n.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(c)),this.setPosition(e,h),i.stopPropagation()}}move3d(e,t,i){if(this.dragging)if(e.isShift);else{var r=e.camera.getWorldDirection(),n=Math.abs(r.x),o=Math.abs(r.y),a=Math.abs(r.z),s=new Ss.Quaternion(1,0,0,1);o>n&&o>a?s=new Ss.Quaternion(0,0,1,1):a>n&&a>o&&(s=new Ss.Quaternion(0,1,0,1)),s.normalize(),(t=new Ss.Vector3(1,0,0)).applyQuaternion(s),this.movePlane(e,t,i)}}movePlane(e,t,i){if(this.dragging){var r=e.currentControlOri,n=t.clone().applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.clone().applyQuaternion(this.dragStart.orientationWorld),s=Rs(i.mouseRay,o,a),c=new Ss.Vector3;c.subVectors(s,o),c.add(this.dragStart.positionWorld),this.setPosition(e,c),i.stopPropagation()}}rotateAxis(e,t,i){if(this.dragging){e.updateMatrixWorld();var r=e.currentControlOri.clone().multiply(t.clone()),n=new Ss.Vector3(1,0,0).applyQuaternion(r),o=this.dragStart.event3d.intersection.point,a=n.applyQuaternion(this.dragStart.orientationWorld),s=Rs(i.mouseRay,o,a),c=new Ss.Ray(this.dragStart.positionWorld,a),h=Rs(c,o,a),l=this.dragStart.orientationWorld.clone().multiply(r).clone().inverse();s.sub(h),s.applyQuaternion(l);var u=this.dragStart.event3d.intersection.point.clone();u.sub(h),u.applyQuaternion(l);var p=Math.atan2(s.y,s.z),d=Math.atan2(u.y,u.z)-p,f=new Ss.Quaternion;f.setFromAxisAngle(n,d),this.setOrientation(e,f.multiply(this.dragStart.orientationWorld)),i.stopPropagation()}}feedbackEvent(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})}startDrag(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var i=new Ss.Vector3;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,i),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}}stopDrag(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))}buttonClick(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)}setPosition(e,t){this.position.copy(t),this.feedbackEvent("user-pose-change",e)}setOrientation(e,t){t.normalize(),this.quaternion.copy(t),this.feedbackEvent("user-pose-change",e)}onServerSetPose(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.copy(t.position),this.quaternion.copy(t.orientation),this.updateMatrixWorld(!0)}}dispose(){this.children.forEach(function(e){e.children.forEach((function(t){t.dispose(),e.remove(t)})),this.remove(e)}.bind(this))}}class Hs extends EventEmitter3{constructor(e){super(),e=e||{},this.message=e.message,this.feedbackTopic=e.feedbackTopic,this.tfClient=e.tfClient,this.menuFontSize=e.menuFontSize||"0.8em",this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new r.Transform,this.pose=new r.Pose,this.setPoseFromClientBound=this.setPoseFromClient.bind(this),this.onMouseDownBound=this.onMouseDown.bind(this),this.onMouseUpBound=this.onMouseUp.bind(this),this.onButtonClickBound=this.onButtonClick.bind(this),this.onMenuSelectBound=this.onMenuSelect.bind(this),this.setPoseFromServer(this.message.pose),this.tfUpdateBound=this.tfUpdate.bind(this)}subscribeTf(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}unsubscribeTf(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}emitServerPoseUpdate(){var e=new r.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}setPoseFromServer(e){this.pose=new r.Pose(e),this.emitServerPoseUpdate()}tfUpdate(e){this.tfTransform=new r.Transform(e),this.emitServerPoseUpdate()}setPoseFromClient(e){this.pose=new r.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}onButtonClick(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}onMouseDown(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}onMouseUp(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}onMenuSelect(e){this.sendFeedback(2,void 0,e.id,e.controlName)}sendFeedback(e,t,i,r){var n=void 0!==t;t=t||{x:0,y:0,z:0};var o={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:r,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:n,menu_entry_id:i};this.feedbackTopic.publish(o)}}class Ws extends Ss.Object3D{constructor(e){super(),e=e||{},this.tfClient=e.tfClient,this.frameID=e.frameID;var t=e.object;this.pose=e.pose||new r.Pose,this.visible=!1,this.add(t),this.updatePose(this.pose),this.tfUpdate=function(e){var t=new r.Transform(e),i=new r.Pose(this.pose);i.applyTransform(t),this.updatePose(i),this.visible=!0},this.tfUpdateBound=this.tfUpdate.bind(this),this.tfClient.subscribe(this.frameID,this.tfUpdateBound)}updatePose(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}unsubscribeTf(){this.tfClient.unsubscribe(this.frameID,this.tfUpdateBound)}}class Xs extends EventEmitter3{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.markers={},this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var i=!1;if(t in this.markers&&((i=this.markers[t].children[0].update(e))||this.removeMarker(t)),!i){var r=new ks({message:e,path:this.path});this.markers[t]=new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var n in this.markers)this.removeMarker(n);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}}class qs extends EventEmitter3{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.lifetime=e.lifetime||0,this.markers={},this.rosTopic=void 0,this.updatedTime={},this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}checkTime(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){var t=e.ns+e.id,i=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),i?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var r=new ks({message:e,path:this.path});this.markers[t]=new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}this.emit("change")}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}}class Ys extends Ss.ArrowHelper{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1;e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Ss.MeshBasicMaterial,super(i,t,r,16711680)}dispose(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}class Zs extends Ss.Object3D{constructor(e){super();var t=this,i=(e=e||{}).shaftRadius||.008,r=e.headRadius||.023,n=e.headLength||.1,o=e.scale||1,a=e.lineType||"full",s=e.lineDashLength||.1;function c(e){var r=new Ss.Color;r.setRGB(e.x,e.y,e.z);var n=new Ss.MeshBasicMaterial({color:r.getHex()}),o=new Ss.Vector3;o.crossVectors(e,new Ss.Vector3(0,-1,0));var c=new Ss.Quaternion;c.setFromAxisAngle(o,.5*Math.PI);var h,l=new Ss.Mesh(t.headGeom,n);if(l.position.copy(e),l.position.multiplyScalar(.95),l.quaternion.copy(c),l.updateMatrix(),t.add(l),"dashed"===a)for(var u=s,p=0;u/2+3*u*p+u/2<=1;++p){var d=new Ss.CylinderGeometry(i,i,u);(h=new Ss.Mesh(d,n)).position.copy(e),h.position.multiplyScalar(u/2+3*u*p),h.quaternion.copy(c),h.updateMatrix(),t.add(h)}else"full"===a?((h=new Ss.Mesh(t.lineGeom,n)).position.copy(e),h.position.multiplyScalar(.45),h.quaternion.copy(c),h.updateMatrix(),t.add(h)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}this.scale.set(o,o,o),this.lineGeom=new Ss.CylinderGeometry(i,i,1-n),this.headGeom=new Ss.CylinderGeometry(0,r,n),c(new Ss.Vector3(1,0,0)),c(new Ss.Vector3(0,1,0)),c(new Ss.Vector3(0,0,1))}}class Js extends Ss.Object3D{constructor(e){var t=(e=e||{}).num_cells||10,i=e.color||"#cccccc",r=e.lineWidth||1,n=e.cellSize||1;super();for(var o=new Ss.LineBasicMaterial({color:i,linewidth:r}),a=0;a<=t;++a){var s=n*t/2,c=s-a*n,h=new Ss.Geometry;h.vertices.push(new Ss.Vector3(-s,c,0),new Ss.Vector3(s,c,0));var l=new Ss.Geometry;l.vertices.push(new Ss.Vector3(c,-s,0),new Ss.Vector3(c,s,0)),this.add(new Ss.Line(h,o)),this.add(new Ss.Line(l,o))}}}class Ks extends Ss.Mesh{constructor(e){var t=(e=e||{}).message,i=e.opacity||1,r=e.color||{r:255,g:255,b:255,a:255},n=t.info,o=n.origin,a=n.width,s=n.height,c=new Ss.PlaneBufferGeometry(a,s),h=new Uint8Array(a*s*4),l=new Ss.DataTexture(h,a,s,Ss.RGBAFormat);l.flipY=!0,l.minFilter=Ss.NearestFilter,l.magFilter=Ss.NearestFilter,l.needsUpdate=!0;var u=new Ss.MeshBasicMaterial({map:l,transparent:i<1,opacity:i});u.side=Ss.DoubleSide,super(c,u),Object.assign(this,e),this.quaternion.copy(new Ss.Quaternion(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),this.position.x=a*n.resolution/2+o.position.x,this.position.y=s*n.resolution/2+o.position.y,this.position.z=o.position.z,this.scale.x=n.resolution,this.scale.y=n.resolution;var p=t.data;this.color=r,this.material=u,this.texture=l;for(var d=0;d{const t="read"+e.kind,i="get"+e.kind;this[t]=()=>{if(this._cursor+e.width>this.length)throw new Error("Cannot read data stream. Overflow. Len="+this.length+" crsr="+this._cursor);const t=this._dataView[i](this._cursor,this.isLittleEndian);return this._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:()=>this.cursor>=this.data.length}),this}class oc{constructor(e){this.resolution=void 0!==e.resolution?e.resolution:1,this.color=new Ss.Color(void 0!==e.color?e.color:"green"),this.opacity=void 0!==e.opacity?e.opacity:1,this.voxelRenderMode=void 0!==e.voxelRenderMode?e.voxelRenderMode:ec,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);let t=this.resolution;for(let e=this._treeDepth-1;e>=0;--e)this.nodeSizeTable[e]=t,t*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}searchAtDepth(e,t){t=void 0!==t&&t>0?t:this._treeDepth;const i=this._adjustKeyAtDepth(e,t),r=this._treeDepth-t;let n=this._rootNode;for(let e=this._treeDepth-1;e>=r;--e){const t=this._computeChildIdx(i,e);if(!n.hasChildAt(t))return n.hasChildren()?null:n;n=n.getChildAt(t)}return n}_computeCoordFromKey(e){return e.map((e=>this.resolution*(e-this._treeMaxKeyVal)))}_computeChildIdx(e,t){let i=0;return e[0]&1<(e-this._treeMaxKeyVal>>i<0;){let e=i.pop();const r=t.readUint16();let n=8;for(;0!==n;){--n;const t=(r&3<<2*n)>>2*n;if(t!==this._BINARY_UNALLOCATED){let r=this._newNode();this._BINARY_CHILD_BUILD_TABLE[t].bind(this)(r),e.createChildNodeAt(r,n),t===this._BINARY_HAS_CHILDREN&&i.push(r)}}}}read(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();let t=new nc(e,!0),i=new Array;for(i.push(this._rootNode);i.length>0;){let e=i.pop();this._readNodeData(t,e);const r=t.readUint8();let n=8;for(;0!==n;){--n;if(r&1<0;){let i=t.pop();if(i.node.isLeafNode())e(i.node,i.key,i.depth-1);else for(let e=0;e<8;++e)if(i.node.hasChildAt(e)){const r=this._computeKeyFromChildIdx(e,i.key,i.depth);t.push({node:i.node.getChildAt(e),depth:i.depth+1,key:r})}}}_obtainColor(e){return this.color}_checkOccupied(e){return!1!==e.value}_buildFaces(){let e={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,i,r){const n=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*i,t[1]+e[1]*i,t[2]+e[2]*i)}));const o=[r.r,r.g,r.b];this.colors.push(...o,...o,...o,...o),this.normals.push(...e.normal,...e.normal,...e.normal,...e.normal),this.indices.push(n,n+1,n+2,n+2,n+1,n+3)},_checkNeighborsTouchingFace:function(e,t,i){let r=new Array;for(r.push(t);0!==r.length;){const t=r.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;{const n=t.getChildAt(e),o=this._checkOccupied(t);(o&&i===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!o&&i===tc)&&r.push(n)}}))}return!1}};return this._traverseLeaves(((t,i,r)=>{const n=this._computeCoordFromKey(i),o=this.nodeSizeTable[r],a=this._treeDepth-r,s=this._checkOccupied(t);(s||this.voxelRenderMode!==ec)&&(s&&this.voxelRenderMode===tc||this._FACES.forEach((function(s){const c=[i[0]+s.normal[0]*a*a,i[1]+s.normal[1]*a*a,i[2]+s.normal[2]*a*a],h=this.searchAtDepth(c);null===h?e._insertFace(s,n,o,this._obtainColor(t)):rnew Ss.Color(e))):[{r:0,g:0,b:128},{r:0,g:255,b:0},{r:255,g:255,b:0},{r:255,g:128,b:0},{r:255,g:0,b:0}],this.paletteScale=void 0!==e.paletteScale?e.paletteScale:1}_readNodeData(e,t){t.value=e.readFloat32()}_obtainColor(e){if(this.useFlatColoring)return this.color;const t=1/(1+Math.exp(-e.value*this.paletteScale))*this.palette.length,i=Math.trunc(t),r=t-i;return i<0?this.palette[0]:i>=this.palette.length-1?this.palette[this.palette.length-1]:{r:r*this.palette[i].r+(1-r)*this.palette[i+1].r,g:r*this.palette[i].g+(1-r)*this.palette[i+1].g,b:r*this.palette[i].b+(1-r)*this.palette[i+1].b}}_checkOccupied(e){return e.value>=this.occupancyThreshold}}class sc extends ac{constructor(e){super(e),this.useOwnColor=void 0!==e.palette&&e.colorMode===rc}_readNodeData(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}_obtainColor(e){return this.useOwnColor?e.color:ac.prototype._obtainColor.call(this,e)}}class cc extends EventEmitter3{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/octomap",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.options={},void 0!==e.color&&(this.options.color=e.color),void 0!==e.opacity&&(this.options.opacity=e.opacity),void 0!==e.colorMode&&(this.options.colorMode=e.colorMode),void 0!==e.palette&&(this.options.palette=e.palette),void 0!==e.paletteScale&&(this.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(this.options.voxelRenderMode=e.voxelRenderMode),this.currentMap=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}_loadOcTree(e){return new Promise(function(t,i){const r=Object.assign({resolution:e.resolution},this.options);let n=null;if(e.binary)n=new oc(r),n.readBinary(e.data);else{const t={OcTree:ac,ColorOcTree:sc};e.id in t&&(console.log(e.id,t),n=new t[e.id](r),n.read(e.data))}n.buildGeometry(),t(n)}.bind(this))}_processMessagePrivate(e){this._loadOcTree(e).then(function(t){const i=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(i),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}}class hc extends Ss.Object3D{constructor(e){super(),this.options=e||{},this.ros=e.ros,this.topicName=e.topic||"/particlecloud",this.tfClient=e.tfClient,this.color=e.color||13369599,this.length=e.length||1,this.rootObject=e.rootObject||new Ss.Object3D,this.keep=e.keep||1,this.sns=[],this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new Ss.Vector3(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new Ss.Quaternion(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new Ss.Vector3(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Ss.MeshBasicMaterial({color:this.color});var i=new Ns(this.options);this.sns.push(new Ws({frameID:e.header.frame_id,tfClient:this.tfClient,object:i})),this.rootObject.add(this.sns[this.sns.length-1])}}class lc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/path",this.tfClient=e.tfClient,this.color=e.color||13369599,this.rootObject=e.rootObject||new Ss.Object3D,this.sn=null,this.line=null,this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new Ss.Geometry,i=0;i=e.range_min&&n<=e.range_max){var o=e.angle_min+r*e.angle_increment;this.points.positions.array[i++]=n*Math.cos(o),this.points.positions.array[i++]=n*Math.sin(o),this.points.positions.array[i++]=0}}this.points.update(i/3)}}}class yc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/gps/fix",this.rootObject=e.rootObject||new Ss.Object3D,this.object3d=e.object3d||new Ss.Object3D;var t=e.material||{};this.altitudeNaN=e.altitudeNaN||0,this.keep=e.keep||100,this.convert=e.convert||function(e,t,i){return new Ss.Vector3(e,t,i)},this.count=0,this.next1=0,this.next2=this.keep,this.geom=new Ss.BufferGeometry,this.vertices=new Ss.BufferAttribute(new Float32Array(6*this.keep),3),this.geom.addAttribute("position",this.vertices),this.material=t.isMaterial?t:new Ss.LineBasicMaterial(t),this.line=new Ss.Line(this.geom,this.material),this.rootObject.add(this.object3d),this.rootObject.add(this.line),this.rosTopic=void 0,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,i=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(i),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=i.x,this.vertices.array[3*this.next1+1]=i.y,this.vertices.array[3*this.next1+2]=i.z,this.vertices.array[3*this.next2]=i.x,this.vertices.array[3*this.next2+1]=i.y,this.vertices.array[3*this.next2+2]=i.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}function xc(e,t,i,r){var n,o=0,a=0,s=0,c=e.length,h=t.length,l=((r=r||1)-1)*(i=i||h)*8;for(n=0;n=8&&(a-=8,t[s++]=o>>>a&255,s%i==0&&(n+=Math.ceil((l-a)/6),(a%=8)>0&&(o=xc.e[e.charAt(n)])));return Math.floor(s/i)}xc.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",xc.e={};for(var bc=0;bc<64;bc++)xc.e[xc.S.charAt(bc)]=bc;class wc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/points",this.throttle_rate=e.throttle_rate||null,this.compression=e.compression||"cbor",this.max_pts=e.max_pts||1e4,this.points=new vc(e),this.rosTopic=void 0,this.buffer=null,this.processMessageBound=this.processMessage.bind(this),this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}processMessage(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,i=this.points.pointRatio,r=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,r)),t=Math.min(e.height*e.width/i,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(r=d[0].object,p.intersection=this.lastIntersection=d[0]):r=this.fallbackTarget,r!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(r,"mouseover",p);0===f?this.notify(this.lastTarget,"mouseout",p):1===f&&(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(r,"mouseover",p),this.notify(this.lastTarget,"mouseout",p))}r!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(r,e.type,p)?(this.notify(this.lastTarget,"touchleave",p),this.notify(this.lastTarget,"touchend",p)):(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",p),this.notify(this.lastTarget,"touchend",p)));this.notify(r,e.type,p),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=r}notify(e,t,i){for(i.type=t,i.cancelBubble=!1,i.continueBubble=!1,i.stopPropagation=function(){i.cancelBubble=!0},i.continuePropagation=function(){i.continueBubble=!0},i.currentTarget=e;i.currentTarget;){if(i.currentTarget.dispatchEvent&&i.currentTarget.dispatchEvent instanceof Function){if(i.currentTarget.dispatchEvent(i),i.cancelBubble)return this.dispatchEvent(i),0;if(i.continueBubble)return 2}i.currentTarget=i.currentTarget.parent}return 1}}class Sc extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).scene;this.camera=e.camera,this.center=new Ss.Vector3,this.userZoom=!0,this.userZoomSpeed=e.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=e.userRotateSpeed||1,this.autoRotate=e.autoRotate,this.autoRotateSpeed=e.autoRotateSpeed||2,this.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,this.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",this.camera.up=new Ss.Vector3(0,0,1);var r=1800,n=new Ss.Vector2,o=new Ss.Vector2,a=new Ss.Vector2,s=new Ss.Vector2,c=new Ss.Vector2,h=new Ss.Vector2,l=new Ss.Vector3,u=new Ss.Vector3,p=new Ss.Vector3,d=new Ss.Vector3,f=new Array(2),m=new Array(2);this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new Ss.Vector3;var v=-1,g=0,y=1,x=2,b=v;function w(e,t,i){var r=new Ss.Vector3;new Ss.Vector3;r.subVectors(t,e.origin);var n=e.direction.dot(i);if(Math.abs(n)0?t.zoomIn():t.zoomOut(),this.showAxes()}}this.axes=new Zs({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:this.lineTypePanAndZoomFrame}),this.displayPanAndZoomFrame&&(i.add(this.axes),this.axes.traverse((function(e){e.visible=!1}))),this.addEventListener("mousedown",(function(e){var i=e.domEvent;switch(i.preventDefault(),i.button){case 0:b=g,n.set(i.clientX,i.clientY);break;case 1:b=x,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u);break;case 2:b=y,s.set(i.clientX,i.clientY)}this.showAxes()})),this.addEventListener("mouseup",(function(e){t.userRotate&&(b=v)})),this.addEventListener("mousemove",(function(e){var i=e.domEvent;if(b===g)o.set(i.clientX,i.clientY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else if(b===y)c.set(i.clientX,i.clientY),h.subVectors(c,s),h.y>0?t.zoomIn():t.zoomOut(),s.copy(c),this.showAxes();else if(b===x){var f=w(e.mouseRay,t.center,u);if(!f)return;var m=(new Ss.Vector3).subVectors(d.clone(),f.clone());t.center.addVectors(l.clone(),m.clone()),t.camera.position.addVectors(p.clone(),m.clone()),t.update(),t.camera.updateMatrixWorld(),this.showAxes()}})),this.addEventListener("touchstart",(function(e){var i=e.domEvent;switch(i.touches.length){case 1:b=g,n.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY);break;case 2:b=v,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u),f[0]=new Ss.Vector2(i.touches[0].pageX,i.touches[0].pageY),f[1]=new Ss.Vector2(i.touches[1].pageX,i.touches[1].pageY),m[0]=new Ss.Vector2(0,0),m[1]=new Ss.Vector2(0,0)}this.showAxes(),i.preventDefault()})),this.addEventListener("touchmove",(function(e){var i=e.domEvent;if(b===g)o.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else{if(m[0].set(f[0].x-i.touches[0].pageX,f[0].y-i.touches[0].pageY),m[1].set(f[1].x-i.touches[1].pageX,f[1].y-i.touches[1].pageY),m[0].lengthSq()>10&&m[1].lengthSq()>10&&(f[0].set(i.touches[0].pageX,i.touches[0].pageY),f[1].set(i.touches[1].pageX,i.touches[1].pageY),m[0].dot(m[1])>0&&b!==y?b=x:m[0].dot(m[1])<0&&b!==x&&(b=y),b===y)){var s=new Ss.Vector2;s.subVectors(f[0],f[1]),m[0].dot(s)<0&&m[1].dot(s)>0?t.zoomOut():m[0].dot(s)>0&&m[1].dot(s)<0&&t.zoomIn()}if(b===x){var c=w(e.mouseRay,t.center,u);if(!c)return;var h=(new Ss.Vector3).subVectors(d.clone(),c.clone());t.center.addVectors(l.clone(),h.clone()),t.camera.position.addVectors(p.clone(),h.clone()),t.update(),t.camera.updateMatrixWorld()}this.showAxes(),i.preventDefault()}})),this.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&b!==g?(b=g,n.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):b=v})),this.addEventListener("mousewheel",_),this.addEventListener("DOMMouseScroll",_)}showAxes(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}rotateLeft(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}rotateRight(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}rotateUp(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}rotateDown(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}zoomIn(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}zoomOut(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}update(){var e=this.camera.position,t=e.clone().sub(this.center),i=Math.atan2(t.y,t.x),r=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),i+=this.thetaDelta,r+=this.phiDelta;var n=1e-6;r=Math.max(n,Math.min(Math.PI-n,r));var o=t.length();t.set(o*Math.sin(r)*Math.cos(i),o*Math.sin(r)*Math.sin(i),o*Math.cos(r)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),o=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*o,.05*o,.05*o),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}return e.Arrow=Ns,e.Arrow2=Ys,e.Axes=Zs,e.ColorOcTree=sc,e.DepthCloud=Ps,e.Grid=Js,e.Highlighter=Ec,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=js,e.InteractiveMarkerClient=class{constructor(e){e=e||{},this.ros=e.ros,this.tfClient=e.tfClient,this.topicName=e.topic,this.path=e.path||"/",this.camera=e.camera,this.rootObject=e.rootObject||new Ss.Object3D,this.loader=e.loader,this.menuFontSize=e.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.processUpdateBound=this.processUpdate.bind(this),this.topicName&&this.subscribe(this.topicName)}subscribe(e){this.unsubscribe(),this.updateTopic=new r.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdateBound),this.feedbackTopic=new r.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new r.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new r.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}unsubscribe(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdateBound),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}processInit(e){var t=e.msg;for(var i in t.erases=[],this.interactiveMarkers)t.erases.push(i);t.poses=[],this.processUpdate(t)}processUpdate(e){e.erases.forEach((function(e){this.eraseIntMarker(e)})),e.poses.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&t.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&this.eraseIntMarker(t.name);var i=new Hs({message:e,feedbackTopic:this.feedbackTopic,tfClient:this.tfClient,menuFontSize:this.menuFontSize});this.interactiveMarkers[e.name]=i;var r=new js({handle:i,camera:this.camera,path:this.path,loader:this.loader});r.name=e.name,this.rootObject.add(r),i.on("pose",(function(e){r.onServerSetPose({pose:e})})),r.addEventListener("user-pose-change",i.setPoseFromClientBound),r.addEventListener("user-mousedown",i.onMouseDownBound),r.addEventListener("user-mouseup",i.onMouseUpBound),r.addEventListener("user-button-click",i.onButtonClickBound),r.addEventListener("menu-select",i.onMenuSelectBound),i.subscribeTf()}))}eraseIntMarker(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var i=this.interactiveMarkers[e];i.unsubscribeTf(),t.removeEventListener("user-pose-change",i.setPoseFromClientBound),t.removeEventListener("user-mousedown",i.onMouseDownBound),t.removeEventListener("user-mouseup",i.onMouseUpBound),t.removeEventListener("user-button-click",i.onButtonClickBound),t.removeEventListener("menu-select",i.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}},e.InteractiveMarkerControl=Gs,e.InteractiveMarkerHandle=Hs,e.InteractiveMarkerMenu=Vs,e.LaserScan=gc,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=ks,e.MarkerArrayClient=Xs,e.MarkerClient=qs,e.MeshLoader=Bs,e.MeshResource=Fs,e.MouseHandler=Tc,e.NavSatFix=yc,e.OcTree=ac,e.OcTreeClient=cc,e.OccupancyGrid=Ks,e.OccupancyGridClient=Qs,e.Odometry=hc,e.OrbitControls=Sc,e.Path=lc,e.Point=uc,e.PointCloud2=wc,e.Points=vc,e.Polygon=pc,e.Pose=dc,e.PoseArray=fc,e.PoseWithCovariance=mc,e.SceneNode=Ws,e.TFAxes=_c,e.TriangleList=zs,e.Urdf=Mc,e.UrdfClient=class{constructor(e){var t=(e=e||{}).ros;this.param=e.param||"robot_description",this.path=e.path||"/",this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.tfPrefix=e.tfPrefix||"",this.loader=e.loader,new r.Param({ros:t,name:this.param}).get(function(e){var t=new r.UrdfModel({string:e});this.urdf=new Mc({urdfModel:t,path:this.path,tfClient:this.tfClient,tfPrefix:this.tfPrefix,loader:this.loader}),this.rootObject.add(this.urdf)}.bind(this))}},e.Viewer=class{constructor(e){var t=(e=e||{}).divID,i=e.elem,r=e.width,n=e.height,o=e.background||"#111111",a=e.antialias,s=e.intensity||.66,c=e.near||.01,h=e.far||1e3,l=e.alpha||1,u=e.cameraPose||{x:3,y:3,z:3},p=e.cameraZoomSpeed||.5,d=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,f=e.lineTypePanAndZoomFrame||"full";this.renderer=new Ss.WebGLRenderer({antialias:a,alpha:!0}),this.renderer.setClearColor(parseInt(o.replace("#","0x"),16),l),this.renderer.sortObjects=!1,this.renderer.setSize(r,n),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ss.Scene,this.camera=new Ss.PerspectiveCamera(40,r/n,c,h),this.camera.position.x=u.x,this.camera.position.y=u.y,this.camera.position.z=u.z,this.cameraControls=new Sc({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:d,lineTypePanAndZoomFrame:f}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Ss.AmbientLight(5592405)),this.directionalLight=new Ss.DirectionalLight(16777215,s),this.scene.add(this.directionalLight),this.selectableObjects=new Ss.Group,this.scene.add(this.selectableObjects);var m=new Tc({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ec({mouseHandler:m}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(t)).appendChild(this.renderer.domElement),this.start()}start(){this.stopped=!1,this.draw()}draw(){this.stopped||(this.cameraControls.update(),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}stop(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}addObject(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}},e.closestAxisPoint=Cs,e.findClosestPoint=Ls,e.intersectPlane=Rs,e.makeColorMaterial=As,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); +var ROS3D=function(e,t){"use strict";function n(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var i=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,i.get?i:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var i=n(t); +/** + * @license + * Copyright 2010-2024 Three.js Authors + * SPDX-License-Identifier: MIT + */const r="167",a=100,s=204,o=205,l="attached",c=301,h=302,u=306,d=1e3,p=1001,f=1002,m=1003,g=1005,v=1006,_=1007,y=1008,x=1009,b=1010,M=1011,S=1012,E=1013,w=1014,T=1015,A=1016,R=1017,C=1018,L=1020,P=35902,I=1023,N=1026,U=1027,D=1029,O=1031,F=1033,k=33776,B=33777,z=33778,H=33779,V=35840,G=35841,W=35842,j=35843,X=36196,q=37492,Y=37496,K=37808,Z=37809,J=37810,Q=37811,$=37812,ee=37813,te=37814,ne=37815,ie=37816,re=37817,ae=37818,se=37819,oe=37820,le=37821,ce=36492,he=36494,ue=36495,de=36284,pe=36285,fe=36286,me=2300,ge=2301,ve=2302,_e="",ye="srgb",xe="srgb-linear",be="display-p3",Me="display-p3-linear",Se="linear",Ee="srgb",we="rec709",Te="p3",Ae=7680,Re=35044,Ce="300 es",Le=2e3,Pe=2001;class Ie{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[e]&&(n[e]=[]),-1===n[e].indexOf(t)&&n[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[e]&&-1!==n[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;const n=this._listeners[e];if(void 0!==n){const e=n.indexOf(t);-1!==e&&n.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;const t=this._listeners[e.type];if(void 0!==t){e.target=this;const n=t.slice(0);for(let t=0,i=n.length;t>8&255]+Ne[e>>16&255]+Ne[e>>24&255]+"-"+Ne[255&t]+Ne[t>>8&255]+"-"+Ne[t>>16&15|64]+Ne[t>>24&255]+"-"+Ne[63&n|128]+Ne[n>>8&255]+"-"+Ne[n>>16&255]+Ne[n>>24&255]+Ne[255&i]+Ne[i>>8&255]+Ne[i>>16&255]+Ne[i>>24&255]).toLowerCase()}function ke(e,t,n){return Math.max(t,Math.min(n,e))}function Be(e,t){return(e%t+t)%t}function ze(e,t,n){return(1-n)*e+n*t}function He(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw new Error("Invalid component type.")}}function Ve(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw new Error("Invalid component type.")}}const Ge={DEG2RAD:De,RAD2DEG:Oe,generateUUID:Fe,clamp:ke,euclideanModulo:Be,mapLinear:function(e,t,n,i,r){return i+(e-t)*(r-i)/(n-t)},inverseLerp:function(e,t,n){return e!==t?(n-e)/(t-e):0},lerp:ze,damp:function(e,t,n,i){return ze(e,t,1-Math.exp(-n*i))},pingpong:function(e,t=1){return t-Math.abs(Be(e,2*t)-t)},smoothstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*(3-2*e)},smootherstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},seededRandom:function(e){void 0!==e&&(Ue=e);let t=Ue+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296},degToRad:function(e){return e*De},radToDeg:function(e){return e*Oe},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,n,i,r){const a=Math.cos,s=Math.sin,o=a(n/2),l=s(n/2),c=a((t+i)/2),h=s((t+i)/2),u=a((t-i)/2),d=s((t-i)/2),p=a((i-t)/2),f=s((i-t)/2);switch(r){case"XYX":e.set(o*h,l*u,l*d,o*c);break;case"YZY":e.set(l*d,o*h,l*u,o*c);break;case"ZXZ":e.set(l*u,l*d,o*h,o*c);break;case"XZX":e.set(o*h,l*f,l*p,o*c);break;case"YXY":e.set(l*p,o*h,l*f,o*c);break;case"ZYZ":e.set(l*f,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Ve,denormalize:He};class We{constructor(e=0,t=0){We.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,n=this.y,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6],this.y=i[1]*t+i[4]*n+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.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(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(ke(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const n=Math.cos(t),i=Math.sin(t),r=this.x-e.x,a=this.y-e.y;return this.x=r*n-a*i+e.x,this.y=r*i+a*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class je{constructor(e,t,n,i,r,a,s,o,l){je.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,n,i,r,a,s,o,l)}set(e,t,n,i,r,a,s,o,l){const c=this.elements;return c[0]=e,c[1]=i,c[2]=s,c[3]=t,c[4]=r,c[5]=o,c[6]=n,c[7]=a,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,i=t.elements,r=this.elements,a=n[0],s=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],f=i[0],m=i[3],g=i[6],v=i[1],_=i[4],y=i[7],x=i[2],b=i[5],M=i[8];return r[0]=a*f+s*v+o*x,r[3]=a*m+s*_+o*b,r[6]=a*g+s*y+o*M,r[1]=l*f+c*v+h*x,r[4]=l*m+c*_+h*b,r[7]=l*g+c*y+h*M,r[2]=u*f+d*v+p*x,r[5]=u*m+d*_+p*b,r[8]=u*g+d*y+p*M,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8];return t*a*c-t*s*l-n*r*c+n*s*o+i*r*l-i*a*o}invert(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8],h=c*a-s*l,u=s*o-c*r,d=l*r-a*o,p=t*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const f=1/p;return e[0]=h*f,e[1]=(i*l-c*n)*f,e[2]=(s*n-i*a)*f,e[3]=u*f,e[4]=(c*t-i*o)*f,e[5]=(i*r-s*t)*f,e[6]=d*f,e[7]=(n*o-l*t)*f,e[8]=(a*t-n*r)*f,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,i,r,a,s){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*a+l*s)+a+e,-i*l,i*o,-i*(-l*a+o*s)+s+t,0,0,1),this}scale(e,t){return this.premultiply(Xe.makeScale(e,t)),this}rotate(e){return this.premultiply(Xe.makeRotation(-e)),this}translate(e,t){return this.premultiply(Xe.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,n=e.elements;for(let e=0;e<9;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return(new this.constructor).fromArray(this.elements)}}const Xe=new je;function qe(e){for(let t=e.length-1;t>=0;--t)if(e[t]>=65535)return!0;return!1}function Ye(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}function Ke(){const e=Ye("canvas");return e.style.display="block",e}const Ze={};function Je(e){e in Ze||(Ze[e]=!0,console.warn(e))}const Qe=(new je).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),$e=(new je).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),et={[xe]:{transfer:Se,primaries:we,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[ye]:{transfer:Ee,primaries:we,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[Me]:{transfer:Se,primaries:Te,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3($e),fromReference:e=>e.applyMatrix3(Qe)},[be]:{transfer:Ee,primaries:Te,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3($e),fromReference:e=>e.applyMatrix3(Qe).convertLinearToSRGB()}},tt=new Set([xe,Me]),nt={enabled:!0,_workingColorSpace:xe,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!tt.has(e))throw new Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,n){if(!1===this.enabled||t===n||!t||!n)return e;const i=et[t].toReference;return(0,et[n].fromReference)(i(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return et[e].primaries},getTransfer:function(e){return e===_e?Se:et[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(et[t].luminanceCoefficients)}};function it(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function rt(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let at;let st=0;class ot{constructor(e=null){this.isSource=!0,Object.defineProperty(this,"id",{value:st++}),this.uuid=Fe(),this.data=e,this.dataReady=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}toJSON(e){const t=void 0===e||"string"==typeof e;if(!t&&void 0!==e.images[this.uuid])return e.images[this.uuid];const n={uuid:this.uuid,url:""},i=this.data;if(null!==i){let e;if(Array.isArray(i)){e=[];for(let t=0,n=i.length;t2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){const t=Ye("canvas");t.width=e.width,t.height=e.height;const n=t.getContext("2d");n.drawImage(e,0,0,e.width,e.height);const i=n.getImageData(0,0,e.width,e.height),r=i.data;for(let e=0;e0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(300!==this.mapping)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case d:e.x=e.x-Math.floor(e.x);break;case p:e.x=e.x<0?0:1;break;case f:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case d:e.y=e.y-Math.floor(e.y);break;case p:e.y=e.y<0?0:1;break;case f:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){!0===e&&this.pmremVersion++}}ht.DEFAULT_IMAGE=null,ht.DEFAULT_MAPPING=300,ht.DEFAULT_ANISOTROPY=1;class ut{constructor(e=0,t=0,n=0,i=1){ut.prototype.isVector4=!0,this.x=e,this.y=t,this.z=n,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,i){return this.x=e,this.y=t,this.z=n,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){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: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,n=this.y,i=this.z,r=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*t+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*t+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*t+a[7]*n+a[11]*i+a[15]*r,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,n,i,r;const a=.01,s=.1,o=e.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],f=o[2],m=o[6],g=o[10];if(Math.abs(c-u)o&&e>v?ev?o=0?1:-1,i=1-t*t;if(i>Number.EPSILON){const r=Math.sqrt(i),a=Math.atan2(r,t*n);e=Math.sin(e*a)/r,s=Math.sin(s*a)/r}const r=s*n;if(o=o*e+u*r,l=l*e+d*r,c=c*e+p*r,h=h*e+f*r,e===1-s){const e=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=e,l*=e,c*=e,h*=e}}e[t]=o,e[t+1]=l,e[t+2]=c,e[t+3]=h}static multiplyQuaternionsFlat(e,t,n,i,r,a){const s=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[a],u=r[a+1],d=r[a+2],p=r[a+3];return e[t]=s*p+c*h+o*d-l*u,e[t+1]=o*p+c*u+l*h-s*d,e[t+2]=l*p+c*d+s*u-o*h,e[t+3]=c*p-s*h-o*u-l*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const n=e._x,i=e._y,r=e._z,a=e._order,s=Math.cos,o=Math.sin,l=s(n/2),c=s(i/2),h=s(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(a){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return!0===t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const n=t/2,i=Math.sin(n);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,n=t[0],i=t[4],r=t[8],a=t[1],s=t[5],o=t[9],l=t[2],c=t[6],h=t[10],u=n+s+h;if(u>0){const e=.5/Math.sqrt(u+1);this._w=.25/e,this._x=(c-o)*e,this._y=(r-l)*e,this._z=(a-i)*e}else if(n>s&&n>h){const e=2*Math.sqrt(1+n-s-h);this._w=(c-o)/e,this._x=.25*e,this._y=(i+a)/e,this._z=(r+l)/e}else if(s>h){const e=2*Math.sqrt(1+s-n-h);this._w=(r-l)/e,this._x=(i+a)/e,this._y=.25*e,this._z=(o+c)/e}else{const e=2*Math.sqrt(1+h-n-s);this._w=(a-i)/e,this._x=(r+l)/e,this._y=(o+c)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return nMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(ke(this.dot(e),-1,1)))}rotateTowards(e,t){const n=this.angleTo(e);if(0===n)return this;const i=Math.min(1,t/n);return this.slerp(e,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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 e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const n=e._x,i=e._y,r=e._z,a=e._w,s=t._x,o=t._y,l=t._z,c=t._w;return this._x=n*c+a*s+i*l-r*o,this._y=i*c+a*o+r*s-n*l,this._z=r*c+a*l+n*o-i*s,this._w=a*c-n*s-i*o-r*l,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);const n=this._x,i=this._y,r=this._z,a=this._w;let s=a*e._w+n*e._x+i*e._y+r*e._z;if(s<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,s=-s):this.copy(e),s>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;const o=1-s*s;if(o<=Number.EPSILON){const e=1-t;return this._w=e*a+t*this._w,this._x=e*n+t*this._x,this._y=e*i+t*this._y,this._z=e*r+t*this._z,this.normalize(),this}const l=Math.sqrt(o),c=Math.atan2(l,s),h=Math.sin((1-t)*c)/l,u=Math.sin(t*c)/l;return this._w=a*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),i=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(i*Math.sin(e),i*Math.cos(e),r*Math.sin(t),r*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class vt{constructor(e=0,t=0,n=0){vt.prototype.isVector3=!0,this.x=e,this.y=t,this.z=n}set(e,t,n){return void 0===n&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(yt.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(yt.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6]*i,this.y=r[1]*t+r[4]*n+r[7]*i,this.z=r[2]*t+r[5]*n+r[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,n=this.y,i=this.z,r=e.elements,a=1/(r[3]*t+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*t+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*t+r[6]*n+r[10]*i+r[14])*a,this}applyQuaternion(e){const t=this.x,n=this.y,i=this.z,r=e.x,a=e.y,s=e.z,o=e.w,l=2*(a*i-s*n),c=2*(s*t-r*i),h=2*(r*n-a*t);return this.x=t+o*l+a*h-s*c,this.y=n+o*c+s*l-r*h,this.z=i+o*h+r*c-a*l,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*n+r[8]*i,this.y=r[1]*t+r[5]*n+r[9]*i,this.z=r[2]*t+r[6]*n+r[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.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(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const n=e.x,i=e.y,r=e.z,a=t.x,s=t.y,o=t.z;return this.x=i*o-r*s,this.y=r*a-n*o,this.z=n*s-i*a,this}projectOnVector(e){const t=e.lengthSq();if(0===t)return this.set(0,0,0);const n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return _t.copy(this).projectOnVector(e),this.sub(_t)}reflect(e){return this.sub(_t.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(ke(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y,i=this.z-e.z;return t*t+n*n+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){const i=Math.sin(t)*e;return this.x=i*Math.sin(n),this.y=Math.cos(t)*e,this.z=i*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=2*Math.random()-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const _t=new vt,yt=new gt;class xt{constructor(e=new vt(1/0,1/0,1/0),t=new vt(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Mt),Mt.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Lt),Pt.subVectors(this.max,Lt),Et.subVectors(e.a,Lt),wt.subVectors(e.b,Lt),Tt.subVectors(e.c,Lt),At.subVectors(wt,Et),Rt.subVectors(Tt,wt),Ct.subVectors(Et,Tt);let t=[0,-At.z,At.y,0,-Rt.z,Rt.y,0,-Ct.z,Ct.y,At.z,0,-At.x,Rt.z,0,-Rt.x,Ct.z,0,-Ct.x,-At.y,At.x,0,-Rt.y,Rt.x,0,-Ct.y,Ct.x,0];return!!Ut(t,Et,wt,Tt,Pt)&&(t=[1,0,0,0,1,0,0,0,1],!!Ut(t,Et,wt,Tt,Pt)&&(It.crossVectors(At,Rt),t=[It.x,It.y,It.z],Ut(t,Et,wt,Tt,Pt)))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Mt).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Mt).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(bt[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),bt[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),bt[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),bt[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),bt[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),bt[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),bt[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),bt[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(bt)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const bt=[new vt,new vt,new vt,new vt,new vt,new vt,new vt,new vt],Mt=new vt,St=new xt,Et=new vt,wt=new vt,Tt=new vt,At=new vt,Rt=new vt,Ct=new vt,Lt=new vt,Pt=new vt,It=new vt,Nt=new vt;function Ut(e,t,n,i,r){for(let a=0,s=e.length-3;a<=s;a+=3){Nt.fromArray(e,a);const s=r.x*Math.abs(Nt.x)+r.y*Math.abs(Nt.y)+r.z*Math.abs(Nt.z),o=t.dot(Nt),l=n.dot(Nt),c=i.dot(Nt);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>s)return!1}return!0}const Dt=new xt,Ot=new vt,Ft=new vt;class kt{constructor(e=new vt,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const n=this.center;void 0!==t?n.copy(t):Dt.setFromPoints(e).getCenter(n);let i=0;for(let t=0,r=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Ot.subVectors(e,this.center);const t=Ot.lengthSq();if(t>this.radius*this.radius){const e=Math.sqrt(t),n=.5*(e-this.radius);this.center.addScaledVector(Ot,n/e),this.radius+=n}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(Ft.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Ot.copy(e.center).add(Ft)),this.expandByPoint(Ot.copy(e.center).sub(Ft))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Bt=new vt,zt=new vt,Ht=new vt,Vt=new vt,Gt=new vt,Wt=new vt,jt=new vt;class Xt{constructor(e=new vt,t=new vt(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Bt)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=Bt.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Bt.copy(this.origin).addScaledVector(this.direction,t),Bt.distanceToSquared(e))}distanceSqToSegment(e,t,n,i){zt.copy(e).add(t).multiplyScalar(.5),Ht.copy(t).sub(e).normalize(),Vt.copy(this.origin).sub(zt);const r=.5*e.distanceTo(t),a=-this.direction.dot(Ht),s=Vt.dot(this.direction),o=-Vt.dot(Ht),l=Vt.lengthSq(),c=Math.abs(1-a*a);let h,u,d,p;if(c>0)if(h=a*o-s,u=a*s-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const e=1/c;h*=e,u*=e,d=h*(h+a*u+2*s)+u*(a*h+u+2*o)+l}else u=r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-a*r+s)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(a*r+s)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=a>0?-r:r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(zt).addScaledVector(Ht,u),d}intersectSphere(e,t){Bt.subVectors(e.center,this.origin);const n=Bt.dot(this.direction),i=Bt.dot(Bt)-n*n,r=e.radius*e.radius;if(i>r)return null;const a=Math.sqrt(r-i),s=n-a,o=n+a;return o<0?null:s<0?this.at(o,t):this.at(s,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){const n=this.distanceToPlane(e);return null===n?null:this.at(n,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);if(0===t)return!0;return e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,i,r,a,s,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(e.min.x-u.x)*l,i=(e.max.x-u.x)*l):(n=(e.max.x-u.x)*l,i=(e.min.x-u.x)*l),c>=0?(r=(e.min.y-u.y)*c,a=(e.max.y-u.y)*c):(r=(e.max.y-u.y)*c,a=(e.min.y-u.y)*c),n>a||r>i?null:((r>n||isNaN(n))&&(n=r),(a=0?(s=(e.min.z-u.z)*h,o=(e.max.z-u.z)*h):(s=(e.max.z-u.z)*h,o=(e.min.z-u.z)*h),n>o||s>i?null:((s>n||n!=n)&&(n=s),(o=0?n:i,t)))}intersectsBox(e){return null!==this.intersectBox(e,Bt)}intersectTriangle(e,t,n,i,r){Gt.subVectors(t,e),Wt.subVectors(n,e),jt.crossVectors(Gt,Wt);let a,s=this.direction.dot(jt);if(s>0){if(i)return null;a=1}else{if(!(s<0))return null;a=-1,s=-s}Vt.subVectors(this.origin,e);const o=a*this.direction.dot(Wt.crossVectors(Vt,Wt));if(o<0)return null;const l=a*this.direction.dot(Gt.cross(Vt));if(l<0)return null;if(o+l>s)return null;const c=-a*Vt.dot(jt);return c<0?null:this.at(c/s,r)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class qt{constructor(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m){qt.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m)}set(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m){const g=this.elements;return g[0]=e,g[4]=t,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=s,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=f,g[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new qt).fromArray(this.elements)}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this}copyPosition(e){const t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,n=e.elements,i=1/Yt.setFromMatrixColumn(e,0).length(),r=1/Yt.setFromMatrixColumn(e,1).length(),a=1/Yt.setFromMatrixColumn(e,2).length();return t[0]=n[0]*i,t[1]=n[1]*i,t[2]=n[2]*i,t[3]=0,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,n=e.x,i=e.y,r=e.z,a=Math.cos(n),s=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===e.order){const e=a*c,n=a*h,i=s*c,r=s*h;t[0]=o*c,t[4]=-o*h,t[8]=l,t[1]=n+i*l,t[5]=e-r*l,t[9]=-s*o,t[2]=r-e*l,t[6]=i+n*l,t[10]=a*o}else if("YXZ"===e.order){const e=o*c,n=o*h,i=l*c,r=l*h;t[0]=e+r*s,t[4]=i*s-n,t[8]=a*l,t[1]=a*h,t[5]=a*c,t[9]=-s,t[2]=n*s-i,t[6]=r+e*s,t[10]=a*o}else if("ZXY"===e.order){const e=o*c,n=o*h,i=l*c,r=l*h;t[0]=e-r*s,t[4]=-a*h,t[8]=i+n*s,t[1]=n+i*s,t[5]=a*c,t[9]=r-e*s,t[2]=-a*l,t[6]=s,t[10]=a*o}else if("ZYX"===e.order){const e=a*c,n=a*h,i=s*c,r=s*h;t[0]=o*c,t[4]=i*l-n,t[8]=e*l+r,t[1]=o*h,t[5]=r*l+e,t[9]=n*l-i,t[2]=-l,t[6]=s*o,t[10]=a*o}else if("YZX"===e.order){const e=a*o,n=a*l,i=s*o,r=s*l;t[0]=o*c,t[4]=r-e*h,t[8]=i*h+n,t[1]=h,t[5]=a*c,t[9]=-s*c,t[2]=-l*c,t[6]=n*h+i,t[10]=e-r*h}else if("XZY"===e.order){const e=a*o,n=a*l,i=s*o,r=s*l;t[0]=o*c,t[4]=-h,t[8]=l*c,t[1]=e*h+r,t[5]=a*c,t[9]=n*h-i,t[2]=i*h-n,t[6]=s*c,t[10]=r*h+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(Zt,e,Jt)}lookAt(e,t,n){const i=this.elements;return en.subVectors(e,t),0===en.lengthSq()&&(en.z=1),en.normalize(),Qt.crossVectors(n,en),0===Qt.lengthSq()&&(1===Math.abs(n.z)?en.x+=1e-4:en.z+=1e-4,en.normalize(),Qt.crossVectors(n,en)),Qt.normalize(),$t.crossVectors(en,Qt),i[0]=Qt.x,i[4]=$t.x,i[8]=en.x,i[1]=Qt.y,i[5]=$t.y,i[9]=en.y,i[2]=Qt.z,i[6]=$t.z,i[10]=en.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,i=t.elements,r=this.elements,a=n[0],s=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],f=n[6],m=n[10],g=n[14],v=n[3],_=n[7],y=n[11],x=n[15],b=i[0],M=i[4],S=i[8],E=i[12],w=i[1],T=i[5],A=i[9],R=i[13],C=i[2],L=i[6],P=i[10],I=i[14],N=i[3],U=i[7],D=i[11],O=i[15];return r[0]=a*b+s*w+o*C+l*N,r[4]=a*M+s*T+o*L+l*U,r[8]=a*S+s*A+o*P+l*D,r[12]=a*E+s*R+o*I+l*O,r[1]=c*b+h*w+u*C+d*N,r[5]=c*M+h*T+u*L+d*U,r[9]=c*S+h*A+u*P+d*D,r[13]=c*E+h*R+u*I+d*O,r[2]=p*b+f*w+m*C+g*N,r[6]=p*M+f*T+m*L+g*U,r[10]=p*S+f*A+m*P+g*D,r[14]=p*E+f*R+m*I+g*O,r[3]=v*b+_*w+y*C+x*N,r[7]=v*M+_*T+y*L+x*U,r[11]=v*S+_*A+y*P+x*D,r[15]=v*E+_*R+y*I+x*O,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[4],i=e[8],r=e[12],a=e[1],s=e[5],o=e[9],l=e[13],c=e[2],h=e[6],u=e[10],d=e[14];return e[3]*(+r*o*h-i*l*h-r*s*u+n*l*u+i*s*d-n*o*d)+e[7]*(+t*o*d-t*l*u+r*a*u-i*a*d+i*l*c-r*o*c)+e[11]*(+t*l*h-t*s*d-r*a*h+n*a*d+r*s*c-n*l*c)+e[15]*(-i*s*c-t*o*h+t*s*u+i*a*h-n*a*u+n*o*c)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,n){const i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=n),this}invert(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8],h=e[9],u=e[10],d=e[11],p=e[12],f=e[13],m=e[14],g=e[15],v=h*m*l-f*u*l+f*o*d-s*m*d-h*o*g+s*u*g,_=p*u*l-c*m*l-p*o*d+a*m*d+c*o*g-a*u*g,y=c*f*l-p*h*l+p*s*d-a*f*d-c*s*g+a*h*g,x=p*h*o-c*f*o-p*s*u+a*f*u+c*s*m-a*h*m,b=t*v+n*_+i*y+r*x;if(0===b)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const M=1/b;return e[0]=v*M,e[1]=(f*u*r-h*m*r-f*i*d+n*m*d+h*i*g-n*u*g)*M,e[2]=(s*m*r-f*o*r+f*i*l-n*m*l-s*i*g+n*o*g)*M,e[3]=(h*o*r-s*u*r-h*i*l+n*u*l+s*i*d-n*o*d)*M,e[4]=_*M,e[5]=(c*m*r-p*u*r+p*i*d-t*m*d-c*i*g+t*u*g)*M,e[6]=(p*o*r-a*m*r-p*i*l+t*m*l+a*i*g-t*o*g)*M,e[7]=(a*u*r-c*o*r+c*i*l-t*u*l-a*i*d+t*o*d)*M,e[8]=y*M,e[9]=(p*h*r-c*f*r-p*n*d+t*f*d+c*n*g-t*h*g)*M,e[10]=(a*f*r-p*s*r+p*n*l-t*f*l-a*n*g+t*s*g)*M,e[11]=(c*s*r-a*h*r-c*n*l+t*h*l+a*n*d-t*s*d)*M,e[12]=x*M,e[13]=(c*f*i-p*h*i+p*n*u-t*f*u-c*n*m+t*h*m)*M,e[14]=(p*s*i-a*f*i-p*n*o+t*f*o+a*n*m-t*s*m)*M,e[15]=(a*h*i-c*s*i+c*n*o-t*h*o-a*n*u+t*s*u)*M,this}scale(e){const t=this.elements,n=e.x,i=e.y,r=e.z;return t[0]*=n,t[4]*=i,t[8]*=r,t[1]*=n,t[5]*=i,t[9]*=r,t[2]*=n,t[6]*=i,t[10]*=r,t[3]*=n,t[7]*=i,t[11]*=r,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,i))}makeTranslation(e,t,n){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const n=Math.cos(t),i=Math.sin(t),r=1-n,a=e.x,s=e.y,o=e.z,l=r*a,c=r*s;return this.set(l*a+n,l*s-i*o,l*o+i*s,0,l*s+i*o,c*s+n,c*o-i*a,0,l*o-i*s,c*o+i*a,r*o*o+n,0,0,0,0,1),this}makeScale(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this}makeShear(e,t,n,i,r,a){return this.set(1,n,r,0,e,1,a,0,t,i,1,0,0,0,0,1),this}compose(e,t,n){const i=this.elements,r=t._x,a=t._y,s=t._z,o=t._w,l=r+r,c=a+a,h=s+s,u=r*l,d=r*c,p=r*h,f=a*c,m=a*h,g=s*h,v=o*l,_=o*c,y=o*h,x=n.x,b=n.y,M=n.z;return i[0]=(1-(f+g))*x,i[1]=(d+y)*x,i[2]=(p-_)*x,i[3]=0,i[4]=(d-y)*b,i[5]=(1-(u+g))*b,i[6]=(m+v)*b,i[7]=0,i[8]=(p+_)*M,i[9]=(m-v)*M,i[10]=(1-(u+f))*M,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this}decompose(e,t,n){const i=this.elements;let r=Yt.set(i[0],i[1],i[2]).length();const a=Yt.set(i[4],i[5],i[6]).length(),s=Yt.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],Kt.copy(this);const o=1/r,l=1/a,c=1/s;return Kt.elements[0]*=o,Kt.elements[1]*=o,Kt.elements[2]*=o,Kt.elements[4]*=l,Kt.elements[5]*=l,Kt.elements[6]*=l,Kt.elements[8]*=c,Kt.elements[9]*=c,Kt.elements[10]*=c,t.setFromRotationMatrix(Kt),n.x=r,n.y=a,n.z=s,this}makePerspective(e,t,n,i,r,a,s=2e3){const o=this.elements,l=2*r/(t-e),c=2*r/(n-i),h=(t+e)/(t-e),u=(n+i)/(n-i);let d,p;if(s===Le)d=-(a+r)/(a-r),p=-2*a*r/(a-r);else{if(s!==Pe)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+s);d=-a/(a-r),p=-a*r/(a-r)}return o[0]=l,o[4]=0,o[8]=h,o[12]=0,o[1]=0,o[5]=c,o[9]=u,o[13]=0,o[2]=0,o[6]=0,o[10]=d,o[14]=p,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this}makeOrthographic(e,t,n,i,r,a,s=2e3){const o=this.elements,l=1/(t-e),c=1/(n-i),h=1/(a-r),u=(t+e)*l,d=(n+i)*c;let p,f;if(s===Le)p=(a+r)*h,f=-2*h;else{if(s!==Pe)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+s);p=r*h,f=-1*h}return o[0]=2*l,o[4]=0,o[8]=0,o[12]=-u,o[1]=0,o[5]=2*c,o[9]=0,o[13]=-d,o[2]=0,o[6]=0,o[10]=f,o[14]=-p,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this}equals(e){const t=this.elements,n=e.elements;for(let e=0;e<16;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<16;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}}const Yt=new vt,Kt=new qt,Zt=new vt(0,0,0),Jt=new vt(1,1,1),Qt=new vt,$t=new vt,en=new vt,tn=new qt,nn=new gt;class rn{constructor(e=0,t=0,n=0,i=rn.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=n,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,n,i=this._order){return this._x=e,this._y=t,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,n=!0){const i=e.elements,r=i[0],a=i[4],s=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(t){case"XYZ":this._y=Math.asin(ke(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-a,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-ke(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(s,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(ke(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-a,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-ke(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-a,l));break;case"YZX":this._z=Math.asin(ke(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(s,d));break;case"XZY":this._z=Math.asin(-ke(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(s,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===n&&this._onChangeCallback(),this}setFromQuaternion(e,t,n){return tn.makeRotationFromQuaternion(e),this.setFromRotationMatrix(tn,t,n)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return nn.setFromEuler(this),this.setFromQuaternion(nn,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}rn.DEFAULT_ORDER="XYZ";class an{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(e),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(e)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(e.geometries,this.geometry);const t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){const n=t.shapes;if(Array.isArray(n))for(let t=0,i=n.length;t0){i.children=[];for(let t=0;t0){i.animations=[];for(let t=0;t0&&(n.geometries=t),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),s.length>0&&(n.images=s),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function a(e){const t=[];for(const n in e){const i=e[n];delete i.metadata,t.push(i)}return t}}clone(e){return(new this.constructor).copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(e,t,n,i,r){Mn.subVectors(i,t),Sn.subVectors(n,t),En.subVectors(e,t);const a=Mn.dot(Mn),s=Mn.dot(Sn),o=Mn.dot(En),l=Sn.dot(Sn),c=Sn.dot(En),h=a*l-s*s;if(0===h)return r.set(0,0,0),null;const u=1/h,d=(l*o-s*c)*u,p=(a*c-s*o)*u;return r.set(1-d-p,p,d)}static containsPoint(e,t,n,i){return null!==this.getBarycoord(e,t,n,i,wn)&&(wn.x>=0&&wn.y>=0&&wn.x+wn.y<=1)}static getInterpolation(e,t,n,i,r,a,s,o){return null===this.getBarycoord(e,t,n,i,wn)?(o.x=0,o.y=0,"z"in o&&(o.z=0),"w"in o&&(o.w=0),null):(o.setScalar(0),o.addScaledVector(r,wn.x),o.addScaledVector(a,wn.y),o.addScaledVector(s,wn.z),o)}static isFrontFacing(e,t,n,i){return Mn.subVectors(n,t),Sn.subVectors(e,t),Mn.cross(Sn).dot(i)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,i){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,n,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,i),this}clone(){return(new this.constructor).copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Mn.subVectors(this.c,this.b),Sn.subVectors(this.a,this.b),.5*Mn.cross(Sn).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return In.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return In.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,n,i,r){return In.getInterpolation(e,this.a,this.b,this.c,t,n,i,r)}containsPoint(e){return In.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return In.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const n=this.a,i=this.b,r=this.c;let a,s;Tn.subVectors(i,n),An.subVectors(r,n),Cn.subVectors(e,n);const o=Tn.dot(Cn),l=An.dot(Cn);if(o<=0&&l<=0)return t.copy(n);Ln.subVectors(e,i);const c=Tn.dot(Ln),h=An.dot(Ln);if(c>=0&&h<=c)return t.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return a=o/(o-c),t.copy(n).addScaledVector(Tn,a);Pn.subVectors(e,r);const d=Tn.dot(Pn),p=An.dot(Pn);if(p>=0&&d<=p)return t.copy(r);const f=d*l-o*p;if(f<=0&&l>=0&&p<=0)return s=l/(l-p),t.copy(n).addScaledVector(An,s);const m=c*p-d*h;if(m<=0&&h-c>=0&&d-p>=0)return Rn.subVectors(r,i),s=(h-c)/(h-c+(d-p)),t.copy(i).addScaledVector(Rn,s);const g=1/(m+f+u);return a=f*g,s=u*g,t.copy(n).addScaledVector(Tn,a).addScaledVector(An,s)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const Nn={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},Un={h:0,s:0,l:0},Dn={h:0,s:0,l:0};function On(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+6*(t-e)*(2/3-n):e}class Fn{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(void 0===t&&void 0===n){const t=e;t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t="srgb"){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,nt.toWorkingColorSpace(this,t),this}setRGB(e,t,n,i=nt.workingColorSpace){return this.r=e,this.g=t,this.b=n,nt.toWorkingColorSpace(this,i),this}setHSL(e,t,n,i=nt.workingColorSpace){if(e=Be(e,1),t=ke(t,0,1),n=ke(n,0,1),0===t)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+t):n+t-n*t,r=2*n-i;this.r=On(r,i,e+1/3),this.g=On(r,i,e),this.b=On(r,i,e-1/3)}return nt.toWorkingColorSpace(this,i),this}setStyle(e,t="srgb"){function n(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let r;const a=i[1],s=i[2];switch(a){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,t);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,t);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,t);if(6===r)return this.setHex(parseInt(n,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t="srgb"){const n=Nn[e.toLowerCase()];return void 0!==n?this.setHex(n,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=it(e.r),this.g=it(e.g),this.b=it(e.b),this}copyLinearToSRGB(e){return this.r=rt(e.r),this.g=rt(e.g),this.b=rt(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e="srgb"){return nt.fromWorkingColorSpace(kn.copy(this),e),65536*Math.round(ke(255*kn.r,0,255))+256*Math.round(ke(255*kn.g,0,255))+Math.round(ke(255*kn.b,0,255))}getHexString(e="srgb"){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=nt.workingColorSpace){nt.fromWorkingColorSpace(kn.copy(this),t);const n=kn.r,i=kn.g,r=kn.b,a=Math.max(n,i,r),s=Math.min(n,i,r);let o,l;const c=(s+a)/2;if(s===a)o=0,l=0;else{const e=a-s;switch(l=c<=.5?e/(a+s):e/(2-a-s),a){case n:o=(i-r)/e+(i0!=e>0&&this.version++,this._alphaTest=e}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(const t in e){const n=e[t];if(void 0===n){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const i=this[t];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[t]=n:console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`)}}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(e){const t=[];for(const n in e){const i=e[n];delete i.metadata,t.push(i)}return t}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(n.dispersion=this.dispersion),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapRotation&&(n.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),0!==this.side&&(n.side=this.side),!0===this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=!0),this.blendSrc!==s&&(n.blendSrc=this.blendSrc),this.blendDst!==o&&(n.blendDst=this.blendDst),this.blendEquation!==a&&(n.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(n.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(n.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(n.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(n.depthFunc=this.depthFunc),!1===this.depthTest&&(n.depthTest=this.depthTest),!1===this.depthWrite&&(n.depthWrite=this.depthWrite),!1===this.colorWrite&&(n.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(n.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(n.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(n.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==Ae&&(n.stencilFail=this.stencilFail),this.stencilZFail!==Ae&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==Ae&&(n.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(n.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaHash&&(n.alphaHash=!0),!0===this.alphaToCoverage&&(n.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=!0),!0===this.forceSinglePass&&(n.forceSinglePass=!0),!0===this.wireframe&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),t){const t=i(e.textures),r=i(e.images);t.length>0&&(n.textures=t),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let n=null;if(null!==t){const e=t.length;n=new Array(e);for(let i=0;i!==e;++i)n[i]=t[i].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}onBeforeRender(){console.warn("Material: onBeforeRender() has been removed.")}}class Hn extends zn{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Fn(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.envMapRotation=new rn,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const Vn=new vt,Gn=new We;class Wn{constructor(e,t,n=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=n,this.usage=Re,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.gpuType=T,this.version=0}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return Je("THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let i=0,r=this.itemSize;i0&&(e.userData=this.userData),void 0!==this.parameters){const t=this.parameters;for(const n in t)void 0!==t[n]&&(e[n]=t[n]);return e}e.data={attributes:{}};const t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const n=this.attributes;for(const t in n){const i=n[t];e.data.attributes[t]=i.toJSON(e.data)}const i={};let r=!1;for(const t in this.morphAttributes){const n=this.morphAttributes[t],a=[];for(let t=0,i=n.length;t0&&(i[t]=a,r=!0)}r&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(e.data.groups=JSON.parse(JSON.stringify(a)));const s=this.boundingSphere;return null!==s&&(e.data.boundingSphere={center:s.center.toArray(),radius:s.radius}),e}clone(){return(new this.constructor).copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const n=e.index;null!==n&&this.setIndex(n.clone(t));const i=e.attributes;for(const e in i){const n=i[e];this.setAttribute(e,n.clone(t))}const r=e.morphAttributes;for(const e in r){const n=[],i=r[e];for(let e=0,r=i.length;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;e(e.far-e.near)**2)return}ni.copy(r).invert(),ii.copy(e.ray).applyMatrix4(ni),null!==n.boundingBox&&!1===ii.intersectsBox(n.boundingBox)||this._computeIntersections(e,t,ii)}}_computeIntersections(e,t,n){let i;const r=this.geometry,a=this.material,s=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==s)if(Array.isArray(a))for(let r=0,o=u.length;rn.far?null:{distance:c,point:_i.clone(),object:e}}(e,t,n,i,si,oi,li,vi);if(h){r&&(ui.fromBufferAttribute(r,o),di.fromBufferAttribute(r,l),pi.fromBufferAttribute(r,c),h.uv=In.getInterpolation(vi,si,oi,li,ui,di,pi,new We)),a&&(ui.fromBufferAttribute(a,o),di.fromBufferAttribute(a,l),pi.fromBufferAttribute(a,c),h.uv1=In.getInterpolation(vi,si,oi,li,ui,di,pi,new We)),s&&(fi.fromBufferAttribute(s,o),mi.fromBufferAttribute(s,l),gi.fromBufferAttribute(s,c),h.normal=In.getInterpolation(vi,si,oi,li,fi,mi,gi,new vt),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const e={a:o,b:l,c:c,normal:new vt,materialIndex:0};In.getNormal(si,oi,li,e.normal),h.face=e}return h}class bi extends ti{constructor(e=1,t=1,n=1,i=1,r=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:n,widthSegments:i,heightSegments:r,depthSegments:a};const s=this;i=Math.floor(i),r=Math.floor(r),a=Math.floor(a);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(e,t,n,i,r,a,p,f,m,g,v){const _=a/m,y=p/g,x=a/2,b=p/2,M=f/2,S=m+1,E=g+1;let w=0,T=0;const A=new vt;for(let a=0;a0?1:-1,c.push(A.x,A.y,A.z),h.push(o/m),h.push(1-a/g),w+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const n={};for(const e in this.extensions)!0===this.extensions[e]&&(n[e]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}}class Ai extends bn{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new qt,this.projectionMatrix=new qt,this.projectionMatrixInverse=new qt,this.coordinateSystem=Le}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Ri=new vt,Ci=new We,Li=new We;class Pi extends Ai{constructor(e=50,t=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=2*Oe*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(.5*De*this.fov);return.5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*Oe*Math.atan(Math.tan(.5*De*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,n){Ri.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Ri.x,Ri.y).multiplyScalar(-e/Ri.z),Ri.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Ri.x,Ri.y).multiplyScalar(-e/Ri.z)}getViewSize(e,t){return this.getViewBounds(e,Ci,Li),t.subVectors(Li,Ci)}setViewOffset(e,t,n,i,r,a){this.aspect=e/t,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(.5*De*this.fov)/this.zoom,n=2*t,i=this.aspect*n,r=-.5*i;const a=this.view;if(null!==this.view&&this.view.enabled){const e=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/e,t-=a.offsetY*n/s,i*=a.width/e,n*=a.height/s}const s=this.filmOffset;0!==s&&(r+=e*s/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-n,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const Ii=-90;class Ni extends bn{constructor(e,t,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Pi(Ii,1,e,t);i.layers=this.layers,this.add(i);const r=new Pi(Ii,1,e,t);r.layers=this.layers,this.add(r);const a=new Pi(Ii,1,e,t);a.layers=this.layers,this.add(a);const s=new Pi(Ii,1,e,t);s.layers=this.layers,this.add(s);const o=new Pi(Ii,1,e,t);o.layers=this.layers,this.add(o);const l=new Pi(Ii,1,e,t);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[n,i,r,a,s,o]=t;for(const e of t)this.remove(e);if(e===Le)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),s.up.set(0,1,0),s.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else{if(e!==Pe)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),s.up.set(0,-1,0),s.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1)}for(const e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[r,a,s,o,l,c]=this.children,h=e.getRenderTarget(),u=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;const f=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,e.setRenderTarget(n,0,i),e.render(t,r),e.setRenderTarget(n,1,i),e.render(t,a),e.setRenderTarget(n,2,i),e.render(t,s),e.setRenderTarget(n,3,i),e.render(t,o),e.setRenderTarget(n,4,i),e.render(t,l),n.texture.generateMipmaps=f,e.setRenderTarget(n,5,i),e.render(t,c),e.setRenderTarget(h,u,d),e.xr.enabled=p,n.texture.needsPMREMUpdate=!0}}class Ui extends ht{constructor(e,t,n,i,r,a,s,o,l,h){super(e=void 0!==e?e:[],t=void 0!==t?t:c,n,i,r,a,s,o,l,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class Di extends pt{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const n={width:e,height:e,depth:1},i=[n,n,n,n,n,n];this.texture=new Ui(i,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:v}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new bi(5,5,5),r=new Ti({name:"CubemapFromEquirect",uniforms:Mi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=t;const a=new yi(i,r),s=t.minFilter;t.minFilter===y&&(t.minFilter=v);return new Ni(1,10,this).update(e,a),t.minFilter=s,a.geometry.dispose(),a.material.dispose(),this}clear(e,t,n,i){const r=e.getRenderTarget();for(let r=0;r<6;r++)e.setRenderTarget(this,r),e.clear(t,n,i);e.setRenderTarget(r)}}const Oi=new vt,Fi=new vt,ki=new je;class Bi{constructor(e=new vt(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,n,i){return this.normal.set(e,t,n),this.constant=i,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,n){const i=Oi.subVectors(n,t).cross(Fi.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(i,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){const e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t){const n=e.delta(Oi),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(e.start)?t.copy(e.start):null;const r=-(e.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:t.copy(e.start).addScaledVector(n,r)}intersectsLine(e){const t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const n=t||ki.getNormalMatrix(e),i=this.coplanarPoint(Oi).applyMatrix4(e),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const zi=new kt,Hi=new vt;class Vi{constructor(e=new Bi,t=new Bi,n=new Bi,i=new Bi,r=new Bi,a=new Bi){this.planes=[e,t,n,i,r,a]}set(e,t,n,i,r,a){const s=this.planes;return s[0].copy(e),s[1].copy(t),s[2].copy(n),s[3].copy(i),s[4].copy(r),s[5].copy(a),this}copy(e){const t=this.planes;for(let n=0;n<6;n++)t[n].copy(e.planes[n]);return this}setFromProjectionMatrix(e,t=2e3){const n=this.planes,i=e.elements,r=i[0],a=i[1],s=i[2],o=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],f=i[10],m=i[11],g=i[12],v=i[13],_=i[14],y=i[15];if(n[0].setComponents(o-r,u-l,m-d,y-g).normalize(),n[1].setComponents(o+r,u+l,m+d,y+g).normalize(),n[2].setComponents(o+a,u+c,m+p,y+v).normalize(),n[3].setComponents(o-a,u-c,m-p,y-v).normalize(),n[4].setComponents(o-s,u-h,m-f,y-_).normalize(),t===Le)n[5].setComponents(o+s,u+h,m+f,y+_).normalize();else{if(t!==Pe)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);n[5].setComponents(s,h,f,_).normalize()}return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),zi.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),zi.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(zi)}intersectsSprite(e){return zi.center.set(0,0,0),zi.radius=.7071067811865476,zi.applyMatrix4(e.matrixWorld),this.intersectsSphere(zi)}intersectsSphere(e){const t=this.planes,n=e.center,i=-e.radius;for(let e=0;e<6;e++){if(t[e].distanceToPoint(n)0?e.max.x:e.min.x,Hi.y=i.normal.y>0?e.max.y:e.min.y,Hi.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(Hi)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function Gi(){let e=null,t=!1,n=null,i=null;function r(t,a){n(t,a),i=e.requestAnimationFrame(r)}return{start:function(){!0!==t&&null!==n&&(i=e.requestAnimationFrame(r),t=!0)},stop:function(){e.cancelAnimationFrame(i),t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function Wi(e){const t=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),t.get(e)},remove:function(n){n.isInterleavedBufferAttribute&&(n=n.data);const i=t.get(n);i&&(e.deleteBuffer(i.buffer),t.delete(n))},update:function(n,i){if(n.isInterleavedBufferAttribute&&(n=n.data),n.isGLBufferAttribute){const e=t.get(n);return void((!e||e.version 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif",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\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn 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}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = 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\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn 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\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",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\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#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 \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},qi={common:{diffuse:{value:new Fn(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new je},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new je}},envmap:{envMap:{value:null},envMapRotation:{value:new je},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new je}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new je}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new je},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new je},normalScale:{value:new We(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new je},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new je}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new je}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new je}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Fn(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,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:new Fn(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0},uvTransform:{value:new je}},sprite:{diffuse:{value:new Fn(16777215)},opacity:{value:1},center:{value:new We(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new je},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0}}},Yi={basic:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.fog]),vertexShader:Xi.meshbasic_vert,fragmentShader:Xi.meshbasic_frag},lambert:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)}}]),vertexShader:Xi.meshlambert_vert,fragmentShader:Xi.meshlambert_frag},phong:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)},specular:{value:new Fn(1118481)},shininess:{value:30}}]),vertexShader:Xi.meshphong_vert,fragmentShader:Xi.meshphong_frag},standard:{uniforms:Si([qi.common,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.roughnessmap,qi.metalnessmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Xi.meshphysical_vert,fragmentShader:Xi.meshphysical_frag},toon:{uniforms:Si([qi.common,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.gradientmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)}}]),vertexShader:Xi.meshtoon_vert,fragmentShader:Xi.meshtoon_frag},matcap:{uniforms:Si([qi.common,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,{matcap:{value:null}}]),vertexShader:Xi.meshmatcap_vert,fragmentShader:Xi.meshmatcap_frag},points:{uniforms:Si([qi.points,qi.fog]),vertexShader:Xi.points_vert,fragmentShader:Xi.points_frag},dashed:{uniforms:Si([qi.common,qi.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Xi.linedashed_vert,fragmentShader:Xi.linedashed_frag},depth:{uniforms:Si([qi.common,qi.displacementmap]),vertexShader:Xi.depth_vert,fragmentShader:Xi.depth_frag},normal:{uniforms:Si([qi.common,qi.bumpmap,qi.normalmap,qi.displacementmap,{opacity:{value:1}}]),vertexShader:Xi.meshnormal_vert,fragmentShader:Xi.meshnormal_frag},sprite:{uniforms:Si([qi.sprite,qi.fog]),vertexShader:Xi.sprite_vert,fragmentShader:Xi.sprite_frag},background:{uniforms:{uvTransform:{value:new je},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Xi.background_vert,fragmentShader:Xi.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new je}},vertexShader:Xi.backgroundCube_vert,fragmentShader:Xi.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Xi.cube_vert,fragmentShader:Xi.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Xi.equirect_vert,fragmentShader:Xi.equirect_frag},distanceRGBA:{uniforms:Si([qi.common,qi.displacementmap,{referencePosition:{value:new vt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Xi.distanceRGBA_vert,fragmentShader:Xi.distanceRGBA_frag},shadow:{uniforms:Si([qi.lights,qi.fog,{color:{value:new Fn(0)},opacity:{value:1}}]),vertexShader:Xi.shadow_vert,fragmentShader:Xi.shadow_frag}};Yi.physical={uniforms:Si([Yi.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new je},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new je},clearcoatNormalScale:{value:new We(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new je},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new je},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new je},sheen:{value:0},sheenColor:{value:new Fn(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new je},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new je},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new je},transmissionSamplerSize:{value:new We},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new je},attenuationDistance:{value:0},attenuationColor:{value:new Fn(0)},specularColor:{value:new Fn(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new je},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new je},anisotropyVector:{value:new We},anisotropyMap:{value:null},anisotropyMapTransform:{value:new je}}]),vertexShader:Xi.meshphysical_vert,fragmentShader:Xi.meshphysical_frag};const Ki={r:0,b:0,g:0},Zi=new rn,Ji=new qt;function Qi(e,t,n,i,r,a,s){const o=new Fn(0);let l,c,h=!0===a?0:1,d=null,p=0,f=null;function m(e){let i=!0===e.isScene?e.background:null;if(i&&i.isTexture){i=(e.backgroundBlurriness>0?n:t).get(i)}return i}function g(t,n){t.getRGB(Ki,Ei(e)),i.buffers.color.setClear(Ki.r,Ki.g,Ki.b,n,s)}return{getClearColor:function(){return o},setClearColor:function(e,t=1){o.set(e),h=t,g(o,h)},getClearAlpha:function(){return h},setClearAlpha:function(e){h=e,g(o,h)},render:function(t){let n=!1;const r=m(t);null===r?g(o,h):r&&r.isColor&&(g(r,1),n=!0);const a=e.xr.getEnvironmentBlendMode();"additive"===a?i.buffers.color.setClear(0,0,0,1,s):"alpha-blend"===a&&i.buffers.color.setClear(0,0,0,0,s),(e.autoClear||n)&&(i.buffers.depth.setTest(!0),i.buffers.depth.setMask(!0),i.buffers.color.setMask(!0),e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil))},addToRenderList:function(t,n){const i=m(n);i&&(i.isCubeTexture||i.mapping===u)?(void 0===c&&(c=new yi(new bi(1,1,1),new Ti({name:"BackgroundCubeMaterial",uniforms:Mi(Yi.backgroundCube.uniforms),vertexShader:Yi.backgroundCube.vertexShader,fragmentShader:Yi.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(c)),Zi.copy(n.backgroundRotation),Zi.x*=-1,Zi.y*=-1,Zi.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(Zi.y*=-1,Zi.z*=-1),c.material.uniforms.envMap.value=i,c.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,c.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,c.material.uniforms.backgroundRotation.value.setFromMatrix4(Ji.makeRotationFromEuler(Zi)),c.material.toneMapped=nt.getTransfer(i.colorSpace)!==Ee,d===i&&p===i.version&&f===e.toneMapping||(c.material.needsUpdate=!0,d=i,p=i.version,f=e.toneMapping),c.layers.enableAll(),t.unshift(c,c.geometry,c.material,0,0,null)):i&&i.isTexture&&(void 0===l&&(l=new yi(new ji(2,2),new Ti({name:"BackgroundMaterial",uniforms:Mi(Yi.background.uniforms),vertexShader:Yi.background.vertexShader,fragmentShader:Yi.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(l)),l.material.uniforms.t2D.value=i,l.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,l.material.toneMapped=nt.getTransfer(i.colorSpace)!==Ee,!0===i.matrixAutoUpdate&&i.updateMatrix(),l.material.uniforms.uvTransform.value.copy(i.matrix),d===i&&p===i.version&&f===e.toneMapping||(l.material.needsUpdate=!0,d=i,p=i.version,f=e.toneMapping),l.layers.enableAll(),t.unshift(l,l.geometry,l.material,0,0,null))}}}function $i(e,t){const n=e.getParameter(e.MAX_VERTEX_ATTRIBS),i={},r=c(null);let a=r,s=!1;function o(t){return e.bindVertexArray(t)}function l(t){return e.deleteVertexArray(t)}function c(e){const t=[],i=[],r=[];for(let e=0;e=0){const n=r[t];let i=s[t];if(void 0===i&&("instanceMatrix"===t&&e.instanceMatrix&&(i=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(i=e.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;o++}}return a.attributesNum!==o||a.index!==i}(n,m,l,g),v&&function(e,t,n,i){const r={},s=t.attributes;let o=0;const l=n.getAttributes();for(const t in l){if(l[t].location>=0){let n=s[t];void 0===n&&("instanceMatrix"===t&&e.instanceMatrix&&(n=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(n=e.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[t]=i,o++}}a.attributes=r,a.attributesNum=o,a.index=i}(n,m,l,g),null!==g&&t.update(g,e.ELEMENT_ARRAY_BUFFER),(v||s)&&(s=!1,function(n,i,r,a){h();const s=a.attributes,o=r.getAttributes(),l=i.defaultAttributeValues;for(const i in o){const r=o[i];if(r.location>=0){let o=s[i];if(void 0===o&&("instanceMatrix"===i&&n.instanceMatrix&&(o=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(o=n.instanceColor)),void 0!==o){const i=o.normalized,s=o.itemSize,l=t.get(o);if(void 0===l)continue;const c=l.buffer,h=l.type,p=l.bytesPerElement,m=h===e.INT||h===e.UNSIGNED_INT||o.gpuType===E;if(o.isInterleavedBufferAttribute){const t=o.data,l=t.stride,g=o.offset;if(t.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let s=void 0!==n.precision?n.precision:"highp";const o=a(s);o!==s&&(console.warn("THREE.WebGLRenderer:",s,"not supported, using",o,"instead."),s=o);const l=!0===n.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===t.has("EXT_texture_filter_anisotropic")){const n=t.get("EXT_texture_filter_anisotropic");r=e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:a,textureFormatReadable:function(t){return t===I||i.convert(t)===e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===A&&(t.has("EXT_color_buffer_half_float")||t.has("EXT_color_buffer_float"));return!(n!==x&&i.convert(n)!==e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==T&&!r)},precision:s,logarithmicDepthBuffer:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:e.getParameter(e.MAX_TEXTURE_SIZE),maxCubemapSize:e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:e.getParameter(e.MAX_VERTEX_ATTRIBS),maxVertexUniforms:e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:e.getParameter(e.MAX_VARYING_VECTORS),maxFragmentUniforms:e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:h>0,maxSamples:e.getParameter(e.MAX_SAMPLES)}}function nr(e){const t=this;let n=null,i=0,r=!1,a=!1;const s=new Bi,o=new je,l={value:null,needsUpdate:!1};function c(e,n,i,r){const a=null!==e?e.length:0;let c=null;if(0!==a){if(c=l.value,!0!==r||null===c){const t=i+4*a,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);t.numPlanes=i,t.numIntersection=0}();else{const e=a?0:i,t=4*e;let r=f.clippingState||null;l.value=r,r=c(u,o,t,h);for(let e=0;e!==t;++e)r[e]=n[e];f.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=e}}}function ir(e){let t=new WeakMap;function n(e,t){return 303===t?e.mapping=c:304===t&&(e.mapping=h),e}function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping;if(303===a||304===a){if(t.has(r)){return n(t.get(r).texture,r.mapping)}{const a=r.image;if(a&&a.height>0){const s=new Di(a.height);return s.fromEquirectangularTexture(e,r),t.set(r,s),r.addEventListener("dispose",i),n(s.texture,r.mapping)}return null}}}return r},dispose:function(){t=new WeakMap}}}class rr extends Ai{constructor(e=-1,t=1,n=1,i=-1,r=.1,a=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=e,this.right=t,this.top=n,this.bottom=i,this.near=r,this.far=a,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.left=e.left,this.right=e.right,this.top=e.top,this.bottom=e.bottom,this.near=e.near,this.far=e.far,this.zoom=e.zoom,this.view=null===e.view?null:Object.assign({},e.view),this}setViewOffset(e,t,n,i,r,a){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=(this.right-this.left)/(2*this.zoom),t=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-e,a=n+e,s=i+t,o=i-t;if(null!==this.view&&this.view.enabled){const e=(this.right-this.left)/this.view.fullWidth/this.zoom,t=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=e*this.view.offsetX,a=r+e*this.view.width,s-=t*this.view.offsetY,o=s-t*this.view.height}this.projectionMatrix.makeOrthographic(r,a,s,o,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.zoom=this.zoom,t.object.left=this.left,t.object.right=this.right,t.object.top=this.top,t.object.bottom=this.bottom,t.object.near=this.near,t.object.far=this.far,null!==this.view&&(t.object.view=Object.assign({},this.view)),t}}const ar=[.125,.215,.35,.446,.526,.582],sr=20,or=new rr,lr=new Fn;let cr=null,hr=0,ur=0,dr=!1;const pr=(1+Math.sqrt(5))/2,fr=1/pr,mr=[new vt(-pr,fr,0),new vt(pr,fr,0),new vt(-fr,0,pr),new vt(fr,0,pr),new vt(0,pr,-fr),new vt(0,pr,fr),new vt(-1,1,-1),new vt(1,1,-1),new vt(-1,1,1),new vt(1,1,1)];class gr{constructor(e){this._renderer=e,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(e,t=0,n=.1,i=100){cr=this._renderer.getRenderTarget(),hr=this._renderer.getActiveCubeFace(),ur=this._renderer.getActiveMipmapLevel(),dr=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,n,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=xr(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=yr(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?o=ar[s-e+4-1]:0===s&&(o=0),i.push(o);const l=1/(a-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,f=3,m=2,g=1,v=new Float32Array(f*p*d),_=new Float32Array(m*p*d),y=new Float32Array(g*p*d);for(let e=0;e2?0:-1,i=[t,n,0,t+2/3,n,0,t+2/3,n+1,0,t,n,0,t+2/3,n+1,0,t,n+1,0];v.set(i,f*p*e),_.set(u,m*p*e);const r=[e,e,e,e,e,e];y.set(r,g*p*e)}const x=new ti;x.setAttribute("position",new Wn(v,f)),x.setAttribute("uv",new Wn(_,m)),x.setAttribute("faceIndex",new Wn(y,g)),t.push(x),r>4&&r--}return{lodPlanes:t,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(e,t,n){const i=new Float32Array(sr),r=new vt(0,1,0);return new Ti({name:"SphericalGaussianBlur",defines:{n:sr,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}(i,e,t)}return i}_compileMaterial(e){const t=new yi(this._lodPlanes[0],e);this._renderer.compile(t,or)}_sceneToCubeUV(e,t,n,i){const r=new Pi(90,1,t,n),a=[1,-1,1,1,1,1],s=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(lr),o.toneMapping=0,o.autoClear=!1;const h=new Hn({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new yi(new bi,h);let d=!1;const p=e.background;p?p.isColor&&(h.color.copy(p),e.background=null,d=!0):(h.color.copy(lr),d=!0);for(let t=0;t<6;t++){const n=t%3;0===n?(r.up.set(0,a[t],0),r.lookAt(s[t],0,0)):1===n?(r.up.set(0,0,a[t]),r.lookAt(0,s[t],0)):(r.up.set(0,a[t],0),r.lookAt(0,0,s[t]));const l=this._cubeSize;_r(i,n*l,t>2?l:0,l,l),o.setRenderTarget(i),d&&o.render(u,r),o.render(e,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,e.background=p}_textureToCubeUV(e,t){const n=this._renderer,i=e.mapping===c||e.mapping===h;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=xr()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===e.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=yr());const r=i?this._cubemapMaterial:this._equirectMaterial,a=new yi(this._lodPlanes[0],r);r.uniforms.envMap.value=e;const s=this._cubeSize;_r(t,0,0,3*s,2*s),n.setRenderTarget(t),n.render(a,or)}_applyPMREM(e){const t=this._renderer,n=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;tsr&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${f} samples when the maximum is set to 20`);const m=[];let g=0;for(let e=0;ev-4?i-v+4:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(t),o.render(c,or)}}function vr(e,t,n){const i=new pt(e,t,n);return i.texture.mapping=u,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function _r(e,t,n,i,r){e.viewport.set(t,n,i,r),e.scissor.set(t,n,i,r)}function yr(){return new Ti({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function xr(){return new Ti({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function br(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Mr(e){let t=new WeakMap,n=null;function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping,s=303===a||304===a,o=a===c||a===h;if(s||o){let a=t.get(r);const l=void 0!==a?a.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new gr(e)),a=s?n.fromEquirectangular(r,a):n.fromCubemap(r,a),a.texture.pmremVersion=r.pmremVersion,t.set(r,a),a.texture;if(void 0!==a)return a.texture;{const l=r.image;return s&&l&&l.height>0||o&&l&&function(e){let t=0;const n=6;for(let i=0;it.maxTextureSize&&(x=Math.ceil(y/t.maxTextureSize),y=t.maxTextureSize);const b=new Float32Array(y*x*4*h),M=new ft(b,y,x,h);M.type=T,M.needsUpdate=!0;const S=4*_;for(let w=0;w0)return e;const r=t*n;let a=Dr[r];if(void 0===a&&(a=new Float32Array(r),Dr[r]=a),0!==t){i.toArray(a,0);for(let i=1,r=0;i!==t;++i)r+=n,e[i].toArray(a,r)}return a}function Hr(e,t){if(e.length!==t.length)return!1;for(let n=0,i=e.length;n":" "} ${r}: ${n[e]}`)}return i.join("\n")}(e.getShaderSource(t),i)}return r}function ka(e,t){const n=function(e){const t=nt.getPrimaries(nt.workingColorSpace),n=nt.getPrimaries(e);let i;switch(t===n?i="":t===Te&&n===we?i="LinearDisplayP3ToLinearSRGB":t===we&&n===Te&&(i="LinearSRGBToLinearDisplayP3"),e){case xe:case Me:return[i,"LinearTransferOETF"];case ye:case be:return[i,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",e),[i,"LinearTransferOETF"]}}(t);return`vec4 ${e}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function Ba(e,t){let n;switch(t){case 1:n="Linear";break;case 2:n="Reinhard";break;case 3:n="OptimizedCineon";break;case 4:n="ACESFilmic";break;case 6:n="AgX";break;case 7:n="Neutral";break;case 5:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),n="Linear"}return"vec3 "+e+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const za=new vt;function Ha(){nt.getLuminanceCoefficients(za);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${za.x.toFixed(4)}, ${za.y.toFixed(4)}, ${za.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function Va(e){return""!==e}function Ga(e,t){const n=t.numSpotLightShadows+t.numSpotLightMaps-t.numSpotLightShadowsWithMaps;return e.replace(/NUM_DIR_LIGHTS/g,t.numDirLights).replace(/NUM_SPOT_LIGHTS/g,t.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,t.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,t.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,t.numPointLights).replace(/NUM_HEMI_LIGHTS/g,t.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,t.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,t.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,t.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,t.numPointLightShadows)}function Wa(e,t){return e.replace(/NUM_CLIPPING_PLANES/g,t.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,t.numClippingPlanes-t.numClipIntersection)}const ja=/^[ \t]*#include +<([\w\d./]+)>/gm;function Xa(e){return e.replace(ja,Ya)}const qa=new Map;function Ya(e,t){let n=Xi[t];if(void 0===n){const e=qa.get(t);if(void 0===e)throw new Error("Can not resolve #include <"+t+">");n=Xi[e],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,e)}return Xa(n)}const Ka=/#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 Za(e){return e.replace(Ka,Ja)}function Ja(e,t,n,i){let r="";for(let e=parseInt(t);e0&&(y+="\n"),x=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(Va).join("\n"),x.length>0&&(x+="\n")):(y=[Qa(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+l:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Va).join("\n"),x=[Qa(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.envMap?"#define "+f:"",m?"#define CUBEUV_TEXEL_WIDTH "+m.texelWidth:"",m?"#define CUBEUV_TEXEL_HEIGHT "+m.texelHeight:"",m?"#define CUBEUV_MAX_MIP "+m.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+l:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?Xi.tonemapping_pars_fragment:"",0!==n.toneMapping?Ba("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",Xi.colorspace_pars_fragment,ka("linearToOutputTexel",n.outputColorSpace),Ha(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Va).join("\n")),s=Xa(s),s=Ga(s,n),s=Wa(s,n),o=Xa(o),o=Ga(o,n),o=Wa(o,n),s=Za(s),o=Za(o),!0!==n.isRawShaderMaterial&&(b="#version 300 es\n",y=[g,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#define varying in",n.glslVersion===Ce?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Ce?"":"#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"+x);const M=b+y+s,S=b+x+o,E=Da(r,r.VERTEX_SHADER,M),w=Da(r,r.FRAGMENT_SHADER,S);function T(t){if(e.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(E).trim(),a=r.getShaderInfoLog(w).trim();let s=!0,o=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(s=!1,"function"==typeof e.debug.onShaderError)e.debug.onShaderError(r,_,E,w);else{const e=Fa(r,E,"vertex"),i=Fa(r,w,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+t.name+"\nMaterial Type: "+t.type+"\n\nProgram Info Log: "+n+"\n"+e+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==a||(o=!1);o&&(t.diagnostics={runnable:s,programLog:n,vertexShader:{log:i,prefix:y},fragmentShader:{log:a,prefix:x}})}r.deleteShader(E),r.deleteShader(w),A=new Ua(r,_),R=function(e,t){const n={},i=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES);for(let r=0;r0,q=a.clearcoat>0,Y=a.dispersion>0,K=a.iridescence>0,Z=a.sheen>0,J=a.transmission>0,Q=X&&!!a.anisotropyMap,$=q&&!!a.clearcoatMap,ee=q&&!!a.clearcoatNormalMap,te=q&&!!a.clearcoatRoughnessMap,ne=K&&!!a.iridescenceMap,ie=K&&!!a.iridescenceThicknessMap,re=Z&&!!a.sheenColorMap,ae=Z&&!!a.sheenRoughnessMap,se=!!a.specularMap,oe=!!a.specularColorMap,le=!!a.specularIntensityMap,ce=J&&!!a.transmissionMap,he=J&&!!a.thicknessMap,ue=!!a.gradientMap,de=!!a.alphaMap,pe=a.alphaTest>0,fe=!!a.alphaHash,me=!!a.extensions;let ge=0;a.toneMapped&&(null!==I&&!0!==I.isXRRenderTarget||(ge=e.toneMapping));const ve={shaderID:E,shaderType:a.type,shaderName:a.name,vertexShader:A,fragmentShader:R,defines:a.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===a.isRawShaderMaterial,glslVersion:a.glslVersion,precision:f,batching:U,batchingColor:U&&null!==_._colorsTexture,instancing:N,instancingColor:N&&null!==_.instanceColor,instancingMorph:N&&null!==_.morphTexture,supportsVertexTextures:p,outputColorSpace:null===I?e.outputColorSpace:!0===I.isXRRenderTarget?I.texture.colorSpace:xe,alphaToCoverage:!!a.alphaToCoverage,map:D,matcap:O,envMap:F,envMapMode:F&&M.mapping,envMapCubeUVHeight:S,aoMap:k,lightMap:B,bumpMap:z,normalMap:H,displacementMap:p&&V,emissiveMap:G,normalMapObjectSpace:H&&1===a.normalMapType,normalMapTangentSpace:H&&0===a.normalMapType,metalnessMap:W,roughnessMap:j,anisotropy:X,anisotropyMap:Q,clearcoat:q,clearcoatMap:$,clearcoatNormalMap:ee,clearcoatRoughnessMap:te,dispersion:Y,iridescence:K,iridescenceMap:ne,iridescenceThicknessMap:ie,sheen:Z,sheenColorMap:re,sheenRoughnessMap:ae,specularMap:se,specularColorMap:oe,specularIntensityMap:le,transmission:J,transmissionMap:ce,thicknessMap:he,gradientMap:ue,opaque:!1===a.transparent&&1===a.blending&&!1===a.alphaToCoverage,alphaMap:de,alphaTest:pe,alphaHash:fe,combine:a.combine,mapUv:D&&g(a.map.channel),aoMapUv:k&&g(a.aoMap.channel),lightMapUv:B&&g(a.lightMap.channel),bumpMapUv:z&&g(a.bumpMap.channel),normalMapUv:H&&g(a.normalMap.channel),displacementMapUv:V&&g(a.displacementMap.channel),emissiveMapUv:G&&g(a.emissiveMap.channel),metalnessMapUv:W&&g(a.metalnessMap.channel),roughnessMapUv:j&&g(a.roughnessMap.channel),anisotropyMapUv:Q&&g(a.anisotropyMap.channel),clearcoatMapUv:$&&g(a.clearcoatMap.channel),clearcoatNormalMapUv:ee&&g(a.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:te&&g(a.clearcoatRoughnessMap.channel),iridescenceMapUv:ne&&g(a.iridescenceMap.channel),iridescenceThicknessMapUv:ie&&g(a.iridescenceThicknessMap.channel),sheenColorMapUv:re&&g(a.sheenColorMap.channel),sheenRoughnessMapUv:ae&&g(a.sheenRoughnessMap.channel),specularMapUv:se&&g(a.specularMap.channel),specularColorMapUv:oe&&g(a.specularColorMap.channel),specularIntensityMapUv:le&&g(a.specularIntensityMap.channel),transmissionMapUv:ce&&g(a.transmissionMap.channel),thicknessMapUv:he&&g(a.thicknessMap.channel),alphaMapUv:de&&g(a.alphaMap.channel),vertexTangents:!!x.attributes.tangent&&(H||X),vertexColors:a.vertexColors,vertexAlphas:!0===a.vertexColors&&!!x.attributes.color&&4===x.attributes.color.itemSize,pointsUvs:!0===_.isPoints&&!!x.attributes.uv&&(D||de),fog:!!y,useFog:!0===a.fog,fogExp2:!!y&&y.isFogExp2,flatShading:!0===a.flatShading,sizeAttenuation:!0===a.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===_.isSkinnedMesh,morphTargets:void 0!==x.morphAttributes.position,morphNormals:void 0!==x.morphAttributes.normal,morphColors:void 0!==x.morphAttributes.color,morphTargetsCount:T,morphTextureStride:P,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numLightProbes:o.numLightProbes,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:a.dithering,shadowMapEnabled:e.shadowMap.enabled&&h.length>0,shadowMapType:e.shadowMap.type,toneMapping:ge,decodeVideoTexture:D&&!0===a.map.isVideoTexture&&nt.getTransfer(a.map.colorSpace)===Ee,premultipliedAlpha:a.premultipliedAlpha,doubleSided:2===a.side,flipSided:1===a.side,useDepthPacking:a.depthPacking>=0,depthPacking:a.depthPacking||0,index0AttributeName:a.index0AttributeName,extensionClipCullDistance:me&&!0===a.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(me&&!0===a.extensions.multiDraw||U)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:a.customProgramCacheKey()};return ve.vertexUv1s=c.has(1),ve.vertexUv2s=c.has(2),ve.vertexUv3s=c.has(3),c.clear(),ve},getProgramCacheKey:function(t){const n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.customVertexShaderID),n.push(t.customFragmentShaderID)),void 0!==t.defines)for(const e in t.defines)n.push(e),n.push(t.defines[e]);return!1===t.isRawShaderMaterial&&(!function(e,t){e.push(t.precision),e.push(t.outputColorSpace),e.push(t.envMapMode),e.push(t.envMapCubeUVHeight),e.push(t.mapUv),e.push(t.alphaMapUv),e.push(t.lightMapUv),e.push(t.aoMapUv),e.push(t.bumpMapUv),e.push(t.normalMapUv),e.push(t.displacementMapUv),e.push(t.emissiveMapUv),e.push(t.metalnessMapUv),e.push(t.roughnessMapUv),e.push(t.anisotropyMapUv),e.push(t.clearcoatMapUv),e.push(t.clearcoatNormalMapUv),e.push(t.clearcoatRoughnessMapUv),e.push(t.iridescenceMapUv),e.push(t.iridescenceThicknessMapUv),e.push(t.sheenColorMapUv),e.push(t.sheenRoughnessMapUv),e.push(t.specularMapUv),e.push(t.specularColorMapUv),e.push(t.specularIntensityMapUv),e.push(t.transmissionMapUv),e.push(t.thicknessMapUv),e.push(t.combine),e.push(t.fogExp2),e.push(t.sizeAttenuation),e.push(t.morphTargetsCount),e.push(t.morphAttributeCount),e.push(t.numDirLights),e.push(t.numPointLights),e.push(t.numSpotLights),e.push(t.numSpotLightMaps),e.push(t.numHemiLights),e.push(t.numRectAreaLights),e.push(t.numDirLightShadows),e.push(t.numPointLightShadows),e.push(t.numSpotLightShadows),e.push(t.numSpotLightShadowsWithMaps),e.push(t.numLightProbes),e.push(t.shadowMapType),e.push(t.toneMapping),e.push(t.numClippingPlanes),e.push(t.numClipIntersection),e.push(t.depthPacking)}(n,t),function(e,t){o.disableAll(),t.supportsVertexTextures&&o.enable(0);t.instancing&&o.enable(1);t.instancingColor&&o.enable(2);t.instancingMorph&&o.enable(3);t.matcap&&o.enable(4);t.envMap&&o.enable(5);t.normalMapObjectSpace&&o.enable(6);t.normalMapTangentSpace&&o.enable(7);t.clearcoat&&o.enable(8);t.iridescence&&o.enable(9);t.alphaTest&&o.enable(10);t.vertexColors&&o.enable(11);t.vertexAlphas&&o.enable(12);t.vertexUv1s&&o.enable(13);t.vertexUv2s&&o.enable(14);t.vertexUv3s&&o.enable(15);t.vertexTangents&&o.enable(16);t.anisotropy&&o.enable(17);t.alphaHash&&o.enable(18);t.batching&&o.enable(19);t.dispersion&&o.enable(20);t.batchingColor&&o.enable(21);e.push(o.mask),o.disableAll(),t.fog&&o.enable(0);t.useFog&&o.enable(1);t.flatShading&&o.enable(2);t.logarithmicDepthBuffer&&o.enable(3);t.skinning&&o.enable(4);t.morphTargets&&o.enable(5);t.morphNormals&&o.enable(6);t.morphColors&&o.enable(7);t.premultipliedAlpha&&o.enable(8);t.shadowMapEnabled&&o.enable(9);t.doubleSided&&o.enable(10);t.flipSided&&o.enable(11);t.useDepthPacking&&o.enable(12);t.dithering&&o.enable(13);t.transmission&&o.enable(14);t.sheen&&o.enable(15);t.opaque&&o.enable(16);t.pointsUvs&&o.enable(17);t.decodeVideoTexture&&o.enable(18);t.alphaToCoverage&&o.enable(19);e.push(o.mask)}(n,t),n.push(e.outputColorSpace)),n.push(t.customProgramCacheKey),n.join()},getUniforms:function(e){const t=m[e.type];let n;if(t){const e=Yi[t];n=wi.clone(e.uniforms)}else n=e.uniforms;return n},acquireProgram:function(t,n){let i;for(let e=0,t=h.length;e0?i.push(h):!0===s.transparent?r.push(h):n.push(h)},unshift:function(e,t,s,o,l,c){const h=a(e,t,s,o,l,c);s.transmission>0?i.unshift(h):!0===s.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=t,i=e.length;n1&&n.sort(e||as),i.length>1&&i.sort(t||ss),r.length>1&&r.sort(t||ss)}}}function ls(){let e=new WeakMap;return{get:function(t,n){const i=e.get(t);let r;return void 0===i?(r=new os,e.set(t,[r])):n>=i.length?(r=new os,i.push(r)):r=i[n],r},dispose:function(){e=new WeakMap}}}function cs(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let n;switch(t.type){case"DirectionalLight":n={direction:new vt,color:new Fn};break;case"SpotLight":n={position:new vt,direction:new vt,color:new Fn,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new vt,color:new Fn,distance:0,decay:0};break;case"HemisphereLight":n={direction:new vt,skyColor:new Fn,groundColor:new Fn};break;case"RectAreaLight":n={color:new Fn,position:new vt,halfWidth:new vt,halfHeight:new vt}}return e[t.id]=n,n}}}let hs=0;function us(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+(t.map?1:0)-(e.map?1:0)}function ds(e){const t=new cs,n=function(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let n;switch(t.type){case"DirectionalLight":case"SpotLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new We};break;case"PointLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new We,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=n,n}}}(),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let e=0;e<9;e++)i.probe.push(new vt);const r=new vt,a=new qt,s=new qt;return{setup:function(r){let a=0,s=0,o=0;for(let e=0;e<9;e++)i.probe[e].set(0,0,0);let l=0,c=0,h=0,u=0,d=0,p=0,f=0,m=0,g=0,v=0,_=0;r.sort(us);for(let e=0,y=r.length;e0&&(!0===e.has("OES_texture_float_linear")?(i.rectAreaLTC1=qi.LTC_FLOAT_1,i.rectAreaLTC2=qi.LTC_FLOAT_2):(i.rectAreaLTC1=qi.LTC_HALF_1,i.rectAreaLTC2=qi.LTC_HALF_2)),i.ambient[0]=a,i.ambient[1]=s,i.ambient[2]=o;const y=i.hash;y.directionalLength===l&&y.pointLength===c&&y.spotLength===h&&y.rectAreaLength===u&&y.hemiLength===d&&y.numDirectionalShadows===p&&y.numPointShadows===f&&y.numSpotShadows===m&&y.numSpotMaps===g&&y.numLightProbes===_||(i.directional.length=l,i.spot.length=h,i.rectArea.length=u,i.point.length=c,i.hemi.length=d,i.directionalShadow.length=p,i.directionalShadowMap.length=p,i.pointShadow.length=f,i.pointShadowMap.length=f,i.spotShadow.length=m,i.spotShadowMap.length=m,i.directionalShadowMatrix.length=p,i.pointShadowMatrix.length=f,i.spotLightMatrix.length=m+g-v,i.spotLightMap.length=g,i.numSpotLightShadowsWithMaps=v,i.numLightProbes=_,y.directionalLength=l,y.pointLength=c,y.spotLength=h,y.rectAreaLength=u,y.hemiLength=d,y.numDirectionalShadows=p,y.numPointShadows=f,y.numSpotShadows=m,y.numSpotMaps=g,y.numLightProbes=_,i.version=hs++)},setupView:function(e,t){let n=0,o=0,l=0,c=0,h=0;const u=t.matrixWorldInverse;for(let t=0,d=e.length;t=r.length?(a=new ps(e),r.push(a)):a=r[i],a},dispose:function(){t=new WeakMap}}}class ms extends zn{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class gs extends zn{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}function vs(e,t,n){let i=new Vi;const r=new We,a=new We,s=new ut,o=new ms({depthPacking:3201}),l=new gs,c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new Ti({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new We},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),p=d.clone();p.defines.HORIZONTAL_PASS=1;const f=new ti;f.setAttribute("position",new Wn(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new yi(f,d),v=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=1;let _=this.type;function y(n,i){const a=t.update(g);d.defines.VSM_SAMPLES!==n.blurSamples&&(d.defines.VSM_SAMPLES=n.blurSamples,p.defines.VSM_SAMPLES=n.blurSamples,d.needsUpdate=!0,p.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new pt(r.x,r.y)),d.uniforms.shadow_pass.value=n.map.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,a,d,g,null),p.uniforms.shadow_pass.value=n.mapPass.texture,p.uniforms.resolution.value=n.mapSize,p.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,a,p,g,null)}function x(t,n,i,r){let a=null;const s=!0===i.isPointLight?t.customDistanceMaterial:t.customDepthMaterial;if(void 0!==s)a=s;else if(a=!0===i.isPointLight?l:o,e.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const e=a.uuid,t=n.uuid;let i=c[e];void 0===i&&(i={},c[e]=i);let r=i[t];void 0===r&&(r=a.clone(),i[t]=r,n.addEventListener("dispose",M)),a=r}if(a.visible=n.visible,a.wireframe=n.wireframe,a.side=3===r?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:u[n.side],a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,!0===i.isPointLight&&!0===a.isMeshDistanceMaterial){e.properties.get(a).light=i}return a}function b(n,r,a,s,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);const i=t.update(n),l=n.material;if(Array.isArray(l)){const t=i.groups;for(let c=0,h=t.length;ch||r.y>h)&&(r.x>h&&(a.x=Math.floor(h/g.x),r.x=a.x*g.x,u.mapSize.x=a.x),r.y>h&&(a.y=Math.floor(h/g.y),r.y=a.y*g.y,u.mapSize.y=a.y)),null===u.map||!0===p||!0===f){const e=3!==this.type?{minFilter:m,magFilter:m}:{};null!==u.map&&u.map.dispose(),u.map=new pt(r.x,r.y,e),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}e.setRenderTarget(u.map),e.clear();const v=u.getViewportCount();for(let e=0;e=1):-1!==N.indexOf("OpenGL ES")&&(I=parseFloat(/^OpenGL ES (\d)/.exec(N)[1]),P=I>=2);let U=null,D={};const O=e.getParameter(e.SCISSOR_BOX),F=e.getParameter(e.VIEWPORT),k=(new ut).fromArray(O),B=(new ut).fromArray(F);function z(t,n,i,r){const a=new Uint8Array(4),s=e.createTexture();e.bindTexture(t,s),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(let s=0;sn||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&e instanceof VideoFrame){const n=Math.floor(i*r.width),a=Math.floor(i*r.height);void 0===u&&(u=E(n,a));const s=t?E(n,a):u;s.width=n,s.height=a;return s.getContext("2d").drawImage(e,0,0,n,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+a+")."),s}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),e}return e}function R(e){return e.generateMipmaps&&e.minFilter!==m&&e.minFilter!==v}function C(t){e.generateMipmap(t)}function P(n,i,r,a,s=!1){if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let o=i;if(i===e.RED&&(r===e.FLOAT&&(o=e.R32F),r===e.HALF_FLOAT&&(o=e.R16F),r===e.UNSIGNED_BYTE&&(o=e.R8)),i===e.RED_INTEGER&&(r===e.UNSIGNED_BYTE&&(o=e.R8UI),r===e.UNSIGNED_SHORT&&(o=e.R16UI),r===e.UNSIGNED_INT&&(o=e.R32UI),r===e.BYTE&&(o=e.R8I),r===e.SHORT&&(o=e.R16I),r===e.INT&&(o=e.R32I)),i===e.RG&&(r===e.FLOAT&&(o=e.RG32F),r===e.HALF_FLOAT&&(o=e.RG16F),r===e.UNSIGNED_BYTE&&(o=e.RG8)),i===e.RG_INTEGER&&(r===e.UNSIGNED_BYTE&&(o=e.RG8UI),r===e.UNSIGNED_SHORT&&(o=e.RG16UI),r===e.UNSIGNED_INT&&(o=e.RG32UI),r===e.BYTE&&(o=e.RG8I),r===e.SHORT&&(o=e.RG16I),r===e.INT&&(o=e.RG32I)),i===e.RGB&&r===e.UNSIGNED_INT_5_9_9_9_REV&&(o=e.RGB9_E5),i===e.RGBA){const t=s?Se:nt.getTransfer(a);r===e.FLOAT&&(o=e.RGBA32F),r===e.HALF_FLOAT&&(o=e.RGBA16F),r===e.UNSIGNED_BYTE&&(o=t===Ee?e.SRGB8_ALPHA8:e.RGBA8),r===e.UNSIGNED_SHORT_4_4_4_4&&(o=e.RGBA4),r===e.UNSIGNED_SHORT_5_5_5_1&&(o=e.RGB5_A1)}return o!==e.R16F&&o!==e.R32F&&o!==e.RG16F&&o!==e.RG32F&&o!==e.RGBA16F&&o!==e.RGBA32F||t.get("EXT_color_buffer_float"),o}function D(t,n){let i;return t?null===n||n===w||n===L?i=e.DEPTH24_STENCIL8:n===T?i=e.DEPTH32F_STENCIL8:n===S&&(i=e.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===w||n===L?i=e.DEPTH_COMPONENT24:n===T?i=e.DEPTH_COMPONENT32F:n===S&&(i=e.DEPTH_COMPONENT16),i}function O(e,t){return!0===R(e)||e.isFramebufferTexture&&e.minFilter!==m&&e.minFilter!==v?Math.log2(Math.max(t.width,t.height))+1:void 0!==e.mipmaps&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function F(e){const t=e.target;t.removeEventListener("dispose",F),function(e){const t=i.get(e);if(void 0===t.__webglInit)return;const n=e.source,r=b.get(n);if(r){const i=r[t.__cacheKey];i.usedTimes--,0===i.usedTimes&&B(e),0===Object.keys(r).length&&b.delete(n)}i.remove(e)}(t),t.isVideoTexture&&h.delete(t)}function k(t){const n=t.target;n.removeEventListener("dispose",k),function(t){const n=i.get(t);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(n.__webglFramebuffer[t]))for(let i=0;i0&&a.__version!==t.version){const e=t.image;if(null===e)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==e.complete)return void q(a,t,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(e.TEXTURE_2D,a.__webglTexture,e.TEXTURE0+r)}const V={[d]:e.REPEAT,[p]:e.CLAMP_TO_EDGE,[f]:e.MIRRORED_REPEAT},G={[m]:e.NEAREST,1004:e.NEAREST_MIPMAP_NEAREST,[g]:e.NEAREST_MIPMAP_LINEAR,[v]:e.LINEAR,[_]:e.LINEAR_MIPMAP_NEAREST,[y]:e.LINEAR_MIPMAP_LINEAR},W={512:e.NEVER,519:e.ALWAYS,513:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL};function j(n,a){if(a.type!==T||!1!==t.has("OES_texture_float_linear")||a.magFilter!==v&&a.magFilter!==_&&a.magFilter!==g&&a.magFilter!==y&&a.minFilter!==v&&a.minFilter!==_&&a.minFilter!==g&&a.minFilter!==y||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),e.texParameteri(n,e.TEXTURE_WRAP_S,V[a.wrapS]),e.texParameteri(n,e.TEXTURE_WRAP_T,V[a.wrapT]),n!==e.TEXTURE_3D&&n!==e.TEXTURE_2D_ARRAY||e.texParameteri(n,e.TEXTURE_WRAP_R,V[a.wrapR]),e.texParameteri(n,e.TEXTURE_MAG_FILTER,G[a.magFilter]),e.texParameteri(n,e.TEXTURE_MIN_FILTER,G[a.minFilter]),a.compareFunction&&(e.texParameteri(n,e.TEXTURE_COMPARE_MODE,e.COMPARE_REF_TO_TEXTURE),e.texParameteri(n,e.TEXTURE_COMPARE_FUNC,W[a.compareFunction])),!0===t.has("EXT_texture_filter_anisotropic")){if(a.magFilter===m)return;if(a.minFilter!==g&&a.minFilter!==y)return;if(a.type===T&&!1===t.has("OES_texture_float_linear"))return;if(a.anisotropy>1||i.get(a).__currentAnisotropy){const s=t.get("EXT_texture_filter_anisotropic");e.texParameterf(n,s.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,r.getMaxAnisotropy())),i.get(a).__currentAnisotropy=a.anisotropy}}}function X(t,n){let i=!1;void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",F));const r=n.source;let a=b.get(r);void 0===a&&(a={},b.set(r,a));const o=function(e){const t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}(n);if(o!==t.__cacheKey){void 0===a[o]&&(a[o]={texture:e.createTexture(),usedTimes:0},s.memory.textures++,i=!0),a[o].usedTimes++;const r=a[t.__cacheKey];void 0!==r&&(a[t.__cacheKey].usedTimes--,0===r.usedTimes&&B(n)),t.__cacheKey=o,t.__webglTexture=a[o].texture}return i}function q(t,s,o){let l=e.TEXTURE_2D;(s.isDataArrayTexture||s.isCompressedArrayTexture)&&(l=e.TEXTURE_2D_ARRAY),s.isData3DTexture&&(l=e.TEXTURE_3D);const c=X(t,s),h=s.source;n.bindTexture(l,t.__webglTexture,e.TEXTURE0+o);const u=i.get(h);if(h.version!==u.__version||!0===c){n.activeTexture(e.TEXTURE0+o);const t=nt.getPrimaries(nt.workingColorSpace),i=s.colorSpace===_e?null:nt.getPrimaries(s.colorSpace),d=s.colorSpace===_e||t===i?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,s.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,s.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,s.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,d);let p=A(s.image,!1,r.maxTextureSize);p=te(s,p);const f=a.convert(s.format,s.colorSpace),m=a.convert(s.type);let g,v=P(s.internalFormat,f,m,s.colorSpace,s.isVideoTexture);j(l,s);const _=s.mipmaps,y=!0!==s.isVideoTexture,x=void 0===u.__version||!0===c,b=h.dataReady,M=O(s,p);if(s.isDepthTexture)v=D(s.format===U,s.type),x&&(y?n.texStorage2D(e.TEXTURE_2D,1,v,p.width,p.height):n.texImage2D(e.TEXTURE_2D,0,v,p.width,p.height,0,f,m,null));else if(s.isDataTexture)if(_.length>0){y&&x&&n.texStorage2D(e.TEXTURE_2D,M,v,_[0].width,_[0].height);for(let t=0,i=_.length;t0){const i=ys(g.width,g.height,s.format,s.type);for(const r of s.layerUpdates){const a=g.data.subarray(r*i/g.data.BYTES_PER_ELEMENT,(r+1)*i/g.data.BYTES_PER_ELEMENT);n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,r,g.width,g.height,1,f,a,0,0)}s.clearLayerUpdates()}else n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,p.depth,f,g.data,0,0)}else n.compressedTexImage3D(e.TEXTURE_2D_ARRAY,t,v,g.width,g.height,p.depth,0,g.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else y?b&&n.texSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,p.depth,f,m,g.data):n.texImage3D(e.TEXTURE_2D_ARRAY,t,v,g.width,g.height,p.depth,0,f,m,g.data)}else{y&&x&&n.texStorage2D(e.TEXTURE_2D,M,v,_[0].width,_[0].height);for(let t=0,i=_.length;t0){const t=ys(p.width,p.height,s.format,s.type);for(const i of s.layerUpdates){const r=p.data.subarray(i*t/p.data.BYTES_PER_ELEMENT,(i+1)*t/p.data.BYTES_PER_ELEMENT);n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,i,p.width,p.height,1,f,m,r)}s.clearLayerUpdates()}else n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,0,p.width,p.height,p.depth,f,m,p.data)}else n.texImage3D(e.TEXTURE_2D_ARRAY,0,v,p.width,p.height,p.depth,0,f,m,p.data);else if(s.isData3DTexture)y?(x&&n.texStorage3D(e.TEXTURE_3D,M,v,p.width,p.height,p.depth),b&&n.texSubImage3D(e.TEXTURE_3D,0,0,0,0,p.width,p.height,p.depth,f,m,p.data)):n.texImage3D(e.TEXTURE_3D,0,v,p.width,p.height,p.depth,0,f,m,p.data);else if(s.isFramebufferTexture){if(x)if(y)n.texStorage2D(e.TEXTURE_2D,M,v,p.width,p.height);else{let t=p.width,i=p.height;for(let r=0;r>=1,i>>=1}}else if(_.length>0){if(y&&x){const t=ne(_[0]);n.texStorage2D(e.TEXTURE_2D,M,v,t.width,t.height)}for(let t=0,i=_.length;t>h),i=Math.max(1,r.height>>h);c===e.TEXTURE_3D||c===e.TEXTURE_2D_ARRAY?n.texImage3D(c,h,p,t,i,r.depth,0,u,d,null):n.texImage2D(c,h,p,t,i,0,u,d,null)}n.bindFramebuffer(e.FRAMEBUFFER,t),ee(r)?o.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,l,c,i.get(s).__webglTexture,0,$(r)):(c===e.TEXTURE_2D||c>=e.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=e.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&e.framebufferTexture2D(e.FRAMEBUFFER,l,c,i.get(s).__webglTexture,h),n.bindFramebuffer(e.FRAMEBUFFER,null)}function K(t,n,i){if(e.bindRenderbuffer(e.RENDERBUFFER,t),n.depthBuffer){const r=n.depthTexture,a=r&&r.isDepthTexture?r.type:null,s=D(n.stencilBuffer,a),l=n.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,c=$(n);ee(n)?o.renderbufferStorageMultisampleEXT(e.RENDERBUFFER,c,s,n.width,n.height):i?e.renderbufferStorageMultisample(e.RENDERBUFFER,c,s,n.width,n.height):e.renderbufferStorage(e.RENDERBUFFER,s,n.width,n.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,l,e.RENDERBUFFER,t)}else{const t=n.textures;for(let r=0;r0&&!0===t.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function te(e,t){const n=e.colorSpace,i=e.format,r=e.type;return!0===e.isCompressedTexture||!0===e.isVideoTexture||n!==xe&&n!==_e&&(nt.getTransfer(n)===Ee?i===I&&r===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),t}function ne(e){return"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement?(c.width=e.naturalWidth||e.width,c.height=e.naturalHeight||e.height):"undefined"!=typeof VideoFrame&&e instanceof VideoFrame?(c.width=e.displayWidth,c.height=e.displayHeight):(c.width=e.width,c.height=e.height),c}this.allocateTextureUnit=function(){const e=z;return e>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+r.maxTextures),z+=1,e},this.resetTextureUnits=function(){z=0},this.setTexture2D=H,this.setTexture2DArray=function(t,r){const a=i.get(t);t.version>0&&a.__version!==t.version?q(a,t,r):n.bindTexture(e.TEXTURE_2D_ARRAY,a.__webglTexture,e.TEXTURE0+r)},this.setTexture3D=function(t,r){const a=i.get(t);t.version>0&&a.__version!==t.version?q(a,t,r):n.bindTexture(e.TEXTURE_3D,a.__webglTexture,e.TEXTURE0+r)},this.setTextureCube=function(t,s){const o=i.get(t);t.version>0&&o.__version!==t.version?function(t,s,o){if(6!==s.image.length)return;const l=X(t,s),c=s.source;n.bindTexture(e.TEXTURE_CUBE_MAP,t.__webglTexture,e.TEXTURE0+o);const h=i.get(c);if(c.version!==h.__version||!0===l){n.activeTexture(e.TEXTURE0+o);const t=nt.getPrimaries(nt.workingColorSpace),i=s.colorSpace===_e?null:nt.getPrimaries(s.colorSpace),u=s.colorSpace===_e||t===i?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,s.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,s.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,s.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,u);const d=s.isCompressedTexture||s.image[0].isCompressedTexture,p=s.image[0]&&s.image[0].isDataTexture,f=[];for(let e=0;e<6;e++)f[e]=d||p?p?s.image[e].image:s.image[e]:A(s.image[e],!0,r.maxCubemapSize),f[e]=te(s,f[e]);const m=f[0],g=a.convert(s.format,s.colorSpace),v=a.convert(s.type),_=P(s.internalFormat,g,v,s.colorSpace),y=!0!==s.isVideoTexture,x=void 0===h.__version||!0===l,b=c.dataReady;let M,S=O(s,m);if(j(e.TEXTURE_CUBE_MAP,s),d){y&&x&&n.texStorage2D(e.TEXTURE_CUBE_MAP,S,_,m.width,m.height);for(let t=0;t<6;t++){M=f[t].mipmaps;for(let i=0;i0&&S++;const t=ne(f[0]);n.texStorage2D(e.TEXTURE_CUBE_MAP,S,_,t.width,t.height)}for(let t=0;t<6;t++)if(p){y?b&&n.texSubImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,0,0,f[t].width,f[t].height,g,v,f[t].data):n.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,_,f[t].width,f[t].height,0,g,v,f[t].data);for(let i=0;i1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=e.createTexture()),l.__version=r.version,s.memory.textures++),h){o.__webglFramebuffer=[];for(let t=0;t<6;t++)if(r.mipmaps&&r.mipmaps.length>0){o.__webglFramebuffer[t]=[];for(let n=0;n0){o.__webglFramebuffer=[];for(let t=0;t0&&!1===ee(t)){o.__webglMultisampledFramebuffer=e.createFramebuffer(),o.__webglColorRenderbuffer=[],n.bindFramebuffer(e.FRAMEBUFFER,o.__webglMultisampledFramebuffer);for(let n=0;n0)for(let i=0;i0)for(let n=0;n0)if(!1===ee(t)){const r=t.textures,a=t.width,s=t.height;let o=e.COLOR_BUFFER_BIT;const c=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,h=i.get(t),u=r.length>1;if(u)for(let t=0;to+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!l.inputState.pinching&&s<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else null!==o&&e.gripSpace&&(r=t.getPose(e.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==s&&(i=t.getPose(e.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(s.matrix.fromArray(i.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,i.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(i.linearVelocity)):s.hasLinearVelocity=!1,i.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(i.angularVelocity)):s.hasAngularVelocity=!1,this.dispatchEvent(Es)))}return null!==s&&(s.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==a),this}_getHandJoint(e,t){if(void 0===e.joints[t.jointName]){const n=new Ss;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}class Ts{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(null===this.texture){const i=new ht;e.properties.get(i).__webglTexture=t.texture,t.depthNear==n.depthNear&&t.depthFar==n.depthFar||(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=i}}getMesh(e){if(null!==this.texture&&null===this.mesh){const t=e.cameras[0].viewport,n=new Ti({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new yi(new ji(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class As extends Ie{constructor(e,t){super();const n=this;let i=null,r=1,a=null,s="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const f=new Ts,m=t.getContextAttributes();let g=null,v=null;const _=[],y=[],b=new We;let M=null;const S=new Pi;S.layers.enable(1),S.viewport=new ut;const E=new Pi;E.layers.enable(2),E.viewport=new ut;const T=[S,E],A=new Ms;A.layers.enable(1),A.layers.enable(2);let R=null,C=null;function P(e){const t=y.indexOf(e.inputSource);if(-1===t)return;const n=_[t];void 0!==n&&(n.update(e.inputSource,e.frame,l||a),n.dispatchEvent({type:e.type,data:e.inputSource}))}function D(){i.removeEventListener("select",P),i.removeEventListener("selectstart",P),i.removeEventListener("selectend",P),i.removeEventListener("squeeze",P),i.removeEventListener("squeezestart",P),i.removeEventListener("squeezeend",P),i.removeEventListener("end",D),i.removeEventListener("inputsourceschange",O);for(let e=0;e<_.length;e++){const t=y[e];null!==t&&(y[e]=null,_[e].disconnect(t))}R=null,C=null,f.reset(),e.setRenderTarget(g),d=null,u=null,h=null,i=null,v=null,H.stop(),n.isPresenting=!1,e.setPixelRatio(M),e.setSize(b.width,b.height,!1),n.dispatchEvent({type:"sessionend"})}function O(e){for(let t=0;t=0&&(y[i]=null,_[i].disconnect(n))}for(let t=0;t=y.length){y.push(n),i=e;break}if(null===y[e]){y[e]=n,i=e;break}}if(-1===i)break}const r=_[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=_[e];return void 0===t&&(t=new ws,_[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=_[e];return void 0===t&&(t=new ws,_[e]=t),t.getGripSpace()},this.getHand=function(e){let t=_[e];return void 0===t&&(t=new ws,_[e]=t),t.getHandSpace()},this.setFramebufferScaleFactor=function(e){r=e,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(e){s=e,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||a},this.setReferenceSpace=function(e){l=e},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(g=e.getRenderTarget(),i.addEventListener("select",P),i.addEventListener("selectstart",P),i.addEventListener("selectend",P),i.addEventListener("squeeze",P),i.addEventListener("squeezestart",P),i.addEventListener("squeezeend",P),i.addEventListener("end",D),i.addEventListener("inputsourceschange",O),!0!==m.xrCompatible&&await t.makeXRCompatible(),M=e.getPixelRatio(),e.getSize(b),void 0===i.renderState.layers){const n={antialias:m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,t,n),i.updateRenderState({baseLayer:d}),e.setPixelRatio(1),e.setSize(d.framebufferWidth,d.framebufferHeight,!1),v=new pt(d.framebufferWidth,d.framebufferHeight,{format:I,type:x,colorSpace:e.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,a=null,s=null;m.depth&&(s=m.stencil?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT24,n=m.stencil?U:N,a=m.stencil?L:w);const o={colorFormat:t.RGBA8,depthFormat:s,scaleFactor:r};h=new XRWebGLBinding(i,t),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),e.setPixelRatio(1),e.setSize(u.textureWidth,u.textureHeight,!1),v=new pt(u.textureWidth,u.textureHeight,{format:I,type:x,depthTexture:new Cr(u.textureWidth,u.textureHeight,a,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:e.outputColorSpace,samples:m.antialias?4:0,resolveDepthBuffer:!1===u.ignoreDepthValues})}v.isXRRenderTarget=!0,this.setFoveation(o),l=null,a=await i.requestReferenceSpace(s),H.setContext(i),H.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode},this.getDepthTexture=function(){return f.getDepthTexture()};const F=new vt,k=new vt;function B(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){if(null===i)return;null!==f.texture&&(e.near=f.depthNear,e.far=f.depthFar),A.near=E.near=S.near=e.near,A.far=E.far=S.far=e.far,R===A.near&&C===A.far||(i.updateRenderState({depthNear:A.near,depthFar:A.far}),R=A.near,C=A.far,S.near=R,S.far=C,E.near=R,E.far=C,S.updateProjectionMatrix(),E.updateProjectionMatrix(),e.updateProjectionMatrix());const t=e.parent,n=A.cameras;B(A,t);for(let e=0;e0&&(e.alphaTest.value=i.alphaTest);const r=t.get(i),a=r.envMap,s=r.envMapRotation;a&&(e.envMap.value=a,Rs.copy(s),Rs.x*=-1,Rs.y*=-1,Rs.z*=-1,a.isCubeTexture&&!1===a.isRenderTargetTexture&&(Rs.y*=-1,Rs.z*=-1),e.envMapRotation.value.setFromMatrix4(Cs.makeRotationFromEuler(Rs)),e.flipEnvMap.value=a.isCubeTexture&&!1===a.isRenderTargetTexture?-1:1,e.reflectivity.value=i.reflectivity,e.ior.value=i.ior,e.refractionRatio.value=i.refractionRatio),i.lightMap&&(e.lightMap.value=i.lightMap,e.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,e.lightMapTransform)),i.aoMap&&(e.aoMap.value=i.aoMap,e.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,e.aoMapTransform))}return{refreshFogUniforms:function(t,n){n.color.getRGB(t.fogColor.value,Ei(e)),n.isFog?(t.fogNear.value=n.near,t.fogFar.value=n.far):n.isFogExp2&&(t.fogDensity.value=n.density)},refreshMaterialUniforms:function(e,r,a,s,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(e,r):r.isMeshToonMaterial?(i(e,r),function(e,t){t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(e,r)):r.isMeshPhongMaterial?(i(e,r),function(e,t){e.specular.value.copy(t.specular),e.shininess.value=Math.max(t.shininess,1e-4)}(e,r)):r.isMeshStandardMaterial?(i(e,r),function(e,t){e.metalness.value=t.metalness,t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap,n(t.metalnessMap,e.metalnessMapTransform));e.roughness.value=t.roughness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap,n(t.roughnessMap,e.roughnessMapTransform));t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}(e,r),r.isMeshPhysicalMaterial&&function(e,t,i){e.ior.value=t.ior,t.sheen>0&&(e.sheenColor.value.copy(t.sheenColor).multiplyScalar(t.sheen),e.sheenRoughness.value=t.sheenRoughness,t.sheenColorMap&&(e.sheenColorMap.value=t.sheenColorMap,n(t.sheenColorMap,e.sheenColorMapTransform)),t.sheenRoughnessMap&&(e.sheenRoughnessMap.value=t.sheenRoughnessMap,n(t.sheenRoughnessMap,e.sheenRoughnessMapTransform)));t.clearcoat>0&&(e.clearcoat.value=t.clearcoat,e.clearcoatRoughness.value=t.clearcoatRoughness,t.clearcoatMap&&(e.clearcoatMap.value=t.clearcoatMap,n(t.clearcoatMap,e.clearcoatMapTransform)),t.clearcoatRoughnessMap&&(e.clearcoatRoughnessMap.value=t.clearcoatRoughnessMap,n(t.clearcoatRoughnessMap,e.clearcoatRoughnessMapTransform)),t.clearcoatNormalMap&&(e.clearcoatNormalMap.value=t.clearcoatNormalMap,n(t.clearcoatNormalMap,e.clearcoatNormalMapTransform),e.clearcoatNormalScale.value.copy(t.clearcoatNormalScale),1===t.side&&e.clearcoatNormalScale.value.negate()));t.dispersion>0&&(e.dispersion.value=t.dispersion);t.iridescence>0&&(e.iridescence.value=t.iridescence,e.iridescenceIOR.value=t.iridescenceIOR,e.iridescenceThicknessMinimum.value=t.iridescenceThicknessRange[0],e.iridescenceThicknessMaximum.value=t.iridescenceThicknessRange[1],t.iridescenceMap&&(e.iridescenceMap.value=t.iridescenceMap,n(t.iridescenceMap,e.iridescenceMapTransform)),t.iridescenceThicknessMap&&(e.iridescenceThicknessMap.value=t.iridescenceThicknessMap,n(t.iridescenceThicknessMap,e.iridescenceThicknessMapTransform)));t.transmission>0&&(e.transmission.value=t.transmission,e.transmissionSamplerMap.value=i.texture,e.transmissionSamplerSize.value.set(i.width,i.height),t.transmissionMap&&(e.transmissionMap.value=t.transmissionMap,n(t.transmissionMap,e.transmissionMapTransform)),e.thickness.value=t.thickness,t.thicknessMap&&(e.thicknessMap.value=t.thicknessMap,n(t.thicknessMap,e.thicknessMapTransform)),e.attenuationDistance.value=t.attenuationDistance,e.attenuationColor.value.copy(t.attenuationColor));t.anisotropy>0&&(e.anisotropyVector.value.set(t.anisotropy*Math.cos(t.anisotropyRotation),t.anisotropy*Math.sin(t.anisotropyRotation)),t.anisotropyMap&&(e.anisotropyMap.value=t.anisotropyMap,n(t.anisotropyMap,e.anisotropyMapTransform)));e.specularIntensity.value=t.specularIntensity,e.specularColor.value.copy(t.specularColor),t.specularColorMap&&(e.specularColorMap.value=t.specularColorMap,n(t.specularColorMap,e.specularColorMapTransform));t.specularIntensityMap&&(e.specularIntensityMap.value=t.specularIntensityMap,n(t.specularIntensityMap,e.specularIntensityMapTransform))}(e,r,o)):r.isMeshMatcapMaterial?(i(e,r),function(e,t){t.matcap&&(e.matcap.value=t.matcap)}(e,r)):r.isMeshDepthMaterial?i(e,r):r.isMeshDistanceMaterial?(i(e,r),function(e,n){const i=t.get(n).light;e.referencePosition.value.setFromMatrixPosition(i.matrixWorld),e.nearDistance.value=i.shadow.camera.near,e.farDistance.value=i.shadow.camera.far}(e,r)):r.isMeshNormalMaterial?i(e,r):r.isLineBasicMaterial?(function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform))}(e,r),r.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(e,r)):r.isPointsMaterial?function(e,t,i,r){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.size.value=t.size*i,e.scale.value=.5*r,t.map&&(e.map.value=t.map,n(t.map,e.uvTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r,a,s):r.isSpriteMaterial?function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.rotation.value=t.rotation,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r):r.isShadowMaterial?(e.color.value.copy(r.color),e.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function Ps(e,t,n,i){let r={},a={},s=[];const o=e.getParameter(e.MAX_UNIFORM_BUFFER_BINDINGS);function l(e,t,n,i){const r=e.value,a=t+"_"+n;if(void 0===i[a])return i[a]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const e=i[a];if("number"==typeof r||"boolean"==typeof r){if(e!==r)return i[a]=r,!0}else if(!1===e.equals(r))return e.copy(r),!0}return!1}function c(e){const t={boundary:0,storage:0};return"number"==typeof e||"boolean"==typeof e?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),t}function h(t){const n=t.target;n.removeEventListener("dispose",h);const i=s.indexOf(n.__bindingPointIndex);s.splice(i,1),e.deleteBuffer(r[n.id]),delete r[n.id],delete a[n.id]}return{bind:function(e,t){const n=t.program;i.uniformBlockBinding(e,n)},update:function(n,u){let d=r[n.id];void 0===d&&(!function(e){const t=e.uniforms;let n=0;const i=16;for(let e=0,r=t.length;e0&&(n+=i-r);e.__size=n,e.__cache={}}(n),d=function(t){const n=function(){for(let e=0;e0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let f=0;i.toneMapped&&(null!==T&&!0!==T.isXRRenderTarget||(f=_.toneMapping));const g=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,v=void 0!==g?g.length:0,y=le.get(i),x=m.state.lights;if(!0===Z&&(!0===J||e!==I)){const t=e===I&&i.id===P;be.setState(i,e,t)}let b=!1;i.version===y.__version?y.needsLights&&y.lightsStateVersion!==x.state.version||y.outputColorSpace!==o||r.isBatchedMesh&&!1===y.batching?b=!0:r.isBatchedMesh||!0!==y.batching?r.isBatchedMesh&&!0===y.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===y.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===y.instancing?b=!0:r.isInstancedMesh||!0!==y.instancing?r.isSkinnedMesh&&!1===y.skinning?b=!0:r.isSkinnedMesh||!0!==y.skinning?r.isInstancedMesh&&!0===y.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===y.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===y.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===y.instancingMorph&&null!==r.morphTexture||y.envMap!==l||!0===i.fog&&y.fog!==a?b=!0:void 0===y.numClippingPlanes||y.numClippingPlanes===be.numPlanes&&y.numIntersection===be.numIntersection?(y.vertexAlphas!==c||y.vertexTangents!==h||y.morphTargets!==u||y.morphNormals!==d||y.morphColors!==p||y.toneMapping!==f||y.morphTargetsCount!==v)&&(b=!0):b=!0:b=!0:b=!0:b=!0:(b=!0,y.__version=i.version);let M=y.currentProgram;!0===b&&(M=Ye(i,t,r));let S=!1,E=!1,w=!1;const A=M.getUniforms(),R=y.uniforms;se.useProgram(M.program)&&(S=!0,E=!0,w=!0);i.id!==P&&(P=i.id,E=!0);if(S||I!==e){A.setValue(Le,"projectionMatrix",e.projectionMatrix),A.setValue(Le,"viewMatrix",e.matrixWorldInverse);const t=A.map.cameraPosition;void 0!==t&&t.setValue(Le,$.setFromMatrixPosition(e.matrixWorld)),ae.logarithmicDepthBuffer&&A.setValue(Le,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&A.setValue(Le,"isOrthographic",!0===e.isOrthographicCamera),I!==e&&(I=e,E=!0,w=!0)}if(r.isSkinnedMesh){A.setOptional(Le,r,"bindMatrix"),A.setOptional(Le,r,"bindMatrixInverse");const e=r.skeleton;e&&(null===e.boneTexture&&e.computeBoneTexture(),A.setValue(Le,"boneTexture",e.boneTexture,ce))}r.isBatchedMesh&&(A.setOptional(Le,r,"batchingTexture"),A.setValue(Le,"batchingTexture",r._matricesTexture,ce),A.setOptional(Le,r,"batchingIdTexture"),A.setValue(Le,"batchingIdTexture",r._indirectTexture,ce),A.setOptional(Le,r,"batchingColorTexture"),null!==r._colorsTexture&&A.setValue(Le,"batchingColorTexture",r._colorsTexture,ce));const C=n.morphAttributes;void 0===C.position&&void 0===C.normal&&void 0===C.color||Ee.update(r,n,M);(E||y.receiveShadow!==r.receiveShadow)&&(y.receiveShadow=r.receiveShadow,A.setValue(Le,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(R.envMap.value=l,R.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==t.environment&&(R.envMapIntensity.value=t.environmentIntensity);E&&(A.setValue(Le,"toneMappingExposure",_.toneMappingExposure),y.needsLights&&function(e,t){e.ambientLightColor.needsUpdate=t,e.lightProbe.needsUpdate=t,e.directionalLights.needsUpdate=t,e.directionalLightShadows.needsUpdate=t,e.pointLights.needsUpdate=t,e.pointLightShadows.needsUpdate=t,e.spotLights.needsUpdate=t,e.spotLightShadows.needsUpdate=t,e.rectAreaLights.needsUpdate=t,e.hemisphereLights.needsUpdate=t}(R,w),a&&!0===i.fog&&ge.refreshFogUniforms(R,a),ge.refreshMaterialUniforms(R,i,G,V,m.state.transmissionRenderTarget[e.id]),Ua.upload(Le,Ze(y),R,ce));i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(Ua.upload(Le,Ze(y),R,ce),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&A.setValue(Le,"center",r.center);if(A.setValue(Le,"modelViewMatrix",r.modelViewMatrix),A.setValue(Le,"normalMatrix",r.normalMatrix),A.setValue(Le,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const e=i.uniformsGroups;for(let t=0,n=e.length;t{function n(){i.forEach((function(e){le.get(e).currentProgram.isReady()&&i.delete(e)})),0!==i.size?setTimeout(n,10):t(e)}null!==re.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let Be=null;function ze(){Ve.stop()}function He(){Ve.start()}const Ve=new Gi;function Ge(e,t,n,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)n=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)m.pushLight(e),e.castShadow&&m.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||K.intersectsSprite(e)){i&&ee.setFromMatrixPosition(e.matrixWorld).applyMatrix4(Q);const t=fe.update(e),r=e.material;r.visible&&f.push(e,t,r,n,ee.z,null)}}else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||K.intersectsObject(e))){const t=fe.update(e),r=e.material;if(i&&(void 0!==e.boundingSphere?(null===e.boundingSphere&&e.computeBoundingSphere(),ee.copy(e.boundingSphere.center)):(null===t.boundingSphere&&t.computeBoundingSphere(),ee.copy(t.boundingSphere.center)),ee.applyMatrix4(e.matrixWorld).applyMatrix4(Q)),Array.isArray(r)){const i=t.groups;for(let a=0,s=i.length;a0&&Xe(r,t,n),a.length>0&&Xe(a,t,n),s.length>0&&Xe(s,t,n),se.buffers.depth.setTest(!0),se.buffers.depth.setMask(!0),se.buffers.color.setMask(!0),se.setPolygonOffset(!1)}function je(e,t,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===m.state.transmissionRenderTarget[i.id]&&(m.state.transmissionRenderTarget[i.id]=new pt(1,1,{generateMipmaps:!0,type:re.has("EXT_color_buffer_half_float")||re.has("EXT_color_buffer_float")?A:x,minFilter:y,samples:4,stencilBuffer:r,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:nt.workingColorSpace}));const a=m.state.transmissionRenderTarget[i.id],s=i.viewport||N;a.setSize(s.z,s.w);const o=_.getRenderTarget();_.setRenderTarget(a),_.getClearColor(B),z=_.getClearAlpha(),z<1&&_.setClearColor(16777215,.5),_.clear(),ne&&Se.render(n);const l=_.toneMapping;_.toneMapping=0;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),m.setupLightsView(i),!0===Z&&be.setGlobalState(_.clippingPlanes,i),Xe(e,n,i),ce.updateMultisampleRenderTarget(a),ce.updateRenderTargetMipmap(a),!1===re.has("WEBGL_multisampled_render_to_texture")){let e=!1;for(let r=0,a=t.length;r0)for(let t=0,a=n.length;t0&&je(i,r,e,t),ne&&Se.render(e),We(f,e,t);null!==T&&(ce.updateMultisampleRenderTarget(T),ce.updateRenderTargetMipmap(T)),!0===e.isScene&&e.onAfterRender(_,e,t),Re.resetDefaultState(),P=-1,I=null,v.pop(),v.length>0?(m=v[v.length-1],!0===Z&&be.setGlobalState(_.clippingPlanes,m.state.camera)):m=null,g.pop(),f=g.length>0?g[g.length-1]:null},this.getActiveCubeFace=function(){return M},this.getActiveMipmapLevel=function(){return E},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(e,t,n){le.get(e.texture).__webglTexture=t,le.get(e.depthTexture).__webglTexture=n;const i=le.get(e);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===re.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(e,t){const n=le.get(e);n.__webglFramebuffer=t,n.__useDefaultFramebuffer=void 0===t},this.setRenderTarget=function(e,t=0,n=0){T=e,M=t,E=n;let i=!0,r=null,a=!1,s=!1;if(e){const o=le.get(e);void 0!==o.__useDefaultFramebuffer?(se.bindFramebuffer(Le.FRAMEBUFFER,null),i=!1):void 0===o.__webglFramebuffer?ce.setupRenderTarget(e):o.__hasExternalTextures&&ce.rebindTextures(e,le.get(e.texture).__webglTexture,le.get(e.depthTexture).__webglTexture);const l=e.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(s=!0);const c=le.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(r=Array.isArray(c[t])?c[t][n]:c[t],a=!0):r=e.samples>0&&!1===ce.useMultisampledRTT(e)?le.get(e).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,N.copy(e.viewport),U.copy(e.scissor),k=e.scissorTest}else N.copy(X).multiplyScalar(G).floor(),U.copy(q).multiplyScalar(G).floor(),k=Y;if(se.bindFramebuffer(Le.FRAMEBUFFER,r)&&i&&se.drawBuffers(e,r),se.viewport(N),se.scissor(U),se.setScissorTest(k),a){const i=le.get(e.texture);Le.framebufferTexture2D(Le.FRAMEBUFFER,Le.COLOR_ATTACHMENT0,Le.TEXTURE_CUBE_MAP_POSITIVE_X+t,i.__webglTexture,n)}else if(s){const i=le.get(e.texture),r=t||0;Le.framebufferTextureLayer(Le.FRAMEBUFFER,Le.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}P=-1},this.readRenderTargetPixels=function(e,t,n,i,r,a,s){if(!e||!e.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=le.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==s&&(o=o[s]),o){se.bindFramebuffer(Le.FRAMEBUFFER,o);try{const s=e.texture,o=s.format,l=s.type;if(!ae.textureFormatReadable(o))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!ae.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&Le.readPixels(t,n,i,r,Ae.convert(o),Ae.convert(l),a)}finally{const e=null!==T?le.get(T).__webglFramebuffer:null;se.bindFramebuffer(Le.FRAMEBUFFER,e)}}},this.readRenderTargetPixelsAsync=async function(e,t,n,i,r,a,s){if(!e||!e.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=le.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==s&&(o=o[s]),o){se.bindFramebuffer(Le.FRAMEBUFFER,o);try{const s=e.texture,o=s.format,l=s.type;if(!ae.textureFormatReadable(o))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ae.textureTypeReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r){const e=Le.createBuffer();Le.bindBuffer(Le.PIXEL_PACK_BUFFER,e),Le.bufferData(Le.PIXEL_PACK_BUFFER,a.byteLength,Le.STREAM_READ),Le.readPixels(t,n,i,r,Ae.convert(o),Ae.convert(l),0),Le.flush();const s=Le.fenceSync(Le.SYNC_GPU_COMMANDS_COMPLETE,0);await function(e,t,n){return new Promise((function(i,r){setTimeout((function a(){switch(e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0)){case e.WAIT_FAILED:r();break;case e.TIMEOUT_EXPIRED:setTimeout(a,n);break;default:i()}}),n)}))}(Le,s,4);try{Le.bindBuffer(Le.PIXEL_PACK_BUFFER,e),Le.getBufferSubData(Le.PIXEL_PACK_BUFFER,0,a)}finally{Le.deleteBuffer(e),Le.deleteSync(s)}return a}}finally{const e=null!==T?le.get(T).__webglFramebuffer:null;se.bindFramebuffer(Le.FRAMEBUFFER,e)}}},this.copyFramebufferToTexture=function(e,t=null,n=0){!0!==e.isTexture&&(Je("WebGLRenderer: copyFramebufferToTexture function signature has changed."),t=arguments[0]||null,e=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),a=Math.floor(e.image.height*i),s=null!==t?t.x:0,o=null!==t?t.y:0;ce.setTexture2D(e,0),Le.copyTexSubImage2D(Le.TEXTURE_2D,n,0,0,s,o,r,a),se.unbindTexture()},this.copyTextureToTexture=function(e,t,n=null,i=null,r=0){let a,s,o,l,c,h;!0!==e.isTexture&&(Je("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,e=arguments[1],t=arguments[2],r=arguments[3]||0,n=null),null!==n?(a=n.max.x-n.min.x,s=n.max.y-n.min.y,o=n.min.x,l=n.min.y):(a=e.image.width,s=e.image.height,o=0,l=0),null!==i?(c=i.x,h=i.y):(c=0,h=0);const u=Ae.convert(t.format),d=Ae.convert(t.type);ce.setTexture2D(t,0),Le.pixelStorei(Le.UNPACK_FLIP_Y_WEBGL,t.flipY),Le.pixelStorei(Le.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Le.pixelStorei(Le.UNPACK_ALIGNMENT,t.unpackAlignment);const p=Le.getParameter(Le.UNPACK_ROW_LENGTH),f=Le.getParameter(Le.UNPACK_IMAGE_HEIGHT),m=Le.getParameter(Le.UNPACK_SKIP_PIXELS),g=Le.getParameter(Le.UNPACK_SKIP_ROWS),v=Le.getParameter(Le.UNPACK_SKIP_IMAGES),_=e.isCompressedTexture?e.mipmaps[r]:e.image;Le.pixelStorei(Le.UNPACK_ROW_LENGTH,_.width),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,_.height),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,o),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,l),e.isDataTexture?Le.texSubImage2D(Le.TEXTURE_2D,r,c,h,a,s,u,d,_.data):e.isCompressedTexture?Le.compressedTexSubImage2D(Le.TEXTURE_2D,r,c,h,_.width,_.height,u,_.data):Le.texSubImage2D(Le.TEXTURE_2D,r,c,h,a,s,u,d,_),Le.pixelStorei(Le.UNPACK_ROW_LENGTH,p),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,f),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,m),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,g),Le.pixelStorei(Le.UNPACK_SKIP_IMAGES,v),0===r&&t.generateMipmaps&&Le.generateMipmap(Le.TEXTURE_2D),se.unbindTexture()},this.copyTextureToTexture3D=function(e,t,n=null,i=null,r=0){let a,s,o,l,c,h,u,d,p;!0!==e.isTexture&&(Je("WebGLRenderer: copyTextureToTexture3D function signature has changed."),n=arguments[0]||null,i=arguments[1]||null,e=arguments[2],t=arguments[3],r=arguments[4]||0);const f=e.isCompressedTexture?e.mipmaps[r]:e.image;null!==n?(a=n.max.x-n.min.x,s=n.max.y-n.min.y,o=n.max.z-n.min.z,l=n.min.x,c=n.min.y,h=n.min.z):(a=f.width,s=f.height,o=f.depth,l=0,c=0,h=0),null!==i?(u=i.x,d=i.y,p=i.z):(u=0,d=0,p=0);const m=Ae.convert(t.format),g=Ae.convert(t.type);let v;if(t.isData3DTexture)ce.setTexture3D(t,0),v=Le.TEXTURE_3D;else{if(!t.isDataArrayTexture&&!t.isCompressedArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");ce.setTexture2DArray(t,0),v=Le.TEXTURE_2D_ARRAY}Le.pixelStorei(Le.UNPACK_FLIP_Y_WEBGL,t.flipY),Le.pixelStorei(Le.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Le.pixelStorei(Le.UNPACK_ALIGNMENT,t.unpackAlignment);const _=Le.getParameter(Le.UNPACK_ROW_LENGTH),y=Le.getParameter(Le.UNPACK_IMAGE_HEIGHT),x=Le.getParameter(Le.UNPACK_SKIP_PIXELS),b=Le.getParameter(Le.UNPACK_SKIP_ROWS),M=Le.getParameter(Le.UNPACK_SKIP_IMAGES);Le.pixelStorei(Le.UNPACK_ROW_LENGTH,f.width),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,f.height),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,l),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,c),Le.pixelStorei(Le.UNPACK_SKIP_IMAGES,h),e.isDataTexture||e.isData3DTexture?Le.texSubImage3D(v,r,u,d,p,a,s,o,m,g,f.data):t.isCompressedArrayTexture?Le.compressedTexSubImage3D(v,r,u,d,p,a,s,o,m,f.data):Le.texSubImage3D(v,r,u,d,p,a,s,o,m,g,f),Le.pixelStorei(Le.UNPACK_ROW_LENGTH,_),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,y),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,x),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,b),Le.pixelStorei(Le.UNPACK_SKIP_IMAGES,M),0===r&&t.generateMipmaps&&Le.generateMipmap(v),se.unbindTexture()},this.initRenderTarget=function(e){void 0===le.get(e).__webglFramebuffer&&ce.setupRenderTarget(e)},this.initTexture=function(e){e.isCubeTexture?ce.setTextureCube(e,0):e.isData3DTexture?ce.setTexture3D(e,0):e.isDataArrayTexture||e.isCompressedArrayTexture?ce.setTexture2DArray(e,0):ce.setTexture2D(e,0),se.unbindTexture()},this.resetState=function(){M=0,E=0,T=null,se.reset(),Re.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return Le}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(e){this._outputColorSpace=e;const t=this.getContext();t.drawingBufferColorSpace=e===be?"display-p3":"srgb",t.unpackColorSpace=nt.workingColorSpace===Me?"display-p3":"srgb"}}class Ns extends bn{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new rn,this.environmentIntensity=1,this.environmentRotation=new rn,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class Us{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=Re,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.version=0,this.uuid=Fe()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return Je("THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,n){e*=this.stride,n*=t.stride;for(let i=0,r=this.stride;ie.far||t.push({distance:o,point:Bs.clone(),uv:In.getInterpolation(Bs,js,Xs,qs,Ys,Ks,Zs,new We),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function Qs(e,t,n,i,r,a){Vs.subVectors(e,n).addScalar(.5).multiply(i),void 0!==r?(Gs.x=a*Vs.x-r*Vs.y,Gs.y=r*Vs.x+a*Vs.y):Gs.copy(Vs),e.copy(t),e.x+=Gs.x,e.y+=Gs.y,e.applyMatrix4(Ws)}const $s=new vt,eo=new ut,to=new ut,no=new vt,io=new qt,ro=new vt,ao=new kt,so=new qt,oo=new Xt;class lo extends yi{constructor(e,t){super(e,t),this.isSkinnedMesh=!0,this.type="SkinnedMesh",this.bindMode=l,this.bindMatrix=new qt,this.bindMatrixInverse=new qt,this.boundingBox=null,this.boundingSphere=null}computeBoundingBox(){const e=this.geometry;null===this.boundingBox&&(this.boundingBox=new xt),this.boundingBox.makeEmpty();const t=e.getAttribute("position");for(let e=0;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;ei)return;bo.applyMatrix4(e.matrixWorld);const o=t.ray.origin.distanceTo(bo);return ot.far?void 0:{distance:o,point:Mo.clone().applyMatrix4(e.matrixWorld),index:r,face:null,faceIndex:null,object:e}}const wo=new vt,To=new vt;class Ao extends So{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const e=this.geometry;if(null===e.index){const t=e.attributes.position,n=[];for(let e=0,i=t.count;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;er.far)return;a.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:t,face:null,object:s})}}class Do extends ti{constructor(e=1,t=1,n=1,i=32,r=1,a=!1,s=0,o=2*Math.PI){super(),this.type="CylinderGeometry",this.parameters={radiusTop:e,radiusBottom:t,height:n,radialSegments:i,heightSegments:r,openEnded:a,thetaStart:s,thetaLength:o};const l=this;i=Math.floor(i),r=Math.floor(r);const c=[],h=[],u=[],d=[];let p=0;const f=[],m=n/2;let g=0;function v(n){const r=p,a=new We,f=new vt;let v=0;const _=!0===n?e:t,y=!0===n?1:-1;for(let e=1;e<=i;e++)h.push(0,m*y,0),u.push(0,y,0),d.push(.5,.5),p++;const x=p;for(let e=0;e<=i;e++){const t=e/i*o+s,n=Math.cos(t),r=Math.sin(t);f.x=_*r,f.y=m*y,f.z=_*n,h.push(f.x,f.y,f.z),u.push(0,y,0),a.x=.5*n+.5,a.y=.5*r*y+.5,d.push(a.x,a.y),p++}for(let e=0;e0&&v(!0),t>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new qn(h,3)),this.setAttribute("normal",new qn(u,3)),this.setAttribute("uv",new qn(d,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Do(e.radiusTop,e.radiusBottom,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class Oo extends ti{constructor(e=1,t=32,n=16,i=0,r=2*Math.PI,a=0,s=Math.PI){super(),this.type="SphereGeometry",this.parameters={radius:e,widthSegments:t,heightSegments:n,phiStart:i,phiLength:r,thetaStart:a,thetaLength:s},t=Math.max(3,Math.floor(t)),n=Math.max(2,Math.floor(n));const o=Math.min(a+s,Math.PI);let l=0;const c=[],h=new vt,u=new vt,d=[],p=[],f=[],m=[];for(let d=0;d<=n;d++){const g=[],v=d/n;let _=0;0===d&&0===a?_=.5/t:d===n&&o===Math.PI&&(_=-.5/t);for(let n=0;n<=t;n++){const o=n/t;h.x=-e*Math.cos(i+o*r)*Math.sin(a+v*s),h.y=e*Math.cos(a+v*s),h.z=e*Math.sin(i+o*r)*Math.sin(a+v*s),p.push(h.x,h.y,h.z),u.copy(h).normalize(),f.push(u.x,u.y,u.z),m.push(o+_,1-v),g.push(l++)}c.push(g)}for(let e=0;e0)&&d.push(t,r,l),(e!==n-1||o=r)break e;{const s=t[1];e=r)break t}a=n,n=0}}for(;n>>1;et;)--a;if(++a,0!==r||a!==i){r>=a&&(a=Math.max(a,1),r=a-1);const e=this.getValueSize();this.times=n.slice(r,a),this.values=this.values.slice(r*e,a*e)}return this}validate(){let e=!0;const t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);let a=null;for(let t=0;t!==r;t++){const i=n[t];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,t,i),e=!1;break}if(null!==a&&a>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,t,i,a),e=!1;break}a=i}if(void 0!==i&&(s=i,ArrayBuffer.isView(s)&&!(s instanceof DataView)))for(let t=0,n=i.length;t!==n;++t){const n=i[t];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,t,n),e=!1;break}}var s;return e}optimize(){const e=this.times.slice(),t=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===ve,r=e.length-1;let a=1;for(let s=1;s0){e[a]=e[r];for(let e=r*n,i=a*n,s=0;s!==n;++s)t[i+s]=t[e+s];++a}return a!==e.length?(this.times=e.slice(0,a),this.values=t.slice(0,a*n)):(this.times=e,this.values=t),this}clone(){const e=this.times.slice(),t=this.values.slice(),n=new(0,this.constructor)(this.name,e,t);return n.createInterpolant=this.createInterpolant,n}}qo.prototype.TimeBufferType=Float32Array,qo.prototype.ValueBufferType=Float32Array,qo.prototype.DefaultInterpolation=ge;class Yo extends qo{constructor(e,t,n){super(e,t,n)}}Yo.prototype.ValueTypeName="bool",Yo.prototype.ValueBufferType=Array,Yo.prototype.DefaultInterpolation=me,Yo.prototype.InterpolantFactoryMethodLinear=void 0,Yo.prototype.InterpolantFactoryMethodSmooth=void 0;class Ko extends qo{}Ko.prototype.ValueTypeName="color";class Zo extends qo{}Zo.prototype.ValueTypeName="number";class Jo extends Go{constructor(e,t,n,i){super(e,t,n,i)}interpolate_(e,t,n,i){const r=this.resultBuffer,a=this.sampleValues,s=this.valueSize,o=(n-t)/(i-t);let l=e*s;for(let e=l+s;l!==e;l+=4)gt.slerpFlat(r,0,a,l-s,a,l,o);return r}}class Qo extends qo{InterpolantFactoryMethodLinear(e){return new Jo(this.times,this.values,this.getValueSize(),e)}}Qo.prototype.ValueTypeName="quaternion",Qo.prototype.InterpolantFactoryMethodSmooth=void 0;class $o extends qo{constructor(e,t,n){super(e,t,n)}}$o.prototype.ValueTypeName="string",$o.prototype.ValueBufferType=Array,$o.prototype.DefaultInterpolation=me,$o.prototype.InterpolantFactoryMethodLinear=void 0,$o.prototype.InterpolantFactoryMethodSmooth=void 0;class el extends qo{}el.prototype.ValueTypeName="vector";class tl{constructor(e="",t=-1,n=[],i=2500){this.name=e,this.tracks=n,this.duration=t,this.blendMode=i,this.uuid=Fe(),this.duration<0&&this.resetDuration()}static parse(e){const t=[],n=e.tracks,i=1/(e.fps||1);for(let e=0,r=n.length;e!==r;++e)t.push(nl(n[e]).scale(i));const r=new this(e.name,e.duration,t,e.blendMode);return r.uuid=e.uuid,r}static toJSON(e){const t=[],n=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,i=n.length;e!==i;++e)t.push(qo.toJSON(n[e]));return i}static CreateFromMorphTargetSequence(e,t,n,i){const r=t.length,a=[];for(let e=0;e1){const e=a[1];let t=i[e];t||(i[e]=t=[]),t.push(n)}}const a=[];for(const e in i)a.push(this.CreateFromMorphTargetSequence(e,i[e],t,n));return a}static parseAnimation(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(e,t,n,i,r){if(0!==n.length){const a=[],s=[];Vo(n,a,s,i),0!==a.length&&r.push(new e(t,a,s))}},i=[],r=e.name||"default",a=e.fps||30,s=e.blendMode;let o=e.length||-1;const l=e.hierarchy||[];for(let e=0;e{t&&t(r),this.manager.itemEnd(e)}),0),r;if(void 0!==ol[e])return void ol[e].push({onLoad:t,onProgress:n,onError:i});ol[e]=[],ol[e].push({onLoad:t,onProgress:n,onError:i});const a=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),s=this.mimeType,o=this.responseType;fetch(a).then((t=>{if(200===t.status||0===t.status){if(0===t.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===t.body||void 0===t.body.getReader)return t;const n=ol[e],i=t.body.getReader(),r=t.headers.get("X-File-Size")||t.headers.get("Content-Length"),a=r?parseInt(r):0,s=0!==a;let o=0;const l=new ReadableStream({start(e){!function t(){i.read().then((({done:i,value:r})=>{if(i)e.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:s,loaded:o,total:a});for(let e=0,t=n.length;e{e.error(t)}))}()}});return new Response(l)}throw new ll(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)})).then((e=>{switch(o){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((e=>(new DOMParser).parseFromString(e,s)));case"json":return e.json();default:if(void 0===s)return e.text();{const t=/charset="?([^;"\s]*)"?/i.exec(s),n=t&&t[1]?t[1].toLowerCase():void 0,i=new TextDecoder(n);return e.arrayBuffer().then((e=>i.decode(e)))}}})).then((t=>{il.add(e,t);const n=ol[e];delete ol[e];for(let e=0,i=n.length;e{const n=ol[e];if(void 0===n)throw this.manager.itemError(e),t;delete ol[e];for(let e=0,i=n.length;e{this.manager.itemEnd(e)})),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}}class hl extends sl{constructor(e){super(e)}load(e,t,n,i){void 0!==this.path&&(e=this.path+e),e=this.manager.resolveURL(e);const r=this,a=il.get(e);if(void 0!==a)return r.manager.itemStart(e),setTimeout((function(){t&&t(a),r.manager.itemEnd(e)}),0),a;const s=Ye("img");function o(){c(),il.add(e,this),t&&t(this),r.manager.itemEnd(e)}function l(t){c(),i&&i(t),r.manager.itemError(e),r.manager.itemEnd(e)}function c(){s.removeEventListener("load",o,!1),s.removeEventListener("error",l,!1)}return s.addEventListener("load",o,!1),s.addEventListener("error",l,!1),"data:"!==e.slice(0,5)&&void 0!==this.crossOrigin&&(s.crossOrigin=this.crossOrigin),r.manager.itemStart(e),s.src=e,s}}class ul extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=new ho,s=new cl(this.manager);return s.setResponseType("arraybuffer"),s.setRequestHeader(this.requestHeader),s.setPath(this.path),s.setWithCredentials(r.withCredentials),s.load(e,(function(e){let n;try{n=r.parse(e)}catch(e){if(void 0===i)return void console.error(e);i(e)}void 0!==n.image?a.image=n.image:void 0!==n.data&&(a.image.width=n.width,a.image.height=n.height,a.image.data=n.data),a.wrapS=void 0!==n.wrapS?n.wrapS:p,a.wrapT=void 0!==n.wrapT?n.wrapT:p,a.magFilter=void 0!==n.magFilter?n.magFilter:v,a.minFilter=void 0!==n.minFilter?n.minFilter:v,a.anisotropy=void 0!==n.anisotropy?n.anisotropy:1,void 0!==n.colorSpace&&(a.colorSpace=n.colorSpace),void 0!==n.flipY&&(a.flipY=n.flipY),void 0!==n.format&&(a.format=n.format),void 0!==n.type&&(a.type=n.type),void 0!==n.mipmaps&&(a.mipmaps=n.mipmaps,a.minFilter=y),1===n.mipmapCount&&(a.minFilter=v),void 0!==n.generateMipmaps&&(a.generateMipmaps=n.generateMipmaps),a.needsUpdate=!0,t&&t(a,n)}),n,i),a}}class dl extends sl{constructor(e){super(e)}load(e,t,n,i){const r=new ht,a=new hl(this.manager);return a.setCrossOrigin(this.crossOrigin),a.setPath(this.path),a.load(e,(function(e){r.image=e,r.needsUpdate=!0,void 0!==t&&t(r)}),n,i),r}}class pl extends bn{constructor(e,t=1){super(),this.isLight=!0,this.type="Light",this.color=new Fn(e),this.intensity=t}dispose(){}copy(e,t){return super.copy(e,t),this.color.copy(e.color),this.intensity=e.intensity,this}toJSON(e){const t=super.toJSON(e);return t.object.color=this.color.getHex(),t.object.intensity=this.intensity,void 0!==this.groundColor&&(t.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(t.object.distance=this.distance),void 0!==this.angle&&(t.object.angle=this.angle),void 0!==this.decay&&(t.object.decay=this.decay),void 0!==this.penumbra&&(t.object.penumbra=this.penumbra),void 0!==this.shadow&&(t.object.shadow=this.shadow.toJSON()),void 0!==this.target&&(t.object.target=this.target.uuid),t}}const fl=new qt,ml=new vt,gl=new vt;class vl{constructor(e){this.camera=e,this.intensity=1,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new We(512,512),this.map=null,this.mapPass=null,this.matrix=new qt,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Vi,this._frameExtents=new We(1,1),this._viewportCount=1,this._viewports=[new ut(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(e){const t=this.camera,n=this.matrix;ml.setFromMatrixPosition(e.matrixWorld),t.position.copy(ml),gl.setFromMatrixPosition(e.target.matrixWorld),t.lookAt(gl),t.updateMatrixWorld(),fl.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this._frustum.setFromProjectionMatrix(fl),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(fl)}getViewport(e){return this._viewports[e]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(e){return this.camera=e.camera.clone(),this.intensity=e.intensity,this.bias=e.bias,this.radius=e.radius,this.mapSize.copy(e.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const e={};return 1!==this.intensity&&(e.intensity=this.intensity),0!==this.bias&&(e.bias=this.bias),0!==this.normalBias&&(e.normalBias=this.normalBias),1!==this.radius&&(e.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(e.mapSize=this.mapSize.toArray()),e.camera=this.camera.toJSON(!1).object,delete e.camera.matrix,e}}class _l extends vl{constructor(){super(new Pi(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(e){const t=this.camera,n=2*Oe*e.angle*this.focus,i=this.mapSize.width/this.mapSize.height,r=e.distance||t.far;n===t.fov&&i===t.aspect&&r===t.far||(t.fov=n,t.aspect=i,t.far=r,t.updateProjectionMatrix()),super.updateMatrices(e)}copy(e){return super.copy(e),this.focus=e.focus,this}}class yl extends pl{constructor(e,t,n=0,i=Math.PI/3,r=0,a=2){super(e,t),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(bn.DEFAULT_UP),this.updateMatrix(),this.target=new bn,this.distance=n,this.angle=i,this.penumbra=r,this.decay=a,this.map=null,this.shadow=new _l}get power(){return this.intensity*Math.PI}set power(e){this.intensity=e/Math.PI}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.angle=e.angle,this.penumbra=e.penumbra,this.decay=e.decay,this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}}const xl=new qt,bl=new vt,Ml=new vt;class Sl extends vl{constructor(){super(new Pi(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new We(4,2),this._viewportCount=6,this._viewports=[new ut(2,1,1,1),new ut(0,1,1,1),new ut(3,1,1,1),new ut(1,1,1,1),new ut(3,0,1,1),new ut(1,0,1,1)],this._cubeDirections=[new vt(1,0,0),new vt(-1,0,0),new vt(0,0,1),new vt(0,0,-1),new vt(0,1,0),new vt(0,-1,0)],this._cubeUps=[new vt(0,1,0),new vt(0,1,0),new vt(0,1,0),new vt(0,1,0),new vt(0,0,1),new vt(0,0,-1)]}updateMatrices(e,t=0){const n=this.camera,i=this.matrix,r=e.distance||n.far;r!==n.far&&(n.far=r,n.updateProjectionMatrix()),bl.setFromMatrixPosition(e.matrixWorld),n.position.copy(bl),Ml.copy(n.position),Ml.add(this._cubeDirections[t]),n.up.copy(this._cubeUps[t]),n.lookAt(Ml),n.updateMatrixWorld(),i.makeTranslation(-bl.x,-bl.y,-bl.z),xl.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(xl)}}class El extends pl{constructor(e,t,n=0,i=2){super(e,t),this.isPointLight=!0,this.type="PointLight",this.distance=n,this.decay=i,this.shadow=new Sl}get power(){return 4*this.intensity*Math.PI}set power(e){this.intensity=e/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.decay=e.decay,this.shadow=e.shadow.clone(),this}}class wl extends vl{constructor(){super(new rr(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Tl extends pl{constructor(e,t){super(e,t),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(bn.DEFAULT_UP),this.updateMatrix(),this.target=new bn,this.shadow=new wl}dispose(){this.shadow.dispose()}copy(e){return super.copy(e),this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}}class Al extends pl{constructor(e,t){super(e,t),this.isAmbientLight=!0,this.type="AmbientLight"}}class Rl{static decodeText(e){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(e);let t="";for(let n=0,i=e.length;n.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{Nl.set(e.z,0,-e.x).normalize();const t=Math.acos(e.y);this.quaternion.setFromAxisAngle(Nl,t)}}setLength(e,t=.2*e,n=.2*t){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(n,t,n),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:r}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=r);var Fl=function(e,t,n,i){var r=new Fn;return r.setRGB(e,t,n),i<=.99?new Hn({color:r.getHex(),opacity:i+.1,transparent:!0,depthWrite:!0,blendSrc:s,blendDst:o,blendEquation:102,blending:1}):new Fo({color:r.getHex(),opacity:i,blending:1})},kl=function(e,t,n){var i=new vt,r=new vt;i.subVectors(t,e.origin);var a=e.direction.dot(n);if(!(Math.abs(a)0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),"," (- z + zOffset / 1000.0) * maxDepthPerTile,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),n.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n"),n}return Kl(t,e),jl(t,[{key:"metaLoaded",value:function(){this.metaLoaded=!0,this.initStreamer()}},{key:"initStreamer",value:function(){var e=this;if(this.metaLoaded){this.texture=new ht(this.video),this.geometry=new ti;for(var t=0,n=this.width*this.height;t256||24!==e.colormap_size||1!==e.colormap_type)throw new Error("THREE.TGALoader: Invalid type colormap data for indexed type.");break;case i:case r:case s:case o:if(e.colormap_type)throw new Error("THREE.TGALoader: Invalid type colormap data for colormap type.");break;case t:throw new Error("THREE.TGALoader: No data.");default:throw new Error("THREE.TGALoader: Invalid type "+e.image_type)}if(e.width<=0||e.height<=0)throw new Error("THREE.TGALoader: Invalid image size.");if(8!==e.pixel_size&&16!==e.pixel_size&&24!==e.pixel_size&&32!==e.pixel_size)throw new Error("THREE.TGALoader: Invalid pixel size "+e.pixel_size)}(g),g.id_length+f>e.length)throw new Error("THREE.TGALoader: No data.");f+=g.id_length;let v=!1,_=!1,x=!1;switch(g.image_type){case a:v=!0,_=!0;break;case n:_=!0;break;case s:v=!0;break;case i:break;case o:v=!0,x=!0;break;case r:x=!0}const b=new Uint8Array(g.width*g.height*4),M=function(e,t,n,i,r){let a,s;const o=n.pixel_size>>3,l=n.width*n.height*o;if(t&&(s=r.subarray(i,i+=n.colormap_length*(n.colormap_size>>3))),e){let e,t,n;a=new Uint8Array(l);let s=0;const c=new Uint8Array(o);for(;s>c){default:case d:a=0,o=1,m=t,s=0,f=1,v=n;break;case h:a=0,o=1,m=t,s=n-1,f=-1,v=-1;break;case p:a=t-1,o=-1,m=-1,s=0,f=1,v=n;break;case u:a=t-1,o=-1,m=-1,s=n-1,f=-1,v=-1}if(x)switch(g.pixel_size){case 8:!function(e,t,n,i,r,a,s,o){let l,c,h,u=0;const d=g.width;for(h=t;h!==i;h+=n)for(c=r;c!==s;c+=a,u++)l=o[u],e[4*(c+d*h)+0]=l,e[4*(c+d*h)+1]=l,e[4*(c+d*h)+2]=l,e[4*(c+d*h)+3]=255}(e,s,f,v,a,o,m,i);break;case 16:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=2)e[4*(l+u*c)+0]=o[h+0],e[4*(l+u*c)+1]=o[h+0],e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+3]=o[h+1]}(e,s,f,v,a,o,m,i);break;default:throw new Error("THREE.TGALoader: Format not supported.")}else switch(g.pixel_size){case 8:!function(e,t,n,i,r,a,s,o,l){const c=l;let h,u,d,p=0;const f=g.width;for(d=t;d!==i;d+=n)for(u=r;u!==s;u+=a,p++)h=o[p],e[4*(u+f*d)+3]=255,e[4*(u+f*d)+2]=c[3*h+0],e[4*(u+f*d)+1]=c[3*h+1],e[4*(u+f*d)+0]=c[3*h+2]}(e,s,f,v,a,o,m,i,r);break;case 16:!function(e,t,n,i,r,a,s,o){let l,c,h,u=0;const d=g.width;for(h=t;h!==i;h+=n)for(c=r;c!==s;c+=a,u+=2)l=o[u+0]+(o[u+1]<<8),e[4*(c+d*h)+0]=(31744&l)>>7,e[4*(c+d*h)+1]=(992&l)>>2,e[4*(c+d*h)+2]=(31&l)<<3,e[4*(c+d*h)+3]=32768&l?0:255}(e,s,f,v,a,o,m,i);break;case 24:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=3)e[4*(l+u*c)+3]=255,e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+1]=o[h+1],e[4*(l+u*c)+0]=o[h+2]}(e,s,f,v,a,o,m,i);break;case 32:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=4)e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+1]=o[h+1],e[4*(l+u*c)+0]=o[h+2],e[4*(l+u*c)+3]=o[h+3]}(e,s,f,v,a,o,m,i);break;default:throw new Error("THREE.TGALoader: Format not supported.")}}(b,g.width,g.height,M.pixel_data,M.palettes),{data:b,width:g.width,height:g.height,flipY:!0,generateMipmaps:!0,minFilter:y}}}function ac(e,t,n){return t=ql(t),Xl(e,sc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function sc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(sc=function(){return!!e})()}var oc=function(e){function t(){return Hl(this,t),ac(this,t,arguments)}return Kl(t,e),jl(t,[{key:"load",value:function(e,t,n,i){var r=this,a=""===r.path?Rl.extractUrlBase(e):r.path,s=new cl(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(e,(function(n){try{t(r.parse(n,a))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}},{key:"parse",value:function(e,t){function n(e,t){for(var n=[],i=e.childNodes,r=0,a=i.length;r0&&t.push(new el(i+".position",r,a)),s.length>0&&t.push(new Qo(i+".quaternion",r,s)),o.length>0&&t.push(new el(i+".scale",r,o)),t}function E(e,t,n){var i,r,a,s=!0;for(r=0,a=e.length;r=0;){var i=e[t];if(null!==i.value[n])return i;t--}return null}function T(e,t,n){for(;t>>0));if("tga"===(n=n.toLowerCase()))t=Je;else t=$e;return t}function J(e){var t,n,i=(t=e.url,f(rt.effects[t],K)),r=i.profile.technique;switch(r.type){case"phong":case"blinn":n=new Fo;break;case"lambert":n=new ko;break;default:n=new Hn}function a(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=i.profile.samplers[e.id],r=null;if(void 0!==n){var a=i.profile.surfaces[n.source];r=D(a.init_from)}else console.warn("THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530)."),r=D(e.id);if(null!==r){var s=Z(r);if(void 0!==s){var l=s.load(r),c=e.extra;if(void 0!==c&&void 0!==c.technique&&!1===o(c.technique)){var h=c.technique;l.wrapS=h.wrapU?d:p,l.wrapT=h.wrapV?d:p,l.offset.set(h.offsetU||0,h.offsetV||0),l.repeat.set(h.repeatU||1,h.repeatV||1)}else l.wrapS=d,l.wrapT=d;return null!==t&&(l.colorSpace=t),l}return console.warn("THREE.ColladaLoader: Loader for texture %s not found.",r),null}return console.warn("THREE.ColladaLoader: Couldn't create texture with ID:",e.id),null}n.name=e.name||"";var s=r.parameters;for(var l in s){var c=s[l];switch(l){case"diffuse":c.color&&n.color.fromArray(c.color),c.texture&&(n.map=a(c.texture,ye));break;case"specular":c.color&&n.specular&&n.specular.fromArray(c.color),c.texture&&(n.specularMap=a(c.texture));break;case"bump":c.texture&&(n.normalMap=a(c.texture));break;case"ambient":c.texture&&(n.lightMap=a(c.texture,ye));break;case"shininess":c.float&&n.shininess&&(n.shininess=c.float);break;case"emission":c.color&&n.emissive&&n.emissive.fromArray(c.color),c.texture&&(n.emissiveMap=a(c.texture,ye))}}n.color.convertSRGBToLinear(),n.specular&&n.specular.convertSRGBToLinear(),n.emissive&&n.emissive.convertSRGBToLinear();var h=s.transparent,u=s.transparency;if(void 0===u&&h&&(u={float:1}),void 0===h&&u&&(h={opaque:"A_ONE",data:{color:[1,1,1,1]}}),h&&u)if(h.data.texture)n.transparent=!0;else{var m=h.data.color;switch(h.opaque){case"A_ONE":n.opacity=m[3]*u.float;break;case"RGB_ZERO":n.opacity=1-m[0]*u.float;break;case"A_ZERO":n.opacity=1-m[3]*u.float;break;case"RGB_ONE":n.opacity=m[0]*u.float;break;default:console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.',h.opaque)}n.opacity<1&&(n.transparent=!0)}if(void 0!==r.extra&&void 0!==r.extra.technique){var g=r.extra.technique;for(var v in g){var _=g[v];switch(v){case"double_sided":n.side=1===_?2:0;break;case"bump":n.normalMap=a(_.texture),n.normalScale=new We(1,1)}}}return n}function Q(e){return f(rt.materials[e],J)}function $(e){for(var t=0;t0?l+h:l;t.inputs[u]={id:o,offset:c},t.stride=Math.max(t.stride,c+1),"TEXCOORD"===l&&(t.hasUV=!0);break;case"vcount":t.vcount=a(r.textContent);break;case"p":t.p=a(r.textContent)}}return t}function ue(e){for(var t=0,n=0,i=e.length;n0&&t0&&p.setAttribute("position",new qn(r.array,r.stride)),a.array.length>0&&p.setAttribute("normal",new qn(a.array,a.stride)),l.array.length>0&&p.setAttribute("color",new qn(l.array,l.stride)),s.array.length>0&&p.setAttribute("uv",new qn(s.array,s.stride)),o.array.length>0&&p.setAttribute("uv1",new qn(o.array,o.stride)),c.length>0&&p.setAttribute("skinIndex",new qn(c,h)),u.length>0&&p.setAttribute("skinWeight",new qn(u,d)),i.data=p,i.type=e[0].type,i.materialKeys=f,i}function fe(e,t,n,i){var r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],a=e.p,s=e.stride,o=e.vcount;function l(e){for(var t=a[e+n]*h,s=t+h;t4)for(var M=1,S=f-2;M<=S;M++){var E=u+0*s,w=u+s*M,T=u+s*(M+1);l(E),l(w),l(T)}u+=s*f}else for(var A=0,R=a.length;A=t.limits.max&&(t.static=!0),t.middlePosition=(t.limits.min+t.limits.max)/2,t}function be(e){for(var t={sid:e.getAttribute("sid"),name:e.getAttribute("name")||"",attachments:[],transforms:[]},n=0;ni.limits.max||t0?t[t.length-1]:"",smooth:void 0!==n?n.smooth:this.smooth,groupStart:void 0!==n?n.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(e){const t={index:"number"==typeof e?e:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return t.clone=this.clone.bind(t),t}};return this.materials.push(i),i},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(e){const t=this.currentMaterial();if(t&&-1===t.groupEnd&&(t.groupEnd=this.geometry.vertices.length/3,t.groupCount=t.groupEnd-t.groupStart,t.inherited=!1),e&&this.materials.length>1)for(let e=this.materials.length-1;e>=0;e--)this.materials[e].groupCount<=0&&this.materials.splice(e,1);return e&&0===this.materials.length&&this.materials.push({name:"",smooth:this.smooth}),t}},n&&n.name&&"function"==typeof n.clone){const e=n.clone(0);e.inherited=!0,this.object.materials.push(e)}this.objects.push(this.object)},finalize:function(){this.object&&"function"==typeof this.object._finalize&&this.object._finalize(!0)},parseVertexIndex:function(e,t){const n=parseInt(e,10);return 3*(n>=0?n-1:n+t/3)},parseNormalIndex:function(e,t){const n=parseInt(e,10);return 3*(n>=0?n-1:n+t/3)},parseUVIndex:function(e,t){const n=parseInt(e,10);return 2*(n>=0?n-1:n+t/2)},addVertex:function(e,t,n){const i=this.vertices,r=this.object.geometry.vertices;r.push(i[e+0],i[e+1],i[e+2]),r.push(i[t+0],i[t+1],i[t+2]),r.push(i[n+0],i[n+1],i[n+2])},addVertexPoint:function(e){const t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){const t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,n){const i=this.normals,r=this.object.geometry.normals;r.push(i[e+0],i[e+1],i[e+2]),r.push(i[t+0],i[t+1],i[t+2]),r.push(i[n+0],i[n+1],i[n+2])},addFaceNormal:function(e,t,n){const i=this.vertices,r=this.object.geometry.normals;pc.fromArray(i,e),fc.fromArray(i,t),mc.fromArray(i,n),vc.subVectors(mc,fc),gc.subVectors(pc,fc),vc.cross(gc),vc.normalize(),r.push(vc.x,vc.y,vc.z),r.push(vc.x,vc.y,vc.z),r.push(vc.x,vc.y,vc.z)},addColor:function(e,t,n){const i=this.colors,r=this.object.geometry.colors;void 0!==i[e]&&r.push(i[e+0],i[e+1],i[e+2]),void 0!==i[t]&&r.push(i[t+0],i[t+1],i[t+2]),void 0!==i[n]&&r.push(i[n+0],i[n+1],i[n+2])},addUV:function(e,t,n){const i=this.uvs,r=this.object.geometry.uvs;r.push(i[e+0],i[e+1]),r.push(i[t+0],i[t+1]),r.push(i[n+0],i[n+1])},addDefaultUV:function(){const e=this.object.geometry.uvs;e.push(0,0),e.push(0,0),e.push(0,0)},addUVLine:function(e){const t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,n,i,r,a,s,o,l){const c=this.vertices.length;let h=this.parseVertexIndex(e,c),u=this.parseVertexIndex(t,c),d=this.parseVertexIndex(n,c);if(this.addVertex(h,u,d),this.addColor(h,u,d),void 0!==s&&""!==s){const e=this.normals.length;h=this.parseNormalIndex(s,e),u=this.parseNormalIndex(o,e),d=this.parseNormalIndex(l,e),this.addNormal(h,u,d)}else this.addFaceNormal(h,u,d);if(void 0!==i&&""!==i){const e=this.uvs.length;h=this.parseUVIndex(i,e),u=this.parseUVIndex(r,e),d=this.parseUVIndex(a,e),this.addUV(h,u,d),this.object.geometry.hasUVIndices=!0}else this.addDefaultUV()},addPointGeometry:function(e){this.object.geometry.type="Points";const t=this.vertices.length;for(let n=0,i=e.length;n=7?(_c.setRGB(parseFloat(e[4]),parseFloat(e[5]),parseFloat(e[6])).convertSRGBToLinear(),t.colors.push(_c.r,_c.g,_c.b)):t.colors.push(void 0,void 0,void 0);break;case"vn":t.normals.push(parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3]));break;case"vt":t.uvs.push(parseFloat(e[1]),parseFloat(e[2]))}}else if("f"===a){const e=r.slice(1).trim().split(dc),n=[];for(let t=0,i=e.length;t0){const e=i.split("/");n.push(e)}}const i=n[0];for(let e=1,r=n.length-1;e1){const e=i[1].trim().toLowerCase();t.object.smooth="0"!==e&&"off"!==e}else t.object.smooth=!0;const e=t.object.currentMaterial();e&&(e.smooth=t.object.smooth)}else{if("\0"===r)continue;console.warn('THREE.OBJLoader: Unexpected line: "'+r+'"')}}t.finalize();const r=new Ss;r.materialLibraries=[].concat(t.materialLibraries);if(!0===!(1===t.objects.length&&0===t.objects[0].geometry.vertices.length))for(let e=0,n=t.objects.length;e0&&c.setAttribute("normal",new qn(i.normals,3)),i.colors.length>0&&(l=!0,c.setAttribute("color",new qn(i.colors,3))),!0===i.hasUVIndices&&c.setAttribute("uv",new qn(i.uvs,2));const h=[];for(let e=0,n=a.length;e1){for(let e=0,t=a.length;e0){const e=new Ro({size:1,sizeAttenuation:!1}),n=new ti;n.setAttribute("position",new qn(t.vertices,3)),t.colors.length>0&&void 0!==t.colors[0]&&(n.setAttribute("color",new qn(t.colors,3)),e.vertexColors=!0);const i=new No(n,e);r.add(i)}return r}}class bc extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=new cl(this.manager);a.setPath(this.path),a.setResponseType("arraybuffer"),a.setRequestHeader(this.requestHeader),a.setWithCredentials(this.withCredentials),a.load(e,(function(n){try{t(r.parse(n))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}parse(e){function t(e,t,n){for(let i=0,r=e.length;i>5&31)/31,a=(e>>10&31)/31):(i=o,r=l,a=c)}for(let o=1;o<=3;o++){const l=n+12*o,c=3*e*3+3*(o-1);p[c]=t.getFloat32(l,!0),p[c+1]=t.getFloat32(l+4,!0),p[c+2]=t.getFloat32(l+8,!0),f[c]=h,f[c+1]=d,f[c+2]=g,u&&(m.set(i,r,a).convertSRGBToLinear(),s[c]=m.r,s[c+1]=m.g,s[c+2]=m.b)}}return d.setAttribute("position",new Wn(p,3)),d.setAttribute("normal",new Wn(f,3)),u&&(d.setAttribute("color",new Wn(s,3)),d.hasColors=!0,d.alpha=h),d}(n):function(e){const t=new ti,n=/solid([\s\S]*?)endsolid/g,i=/facet([\s\S]*?)endfacet/g,r=/solid\s(.+)/;let a=0;const s=/[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source,o=new RegExp("vertex"+s+s+s,"g"),l=new RegExp("normal"+s+s+s,"g"),c=[],h=[],u=[],d=new vt;let p,f=0,m=0,g=0;for(;null!==(p=n.exec(e));){m=g;const e=p[0],n=null!==(p=r.exec(e))?p[1]:"";for(u.push(n);null!==(p=i.exec(e));){let e=0,t=0;const n=p[0];for(;null!==(p=l.exec(n));)d.x=parseFloat(p[1]),d.y=parseFloat(p[2]),d.z=parseFloat(p[3]),t++;for(;null!==(p=o.exec(n));)c.push(parseFloat(p[1]),parseFloat(p[2]),parseFloat(p[3])),h.push(d.x,d.y,d.z),e++,g++;1!==t&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+a),3!==e&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+a),a++}const s=m,v=g-m;t.userData.groupNames=u,t.addGroup(s,v,f),f++}return t.setAttribute("position",new qn(c,3)),t.setAttribute("normal",new qn(h,3)),t}("string"!=typeof(i=e)?(new TextDecoder).decode(i):i);var i}}class Mc extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=""===this.path?Rl.extractUrlBase(e):this.path,s=new cl(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(e,(function(n){try{t(r.parse(n,a))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}setMaterialOptions(e){return this.materialOptions=e,this}parse(e,t){const n=e.split("\n");let i={};const r=/\s+/,a={};for(let e=0;e=0?t.substring(0,s):t;o=o.toLowerCase();let l=s>=0?t.substring(s+1):"";if(l=l.trim(),"newmtl"===o)i={name:l},a[l]=i;else if("ka"===o||"kd"===o||"ks"===o||"ke"===o){const e=l.split(r,3);i[o]=[parseFloat(e[0]),parseFloat(e[1]),parseFloat(e[2])]}else i[o]=l}const s=new Sc(this.resourcePath||t,this.materialOptions);return s.setCrossOrigin(this.crossOrigin),s.setManager(this.manager),s.setMaterials(a),s}}class Sc{constructor(e="",t={}){this.baseUrl=e,this.options=t,this.materialsInfo={},this.materials={},this.materialsArray=[],this.nameLookup={},this.crossOrigin="anonymous",this.side=void 0!==this.options.side?this.options.side:0,this.wrap=void 0!==this.options.wrap?this.options.wrap:d}setCrossOrigin(e){return this.crossOrigin=e,this}setManager(e){this.manager=e}setMaterials(e){this.materialsInfo=this.convert(e),this.materials={},this.materialsArray=[],this.nameLookup={}}convert(e){if(!this.options)return e;const t={};for(const n in e){const i=e[n],r={};t[n]=r;for(const e in i){let t=!0,n=i[e];const a=e.toLowerCase();switch(a){case"kd":case"ka":case"ks":this.options&&this.options.normalizeRGB&&(n=[n[0]/255,n[1]/255,n[2]/255]),this.options&&this.options.ignoreZeroRGBs&&0===n[0]&&0===n[1]&&0===n[2]&&(t=!1)}t&&(r[a]=n)}}return t}preload(){for(const e in this.materialsInfo)this.create(e)}getIndex(e){return this.nameLookup[e]}getAsArray(){let e=0;for(const t in this.materialsInfo)this.materialsArray[e]=this.create(t),this.nameLookup[t]=e,e++;return this.materialsArray}create(e){return void 0===this.materials[e]&&this.createMaterial_(e),this.materials[e]}createMaterial_(e){const t=this,n=this.materialsInfo[e],i={name:e,side:this.side};function r(e,n){if(i[e])return;const r=t.getTextureParams(n,i),a=t.loadTexture((s=t.baseUrl,"string"!=typeof(o=r.url)||""===o?"":/^https?:\/\//i.test(o)?o:s+o));var s,o;a.repeat.copy(r.scale),a.offset.copy(r.offset),a.wrapS=t.wrap,a.wrapT=t.wrap,"map"!==e&&"emissiveMap"!==e||(a.colorSpace=ye),i[e]=a}for(const e in n){const t=n[e];let a;if(""!==t)switch(e.toLowerCase()){case"kd":i.color=(new Fn).fromArray(t).convertSRGBToLinear();break;case"ks":i.specular=(new Fn).fromArray(t).convertSRGBToLinear();break;case"ke":i.emissive=(new Fn).fromArray(t).convertSRGBToLinear();break;case"map_kd":r("map",t);break;case"map_ks":r("specularMap",t);break;case"map_ke":r("emissiveMap",t);break;case"norm":r("normalMap",t);break;case"map_bump":case"bump":r("bumpMap",t);break;case"map_d":r("alphaMap",t),i.transparent=!0;break;case"ns":i.shininess=parseFloat(t);break;case"d":a=parseFloat(t),a<1&&(i.opacity=a,i.transparent=!0);break;case"tr":a=parseFloat(t),this.options&&this.options.invertTrProperty&&(a=1-a),a>0&&(i.opacity=1-a,i.transparent=!0)}}return this.materials[e]=new Fo(i),this.materials[e]}getTextureParams(e,t){const n={scale:new We(1,1),offset:new We(0,0)},i=e.split(/\s+/);let r;return r=i.indexOf("-bm"),r>=0&&(t.bumpScale=parseFloat(i[r+1]),i.splice(r,2)),r=i.indexOf("-s"),r>=0&&(n.scale.set(parseFloat(i[r+1]),parseFloat(i[r+2])),i.splice(r,4)),r=i.indexOf("-o"),r>=0&&(n.offset.set(parseFloat(i[r+1]),parseFloat(i[r+2])),i.splice(r,4)),n.url=i.join(" ").trim(),n}loadTexture(e,t,n,i,r){const a=void 0!==this.manager?this.manager:al;let s=a.getHandler(e);null===s&&(s=new dl(a)),s.setCrossOrigin&&s.setCrossOrigin(this.crossOrigin);const o=s.load(e,n,i,r);return void 0!==t&&(o.mapping=t),o}}var Ec={onError:function(e){console.error(e)},loaders:{dae:function(e,t,n){var i=new oc(n.loader);return console.log("Loading collada: "+t),i.load(t,(function(t){var n=t.scene;e.add(n),console.log("Done loading collada")})),i.log=function(t){e.warnings&&console.warn(t)},i},obj:function(e,t,n){n.material;var i=new xc(n.loader);return i.log=function(t){e.warnings&&console.warn(t)},i.load(t,(function(r){var a=Rl.extractUrlBase(t);if(r.materialLibraries.length){var s=r.materialLibraries[0];new Mc(n.loader).setPath(a).load(s,(function(n){n.preload(),function(n,i){n.setMaterials(i).load(t,(function(t){e.add(t)}),null,Ec.onError)}(i,n)}),null,Ec.onError)}else e.add(r)}),null,Ec.onError),i},stl:function(e,t,n){var i=n.material,r=new bc(n.loader);return r.load(t,(function(t){var n;t.computeVertexNormals(),n=new yi(t,null!==i?i:new Hn({color:10066329})),e.add(n)}),null,Ec.onError),r}}};function wc(e,t,n){return t=ql(t),Xl(e,Tc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Tc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Tc=function(){return!!e})()}var Ac=function(e){function t(e){var n;Hl(this,t),n=wc(this,t);var i=(e=e||{}).path||"/",r=e.resource;e.material,n.warnings=e.warnings,"/"!==i.substr(i.length-1)&&(i+="/");var a=i+r,s=a.substr(-3).toLowerCase(),o=Ec.loaders[s];return o?o(n,a,e):console.warn("Unsupported loader for file type: '"+s+"'"),n}return Kl(t,e),jl(t)}(bn);function Rc(e,t,n){return t=ql(t),Xl(e,Cc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Cc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Cc=function(){return!!e})()}var Lc=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).material||new Hn,r=e.vertices,a=e.colors;n=Rc(this,t),i.side=2;for(var s,o,l=new ti,c=new Float32Array(3*r.length),h=0;h0){var K=n.msgColor,Z=document.createElement("canvas"),J=Z.getContext("2d"),Q="normal 100px sans-serif";J.font=Q;var $=J.measureText(r.text).width;Z.width=$,Z.height=150,J.font=Q,J.fillStyle="rgba("+Math.round(255*K.r)+", "+Math.round(255*K.g)+", "+Math.round(255*K.b)+", "+K.a+")",J.textAlign="left",J.textBaseline="middle",J.fillText(r.text,0,Z.height/2);var ee=new ht(Z);ee.needsUpdate=!0;var te=new Fs({map:ee,useScreenCoordinates:!1}),ne=new Js(te),ie=r.scale.x;ne.scale.set($/Z.height*ie,ie,1),n.add(ne)}break;case 10:var re=null;0===r.color.r&&0===r.color.g&&0===r.color.b&&0===r.color.a||(re=a),n.msgMesh=r.mesh_resource.substr(10);var ae=new Ac({path:i,resource:n.msgMesh,material:re});n.add(ae);break;case 11:var se=new Lc({material:a,vertices:r.points,colors:r.colors});se.scale.set(r.scale.x,r.scale.y,r.scale.z),n.add(se);break;default:console.error("Currently unsupported marker type: "+r.type)}return n}return Kl(t,e),jl(t,[{key:"setPose",value:function(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()}},{key:"update",value:function(e){if(this.setPose(e.pose),e.color.r!==this.msgColor.r||e.color.g!==this.msgColor.g||e.color.b!==this.msgColor.b||e.color.a!==this.msgColor.a){var t=Fl(e.color.r,e.color.g,e.color.b,e.color.a);switch(e.type){case 4:case 5:case 8:break;case 0:case 1:case 2:case 3:case 11:case 9:this.traverse((function(e){e instanceof yi&&(e.material=t)}));break;case 10:var n=null;0===e.color.r&&0===e.color.g&&0===e.color.b&&0===e.color.a||(n=this.colorMaterial),this.traverse((function(e){e instanceof yi&&(e.material=n)}));break;default:return!1}this.msgColor=e.color}var i=Math.abs(this.msgScale[0]-e.scale.x)>1e-6||Math.abs(this.msgScale[1]-e.scale.y)>1e-6||Math.abs(this.msgScale[2]-e.scale.z)>1e-6;switch(this.msgScale=[e.scale.x,e.scale.y,e.scale.z],e.type){case 1:case 2:case 3:if(i)return!1;break;case 9:if(i||this.text!==e.text)return!1;break;case 10:if(e.mesh_resource.substr(10)!==this.msgMesh)return!1;if(i)return!1;break;case 0:case 4:case 5:case 6:case 7:case 8:case 11:return!1}return!0}},{key:"dispose",value:function(){this.children.forEach((function(e){e instanceof Ac?e.children.forEach((function(t){void 0!==t.material&&t.material.dispose(),t.children.forEach((function(e){void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose(),t.remove(e)})),e.remove(t)})):(void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose()),e.parent.remove(e)}))}}])}(bn);function Uc(e,t,n){return t=ql(t),Xl(e,Dc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Dc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Dc=function(){return!!e})()}function Oc(e,t,n,i){var r=ec(ql(1&i?e.prototype:e),t,n);return 2&i?function(e){return r.apply(n,e)}:r}var Fc=function(e){function t(e){var n;Hl(this,t);var r=n=Uc(this,t);e=e||{},n.parent=e.parent;var a=e.handle,s=e.message;n.message=s,n.name=s.name,n.camera=e.camera,n.path=e.path||"/",n.loader=e.loader,n.dragging=!1,n.startMousePos=new We,n.isShift=!1;var o=new gt(s.orientation.x,s.orientation.y,s.orientation.z,s.orientation.w);o.normalize();var l=new vt(1,0,0);switch(l.applyQuaternion(o),n.currentControlOri=new gt,s.interaction_mode){case 9:case 7:n.addEventListener("mousemove",n.parent.move3d.bind(n.parent,n,l));break;case 3:n.addEventListener("mousemove",n.parent.moveAxis.bind(n.parent,n,l)),n.addEventListener("touchmove",n.parent.moveAxis.bind(n.parent,n,l));break;case 5:n.addEventListener("mousemove",n.parent.rotateAxis.bind(n.parent,n,o));break;case 4:n.addEventListener("mousemove",n.parent.movePlane.bind(n.parent,n,l));break;case 2:n.addEventListener("click",n.parent.buttonClick.bind(n.parent,n))}function c(e){e.stopPropagation()}0!==s.interaction_mode&&(n.addEventListener("mousedown",n.parent.startDrag.bind(n.parent,n)),n.addEventListener("mouseup",n.parent.stopDrag.bind(n.parent,n)),n.addEventListener("contextmenu",n.parent.showMenu.bind(n.parent,n)),n.addEventListener("mouseup",(function(e){0===r.startMousePos.distanceToSquared(e.mousePos)&&(e.type="contextmenu",r.dispatchEvent(e))})),n.addEventListener("mouseover",c),n.addEventListener("mouseout",c),n.addEventListener("click",c),n.addEventListener("mousedown",(function(e){r.startMousePos=e.mousePos})),n.addEventListener("touchstart",(function(e){1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,r.dispatchEvent(e))})),n.addEventListener("touchmove",(function(e){1===e.domEvent.touches.length&&(e.type="mousemove",e.domEvent.button=0,r.dispatchEvent(e))})),n.addEventListener("touchend",(function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",r.dispatchEvent(e),e.type="click",r.dispatchEvent(e))})),window.addEventListener("keydown",(function(e){16===e.keyCode&&(r.isShift=!0)})),window.addEventListener("keyup",(function(e){16===e.keyCode&&(r.isShift=!1)})));var h=new gt,u=n.parent.position.clone().multiplyScalar(-1);switch(s.orientation_mode){case 0:h=n.parent.quaternion.clone().inverse();break;case 1:case 2:break;default:console.error("Unkown orientation mode: "+s.orientation_mode)}var d=new i.TFClient({ros:a.tfClient.ros,fixedFrame:a.message.header.frame_id,serverName:a.tfClient.serverName});return s.markers.forEach((function(e){var t=function(t){var n=new Nc({message:e,path:r.path,loader:r.loader});if(null!==t){var a=new i.Pose({position:n.position,orientation:n.quaternion});a.applyTransform(new i.Transform(t));var s=new Nc({message:e,path:r.path,loader:r.loader});s.position.add(u),s.position.applyQuaternion(h),s.quaternion.multiplyQuaternions(h,s.quaternion);var o=new vt(s.position.x,s.position.y,s.position.z),l=new i.Transform({translation:o,orientation:s.quaternion});a.applyTransform(l),n.setPose(a),n.updateMatrixWorld(),d.unsubscribe(e.header.frame_id)}r.add(n)};""!==e.header.frame_id?d.subscribe(e.header.frame_id,t):t(null)})),n}return Kl(t,e),jl(t,[{key:"updateMatrixWorld",value:function(e){var n=this,i=this.message;switch(i.orientation_mode){case 0:Oc(t,"updateMatrixWorld",this,3)([e]),n.currentControlOri.copy(n.quaternion),n.currentControlOri.normalize();break;case 1:n.quaternion.copy(n.parent.quaternion.clone().inverse()),n.updateMatrix(),n.matrixWorldNeedsUpdate=!0,Oc(t,"updateMatrixWorld",this,3)([e]),n.currentControlOri.copy(n.quaternion);break;case 2:n.camera.updateMatrixWorld();var r=(new qt).extractRotation(n.camera.matrixWorld),a=new qt,s=.5*Math.PI,o=new rn(-s,0,s);a.makeRotationFromEuler(o);var l=new qt;l.getInverse(n.parent.matrixWorld),r.multiplyMatrices(r,a),r.multiplyMatrices(l,r),n.currentControlOri.setFromRotationMatrix(r),i.independent_marker_orientation||(n.quaternion.copy(n.currentControlOri),n.updateMatrix(),n.matrixWorldNeedsUpdate=!0),Oc(t,"updateMatrixWorld",this,3)([e]);break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}}}])}(bn);function kc(e,t,n){return t=ql(t),Xl(e,Bc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Bc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Bc=function(){return!!e})()}var zc=function(e){function t(e){var n;Hl(this,t);var i=n=kc(this,t),r=(e=e||{}).menuEntries,a=e.className||"default-interactive-marker-menu";e.entryClassName;var s,o,l,c=e.overlayClassName||"default-interactive-marker-overlay",h=e.menuFontSize||"0.8em",u=[];if(u[0]={children:[]},null===document.getElementById("default-interactive-marker-menu-css")){var d=document.createElement("style");d.id="default-interactive-marker-menu-css",d.type="text/css",d.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: "+h+";z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(d)}for(n.menuDomElem=document.createElement("div"),n.menuDomElem.style.position="absolute",n.menuDomElem.className=a,n.menuDomElem.addEventListener("contextmenu",(function(e){e.preventDefault()})),n.overlayDomElem=document.createElement("div"),n.overlayDomElem.className=c,n.hideListener=n.hide.bind(n),n.overlayDomElem.addEventListener("contextmenu",n.hideListener),n.overlayDomElem.addEventListener("click",n.hideListener),n.overlayDomElem.addEventListener("touchstart",n.hideListener),s=0;s0?(e(o,a[s]),l.addEventListener("click",i.hide.bind(i)),l.addEventListener("touchstart",i.hide.bind(i))):(l.addEventListener("click",f.bind(i,a[s])),l.addEventListener("touchstart",f.bind(i,a[s])),l.className="default-interactive-marker-menu-entry")}}(n.menuDomElem,u[0]),n}return Kl(t,e),jl(t,[{key:"show",value:function(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,void 0!==t.domEvent.changedTouches?(this.menuDomElem.style.left=t.domEvent.changedTouches[0].pageX+"px",this.menuDomElem.style.top=t.domEvent.changedTouches[0].pageY+"px"):(this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px"),document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)}},{key:"hide",value:function(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)}}])}(Ie);function Hc(e,t,n){return t=ql(t),Xl(e,Vc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Vc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Vc=function(){return!!e})()}var Gc=function(e){function t(e){var n;Hl(this,t),n=Hc(this,t);var i=(e=e||{}).handle;n.name=i.name;var r=e.camera,a=e.path||"/",s=e.loader;return n.dragging=!1,n.onServerSetPose({pose:i.pose}),n.dragStart={position:new vt,orientation:new gt,positionWorld:new vt,orientationWorld:new gt,event3d:{}},i.controls.forEach(function(e){this.add(new Fc({parent:this,handle:i,message:e,camera:r,path:a,loader:s}))}.bind(n)),i.menuEntries.length>0&&(n.menu=new zc({menuEntries:i.menuEntries,menuFontSize:i.menuFontSize}),n.menu.addEventListener("menu-select",function(e){this.dispatchEvent(e)}.bind(n))),n}return Kl(t,e),jl(t,[{key:"showMenu",value:function(e,t){this.menu&&this.menu.show(e,t)}},{key:"moveAxis",value:function(e,t,n){if(this.dragging){var i=e.currentControlOri,r=t.clone().applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),o=new Xt(a,s),l=zl(o,n.camera,n.mousePos),c=new vt;c.addVectors(this.dragStart.position,r.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(l)),this.setPosition(e,c),n.stopPropagation()}}},{key:"move3d",value:function(e,t,n){if(this.dragging)if(e.isShift);else{var i=e.camera.getWorldDirection(),r=Math.abs(i.x),a=Math.abs(i.y),s=Math.abs(i.z),o=new gt(1,0,0,1);a>r&&a>s?o=new gt(0,0,1,1):s>r&&s>a&&(o=new gt(0,1,0,1)),o.normalize(),(t=new vt(1,0,0)).applyQuaternion(o),this.movePlane(e,t,n)}}},{key:"movePlane",value:function(e,t,n){if(this.dragging){var i=e.currentControlOri,r=t.clone().applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.clone().applyQuaternion(this.dragStart.orientationWorld),o=kl(n.mouseRay,a,s),l=new vt;l.subVectors(o,a),l.add(this.dragStart.positionWorld),this.setPosition(e,l),n.stopPropagation()}}},{key:"rotateAxis",value:function(e,t,n){if(this.dragging){e.updateMatrixWorld();var i=e.currentControlOri.clone().multiply(t.clone()),r=new vt(1,0,0).applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.applyQuaternion(this.dragStart.orientationWorld),o=kl(n.mouseRay,a,s),l=new Xt(this.dragStart.positionWorld,s),c=kl(l,a,s),h=this.dragStart.orientationWorld.clone().multiply(i).clone().inverse();o.sub(c),o.applyQuaternion(h);var u=this.dragStart.event3d.intersection.point.clone();u.sub(c),u.applyQuaternion(h);var d=Math.atan2(o.y,o.z),p=Math.atan2(u.y,u.z)-d,f=new gt;f.setFromAxisAngle(r,p),this.setOrientation(e,f.multiply(this.dragStart.orientationWorld)),n.stopPropagation()}}},{key:"feedbackEvent",value:function(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})}},{key:"startDrag",value:function(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var n=new vt;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,n),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}}},{key:"stopDrag",value:function(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))}},{key:"buttonClick",value:function(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)}},{key:"setPosition",value:function(e,t){this.position.copy(t),this.feedbackEvent("user-pose-change",e)}},{key:"setOrientation",value:function(e,t){t.normalize(),this.quaternion.copy(t),this.feedbackEvent("user-pose-change",e)}},{key:"onServerSetPose",value:function(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.copy(t.position),this.quaternion.copy(t.orientation),this.updateMatrixWorld(!0)}}},{key:"dispose",value:function(){this.children.forEach(function(e){e.children.forEach((function(t){t.dispose(),e.remove(t)})),this.remove(e)}.bind(this))}}])}(bn);function Wc(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var jc,Xc={exports:{}}; +/*! + * EventEmitter2 + * https://github.com/hij1nx/EventEmitter2 + * + * Copyright (c) 2013 hij1nx + * Licensed under the MIT license. + */jc=Xc,function(e){var t=Object.hasOwnProperty,n=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},i="object"==typeof process&&"function"==typeof process.nextTick,r="function"==typeof Symbol,a="object"==typeof Reflect,s="function"==typeof setImmediate?setImmediate:setTimeout,o=r?a&&"function"==typeof Reflect.ownKeys?Reflect.ownKeys:function(e){var t=Object.getOwnPropertyNames(e);return t.push.apply(t,Object.getOwnPropertySymbols(e)),t}:Object.keys;function l(){this._events={},this._conf&&c.call(this,this._conf)}function c(t){t&&(this._conf=t,t.delimiter&&(this.delimiter=t.delimiter),t.maxListeners!==e&&(this._maxListeners=t.maxListeners),t.wildcard&&(this.wildcard=t.wildcard),t.newListener&&(this._newListener=t.newListener),t.removeListener&&(this._removeListener=t.removeListener),t.verboseMemoryLeak&&(this.verboseMemoryLeak=t.verboseMemoryLeak),t.ignoreErrors&&(this.ignoreErrors=t.ignoreErrors),this.wildcard&&(this.listenerTree={}))}function h(e,t){var n="(node) warning: possible EventEmitter memory leak detected. "+e+" listeners added. Use emitter.setMaxListeners() to increase limit.";if(this.verboseMemoryLeak&&(n+=" Event name: "+t+"."),"undefined"!=typeof process&&process.emitWarning){var i=new Error(n);i.name="MaxListenersExceededWarning",i.emitter=this,i.count=e,process.emitWarning(i)}else console.error(n),console.trace&&console.trace()}var u=function(e,t,n){var i=arguments.length;switch(i){case 0:return[];case 1:return[e];case 2:return[e,t];case 3:return[e,t,n];default:for(var r=new Array(i);i--;)r[i]=arguments[i];return r}};function d(t,n){for(var i={},r=t.length,a=n?value.length:0,s=0;s0;)if(a===e[s])return i;r(t)}}Object.assign(p.prototype,{subscribe:function(e,t,n){var i=this,r=this._target,a=this._emitter,s=this._listeners,o=function(){var i=u.apply(null,arguments),s={data:i,name:t,original:e};if(n){var o=n.call(r,s);!1!==o&&a.emit.apply(a,[s.name].concat(i))}else a.emit.apply(a,[t].concat(i))};if(s[e])throw Error("Event '"+e+"' is already listening");this._listenersCount++,a._newListener&&a._removeListener&&!i._onNewListener?(this._onNewListener=function(n){n===t&&null===s[e]&&(s[e]=o,i._on.call(r,e,o))},a.on("newListener",this._onNewListener),this._onRemoveListener=function(n){n===t&&!a.hasListeners(n)&&s[e]&&(s[e]=null,i._off.call(r,e,o))},s[e]=null,a.on("removeListener",this._onRemoveListener)):(s[e]=o,i._on.call(r,e,o))},unsubscribe:function(e){var t,n,i,r=this,a=this._listeners,s=this._emitter,l=this._off,c=this._target;if(e&&"string"!=typeof e)throw TypeError("event must be a string");function h(){r._onNewListener&&(s.off("newListener",r._onNewListener),s.off("removeListener",r._onRemoveListener),r._onNewListener=null,r._onRemoveListener=null);var e=x.call(s,r);s._observers.splice(e,1)}if(e){if(!(t=a[e]))return;l.call(c,e,t),delete a[e],--this._listenersCount||h()}else{for(i=(n=o(a)).length;i-- >0;)e=n[i],l.call(c,e,a[e]);this._listeners={},this._listenersCount=0,h()}}});var v=g(["function"]),_=g(["object","function"]);function y(e,t,n){var i,r,a,s=0,o=new e((function(l,c,h){function u(){r&&(r=null),s&&(clearTimeout(s),s=0)}n=f(n,{timeout:0,overload:!1},{timeout:function(e,t){return("number"!=typeof(e*=1)||e<0||!Number.isFinite(e))&&t("timeout must be a positive number"),e}}),i=!n.overload&&"function"==typeof e.prototype.cancel&&"function"==typeof h;var d=function(e){u(),l(e)},p=function(e){u(),c(e)};i?t(d,p,h):(r=[function(e){p(e||Error("canceled"))}],t(d,p,(function(e){if(a)throw Error("Unable to subscribe on cancel event asynchronously");if("function"!=typeof e)throw TypeError("onCancel callback must be a function");r.push(e)})),a=!0),n.timeout>0&&(s=setTimeout((function(){var e=Error("timeout");e.code="ETIMEDOUT",s=0,o.cancel(e),c(e)}),n.timeout))}));return i||(o.cancel=function(e){if(r){for(var t=r.length,n=1;n0;)"_listeners"!==(p=_[l])&&(y=b(e,t,n[p],i+1,r))&&(x?x.push.apply(x,y):x=y);return x}if("**"===M){for((v=i+1===r||i+2===r&&"*"===S)&&n._listeners&&(x=b(e,t,n,r,r)),l=(_=o(n)).length;l-- >0;)"_listeners"!==(p=_[l])&&("*"===p||"**"===p?(n[p]._listeners&&!v&&(y=b(e,t,n[p],r,r))&&(x?x.push.apply(x,y):x=y),y=b(e,t,n[p],i,r)):y=b(e,t,n[p],p===S?i+2:i,r),y&&(x?x.push.apply(x,y):x=y));return x}n[M]&&(x=b(e,t,n[M],i+1,r))}if((f=n["*"])&&b(e,t,f,i+1,r),m=n["**"])if(i0;)"_listeners"!==(p=_[l])&&(p===S?b(e,t,m[p],i+2,r):p===M?b(e,t,m[p],i+1,r):((g={})[p]=m[p],b(e,t,{"**":g},i+1,r)));else m._listeners?b(e,t,m,r,r):m["*"]&&m["*"]._listeners&&b(e,t,m["*"],r,r);return x}function M(e,t,n){var i,r,a=0,s=0,o=this.delimiter,l=o.length;if("string"==typeof e)if(-1!==(i=e.indexOf(o))){r=new Array(5);do{r[a++]=e.slice(s,i),s=i+l}while(-1!==(i=e.indexOf(o,s)));r[a++]=e.slice(s)}else r=[e],a=1;else r=e,a=e.length;if(a>1)for(i=0;i+10&&u._listeners.length>this._maxListeners&&(u._listeners.warned=!0,h.call(this,u._listeners.length,c))):u._listeners=t,!0;return!0}function S(e,t,n,i){for(var r,a,s,l,c=o(e),h=c.length,u=e._listeners;h-- >0;)r=e[a=c[h]],s="_listeners"===a?n:n?n.concat(a):[a],l=i||"symbol"==typeof a,u&&t.push(l?s:s.join(this.delimiter)),"object"==typeof r&&S.call(this,r,t,s,l);return t}function E(e){for(var t,n,i,r=o(e),a=r.length;a-- >0;)(t=e[n=r[a]])&&(i=!0,"_listeners"===n||E(t)||delete e[n]);return i}function w(e,t,n){this.emitter=e,this.event=t,this.listener=n}function T(t,n,r){if(!0===r)o=!0;else if(!1===r)a=!0;else{if(!r||"object"!=typeof r)throw TypeError("options should be an object or true");var a=r.async,o=r.promisify,l=r.nextTick,c=r.objectify}if(a||l||o){var h=n,u=n._origin||n;if(l&&!i)throw Error("process.nextTick is not supported");o===e&&(o="AsyncFunction"===n.constructor.name),n=function(){var e=arguments,t=this,n=this.event;return o?l?Promise.resolve():new Promise((function(e){s(e)})).then((function(){return t.event=n,h.apply(t,e)})):(l?process.nextTick:s)((function(){t.event=n,h.apply(t,e)}))},n._async=!0,n._origin=u}return[n,c?new w(this,t,n):this]}function A(e){this._events={},this._newListener=!1,this._removeListener=!1,this.verboseMemoryLeak=!1,c.call(this,e)}w.prototype.off=function(){return this.emitter.off(this.event,this.listener),this},A.EventEmitter2=A,A.prototype.listenTo=function(t,i,r){if("object"!=typeof t)throw TypeError("target musts be an object");var a=this;function s(e){if("object"!=typeof e)throw TypeError("events must be an object");var n,i=r.reducers,s=x.call(a,t);n=-1===s?new p(a,t,r):a._observers[s];for(var l,c=o(e),h=c.length,u="function"==typeof i,d=0;d0;)i=n[r],e&&i._target!==e||(i.unsubscribe(t),a=!0);return a},A.prototype.delimiter=".",A.prototype.setMaxListeners=function(t){t!==e&&(this._maxListeners=t,this._conf||(this._conf={}),this._conf.maxListeners=t)},A.prototype.getMaxListeners=function(){return this._maxListeners},A.prototype.event="",A.prototype.once=function(e,t,n){return this._once(e,t,!1,n)},A.prototype.prependOnceListener=function(e,t,n){return this._once(e,t,!0,n)},A.prototype._once=function(e,t,n,i){return this._many(e,1,t,n,i)},A.prototype.many=function(e,t,n,i){return this._many(e,t,n,!1,i)},A.prototype.prependMany=function(e,t,n,i){return this._many(e,t,n,!0,i)},A.prototype._many=function(e,t,n,i,r){var a=this;if("function"!=typeof n)throw new Error("many only accepts instances of Function");function s(){return 0==--t&&a.off(e,s),n.apply(this,arguments)}return s._origin=n,this._on(e,s,i,r)},A.prototype.emit=function(){if(!this._events&&!this._all)return!1;this._events||l.call(this);var e,t,n,i,a,s,o=arguments[0],c=this.wildcard;if("newListener"===o&&!this._newListener&&!this._events.newListener)return!1;if(c&&(e=o,"newListener"!==o&&"removeListener"!==o&&"object"==typeof o)){if(n=o.length,r)for(i=0;i3)for(t=new Array(u-1),a=1;a3)for(n=new Array(d-1),s=1;s0&&this._events[t].length>this._maxListeners&&(this._events[t].warned=!0,h.call(this,this._events[t].length,t))):this._events[t]=n,s)},A.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var i,r=[];if(this.wildcard){var a="string"==typeof e?e.split(this.delimiter):e.slice();if(!(r=b.call(this,null,a,this.listenerTree,0)))return this}else{if(!this._events[e])return this;i=this._events[e],r.push({_listeners:i})}for(var s=0;s0){for(n=0,i=(t=this._all).length;n0;)"function"==typeof(i=l[n[a]])?r.push(i):r.push.apply(r,i);return r}if(this.wildcard){if(!(s=this.listenerTree))return[];var c=[],h="string"==typeof t?t.split(this.delimiter):t.slice();return b.call(this,c,h,s,0),c}return l&&(i=l[t])?"function"==typeof i?[i]:i:[]},A.prototype.eventNames=function(e){var t=this._events;return this.wildcard?S.call(this,this.listenerTree,[],null,e):t?o(t):[]},A.prototype.listenerCount=function(e){return this.listeners(e).length},A.prototype.hasListeners=function(t){if(this.wildcard){var n=[],i="string"==typeof t?t.split(this.delimiter):t.slice();return b.call(this,n,i,this.listenerTree,0),n.length>0}var r=this._events,a=this._all;return!!(a&&a.length||r&&(t===e?o(r).length:r[t]))},A.prototype.listenersAny=function(){return this._all?this._all:[]},A.prototype.waitFor=function(t,n){var i=this,r=typeof n;return"number"===r?n={timeout:n}:"function"===r&&(n={filter:n}),y((n=f(n,{timeout:0,filter:e,handleError:!1,Promise:Promise,overload:!1},{filter:v,Promise:m})).Promise,(function(e,r,a){function s(){var a=n.filter;if(!a||a.apply(i,arguments))if(i.off(t,s),n.handleError){var o=arguments[0];o?r(o):e(u.apply(null,arguments).slice(1))}else e(u.apply(null,arguments))}a((function(){i.off(t,s)})),i._on(t,s,!1)}),{timeout:n.timeout,overload:n.overload})};var R=A.prototype;Object.defineProperties(A,{defaultMaxListeners:{get:function(){return R._maxListeners},set:function(e){if("number"!=typeof e||e<0||Number.isNaN(e))throw TypeError("n must be a non-negative number");R._maxListeners=e},enumerable:!0},once:{value:function(e,t,n){return y((n=f(n,{Promise:Promise,timeout:0,overload:!1},{Promise:m})).Promise,(function(n,i,r){var a;if("function"==typeof e.addEventListener)return a=function(){n(u.apply(null,arguments))},r((function(){e.removeEventListener(t,a)})),void e.addEventListener(t,a,{once:!0});var s,o=function(){s&&e.removeListener("error",s),n(u.apply(null,arguments))};"error"!==t&&(s=function(n){e.removeListener(t,o),i(n)},e.once("error",s)),r((function(){s&&e.removeListener("error",s),e.removeListener(t,o)})),e.once(t,o)}),{timeout:n.timeout,overload:n.overload})},writable:!0,configurable:!0}}),Object.defineProperties(R,{_maxListeners:{value:10,writable:!0,configurable:!0},_observers:{value:null,writable:!0,configurable:!0}}),jc.exports=A}();var qc=Wc(Xc.exports);function Yc(e,t,n){return t=ql(t),Xl(e,Kc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Kc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Kc=function(){return!!e})()}var Zc=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Yc(this,t)).message=e.message,n.feedbackTopic=e.feedbackTopic,n.tfClient=e.tfClient,n.menuFontSize=e.menuFontSize||"0.8em",n.name=n.message.name,n.header=n.message.header,n.controls=n.message.controls,n.menuEntries=n.message.menu_entries,n.dragging=!1,n.timeoutHandle=null,n.tfTransform=new i.Transform,n.pose=new i.Pose,n.setPoseFromClientBound=n.setPoseFromClient.bind(n),n.onMouseDownBound=n.onMouseDown.bind(n),n.onMouseUpBound=n.onMouseUp.bind(n),n.onButtonClickBound=n.onButtonClick.bind(n),n.onMenuSelectBound=n.onMenuSelect.bind(n),n.setPoseFromServer(n.message.pose),n.tfUpdateBound=n.tfUpdate.bind(n),n}return Kl(t,e),jl(t,[{key:"subscribeTf",value:function(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}},{key:"unsubscribeTf",value:function(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}},{key:"emitServerPoseUpdate",value:function(){var e=new i.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}},{key:"setPoseFromServer",value:function(e){this.pose=new i.Pose(e),this.emitServerPoseUpdate()}},{key:"tfUpdate",value:function(e){this.tfTransform=new i.Transform(e),this.emitServerPoseUpdate()}},{key:"setPoseFromClient",value:function(e){this.pose=new i.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}},{key:"onButtonClick",value:function(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}},{key:"onMouseDown",value:function(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}},{key:"onMouseUp",value:function(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}},{key:"onMenuSelect",value:function(e){this.sendFeedback(2,void 0,e.id,e.controlName)}},{key:"sendFeedback",value:function(e,t,n,i){var r=void 0!==t;t=t||{x:0,y:0,z:0};var a={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:i,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:r,menu_entry_id:n};this.feedbackTopic.publish(a)}}])}(qc),Jc=function(){return jl((function e(t){Hl(this,e),t=t||{},this.ros=t.ros,this.tfClient=t.tfClient,this.topicName=t.topic,this.path=t.path||"/",this.camera=t.camera,this.rootObject=t.rootObject||new bn,this.loader=t.loader,this.menuFontSize=t.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.processUpdateBound=this.processUpdate.bind(this),this.topicName&&this.subscribe(this.topicName)}),[{key:"subscribe",value:function(e){this.unsubscribe(),this.updateTopic=new i.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdateBound),this.feedbackTopic=new i.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new i.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new i.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}},{key:"unsubscribe",value:function(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdateBound),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}},{key:"processInit",value:function(e){var t=e.msg;for(var n in t.erases=[],this.interactiveMarkers)t.erases.push(n);t.poses=[],this.processUpdate(t)}},{key:"processUpdate",value:function(e){e.erases.forEach((function(e){this.eraseIntMarker(e)})),e.poses.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&t.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&this.eraseIntMarker(t.name);var n=new Zc({message:e,feedbackTopic:this.feedbackTopic,tfClient:this.tfClient,menuFontSize:this.menuFontSize});this.interactiveMarkers[e.name]=n;var i=new Gc({handle:n,camera:this.camera,path:this.path,loader:this.loader});i.name=e.name,this.rootObject.add(i),n.on("pose",(function(e){i.onServerSetPose({pose:e})})),i.addEventListener("user-pose-change",n.setPoseFromClientBound),i.addEventListener("user-mousedown",n.onMouseDownBound),i.addEventListener("user-mouseup",n.onMouseUpBound),i.addEventListener("user-button-click",n.onButtonClickBound),i.addEventListener("menu-select",n.onMenuSelectBound),n.subscribeTf()}))}},{key:"eraseIntMarker",value:function(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var n=this.interactiveMarkers[e];n.unsubscribeTf(),t.removeEventListener("user-pose-change",n.setPoseFromClientBound),t.removeEventListener("user-mousedown",n.onMouseDownBound),t.removeEventListener("user-mouseup",n.onMouseUpBound),t.removeEventListener("user-button-click",n.onButtonClickBound),t.removeEventListener("menu-select",n.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}}])}();function Qc(e,t,n){return t=ql(t),Xl(e,$c()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function $c(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return($c=function(){return!!e})()}var eh=function(e){function t(e){var n;Hl(this,t),e=e||{},(n=Qc(this,t)).tfClient=e.tfClient,n.frameID=e.frameID;var r=e.object;return n.pose=e.pose||new i.Pose,n.visible=!1,n.add(r),n.updatePose(n.pose),n.tfUpdate=function(e){var t=new i.Transform(e),n=new i.Pose(this.pose);n.applyTransform(t),this.updatePose(n),this.visible=!0},n.tfUpdateBound=n.tfUpdate.bind(n),n.tfClient.subscribe(n.frameID,n.tfUpdateBound),n}return Kl(t,e),jl(t,[{key:"updatePose",value:function(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}},{key:"unsubscribeTf",value:function(){this.tfClient.unsubscribe(this.frameID,this.tfUpdateBound)}}])}(bn);function th(e,t,n){return t=ql(t),Xl(e,nh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function nh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(nh=function(){return!!e})()}var ih=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=th(this,t)).ros=e.ros,n.topicName=e.topic,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.path=e.path||"/",n.markers={},n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var n=!1;if(t in this.markers&&((n=this.markers[t].children[0].update(e))||this.removeMarker(t)),!n){var i=new Nc({message:e,path:this.path});this.markers[t]=new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:i}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var r in this.markers)this.removeMarker(r);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}},{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"removeMarker",value:function(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((function(e){e.dispose()})),delete this.markers[e])}}])}(qc);function rh(e,t,n){return t=ql(t),Xl(e,ah()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function ah(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(ah=function(){return!!e})()}var sh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=rh(this,t)).ros=e.ros,n.topicName=e.topic,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.path=e.path||"/",n.lifetime=e.lifetime||0,n.markers={},n.rosTopic=void 0,n.updatedTime={},n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"checkTime",value:function(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){var t=e.ns+e.id,n=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),n?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var i=new Nc({message:e,path:this.path});this.markers[t]=new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:i}),this.rootObject.add(this.markers[t])}this.emit("change")}},{key:"removeMarker",value:function(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((function(e){e.dispose()})),delete this.markers[e])}}])}(qc);function oh(e,t,n){return t=ql(t),Xl(e,lh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function lh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(lh=function(){return!!e})()}var ch=function(e){function t(e){Hl(this,t);var n=(e=e||{}).origin||new vt(0,0,0),i=e.direction||new vt(1,0,0),r=e.length||1;return e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Hn,oh(this,t,[i,n,r,16711680])}return Kl(t,e),jl(t,[{key:"dispose",value:function(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}])}(Ol);function hh(e,t,n){return t=ql(t),Xl(e,uh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function uh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(uh=function(){return!!e})()}var dh=function(e){function t(e){var n;Hl(this,t);var i=n=hh(this,t),r=(e=e||{}).shaftRadius||.008,a=e.headRadius||.023,s=e.headLength||.1,o=e.scale||1,l=e.lineType||"full",c=e.lineDashLength||.1;function h(e){var t=new Fn;t.setRGB(e.x,e.y,e.z);var n=new Hn({color:t.getHex()}),a=new vt;a.crossVectors(e,new vt(0,-1,0));var s=new gt;s.setFromAxisAngle(a,.5*Math.PI);var o,h=new yi(i.headGeom,n);if(h.position.copy(e),h.position.multiplyScalar(.95),h.quaternion.copy(s),h.updateMatrix(),i.add(h),"dashed"===l)for(var u=c,d=0;u/2+3*u*d+u/2<=1;++d){var p=new Do(r,r,u);(o=new yi(p,n)).position.copy(e),o.position.multiplyScalar(u/2+3*u*d),o.quaternion.copy(s),o.updateMatrix(),i.add(o)}else"full"===l?((o=new yi(i.lineGeom,n)).position.copy(e),o.position.multiplyScalar(.45),o.quaternion.copy(s),o.updateMatrix(),i.add(o)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}return n.scale.set(o,o,o),n.lineGeom=new Do(r,r,1-s),n.headGeom=new Do(0,a,s),h(new vt(1,0,0)),h(new vt(0,1,0)),h(new vt(0,0,1)),n}return Kl(t,e),jl(t)}(bn);function ph(e,t,n){return t=ql(t),Xl(e,fh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function fh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(fh=function(){return!!e})()}var mh=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).num_cells||10,r=e.color||"#cccccc",a=e.lineWidth||1,s=e.cellSize||1;n=ph(this,t);for(var o=new mo({color:r,linewidth:a}),l=[],c=0;c<=i;++c){var h=s*i/2,u=h-c*s;l.push(new vt(-h,u,0),new vt(h,u,0)),l.push(new vt(u,-h,0),new vt(u,h,0))}var d=(new ti).setFromPoints(l),p=new Ao(d,o);return n.add(p),n}return Kl(t,e),jl(t)}(bn);function gh(e,t,n){return t=ql(t),Xl(e,vh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function vh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(vh=function(){return!!e})()}var _h=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).message,r=e.opacity||1,a=e.color||{r:255,g:255,b:255,a:255},s=i.info,o=s.origin,l=s.width,c=s.height,h=new ji(l,c),u=new Uint8Array(l*c*4),d=new ho(u,l,c,I);d.flipY=!0,d.minFilter=m,d.magFilter=m,d.needsUpdate=!0;var p=new Hn({map:d,transparent:r<1,opacity:r});p.side=2,n=gh(this,t,[h,p]),Object.assign(n,e),n.quaternion.copy(new gt(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),n.position.x=l*s.resolution/2+o.position.x,n.position.y=c*s.resolution/2+o.position.y,n.position.z=o.position.z,n.scale.x=s.resolution,n.scale.y=s.resolution;var f=i.data;n.color=a,n.material=p,n.texture=d;for(var g=0;ge.length)&&(t=e.length);for(var n=0,i=Array(t);nn.length)throw new Error("Cannot read data stream. Overflow. Len="+n.length+" crsr="+n._cursor);var t=n._dataView[i](n._cursor,n.isLittleEndian);return n._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:function(){return n.cursor>=n.data.length}}),this}var Lh=function(){return jl((function e(t){Hl(this,e),this.resolution=void 0!==t.resolution?t.resolution:1,this.color=new Fn(void 0!==t.color?t.color:"green"),this.opacity=void 0!==t.opacity?t.opacity:1,this.voxelRenderMode=void 0!==t.voxelRenderMode?t.voxelRenderMode:wh,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);for(var n=this.resolution,i=this._treeDepth-1;i>=0;--i)this.nodeSizeTable[i]=n,n*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}),[{key:"searchAtDepth",value:function(e,t){t=void 0!==t&&t>0?t:this._treeDepth;for(var n=this._adjustKeyAtDepth(e,t),i=this._treeDepth-t,r=this._rootNode,a=this._treeDepth-1;a>=i;--a){var s=this._computeChildIdx(n,a);if(!r.hasChildAt(s))return r.hasChildren()?null:r;r=r.getChildAt(s)}return r}},{key:"_computeCoordFromKey",value:function(e){var t=this;return e.map((function(e){return t.resolution*(e-t._treeMaxKeyVal)}))}},{key:"_computeChildIdx",value:function(e,t){var n=0;return e[0]&1<>i<0;)for(var i=n.pop(),r=t.readUint16(),a=8;0!==a;){var s=(r&3<<2*--a)>>2*a;if(s!==this._BINARY_UNALLOCATED){var o=this._newNode();this._BINARY_CHILD_BUILD_TABLE[s].bind(this)(o),i.createChildNodeAt(o,a),s===this._BINARY_HAS_CHILDREN&&n.push(o)}}}},{key:"read",value:function(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();var t=new Ch(e,!0),n=new Array;for(n.push(this._rootNode);n.length>0;){var i=n.pop();this._readNodeData(t,i);for(var r=t.readUint8(),a=8;0!==a;){if(r&1<<--a){var s=this._newNode();s.value=null,i.createChildNodeAt(s,a),n.push(s)}}}}},{key:"_readNodeData",value:function(e,t){console.error("Not implemented")}},{key:"buildGeometry",value:function(){console.assert(null!==this._rootNode,"No tree data");var e=this._buildFaces(),t=e.vertices,n=e.normals,i=e.colors,r=e.indices,a=new ti,s=new Hn({color:"white",flatShading:!0,vertexColors:!0,transparent:this.opacity<1,opacity:this.opacity});a.addAttribute("position",new Wn(new Float32Array(t),3)),a.addAttribute("normal",new Wn(new Float32Array(n),3)),a.addAttribute("color",new Wn(new Float32Array(i),3)),a.setIndex(r);var o=new yi(a,s);this.object=new bn,this.object.add(o)}},{key:"_traverseLeaves",value:function(e){var t=new Array;for(t.push({node:this._rootNode,depth:0,key:[0,0,0]});t.length>0;){var n=t.pop();if(n.node.isLeafNode())e(n.node,n.key,n.depth-1);else for(var i=0;i<8;++i)if(n.node.hasChildAt(i)){var r=this._computeKeyFromChildIdx(i,n.key,n.depth);t.push({node:n.node.getChildAt(i),depth:n.depth+1,key:r})}}}},{key:"_obtainColor",value:function(e){return this.color}},{key:"_checkOccupied",value:function(e){return!1!==e.value}},{key:"_buildFaces",value:function(){var e=this,t={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,n,i){var r,a,s=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*n,t[1]+e[1]*n,t[2]+e[2]*n)}));var o=[i.r,i.g,i.b];(r=this.colors).push.apply(r,o.concat(o,o,o)),(a=this.normals).push.apply(a,Sh(e.normal).concat(Sh(e.normal),Sh(e.normal),Sh(e.normal))),this.indices.push(s,s+1,s+2,s+2,s+1,s+3)},_checkNeighborsTouchingFace:function(e,t,n){var i=new Array;i.push(t);for(var r=function(){var t=i.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;var r=t.getChildAt(e),a=this._checkOccupied(t);(a&&n===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!a&&n===Th)&&i.push(r)}))};0!==i.length;)r();return!1}};return this._traverseLeaves((function(n,i,r){var a=e._computeCoordFromKey(i),s=e.nodeSizeTable[r],o=e._treeDepth-r,l=e._checkOccupied(n);(l||e.voxelRenderMode!==wh)&&(l&&e.voxelRenderMode===Th||e._FACES.forEach((function(e){var l=[i[0]+e.normal[0]*o*o,i[1]+e.normal[1]*o*o,i[2]+e.normal[2]*o*o],c=this.searchAtDepth(l);null===c?t._insertFace(e,a,s,this._obtainColor(n)):r=this.palette.length-1?this.palette[this.palette.length-1]:{r:i*this.palette[n].r+(1-i)*this.palette[n+1].r,g:i*this.palette[n].g+(1-i)*this.palette[n+1].g,b:i*this.palette[n].b+(1-i)*this.palette[n+1].b}}},{key:"_checkOccupied",value:function(e){return e.value>=this.occupancyThreshold}}])}(Lh);function Uh(e,t,n){return t=ql(t),Xl(e,Dh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Dh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Dh=function(){return!!e})()}var Oh=function(e){function t(e){var n;return Hl(this,t),(n=Uh(this,t,[e])).useOwnColor=void 0!==e.palette&&e.colorMode===Rh,n}return Kl(t,e),jl(t,[{key:"_readNodeData",value:function(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}},{key:"_obtainColor",value:function(e){return this.useOwnColor?e.color:Nh.prototype._obtainColor.call(this,e)}}])}(Nh);function Fh(e,t,n){return t=ql(t),Xl(e,kh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function kh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(kh=function(){return!!e})()}var Bh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Fh(this,t)).ros=e.ros,n.topicName=e.topic||"/octomap",n.compression=e.compression||"cbor",n.continuous=e.continuous,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.offsetPose=e.offsetPose||new i.Pose,n.options={},void 0!==e.color&&(n.options.color=e.color),void 0!==e.opacity&&(n.options.opacity=e.opacity),void 0!==e.colorMode&&(n.options.colorMode=e.colorMode),void 0!==e.palette&&(n.options.palette=e.palette),void 0!==e.paletteScale&&(n.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(n.options.voxelRenderMode=e.voxelRenderMode),n.currentMap=null,n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"_loadOcTree",value:function(e){return new Promise(function(t,n){var i=Object.assign({resolution:e.resolution},this.options),r=null;if(e.binary)(r=new Lh(i)).readBinary(e.data);else{var a={OcTree:Nh,ColorOcTree:Oh};e.id in a&&(console.log(e.id,a),(r=new a[e.id](i)).read(e.data))}r.buildGeometry(),t(r)}.bind(this))}},{key:"_processMessagePrivate",value:function(e){this._loadOcTree(e).then(function(t){var n=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(n),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}}])}(qc);function zh(e,t,n){return t=ql(t),Xl(e,Hh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Hh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Hh=function(){return!!e})()}var Vh=function(e){function t(e){var n;return Hl(this,t),(n=zh(this,t)).options=e||{},n.ros=e.ros,n.topicName=e.topic||"/particlecloud",n.tfClient=e.tfClient,n.color=e.color||13369599,n.length=e.length||1,n.rootObject=e.rootObject||new bn,n.keep=e.keep||1,n.sns=[],n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new vt(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new gt(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new vt(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Hn({color:this.color});var n=new ic(this.options);this.sns.push(new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:n})),this.rootObject.add(this.sns[this.sns.length-1])}}])}(bn);function Gh(e,t,n){return t=ql(t),Xl(e,Wh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Wh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Wh=function(){return!!e})()}var jh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Gh(this,t)).ros=e.ros,n.topicName=e.topic||"/path",n.tfClient=e.tfClient,n.color=e.color||13369599,n.rootObject=e.rootObject||new bn,n.sn=null,n.line=null,n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new ti,n=0;n=e.range_min&&r<=e.range_max){var a=e.angle_min+i*e.angle_increment;this.points.positions.array[n++]=r*Math.cos(a),this.points.positions.array[n++]=r*Math.sin(a),this.points.positions.array[n++]=0}}this.points.update(n/3)}}}])}(bn);function pu(e,t,n){return t=ql(t),Xl(e,fu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function fu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(fu=function(){return!!e})()}var mu=function(e){function t(e){var n;Hl(this,t),e=e||{},(n=pu(this,t)).ros=e.ros,n.topicName=e.topic||"/gps/fix",n.rootObject=e.rootObject||new bn,n.object3d=e.object3d||new bn;var i=e.material||{};return n.altitudeNaN=e.altitudeNaN||0,n.keep=e.keep||100,n.convert=e.convert||function(e,t,n){return new vt(e,t,n)},n.count=0,n.next1=0,n.next2=n.keep,n.geom=new ti,n.vertices=new Wn(new Float32Array(6*n.keep),3),n.geom.addAttribute("position",n.vertices),n.material=i.isMaterial?i:new mo(i),n.line=new So(n.geom,n.material),n.rootObject.add(n.object3d),n.rootObject.add(n.line),n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,n=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(n),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=n.x,this.vertices.array[3*this.next1+1]=n.y,this.vertices.array[3*this.next1+2]=n.z,this.vertices.array[3*this.next2]=n.x,this.vertices.array[3*this.next2+1]=n.y,this.vertices.array[3*this.next2+2]=n.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}])}(bn);function gu(e,t,n){return t=ql(t),Xl(e,vu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function vu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(vu=function(){return!!e})()}function _u(e,t,n,i){var r,a=0,s=0,o=0,l=e.length,c=t.length,h=((i=i||1)-1)*(n=n||c)*8;for(r=0;r=8&&(s-=8,t[o++]=a>>>s&255,o%n==0&&(r+=Math.ceil((h-s)/6),(s%=8)>0&&(a=_u.e[e.charAt(r)])));return Math.floor(o/n)}_u.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",_u.e={};for(var yu=0;yu<64;yu++)_u.e[_u.S.charAt(yu)]=yu;var xu=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=gu(this,t)).ros=e.ros,n.topicName=e.topic||"/points",n.throttle_rate=e.throttle_rate||null,n.compression=e.compression||"cbor",n.max_pts=e.max_pts||1e4,n.points=new cu(e),n.rosTopic=void 0,n.buffer=null,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,n=this.points.pointRatio,i=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,i)),t=Math.min(e.height*e.width/n,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(i=p[0].object,d.intersection=this.lastIntersection=p[0]):i=this.fallbackTarget,i!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(i,"mouseover",d);0===f?this.notify(this.lastTarget,"mouseout",d):1===f&&(i=this.fallbackTarget)!==this.lastTarget&&(this.notify(i,"mouseover",d),this.notify(this.lastTarget,"mouseout",d))}i!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(i,e.type,d)?(this.notify(this.lastTarget,"touchleave",d),this.notify(this.lastTarget,"touchend",d)):(i=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",d),this.notify(this.lastTarget,"touchend",d)));this.notify(i,e.type,d),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=i}},{key:"notify",value:function(e,t,n){for(n.type=t,n.cancelBubble=!1,n.continueBubble=!1,n.stopPropagation=function(){n.cancelBubble=!0},n.continuePropagation=function(){n.continueBubble=!0},n.currentTarget=e;n.currentTarget;){if(n.currentTarget.dispatchEvent&&n.currentTarget.dispatchEvent instanceof Function){if(n.currentTarget.dispatchEvent(n),n.cancelBubble)return this.dispatchEvent(n),0;if(n.continueBubble)return 2}n.currentTarget=n.currentTarget.parent}return 1}}])}(Ie);function Iu(e,t,n){return t=ql(t),Xl(e,Nu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Nu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Nu=function(){return!!e})()}var Uu=function(e){function t(e){var n;Hl(this,t);var i=n=Iu(this,t),r=(e=e||{}).scene;n.camera=e.camera,n.center=new vt,n.userZoom=!0,n.userZoomSpeed=e.userZoomSpeed||1,n.userRotate=!0,n.userRotateSpeed=e.userRotateSpeed||1,n.autoRotate=e.autoRotate,n.autoRotateSpeed=e.autoRotateSpeed||2,n.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,n.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",n.camera.up=new vt(0,0,1);var a=1800,s=new We,o=new We,l=new We,c=new We,h=new We,u=new We,d=new vt,p=new vt,f=new vt,m=new vt,g=new Array(2),v=new Array(2);n.phiDelta=0,n.thetaDelta=0,n.scale=1,n.lastPosition=new vt;var _=-1,y=0,x=1,b=2,M=_;function S(e,t,n){var i=new vt;new vt;i.subVectors(t,e.origin);var r=e.direction.dot(n);if(Math.abs(r)0?i.zoomIn():i.zoomOut(),this.showAxes()}}return n.axes=new dh({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:n.lineTypePanAndZoomFrame}),n.displayPanAndZoomFrame&&(r.add(n.axes),n.axes.traverse((function(e){e.visible=!1}))),n.addEventListener("mousedown",(function(e){var t=e.domEvent;switch(t.preventDefault(),t.button){case 0:M=y,s.set(t.clientX,t.clientY);break;case 1:M=b,p=new vt(0,0,1);var n=(new qt).extractRotation(this.camera.matrix);p.applyMatrix4(n),d=i.center.clone(),f=i.camera.position.clone(),m=S(e.mouseRay,d,p);break;case 2:M=x,c.set(t.clientX,t.clientY)}this.showAxes()})),n.addEventListener("mouseup",(function(e){i.userRotate&&(M=_)})),n.addEventListener("mousemove",(function(e){var t=e.domEvent;if(M===y)o.set(t.clientX,t.clientY),l.subVectors(o,s),i.rotateLeft(2*Math.PI*l.x/a*i.userRotateSpeed),i.rotateUp(2*Math.PI*l.y/a*i.userRotateSpeed),s.copy(o),this.showAxes();else if(M===x)h.set(t.clientX,t.clientY),u.subVectors(h,c),u.y>0?i.zoomIn():i.zoomOut(),c.copy(h),this.showAxes();else if(M===b){var n=S(e.mouseRay,i.center,p);if(!n)return;var r=(new vt).subVectors(m.clone(),n.clone());i.center.addVectors(d.clone(),r.clone()),i.camera.position.addVectors(f.clone(),r.clone()),i.update(),i.camera.updateMatrixWorld(),this.showAxes()}})),n.addEventListener("touchstart",(function(e){var t=e.domEvent;switch(t.touches.length){case 1:M=y,s.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY);break;case 2:M=_,p=new vt(0,0,1);var n=(new qt).extractRotation(this.camera.matrix);p.applyMatrix4(n),d=i.center.clone(),f=i.camera.position.clone(),m=S(e.mouseRay,d,p),g[0]=new We(t.touches[0].pageX,t.touches[0].pageY),g[1]=new We(t.touches[1].pageX,t.touches[1].pageY),v[0]=new We(0,0),v[1]=new We(0,0)}this.showAxes(),t.preventDefault()})),n.addEventListener("touchmove",(function(e){var t=e.domEvent;if(M===y)o.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY),l.subVectors(o,s),i.rotateLeft(2*Math.PI*l.x/a*i.userRotateSpeed),i.rotateUp(2*Math.PI*l.y/a*i.userRotateSpeed),s.copy(o),this.showAxes();else{if(v[0].set(g[0].x-t.touches[0].pageX,g[0].y-t.touches[0].pageY),v[1].set(g[1].x-t.touches[1].pageX,g[1].y-t.touches[1].pageY),v[0].lengthSq()>10&&v[1].lengthSq()>10&&(g[0].set(t.touches[0].pageX,t.touches[0].pageY),g[1].set(t.touches[1].pageX,t.touches[1].pageY),v[0].dot(v[1])>0&&M!==x?M=b:v[0].dot(v[1])<0&&M!==b&&(M=x),M===x)){var n=new We;n.subVectors(g[0],g[1]),v[0].dot(n)<0&&v[1].dot(n)>0?i.zoomOut():v[0].dot(n)>0&&v[1].dot(n)<0&&i.zoomIn()}if(M===b){var r=S(e.mouseRay,i.center,p);if(!r)return;var c=(new vt).subVectors(m.clone(),r.clone());i.center.addVectors(d.clone(),c.clone()),i.camera.position.addVectors(f.clone(),c.clone()),i.update(),i.camera.updateMatrixWorld()}this.showAxes(),t.preventDefault()}})),n.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&M!==y?(M=y,s.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):M=_})),n.addEventListener("mousewheel",E),n.addEventListener("DOMMouseScroll",E),n}return Kl(t,e),jl(t,[{key:"showAxes",value:function(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}},{key:"rotateLeft",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}},{key:"rotateRight",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}},{key:"rotateUp",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}},{key:"rotateDown",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}},{key:"zoomIn",value:function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}},{key:"zoomOut",value:function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}},{key:"update",value:function(){var e=this.camera.position,t=e.clone().sub(this.center),n=Math.atan2(t.y,t.x),i=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),n+=this.thetaDelta,i+=this.phiDelta;var r=1e-6;i=Math.max(r,Math.min(Math.PI-r,i));var a=t.length();t.set(a*Math.sin(i)*Math.cos(n),a*Math.sin(i)*Math.sin(n),a*Math.cos(i)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),a=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*a,.05*a,.05*a),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}])}(Ie),Du=function(){return jl((function e(t){Hl(this,e),console.log("Here 1");var n=(t=t||{}).divID,i=t.elem,r=t.width,a=t.height,s=t.background||"#111111",o=t.antialias,l=t.intensity||.66,c=t.near||.01,h=t.far||1e3,u=t.alpha||1,d=t.cameraPose||{x:3,y:3,z:3},p=t.cameraZoomSpeed||.5,f=void 0===t.displayPanAndZoomFrame||!!t.displayPanAndZoomFrame,m=t.lineTypePanAndZoomFrame||"full";this.renderer=new Is({antialias:o,alpha:!0}),this.renderer.setClearColor(parseInt(s.replace("#","0x"),16),u),this.renderer.sortObjects=!1,this.renderer.setSize(r,a),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ns,this.camera=new Pi(40,r/a,c,h),this.camera.position.x=d.x,this.camera.position.y=d.y,this.camera.position.z=d.z,this.cameraControls=new Uu({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:f,lineTypePanAndZoomFrame:m}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Al(5592405)),this.directionalLight=new Tl(16777215,l),this.scene.add(this.directionalLight),console.log("Here 2"),this.selectableObjects=new Ss,this.scene.add(this.selectableObjects);var g=new Pu({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ru({mouseHandler:g}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(n)).appendChild(this.renderer.domElement),this.start(),console.log("Here 3")}),[{key:"start",value:function(){this.stopped=!1,this.draw()}},{key:"draw",value:function(){this.stopped||(this.cameraControls.update(),console.log("Here 5"),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}},{key:"stop",value:function(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}},{key:"addObject",value:function(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}},{key:"resize",value:function(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}}])}();return e.Arrow=ic,e.Arrow2=ch,e.Axes=dh,e.ColorOcTree=Oh,e.DepthCloud=Ql,e.Grid=mh,e.Highlighter=Ru,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=Gc,e.InteractiveMarkerClient=Jc,e.InteractiveMarkerControl=Fc,e.InteractiveMarkerHandle=Zc,e.InteractiveMarkerMenu=zc,e.LaserScan=du,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=Nc,e.MarkerArrayClient=ih,e.MarkerClient=sh,e.MeshLoader=Ec,e.MeshResource=Ac,e.MouseHandler=Pu,e.NavSatFix=mu,e.OcTree=Nh,e.OcTreeClient=Bh,e.OccupancyGrid=_h,e.OccupancyGridClient=bh,e.Odometry=Vh,e.OrbitControls=Uu,e.Path=jh,e.Point=Yh,e.PointCloud2=xu,e.Points=cu,e.Polygon=Jh,e.Pose=eu,e.PoseArray=iu,e.PoseWithCovariance=su,e.SceneNode=eh,e.TFAxes=Su,e.TriangleList=Lc,e.Urdf=Tu,e.UrdfClient=Au,e.Viewer=Du,e.closestAxisPoint=zl,e.findClosestPoint=Bl,e.intersectPlane=kl,e.makeColorMaterial=Fl,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); diff --git a/es6-transpiler.js b/es6-transpiler.js index ff3f5df3..18beda36 100644 --- a/es6-transpiler.js +++ b/es6-transpiler.js @@ -258,7 +258,7 @@ const transpile = { ], // Track external dependencies for import injection externalDependencies: (filepath) => [ - /(.*)(THREE|EventEmitter2|ROSLIB|ColladaLoader|OBJLoader|MTLLoader|STLLoader).*/g, + /(.*)(THREE|EventEmitter2|ROSLIB|ColladaLoader).*/g, (match, $preStuffs, $dep) => { if (/^\s*(?:\*|\/\/)/.test($preStuffs)) { @@ -498,7 +498,7 @@ const transpile = { if (externalDeps && externalDeps.length > 0) { // Make sure these come after importing THREE - const threeExtensions = ['ColladaLoader', 'MTLLoader', 'OBJLoader', 'STLLoader'] + const threeExtensions = ['ColladaLoader'] const threeExtensionsUsed = [] threeExtensions.forEach(ext => { @@ -527,9 +527,9 @@ const transpile = { switch (dep) { case 'THREE': { - const modulePath = 'shims/three/core.js' + const modulePath = 'node_modules/three/build/three.module.js' const resolvedPath = path.relative(path.dirname(filepath), modulePath) - importString = `import THREE from '${resolvedPath}';` + importString = `import * as THREE from '${resolvedPath}';` break; } case 'ROSLIB': { @@ -546,24 +546,6 @@ const transpile = { importString = `import '${resolvedPath}';` break; } - case 'MTLLoader': { - const modulePath = 'shims/three/MTLLoader.js' - const resolvedPath = path.relative(path.dirname(filepath), modulePath) - importString = `import '${resolvedPath}';` - break; - } - case 'OBJLoader': { - const modulePath = 'shims/three/OBJLoader.js' - const resolvedPath = path.relative(path.dirname(filepath), modulePath) - importString = `import '${resolvedPath}';` - break; - } - case 'STLLoader': { - const modulePath = 'shims/three/STLLoader.js' - const resolvedPath = path.relative(path.dirname(filepath), modulePath) - importString = `import '${resolvedPath}';` - break; - } default: { logError('unknown external dependency', dep, { filepath, externalDeps }) return undefined diff --git a/examples/html-import/yarn.lock b/examples/html-import/yarn.lock index 4651e1f9..1826d246 100644 --- a/examples/html-import/yarn.lock +++ b/examples/html-import/yarn.lock @@ -586,8 +586,8 @@ socket.io-client@2.2.0: to-array "0.1.4" socket.io-parser@~3.3.0: - version "3.3.4" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.4.tgz#ab84236b6d06eaf1fb68b179b3a7501195886cc3" + version "3.3.3" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.3.tgz#3a8b84823eba87f3f7624e64a8aaab6d6318a72f" dependencies: component-emitter "~1.3.0" debug "~3.1.0" diff --git a/package-lock.json b/package-lock.json index 633ec816..f5a27ba1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,18 @@ "version": "1.1.0", "license": "BSD-3-Clause", "dependencies": { - "eventemitter3": "^5.0.1", + "@babel/core": "^7.25.2", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/preset-env": "^7.25.2", + "@babel/runtime": "^7.25.0", + "@rollup/plugin-babel": "^6.0.4", + "eventemitter2": "^6.4.0", "roslib": "^1.0.0", - "three": "^0.89.0" + "three": "^0.167.0" }, "devDependencies": { "@rollup/plugin-buble": "^1.0.0", - "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.0.0", "chai": "^4.3.0", "debug": "^4.3.0", @@ -38,4602 +43,4957 @@ "rollup-plugin-terser": "^7.0.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "dev": true, + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.12.13" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true + "node_modules/@babel/compat-data": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dependencies": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/highlight/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@babel/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", - "dev": true, + "node_modules/@babel/generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "dependencies": { + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "bin": { - "parser": "bin/babel-parser.js" + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", - "dev": true, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, "engines": { - "node": ">=0.1.90" + "node": ">=6.9.0" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", + "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.0", + "semver": "^6.3.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dependencies": { - "ansi-regex": "^6.0.1" + "regenerate": "^1.4.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=4" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { - "node": ">=12" + "node": ">=4" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", - "dev": true, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dependencies": { - "semver": "^7.3.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@npmcli/git": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.0.3.tgz", - "integrity": "sha512-8cXNkDIbnXPVbhXMmQ7/bklCAjtmPaXfI9aEM4iH+xSuEHINLMHhlfESvVwdqmHJRJkR48vNJTSUvoF6GRPSFA==", - "dev": true, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dependencies": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" + "@babel/types": "^7.24.7" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/git/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", - "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", - "dev": true, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", - "dev": true, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" }, - "bin": { - "installed-package-contents": "lib/index.js" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", - "dev": true, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", - "dev": true, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", "dependencies": { - "which": "^3.0.0" + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", - "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", - "dev": true, + "node_modules/@babel/helpers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/run-script": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.0.tgz", - "integrity": "sha512-ql+AbRur1TeOdl1FY+RAwGW9fcr4ZwiVKabdvm93mujGREVuVLbdkXRJDrkTXSdCjaxYydr1wlA2v67jxWG5BQ==", - "dev": true, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@npmcli/run-script/node_modules/which": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", - "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, + "node_modules/@babel/parser": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", + "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", "bin": { - "node-which": "bin/which.js" + "parser": "bin/babel-parser.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.0.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.0.tgz", + "integrity": "sha512-dG0aApncVQwAUJa8tP1VHTnmU67BeIQvKafd3raEx315H54FfkZSz3B/TT+33ZQAjatGJA79gZqTtqL5QZUKXw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, "engines": { - "node": ">=14" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@rollup/plugin-buble": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-buble/-/plugin-buble-1.0.0.tgz", - "integrity": "sha512-VDbhsNtC4cXZ20+hhilL0hzUskrTZWhF9PTabCOuye1NK5Ht8LZzpM1Q0S/yo0kMArjrFnIb2P4N8d3uEKuxnA==", - "dev": true, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "@types/buble": "^0.19.2", - "buble": "^0.20.0" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@rollup/plugin-commonjs": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", - "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", - "dev": true, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "glob": "^10.4.1", - "is-reference": "1.2.1", - "magic-string": "^0.30.3" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { - "node": ">=16.0.0 || 14 >= 14.17" + "node": ">=6.9.0" }, "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dependencies": { - "balanced-match": "^1.0.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", - "dev": true, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" + "@babel/helper-plugin-utils": "^7.12.13" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dependencies": { - "brace-expansion": "^2.0.1" + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz", - "integrity": "sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q==", - "dev": true, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.1", - "is-module": "^1.0.0", - "resolve": "^1.22.1" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "rollup": "^2.78.0||^3.0.0" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 8.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">= 10" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/buble": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@types/buble/-/buble-0.19.2.tgz", - "integrity": "sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q==", - "dev": true, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dependencies": { - "magic-string": "^0.25.0" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dependencies": { - "@types/node": "*" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", - "dev": true + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", + "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", - "dev": true, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz", - "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==" - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz", - "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=10.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "dev": true, + "node": ">=6.9.0" + }, "peerDependencies": { - "acorn": "^6.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@babel/core": "^7.12.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", + "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", "dependencies": { - "debug": "4" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.0", + "globals": "^11.1.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "dev": true, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { - "node": ">= 8.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "dependencies": { - "string-width": "^3.0.0" + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { - "node": ">=6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "license": "MIT", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dependencies": { - "color-convert": "^1.9.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", "dependencies": { - "sprintf-js": "~1.0.2" + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": "*" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, "engines": { - "node": ">=4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", "dependencies": { - "lodash": "^4.17.14" + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": "^4.5.0 || >= 5.9" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "dependencies": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", "dependencies": { - "ms": "2.0.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body-parser/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/body-parser/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dependencies": { - "ee-first": "1.1.1" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body/node_modules/bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "node_modules/body/node_modules/raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "dev": true, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", "dependencies": { - "bytes": "1", - "string_decoder": "0.10" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/body/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/boxen": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", - "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", - "dev": true, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.0", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/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, - "license": "MIT", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/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, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/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, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dependencies": { - "color-name": "~1.1.4" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/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/boxen/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/boxen/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, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/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, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dependencies": { - "ansi-regex": "^5.0.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/boxen/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, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dependencies": { - "has-flag": "^4.0.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dependencies": { - "fill-range": "^7.1.1" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/brotli-size": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz", - "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==", - "dev": true, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", "dependencies": { - "duplexer": "0.1.1" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { - "node": ">= 10.16.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buble": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/buble/-/buble-0.20.0.tgz", - "integrity": "sha512-/1gnaMQE8xvd5qsNBl+iTuyjJ9XxeaVxAMF86dQ4EyxFJOZtsgOS8Ra+7WHgZTam5IFDtt4BguN0sH0tVTKrOw==", - "dev": true, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "dependencies": { - "acorn": "^6.4.1", - "acorn-dynamic-import": "^4.0.0", - "acorn-jsx": "^5.2.0", - "chalk": "^2.4.2", - "magic-string": "^0.25.7", - "minimist": "^1.2.5", - "regexpu-core": "4.5.4" + "@babel/helper-plugin-utils": "^7.24.7" }, - "bin": { - "buble": "bin/buble" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", "dependencies": { - "semver": "^7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.2.tgz", + "integrity": "sha512-Y2Vkwy3ITW4id9c6KXshVV/x5yCGK7VdJmKkzOzNsDZMojRKfSA/033rRbLqlRozmhRXCejxWHLSJOg/wUHfzw==", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.0", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.0", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.0", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/builtins/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/cacache": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz", - "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==", - "dev": true, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^8.0.1", - "lru-cache": "^7.7.1", - "minipass": "^4.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "regenerator-runtime": "^0.14.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dependencies": { - "balanced-match": "^1.0.0" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, + "node_modules/@babel/traverse": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.2.tgz", + "integrity": "sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=6.9.0" } }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, + "node_modules/@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dependencies": { - "brace-expansion": "^2.0.1" + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/callsites": { + "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.0.0" } }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", "dev": true, "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/cbor-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cbor-js/-/cbor-js-0.1.0.tgz", - "integrity": "sha1-yAzmEg84fo+qdDcN/aIdlluPx/k=" + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "semver": "^7.3.5" }, "engines": { - "node": ">=4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "node_modules/@npmcli/fs/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">= 6" + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "node_modules/@npmcli/git": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.0.3.tgz", + "integrity": "sha512-8cXNkDIbnXPVbhXMmQ7/bklCAjtmPaXfI9aEM4iH+xSuEHINLMHhlfESvVwdqmHJRJkR48vNJTSUvoF6GRPSFA==", "dev": true, "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/@npmcli/git/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">= 8.10.0" + "bin": { + "semver": "bin/semver.js" }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, "engines": { "node": ">=10" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/@npmcli/git/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "node_modules/@npmcli/git/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "isexe": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", "dev": true, "dependencies": { - "restore-cursor": "^2.0.0" + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" }, "engines": { - "node": ">=4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "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==", + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/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, - "license": "MIT", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/cliui/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/cliui/node_modules/is-fullwidth-code-point": { + "node_modules/@npmcli/node-gyp": { "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==", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "dev": true, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "which": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@npmcli/run-script": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.0.tgz", + "integrity": "sha512-ql+AbRur1TeOdl1FY+RAwGW9fcr4ZwiVKabdvm93mujGREVuVLbdkXRJDrkTXSdCjaxYydr1wlA2v67jxWG5BQ==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, "bin": { - "color-support": "bin.js" + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true, + "node_modules/@rollup/plugin-babel": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", + "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@rollup/pluginutils": "^5.0.1" + }, "engines": { - "node": ">=0.1.90" + "node": ">=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + }, + "rollup": { + "optional": true + } } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, + "node_modules/@rollup/plugin-babel/node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 0.10.0" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@rollup/plugin-buble": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-buble/-/plugin-buble-1.0.0.tgz", + "integrity": "sha512-VDbhsNtC4cXZ20+hhilL0hzUskrTZWhF9PTabCOuye1NK5Ht8LZzpM1Q0S/yo0kMArjrFnIb2P4N8d3uEKuxnA==", "dev": true, "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", - "dev": true - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "@rollup/pluginutils": "^4.2.1", + "@types/buble": "^0.19.2", + "buble": "^0.20.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", + "dev": true, "dependencies": { - "object-assign": "^4", - "vary": "^1" + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" }, "engines": { - "node": ">= 0.10" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/@rollup/plugin-commonjs/node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "balanced-match": "^1.0.0" } }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, "engines": { - "node": ">= 6" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "node_modules/date-format": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", - "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "node_modules/@rollup/plugin-commonjs/node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, - "engines": { - "node": ">=4.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz", + "integrity": "sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" }, "engines": { - "node": ">=6.0" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "rollup": { "optional": true } } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, "engines": { - "node": ">=10" + "node": ">=14.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dev": true, "dependencies": { - "type-detect": "^4.0.0" + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" }, "engines": { - "node": ">=0.12" + "node": ">= 8.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/delegates": { + "node_modules/@types/buble": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@types/buble/-/buble-0.19.2.tgz", + "integrity": "sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q==", + "dev": true, + "dependencies": { + "magic-string": "^0.25.0" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", "dev": true }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz", + "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz", + "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, "engines": { "node": ">= 0.6" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true, + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=0.4.0" } }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "node_modules/acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "acorn": "^6.0.0" } }, - "node_modules/di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "dependencies": { + "debug": "4" + }, "engines": { - "node": ">=0.3.1" + "node": ">= 6.0.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" }, "engines": { - "node": ">=6.0.0" + "node": ">= 8.0.0" } }, - "node_modules/dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "node_modules/ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] + "dependencies": { + "string-width": "^3.0.0" + } }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "node_modules/ansi-align/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "dependencies": { - "domelementtype": "^2.3.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">=6" } }, - "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=6" } }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true + "node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "iconv-lite": "^0.6.2" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, - "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">=10.2.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", - "engines": { - "node": ">=10.0.0" + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true, "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "node_modules/error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, - "dependencies": { - "string-template": "~0.2.1" + "engines": { + "node": "*" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, - "engines": { - "node": ">=0.8.0" + "dependencies": { + "lodash": "^4.17.14" } }, - "node_modules/eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", - "dev": true, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^6.14.0 || ^8.10.0 || >=9.10.0" + "semver": "bin/semver.js" } }, - "node_modules/eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" }, - "engines": { - "node": ">=4.0.0" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "dependencies": { - "eslint-visitor-keys": "^1.1.0" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, - "engines": { - "node": ">=6" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, + "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/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "engines": { - "node": ">=4" + "node": "^4.5.0 || >= 5.9" } }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/eslint/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true }, - "node_modules/eslint/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "node_modules/body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", "dev": true, "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" } }, - "node_modules/eslint/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, "engines": { - "node": ">=4" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/eslint/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "ms": "2.0.0" } }, - "node_modules/eslint/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/eslint/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/body/node_modules/bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", + "dev": true + }, + "node_modules/body/node_modules/raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "bytes": "1", + "string_decoder": "0.10" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/espree": { + "node_modules/body/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/boxen": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", + "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", "dev": true, "dependencies": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.0", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/boxen/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "node_modules/boxen/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": { - "estraverse": "^5.1.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/boxen/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": { - "estraverse": "^5.2.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=4.0" + "node": ">=7.0.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } + "node_modules/boxen/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/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/boxen/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/boxen/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": ">=4.0" + "node": ">=8" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/boxen/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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/eventemitter2": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", - "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "node_modules/boxen/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "dependencies": { - "homedir-polyfill": "^1.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "node_modules/boxen/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "ansi-regex": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "node_modules/boxen/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": { - "websocket-driver": ">=0.5.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "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": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "flat-cache": "^2.0.1" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/filesize": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.3.0.tgz", - "integrity": "sha512-ytx0ruGpDHKWVoiui6+BY/QMNngtDQ/pJaFwfBpQif0J63+E8DLdFyqS3NkKQn7vIruUEpoGD9JUJSg7Kp+I0g==", - "dev": true, - "engines": { - "node": ">= 0.4.0" + "node": ">=8" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/brotli-size": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz", + "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "duplexer": "0.1.1" }, "engines": { - "node": ">=8" + "node": ">= 10.16.0" } }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">= 0.8" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/buble": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.20.0.tgz", + "integrity": "sha512-/1gnaMQE8xvd5qsNBl+iTuyjJ9XxeaVxAMF86dQ4EyxFJOZtsgOS8Ra+7WHgZTam5IFDtt4BguN0sH0tVTKrOw==", "dev": true, "dependencies": { - "ms": "2.0.0" + "acorn": "^6.4.1", + "acorn-dynamic-import": "^4.0.0", + "acorn-jsx": "^5.2.0", + "chalk": "^2.4.2", + "magic-string": "^0.25.7", + "minimist": "^1.2.5", + "regexpu-core": "4.5.4" + }, + "bin": { + "buble": "bin/buble" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/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==", + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/findup-sync": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", - "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.3", - "micromatch": "^4.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 10.13.0" + "semver": "^7.0.0" } }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "node_modules/builtins/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" } }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "node_modules/builtins/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 0.10" + "node": ">=10" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, - "bin": { - "flat": "cli.js" + "engines": { + "node": ">= 0.8" } }, - "node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "node_modules/cacache": { + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz", + "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==", "dev": true, "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^8.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { - "for-in": "^1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, - "engines": { - "node": ">=14" + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/fs-minipass": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.1.tgz", - "integrity": "sha512-MhaJDcFRTuLidHrIttu0RDGyyXs/IYHVmlcxfLAEFIWjc1vdLAkdwT7Ace2u7DbitWC0toKMl5eJZRYNVreIMw==", + "node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true, - "dependencies": { - "minipass": "^4.0.0" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/caniuse-lite": { + "version": "1.0.30001645", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001645.tgz", + "integrity": "sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "lodash": "^4.17.15" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 10" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "node_modules/cbor-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cbor-js/-/cbor-js-0.1.0.tgz", + "integrity": "sha1-yAzmEg84fo+qdDcN/aIdlluPx/k=" }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "node_modules/chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=4" } }, - "node_modules/gauge/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, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/gauge/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==", + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "node_modules/gauge/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==", + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/gauge/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==", + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/gauge/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==", + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "globule": "^1.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "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==", + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=10" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "license": "MIT", "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getobject": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.0.tgz", - "integrity": "sha512-tbUz6AKKKr2YiMB+fLWIgq5ZeBOobop9YMMAU9dC54/ot2ksMXt3DOFyBuhZw6ptcVszEykgByK20j7W9jHFag==", + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "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": { - "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" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "node_modules/cliui/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/cliui/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, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "ansi-regex": "^5.0.0" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=8" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" } }, - "node_modules/globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, - "dependencies": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "engines": { - "node": ">= 0.10" + "bin": { + "color-support": "bin.js" } }, - "node_modules/globule/node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "node_modules/colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">=0.1.90" } }, - "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/grunt": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.0.tgz", - "integrity": "sha512-dRcJXAaWLIt9khaZKfAgitjlFnEABGKT+jpyG/rlFxZd5kZkF7v4HvuoYIU7FjrG+BRDySwEHYrSYUHd5p9P4w==", + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "dependencies": { - "dateformat": "~4.6.2", - "eventemitter2": "~0.4.13", - "exit": "~0.1.2", - "findup-sync": "~5.0.0", - "glob": "~8.1.0", - "grunt-cli": "~1.4.3", - "grunt-known-options": "~2.0.0", - "grunt-legacy-log": "~3.0.0", - "grunt-legacy-util": "~2.0.1", - "iconv-lite": "~0.6.3", - "js-yaml": "~3.14.0", - "minimatch": "~3.0.4", - "mkdirp": "~2.1.3", - "nopt": "~3.0.6", - "rimraf": "~4.1.2" - }, - "bin": { - "grunt": "bin/grunt" + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" }, "engines": { - "node": ">=16" + "node": ">= 0.10.0" } }, - "node_modules/grunt-cli": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", - "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "grunt-known-options": "~2.0.0", - "interpret": "~1.1.0", - "liftup": "~3.0.1", - "nopt": "~4.0.1", - "v8flags": "~3.2.0" - }, - "bin": { - "grunt": "bin/grunt" - }, - "engines": { - "node": ">=10" + "ms": "2.0.0" } }, - "node_modules/grunt-cli/node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true, - "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" - }, - "bin": { - "nopt": "bin/nopt.js" + "engines": { + "node": ">= 0.6" } }, - "node_modules/grunt-contrib-clean": { + "node_modules/continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", + "dev": true + }, + "node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.0.tgz", - "integrity": "sha512-g5ZD3ORk6gMa5ugZosLDQl3dZO7cI3R14U75hTM+dVLVxdMNJCPVmwf9OUt4v4eWgpKKWWoVK9DZc1amJp4nQw==", - "dev": true, - "dependencies": { - "async": "^2.6.1", - "rimraf": "^2.6.2" - }, + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { - "node": ">=6" - }, - "peerDependencies": { - "grunt": ">=0.4.5" + "node": ">= 0.6" } }, - "node_modules/grunt-contrib-clean/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dependencies": { - "glob": "^7.1.3" + "browserslist": "^4.23.0" }, - "bin": { - "rimraf": "bin.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/grunt-contrib-watch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", - "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", - "dev": true, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dependencies": { - "async": "^2.6.0", - "gaze": "^1.1.0", - "lodash": "^4.17.10", - "tiny-lr": "^1.1.1" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-execute": { - "version": "0.2.2", - "resolved": "git+ssh://git@github.com/gruntjs-updater/grunt-execute.git#a828fc41e070759df038d1126b9bf842db34004c", - "dev": true, - "engines": { - "node": ">= 0.8.0" - }, - "peerDependencies": { - "grunt": ">=0.4.0" + "node": ">= 0.10" } }, - "node_modules/grunt-jsdoc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", - "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", + "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": { - "cross-spawn": "^7.0.1", - "jsdoc": "^3.6.3" - }, - "bin": { - "grunt-jsdoc": "bin/grunt-jsdoc" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 8.12.0" + "node": ">= 8" } }, - "node_modules/grunt-karma": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/grunt-karma/-/grunt-karma-4.0.2.tgz", - "integrity": "sha512-4+iBBkXZjHHMDAG5kpHCdDUqlSEBJ6sqouLMRf0p+QB8wGMs300DtaCQphHqd7pM3gpXoGVT3yRRsT7KOZpJMA==", + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dev": true, "dependencies": { - "lodash": "^4.17.10" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, - "peerDependencies": { - "grunt": ">=0.4.x", - "karma": "^4.0.0 || ^5.0.0 || ^6.0.0" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/grunt-known-options": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", - "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/grunt-legacy-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", - "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "node_modules/date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", "dev": true, - "dependencies": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.19" - }, "engines": { - "node": ">= 0.10.0" + "node": ">=4.0" } }, - "node_modules/grunt-legacy-log-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", - "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "dev": true, - "dependencies": { - "chalk": "~4.1.0", - "lodash": "~4.17.19" - }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/grunt-legacy-log-utils/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, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "color-convert": "^2.0.1" + "ms": "2.1.2" }, "engines": { - "node": ">=8" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/grunt-legacy-log-utils/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/grunt-legacy-log-utils/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==", + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "type-detect": "^4.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=0.12" } }, - "node_modules/grunt-legacy-log-utils/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==", + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "node_modules/grunt-legacy-log-utils/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==", + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/grunt-legacy-log-utils/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==", + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/grunt-legacy-util": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", - "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, - "dependencies": { - "async": "~3.2.0", - "exit": "~0.1.2", - "getobject": "~1.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.21", - "underscore.string": "~3.3.5", - "which": "~2.0.2" - }, "engines": { - "node": ">=10" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/grunt-legacy-util/node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, - "node_modules/grunt-pipe": { - "version": "2.0.1", - "resolved": "git+ssh://git@github.com/RobotWebTools/grunt-pipe.git#d0937a52726f8f73df5d6d704d0519473150fb0e", - "integrity": "sha512-DPgn249Wea0hGLV8SHUGHk7Wdk9r4rY/L3tRHPSrYFRsCV9o8jR0P31wUXCEz2u5ci/0JEJ7eLn1jtYJ2+wS1g==", + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, - "dependencies": { - "cheerio": "^1.0.0-rc.12" - }, "engines": { - "node": ">= 0.8.0" - }, - "peerDependencies": { - "grunt": ">=0.4.0" + "node": ">=0.3.1" } }, - "node_modules/grunt-shell": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-4.0.0.tgz", - "integrity": "sha512-dHFy8VZDfWGYLTeNvIHze4PKXGvIlDWuN0UE7hUZstTQeiEyv1VmW1MaDYQ3X5tE3bCi3bEia1gGKH8z/f1czQ==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "chalk": "^3.0.0", - "npm-run-path": "^2.0.0", - "strip-ansi": "^6.0.1" + "esutils": "^2.0.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - }, - "peerDependencies": { - "grunt": ">=1" + "node": ">=6.0.0" } }, - "node_modules/grunt-shell/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==", + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" } }, - "node_modules/grunt-shell/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==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/grunt-shell/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "domelementtype": "^2.3.0" }, "engines": { - "node": ">=8" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/grunt-shell/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==", + "node_modules/domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/grunt-shell/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==", + "node_modules/duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, - "node_modules/grunt-shell/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==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/grunt-shell/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==", + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, + "optional": true, "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "iconv-lite": "^0.6.2" } }, - "node_modules/grunt-shell/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==", + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "optional": true, "dependencies": { - "has-flag": "^4.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/grunt/node_modules/eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", - "dev": true - }, - "node_modules/grunt/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, + "node_modules/engine.io": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz", + "integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10.0.0" } }, - "node_modules/grunt/node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "engines": { + "node": ">=10.0.0" } }, - "node_modules/grunt/node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=10" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/grunt/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/grunt/node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/error": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", + "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, + "string-template": "~0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/grunt/node_modules/mkdirp": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", - "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==", - "dev": true, - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.8.0" } }, - "node_modules/grunt/node_modules/rimraf": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.1.2.tgz", - "integrity": "sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==", + "node_modules/eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, "bin": { - "rimraf": "dist/cjs/src/bin.js" + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^6.14.0 || ^8.10.0 || >=9.10.0" } }, - "node_modules/gruntify-eslint": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gruntify-eslint/-/gruntify-eslint-5.0.0.tgz", - "integrity": "sha512-pa2sXHK9+U4dCGdGSIMkpJARNwRStdLBsddNxmSHSSWROUdhWMrXvFWm6pj48zJhyV3Qy068VIuF1seYIvc0cw==", + "node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "dependencies": { - "eslint": "^5.0.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "grunt": ">=0.4.5" + "node": ">=4.0.0" } }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "node_modules/eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "dependencies": { - "duplexer": "^0.1.2" + "eslint-visitor-keys": "^1.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/gzip-size/node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, "engines": { - "node": ">= 0.4.0" + "node": ">=4" } }, - "node_modules/has-flag": { + "node_modules/eslint/node_modules/ansi-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/eslint/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, - "engines": { - "node": ">= 0.4" + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=4.8" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/eslint/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, "bin": { - "he": "bin/he" + "mkdirp": "bin/cmd.js" } }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "node_modules/eslint/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "dependencies": { - "parse-passwd": "^1.0.0" + "shebang-regex": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "node_modules/eslint/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "node_modules/eslint/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "dependencies": { - "lru-cache": "^7.5.1" + "ansi-regex": "^3.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "node_modules/eslint/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "entities": "^4.3.0" + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=6.0.0" } }, - "node_modules/http-errors/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=0.10" } }, - "node_modules/http-parser-js": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", - "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=4.0" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 6" + "node": ">=4.0" } }, - "node_modules/http-proxy/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, "engines": { - "node": ">= 6" + "node": ">=4.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "dependencies": { - "ms": "^2.0.0" + "engines": { + "node": ">=4.0" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { "node": ">=0.10.0" } }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "node_modules/eventemitter2": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", + "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true, "engines": { - "node": ">= 4" + "node": ">= 0.8.0" } }, - "node_modules/ignore-walk": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.1.tgz", - "integrity": "sha512-/c8MxUAqpRccq+LyDOecwF+9KqajueJHh8fz7g3YqjMZt+NSfJzx05zrKiXwa2sKwFCzaiZ5qUVfRj0pmxixEA==", + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "dependencies": { - "minimatch": "^6.1.6" + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", - "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/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==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "node_modules/inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "node_modules/faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "dependencies": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" + "websocket-driver": ">=0.5.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.4.0" } }, - "node_modules/interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, - "license": "MIT", "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">= 12" + "node": ">=4" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "flat-cache": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/filesize": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.3.0.tgz", + "integrity": "sha512-ytx0ruGpDHKWVoiui6+BY/QMNngtDQ/pJaFwfBpQif0J63+E8DLdFyqS3NkKQn7vIruUEpoGD9JUJSg7Kp+I0g==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "dependencies": { - "builtin-modules": "^3.3.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "2.0.0" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/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, - "bin": { - "is-docker": "cli.js" + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/findup-sync": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + }, "engines": { - "node": ">=4" + "node": ">= 10.13.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/is-lambda": { + "node_modules/flagged-respawn": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">= 0.10" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "engines": { - "node": ">=8" + "bin": { + "flat": "cli.js" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "node_modules/flat-cache/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "dependencies": { - "@types/estree": "*" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" } }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": ">=0.10.0" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "for-in": "^1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "dev": true, "dependencies": { - "is-docker": "^2.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/isbinaryfile": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", - "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "node_modules/fs-minipass": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.1.tgz", + "integrity": "sha512-MhaJDcFRTuLidHrIttu0RDGyyXs/IYHVmlcxfLAEFIWjc1vdLAkdwT7Ace2u7DbitWC0toKMl5eJZRYNVreIMw==", "dev": true, - "engines": { - "node": ">= 8.0.0" + "dependencies": { + "minipass": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "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/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "dev": true, "dependencies": { - "@isaacs/cliui": "^8.0.2" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "node_modules/gauge/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, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, "engines": { - "node": ">= 10.13.0" + "node": ">=8" } }, - "node_modules/jest-worker/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==", + "node_modules/gauge/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/gauge/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/jest-worker/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==", + "node_modules/gauge/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": { - "has-flag": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/gauge/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": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "ansi-regex": "^5.0.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "dependencies": { - "xmlcreate": "^2.0.4" + "engines": { + "node": ">=8" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsdoc": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", - "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", "dev": true, "dependencies": { - "@babel/parser": "^7.9.4", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" + "globule": "^1.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">= 4.0.0" } }, - "node_modules/jsdoc/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/jsdoc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jsdoc/node_modules/underscore": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", - "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", - "dev": true - }, - "node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "*" } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "node_modules/getobject": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.0.tgz", + "integrity": "sha512-tbUz6AKKKr2YiMB+fLWIgq5ZeBOobop9YMMAU9dC54/ot2ksMXt3DOFyBuhZw6ptcVszEykgByK20j7W9jHFag==", "dev": true, - "engines": [ - "node >= 0.2.0" - ] + "engines": { + "node": ">=10" + } }, - "node_modules/karma": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.0.tgz", - "integrity": "sha512-s8m7z0IF5g/bS5ONT7wsOavhW4i4aFkzD4u4wgzAQWT4HGUeWI3i21cK2Yz6jndMAeHETp5XuNsRoyGJZXVd4w==", + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 10" - } - }, - "node_modules/karma-chai": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", - "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", - "dev": true, - "peerDependencies": { - "chai": "*", - "karma": ">=0.10.9" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/karma-firefox-launcher": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz", - "integrity": "sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "is-wsl": "^2.2.0", - "which": "^2.0.1" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/karma-mocha": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", - "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "dependencies": { - "minimist": "^1.2.3" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/karma/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "dependencies": { - "minimist": "^1.2.5" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/karma/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { - "rimraf": "^3.0.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=8.17.0" + "bin": { + "which": "bin/which" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "node_modules/globule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.9" + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "node_modules/globule/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.8.0" + "node": "*" } }, - "node_modules/liftup": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", - "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/grunt": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.0.tgz", + "integrity": "sha512-dRcJXAaWLIt9khaZKfAgitjlFnEABGKT+jpyG/rlFxZd5kZkF7v4HvuoYIU7FjrG+BRDySwEHYrSYUHd5p9P4w==", "dev": true, "dependencies": { - "extend": "^3.0.2", - "findup-sync": "^4.0.0", - "fined": "^1.2.0", - "flagged-respawn": "^1.0.1", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.1", - "rechoir": "^0.7.0", - "resolve": "^1.19.0" + "dateformat": "~4.6.2", + "eventemitter2": "~0.4.13", + "exit": "~0.1.2", + "findup-sync": "~5.0.0", + "glob": "~8.1.0", + "grunt-cli": "~1.4.3", + "grunt-known-options": "~2.0.0", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.1", + "iconv-lite": "~0.6.3", + "js-yaml": "~3.14.0", + "minimatch": "~3.0.4", + "mkdirp": "~2.1.3", + "nopt": "~3.0.6", + "rimraf": "~4.1.2" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/grunt-cli": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", + "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", + "dev": true, + "dependencies": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "bin": { + "grunt": "bin/grunt" }, "engines": { "node": ">=10" } }, - "node_modules/liftup/node_modules/findup-sync": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", - "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "node_modules/grunt-cli/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^4.0.2", - "resolve-dir": "^1.0.1" + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/grunt-contrib-clean": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.0.tgz", + "integrity": "sha512-g5ZD3ORk6gMa5ugZosLDQl3dZO7cI3R14U75hTM+dVLVxdMNJCPVmwf9OUt4v4eWgpKKWWoVK9DZc1amJp4nQw==", + "dev": true, + "dependencies": { + "async": "^2.6.1", + "rimraf": "^2.6.2" }, "engines": { - "node": ">= 8" + "node": ">=6" + }, + "peerDependencies": { + "grunt": ">=0.4.5" } }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "node_modules/grunt-contrib-clean/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { - "uc.micro": "^1.0.1" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" } }, - "node_modules/livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", - "dev": true + "node_modules/grunt-contrib-watch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", + "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", + "dev": true, + "dependencies": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "engines": { + "node": ">=0.10.0" + } }, - "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==", + "node_modules/grunt-execute": { + "version": "0.2.2", + "resolved": "git+ssh://git@github.com/gruntjs-updater/grunt-execute.git#a828fc41e070759df038d1126b9bf842db34004c", + "dev": true, + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-jsdoc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", + "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "cross-spawn": "^7.0.1", + "jsdoc": "^3.6.3" + }, + "bin": { + "grunt-jsdoc": "bin/grunt-jsdoc" }, "engines": { - "node": ">=10" + "node": ">= 8.12.0" + } + }, + "node_modules/grunt-karma": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/grunt-karma/-/grunt-karma-4.0.2.tgz", + "integrity": "sha512-4+iBBkXZjHHMDAG5kpHCdDUqlSEBJ6sqouLMRf0p+QB8wGMs300DtaCQphHqd7pM3gpXoGVT3yRRsT7KOZpJMA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.10" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "grunt": ">=0.4.x", + "karma": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "node_modules/grunt-known-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", + "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/grunt-legacy-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", + "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.19" }, "engines": { - "node": ">=10" + "node": ">= 0.10.0" + } + }, + "node_modules/grunt-legacy-log-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", + "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", + "dev": true, + "dependencies": { + "chalk": "~4.1.0", + "lodash": "~4.17.19" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { + "node_modules/grunt-legacy-log-utils/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==", @@ -4648,7 +5008,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/log-symbols/node_modules/chalk": { + "node_modules/grunt-legacy-log-utils/node_modules/chalk": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", @@ -4664,7 +5024,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/log-symbols/node_modules/color-convert": { + "node_modules/grunt-legacy-log-utils/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==", @@ -4676,13 +5036,13 @@ "node": ">=7.0.0" } }, - "node_modules/log-symbols/node_modules/color-name": { + "node_modules/grunt-legacy-log-utils/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/log-symbols/node_modules/has-flag": { + "node_modules/grunt-legacy-log-utils/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==", @@ -4691,7 +5051,7 @@ "node": ">=8" } }, - "node_modules/log-symbols/node_modules/supports-color": { + "node_modules/grunt-legacy-log-utils/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==", @@ -4703,146 +5063,160 @@ "node": ">=8" } }, - "node_modules/log4js": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", - "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "node_modules/grunt-legacy-util": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", + "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", "dev": true, "dependencies": { - "date-format": "^4.0.3", - "debug": "^4.3.3", - "flatted": "^3.2.4", - "rfdc": "^1.3.0", - "streamroller": "^3.0.2" + "async": "~3.2.0", + "exit": "~0.1.2", + "getobject": "~1.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.21", + "underscore.string": "~3.3.5", + "which": "~2.0.2" }, "engines": { - "node": ">=8.0" + "node": ">=10" } }, - "node_modules/log4js/node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "node_modules/grunt-legacy-util/node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", "dev": true }, - "node_modules/loupe": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", - "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", + "node_modules/grunt-pipe": { + "version": "2.0.1", + "resolved": "git+ssh://git@github.com/RobotWebTools/grunt-pipe.git#d0937a52726f8f73df5d6d704d0519473150fb0e", + "integrity": "sha512-DPgn249Wea0hGLV8SHUGHk7Wdk9r4rY/L3tRHPSrYFRsCV9o8jR0P31wUXCEz2u5ci/0JEJ7eLn1jtYJ2+wS1g==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "cheerio": "^1.0.0-rc.12" + }, + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" } }, - "node_modules/lru-cache": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.17.0.tgz", - "integrity": "sha512-zSxlVVwOabhVyTi6E8gYv2cr6bXK+8ifYz5/uyJb9feXX6NACVDwY4p5Ut3WC3Ivo/QhpARHU3iujx2xGAYHbQ==", + "node_modules/grunt-shell": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-4.0.0.tgz", + "integrity": "sha512-dHFy8VZDfWGYLTeNvIHze4PKXGvIlDWuN0UE7hUZstTQeiEyv1VmW1MaDYQ3X5tE3bCi3bEia1gGKH8z/f1czQ==", "dev": true, + "dependencies": { + "chalk": "^3.0.0", + "npm-run-path": "^2.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "peerDependencies": { + "grunt": ">=1" } }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "node_modules/grunt-shell/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, - "dependencies": { - "sourcemap-codec": "^1.4.4" + "engines": { + "node": ">=8" } }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "node_modules/grunt-shell/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": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "node_modules/grunt-shell/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/make-fetch-happen/node_modules/brace-expansion": { + "node_modules/grunt-shell/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "node_modules/grunt-shell/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/grunt-shell/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/grunt-shell/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": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/make-fetch-happen/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/grunt-shell/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": { - "minipass": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/make-fetch-happen/node_modules/glob": { + "node_modules/grunt/node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "node_modules/grunt/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", @@ -4861,7 +5235,16 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/make-fetch-happen/node_modules/minimatch": { + "node_modules/grunt/node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/grunt/node_modules/glob/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", @@ -4873,1070 +5256,1033 @@ "node": ">=10" } }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/grunt/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/make-fetch-happen/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/grunt/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "node_modules/grunt/node_modules/mkdirp": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", + "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==", "dev": true, - "dependencies": { - "minipass": "^3.1.1" + "bin": { + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "node_modules/grunt/node_modules/rimraf": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.1.2.tgz", + "integrity": "sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==", "dev": true, - "dependencies": { - "unique-slug": "^3.0.0" + "bin": { + "rimraf": "dist/cjs/src/bin.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/make-fetch-happen/node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "node_modules/gruntify-eslint": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gruntify-eslint/-/gruntify-eslint-5.0.0.tgz", + "integrity": "sha512-pa2sXHK9+U4dCGdGSIMkpJARNwRStdLBsddNxmSHSSWROUdhWMrXvFWm6pj48zJhyV3Qy068VIuF1seYIvc0cw==", "dev": true, "dependencies": { - "imurmurhash": "^0.1.4" + "eslint": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=0.10.0" + }, + "peerDependencies": { + "grunt": ">=0.4.5" } }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", "dev": true, "dependencies": { - "kind-of": "^6.0.2" + "duplexer": "^0.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/gzip-size/node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "function-bind": "^1.1.1" }, - "bin": { - "markdown-it": "bin/markdown-it.js" + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/markdown-it-anchor": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.5.tgz", - "integrity": "sha512-PI1qEHHkTNWT+X6Ip9w+paonfIQ+QZP9sCeMYi47oqhH+EsW8CrJ8J7CzV19QVOj6il8ATGbK2nTECj22ZHGvQ==", + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, - "peerDependencies": { - "@types/markdown-it": "*", - "markdown-it": "*" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/markdown-it/node_modules/argparse": { + "node_modules/has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "bin": { + "he": "bin/he" } }, - "node_modules/marked": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz", - "integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==", + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, - "bin": { - "marked": "bin/marked.js" + "dependencies": { + "parse-passwd": "^1.0.0" }, "engines": { - "node": ">= 12" + "node": ">=0.10.0" } }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "node_modules/hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", "dev": true, "engines": { - "node": ">= 0.6" + "node": "*" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", "dev": true, "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "lru-cache": "^7.5.1" }, "engines": { - "node": ">=8.6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "node_modules/htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, "dependencies": { - "mime-db": "1.52.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "node_modules/http-errors/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">= 0.8" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "node_modules/http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", "dev": true }, - "node_modules/minipass": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.4.tgz", - "integrity": "sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==", + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">= 8" + "node": ">= 6" } }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" + "ms": "^2.0.0" } }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, "engines": { - "node": ">= 8" + "node": ">= 4" } }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/ignore-walk": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.1.tgz", + "integrity": "sha512-/c8MxUAqpRccq+LyDOecwF+9KqajueJHh8fz7g3YqjMZt+NSfJzx05zrKiXwa2sKwFCzaiZ5qUVfRj0pmxixEA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "minimatch": "^6.1.6" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/minipass-json-stream/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", + "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=0.8.19" } }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "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": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "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/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "dev": true, "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" }, "engines": { - "node": ">= 8" + "node": ">=6.0.0" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "node_modules/ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/mocha": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", - "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" }, "engines": { - "node": ">= 14.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dependencies": { + "has": "^1.0.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/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==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=4" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", "dev": true }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" } }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" + "is-unc-path": "^1.0.0" }, "engines": { - "node": "^12.13 || ^14.13 || >=16" + "node": ">=0.10.0" } }, - "node_modules/node-gyp/node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" + "unc-path-regex": "^0.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=0.10.0" } }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "dependencies": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" + "is-docker": "^2.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/npm-bundled": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", - "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, "dependencies": { - "npm-normalize-package-bin": "^3.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 10.13.0" } }, - "node_modules/npm-install-checks": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.0.0.tgz", - "integrity": "sha512-SBU9oFglRVZnfElwAtF14NivyulDqF1VKqqwNsFW9HDcbHMAPHpRSsVFgKuwFGq/hVvWZExz62Th0kvxn/XE7Q==", + "node_modules/jest-worker/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, - "dependencies": { - "semver": "^7.1.1" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/npm-install-checks/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/jest-worker/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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz", - "integrity": "sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "dev": true, "dependencies": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "xmlcreate": "^2.0.4" } }, - "node_modules/npm-package-arg/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/jsdoc": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", + "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", "dev": true, - "license": "ISC", + "dependencies": { + "@babel/parser": "^7.9.4", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.2" + }, "bin": { - "semver": "bin/semver.js" + "jsdoc": "jsdoc.js" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" } }, - "node_modules/npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "dependencies": { - "ignore-walk": "^6.0.0" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/npm-pick-manifest": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", - "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", + "node_modules/jsdoc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-pick-manifest/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", + "node_modules/jsdoc/node_modules/underscore": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", + "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "jsesc": "bin/jsesc" } }, - "node_modules/npm-registry-fetch": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.3.tgz", - "integrity": "sha512-YaeRbVNpnWvsGOjX2wk5s85XJ7l1qQBGAp724h8e2CZFFhMSuw9enom7K1mWVUtvXO1uUSFIAPofQK0pPN0ZcA==", + "node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", "dev": true, - "dependencies": { - "make-fetch-happen": "^11.0.0", - "minipass": "^4.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", - "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^4.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", - "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "dependencies": { - "minipass": "^4.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "universalify": "^2.0.0" }, "optionalDependencies": { - "encoding": "^0.1.13" + "graceful-fs": "^4.1.6" } }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } + "engines": [ + "node >= 0.2.0" + ] }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "node_modules/karma": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.0.tgz", + "integrity": "sha512-s8m7z0IF5g/bS5ONT7wsOavhW4i4aFkzD4u4wgzAQWT4HGUeWI3i21cK2Yz6jndMAeHETp5XuNsRoyGJZXVd4w==", "dev": true, "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" + "bin": { + "karma": "bin/karma" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "node_modules/karma-chai": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "chai": "*", + "karma": ">=0.10.9" } }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "node_modules/karma-firefox-launcher": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz", + "integrity": "sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==", "dev": true, "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "is-wsl": "^2.2.0", + "which": "^2.0.1" } }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "node_modules/karma-mocha": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", + "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", "dev": true, "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "minimist": "^1.2.3" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "node_modules/karma/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "minimist": "^1.2.5" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "node_modules/karma/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "dependencies": { - "ee-first": "1.1.1" + "rimraf": "^3.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8.17.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "dependencies": { - "wrappy": "1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "dev": true, "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" + "graceful-fs": "^4.1.9" } }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "type-check": "~0.3.2" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "node_modules/liftup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", + "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", "dev": true, + "dependencies": { + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "node_modules/liftup/node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dev": true, "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "uc.micro": "^1.0.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==", + "node_modules/livereload-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", + "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", + "dev": true + }, + "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": { - "yocto-queue": "^0.1.0" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" @@ -5945,14 +6291,26 @@ "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==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" - }, + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, "engines": { "node": ">=10" }, @@ -5960,2335 +6318,4681 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/log-symbols/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": { - "aggregate-error": "^3.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pacote": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.1.1.tgz", - "integrity": "sha512-eeqEe77QrA6auZxNHIp+1TzHQ0HBKf5V6c8zcaYZ134EJe1lCi+fjXATkNiEEfbG+e50nu02GLvUtmZcGOYabQ==", + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "dependencies": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^4.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" + "node": ">=10" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "node_modules/log-symbols/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": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.8" + "node": ">=7.0.0" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "node_modules/log-symbols/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/log-symbols/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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "node_modules/log-symbols/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": { - "entities": "^4.4.0" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "node_modules/log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", "dev": true, "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=8.0" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/log4js/node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/loupe": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", + "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", "dev": true, - "engines": { - "node": ">= 0.8" + "dependencies": { + "get-func-name": "^2.0.0" } }, - "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==", + "node_modules/lru-cache": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.17.0.tgz", + "integrity": "sha512-zSxlVVwOabhVyTi6E8gYv2cr6bXK+8ifYz5/uyJb9feXX6NACVDwY4p5Ut3WC3Ivo/QhpARHU3iujx2xGAYHbQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" } }, - "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=", + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "sourcemap-codec": "^1.4.4" } }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "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==", + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "dependencies": { - "path-root-regex": "^0.1.0" + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "node_modules/make-fetch-happen/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "node_modules/make-fetch-happen/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" }, "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, "engines": { - "node": "*" + "node": ">= 8" } }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/make-fetch-happen/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pngparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pngparse/-/pngparse-2.0.1.tgz", - "integrity": "sha1-hoUt5N40n077HoUudSVlXlrF37g=" - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "node_modules/make-fetch-happen/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "node_modules/make-fetch-happen/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "node_modules/make-fetch-happen/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, "engines": { - "node": ">=0.9" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "unique-slug": "^3.0.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/make-fetch-happen/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, + "imurmurhash": "^0.1.4" + }, "engines": { - "node": ">= 0.6" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "kind-of": "^6.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/read-package-json": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.0.tgz", - "integrity": "sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w==", + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true, - "dependencies": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "dev": true, "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "node_modules/read-package-json/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/markdown-it-anchor": { + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.5.tgz", + "integrity": "sha512-PI1qEHHkTNWT+X6Ip9w+paonfIQ+QZP9sCeMYi47oqhH+EsW8CrJ8J7CzV19QVOj6il8ATGbK2nTECj22ZHGvQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" } }, - "node_modules/read-package-json/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/read-package-json/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/marked": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz", + "integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" + "bin": { + "marked": "bin/marked.js" }, "engines": { - "node": ">=10" + "node": ">= 12" } }, - "node_modules/readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, "engines": { - "node": ">= 6" + "node": ">= 0.6" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "picomatch": "^2.2.1" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=8.10.0" + "node": ">=8.6" } }, - "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true, - "dependencies": { - "resolve": "^1.9.0" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 0.10" + "node": ">=4.0.0" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "regenerate": "^1.4.0" + "mime-db": "1.52.0" }, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - }, - "node_modules/regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true, "engines": { - "node": ">=6.5.0" + "node": ">=4" } }, - "node_modules/regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "node_modules/regjsparser": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", - "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "node_modules/minipass": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.4.tgz", + "integrity": "sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==", "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" + "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=", + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "node_modules/requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "lodash": "^4.17.14" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, "engines": { - "node": ">=4" + "node": ">= 8" } }, - "node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "yallist": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", "dev": true, - "engines": { - "node": ">= 4" + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" } }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "yallist": "^4.0.0" }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8" } }, - "node_modules/rollup": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz", - "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==", + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, - "bin": { - "rollup": "dist/bin/rollup" + "dependencies": { + "minipass": "^3.0.0" }, "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=8" } }, - "node_modules/rollup-plugin-filesize": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-filesize/-/rollup-plugin-filesize-10.0.0.tgz", - "integrity": "sha512-JAYYhzCcmGjmCzo3LEHSDE3RAPHKIeBdpqRhiyZSv5o/3wFhktUOzYAWg/uUKyEu5dEaVaql6UOmaqHx1qKrZA==", + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "@babel/runtime": "^7.13.8", - "boxen": "^5.0.0", - "brotli-size": "4.0.0", - "colors": "1.4.0", - "filesize": "^6.1.0", - "gzip-size": "^6.0.0", - "pacote": "^15.1.1", - "terser": "^5.6.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=8" } }, - "node_modules/rollup-plugin-filesize/node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, "engines": { - "node": ">=0.1.90" + "node": ">=8" } }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" + "yallist": "^4.0.0" }, - "peerDependencies": { - "rollup": "^2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "dependencies": { - "randombytes": "^2.1.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/roslib": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/roslib/-/roslib-1.4.1.tgz", - "integrity": "sha512-l3BOHqG99RHb73XROykj8o2rRaUqqYwN0E6C1EkH+R1GIfDjMaUGPaCNEoKKmsXT0Vu0EOyL1BudQtdVlMsgjA==", + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { - "@xmldom/xmldom": "^0.8.0", - "cbor-js": "^0.1.0", - "eventemitter2": "^6.4.0", - "object-assign": "^4.0.0", - "pngparse": "^2.0.0", - "socket.io": "^4.0.0", - "webworkify": "^1.5.0", - "webworkify-webpack": "^2.1.5", - "ws": "^8.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=0.10" + "node": ">=8" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, "engines": { - "node": ">=0.12.0" + "node": ">=10" } }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" + "node_modules/mocha": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" }, "engines": { - "npm": ">=2.0.0" + "node": ">= 14.0.0" } }, - "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/safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", - "dev": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "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==", + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/mocha/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/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sigstore": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.0.0.tgz", - "integrity": "sha512-e+qfbn/zf1+rCza/BhIA//Awmf0v1pa5HQS8Xk8iXrn9bgytytVLqYD0P7NSqZ6IELTgq+tcDvLPkQjNHyWLNg==", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "dependencies": { - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.0.0" - }, - "bin": { - "sigstore": "bin/sigstore.js" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/sigstore/node_modules/make-fetch-happen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", - "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", + "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^4.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/sigstore/node_modules/minipass-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", - "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "minipass": "^4.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" }, - "optionalDependencies": { - "encoding": "^0.1.13" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">= 0.6" } }, - "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-gyp": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "dev": true, "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.5.2", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">=10.2.0" + "node": "^12.13 || ^14.13 || >=16" } }, - "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "node_modules/node-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "node_modules/node-gyp/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" }, "engines": { - "node": ">=10.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "node_modules/node-gyp/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, - "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">=10" } }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "abbrev": "1" }, - "engines": { - "node": ">= 10" + "bin": { + "nopt": "bin/nopt.js" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/ssri": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.1.tgz", - "integrity": "sha512-WVy6di9DlPOeBWEjMScpNipeSX2jIZBGEn5Uuo8Q7aIuFEuDX0pw8RxcOjlD1TWP4obi24ki7m/13+nFpcbXrw==", + "node_modules/npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", "dev": true, "dependencies": { - "minipass": "^4.0.0" + "npm-normalize-package-bin": "^3.0.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "node_modules/npm-install-checks": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.0.0.tgz", + "integrity": "sha512-SBU9oFglRVZnfElwAtF14NivyulDqF1VKqqwNsFW9HDcbHMAPHpRSsVFgKuwFGq/hVvWZExz62Th0kvxn/XE7Q==", "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, "engines": { - "node": ">= 0.6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/streamroller": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", - "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "node_modules/npm-install-checks/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "date-format": "^4.0.3", - "debug": "^4.1.1", - "fs-extra": "^10.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=10" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/npm-normalize-package-bin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz", + "integrity": "sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==", "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, "engines": { - "node": ">=4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/string-width-cjs": { - "name": "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==", + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/string-width-cjs/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==", + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/string-width-cjs/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/string-width-cjs/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==", + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/string-width-cjs/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==", + "node_modules/npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "ignore-walk": "^6.0.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "node_modules/npm-pick-manifest": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", "dev": true, - "license": "MIT", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, "engines": { - "node": ">=4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/npm-pick-manifest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/npm-registry-fetch": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.3.tgz", + "integrity": "sha512-YaeRbVNpnWvsGOjX2wk5s85XJ7l1qQBGAp724h8e2CZFFhMSuw9enom7K1mWVUtvXO1uUSFIAPofQK0pPN0ZcA==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "make-fetch-happen": "^11.0.0", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/strip-ansi-cjs/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==", + "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", + "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", + "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", "dev": true, + "dependencies": { + "minipass": "^4.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "path-key": "^2.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "dev": true, "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" }, "engines": { - "node": ">=6.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", - "dev": true - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "isobject": "^3.0.1" }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/three": { - "version": "0.89.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.89.0.tgz", - "integrity": "sha512-Evv3JolLQtag/lCWu1o3cgz2E5UYCSZHbh9lfBjeLz7nlK8DMmASID680Odl++ZPYk63rrZjPAMq88IrMP3GCA==" - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "dependencies": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/tiny-lr/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { - "ms": "^2.1.1" + "wrappy": "1" } }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "dependencies": { - "os-tmpdir": "~1.0.2" + "mimic-fn": "^1.0.0" }, "engines": { - "node": ">=0.6.0" + "node": ">=4" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "dependencies": { - "is-number": "^7.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" }, "engines": { - "node": ">=8.0" + "node": ">= 0.8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "engines": { - "node": ">=0.6" + "node": ">=0.10.0" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tuf-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.0.0.tgz", - "integrity": "sha512-1dxsQwESDzACJjTdYHQ4wJ1f/of7jALWKfJEHSBWUQB/5UTJUx9SW6GHXp4mZ1KvdBRJCpGjssoPFGi4hvw8/A==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, - "dependencies": { - "make-fetch-happen": "^11.0.1", - "minimatch": "^6.1.0" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/tuf-js/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, - "node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", - "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", + "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": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^4.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tuf-js/node_modules/minimatch": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", - "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", + "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": { - "brace-expansion": "^2.0.1" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", - "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "dependencies": { - "minipass": "^4.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "aggregate-error": "^3.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" }, - "optionalDependencies": { - "encoding": "^0.1.13" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "node_modules/pacote": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.1.1.tgz", + "integrity": "sha512-eeqEe77QrA6auZxNHIp+1TzHQ0HBKf5V6c8zcaYZ134EJe1lCi+fjXATkNiEEfbG+e50nu02GLvUtmZcGOYabQ==", "dev": true, "dependencies": { - "prelude-ls": "~1.1.2" + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^4.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" }, "engines": { - "node": ">= 0.8.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true, "engines": { - "node": ">=10" + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "domhandler": "^5.0.2", + "parse5": "^7.0.0" }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/ua-parser-js": { - "version": "0.7.33", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", - "integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==", + "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, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "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-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "dependencies": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" + "path-root-regex": "^0.1.0" }, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "engines": { - "node": ">=4" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "node_modules/pngparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pngparse/-/pngparse-2.0.1.tgz", + "integrity": "sha1-hoUt5N40n077HoUudSVlXlrF37g=" + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/unique-filename": { + "node_modules/proc-log": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "dev": true, - "dependencies": { - "unique-slug": "^4.0.0" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.4.0" } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "engines": { + "node": ">=6" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true, "engines": { - "node": ">= 0.4.0" + "node": ">=0.9" } }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, "dependencies": { - "homedir-polyfill": "^1.0.1" + "side-channel": "^1.0.4" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" + "safe-buffer": "^5.1.0" } }, - "node_modules/void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dev": true, "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.8" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "node_modules/read-package-json": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.0.tgz", + "integrity": "sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w==", "dev": true, + "dependencies": { + "glob": "^8.0.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, "engines": { - "node": ">=0.8.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/webworkify": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", - "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==" - }, - "node_modules/webworkify-webpack": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz", - "integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "balanced-match": "^1.0.0" } }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "node_modules/read-package-json/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { - "string-width": "^4.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/widest-line/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==", + "node_modules/read-package-json/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "license": "MIT", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/widest-line/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/widest-line/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==", + "node_modules/readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", + "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/widest-line/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=8" + "node": ">=8.10.0" } }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "resolve": "^1.9.0" }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, - "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==", + "node_modules/regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "regenerate": "^1.4.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=4" } }, - "node_modules/wrap-ansi-cjs": { - "name": "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/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/wrap-ansi-cjs/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/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" } }, - "node_modules/wrap-ansi-cjs/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==", + "node_modules/regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6.5.0" } }, - "node_modules/wrap-ansi-cjs/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==", + "node_modules/regexpu-core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=4" } }, - "node_modules/wrap-ansi-cjs/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/wrap-ansi-cjs/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==", + "node_modules/regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", "dev": true }, - "node_modules/wrap-ansi-cjs/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/wrap-ansi-cjs/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==", + "node_modules/regjsparser": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", + "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "jsesc": "~0.5.0" }, - "engines": { - "node": ">=8" + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/wrap-ansi-cjs/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==", + "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, - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi/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==", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "lodash": "^4.17.14" } }, - "node_modules/wrap-ansi/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, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dependencies": { - "color-convert": "^2.0.1" + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "resolve": "bin/resolve" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wrap-ansi/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==", + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, - "node_modules/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "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": { - "mkdirp": "^0.5.1" + "glob": "^7.1.3" }, - "engines": { - "node": ">=4" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/write/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, + "node_modules/rollup": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz", + "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==", + "devOptional": true, "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "rollup": "dist/bin/rollup" + }, "engines": { "node": ">=10.0.0" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true + "node_modules/rollup-plugin-filesize": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-filesize/-/rollup-plugin-filesize-10.0.0.tgz", + "integrity": "sha512-JAYYhzCcmGjmCzo3LEHSDE3RAPHKIeBdpqRhiyZSv5o/3wFhktUOzYAWg/uUKyEu5dEaVaql6UOmaqHx1qKrZA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.8", + "boxen": "^5.0.0", + "brotli-size": "4.0.0", + "colors": "1.4.0", + "filesize": "^6.1.0", + "gzip-size": "^6.0.0", + "pacote": "^15.1.1", + "terser": "^5.6.0" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/rollup-plugin-filesize/node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=0.1.90" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", "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" + "randombytes": "^2.1.0" + } + }, + "node_modules/roslib": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/roslib/-/roslib-1.4.1.tgz", + "integrity": "sha512-l3BOHqG99RHb73XROykj8o2rRaUqqYwN0E6C1EkH+R1GIfDjMaUGPaCNEoKKmsXT0Vu0EOyL1BudQtdVlMsgjA==", + "dependencies": { + "@xmldom/xmldom": "^0.8.0", + "cbor-js": "^0.1.0", + "eventemitter2": "^6.4.0", + "object-assign": "^4.0.0", + "pngparse": "^2.0.0", + "socket.io": "^4.0.0", + "webworkify": "^1.5.0", + "webworkify-webpack": "^2.1.5", + "ws": "^8.0.0" }, "engines": { - "node": ">=10" + "node": ">=0.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==", + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=0.12.0" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "tslib": "^1.9.0" }, "engines": { - "node": ">=10" + "npm": ">=2.0.0" } }, - "node_modules/yargs/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==", + "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/safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "bin": { + "semver": "bin/semver" } }, - "node_modules/yargs/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==", + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "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/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "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/yargs/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sigstore": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.0.0.tgz", + "integrity": "sha512-e+qfbn/zf1+rCza/BhIA//Awmf0v1pa5HQS8Xk8iXrn9bgytytVLqYD0P7NSqZ6IELTgq+tcDvLPkQjNHyWLNg==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "make-fetch-happen": "^11.0.1", + "tuf-js": "^1.0.0" + }, + "bin": { + "sigstore": "bin/sigstore.js" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "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==", + "node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", + "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/minipass-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", + "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz", + "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.1.tgz", + "integrity": "sha512-WVy6di9DlPOeBWEjMScpNipeSX2jIZBGEn5Uuo8Q7aIuFEuDX0pw8RxcOjlD1TWP4obi24ki7m/13+nFpcbXrw==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "dev": true + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "node_modules/tar": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/three": { + "version": "0.167.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.167.0.tgz", + "integrity": "sha512-9Y1a66fpjqF3rhq7ivKTaKtjQLZ97Hj/lZ00DmZWaKHaQFH4uzYT1znwRDWQOcgMmCcOloQzo61gDmqO8l9xmA==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "dev": true, + "dependencies": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "node_modules/tiny-lr/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tuf-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.0.0.tgz", + "integrity": "sha512-1dxsQwESDzACJjTdYHQ4wJ1f/of7jALWKfJEHSBWUQB/5UTJUx9SW6GHXp4mZ1KvdBRJCpGjssoPFGi4hvw8/A==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^11.0.1", + "minimatch": "^6.1.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", + "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/minimatch": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", + "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tuf-js/node_modules/minipass-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", + "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", + "dev": true, + "dependencies": { + "minipass": "^4.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.33", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", + "integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/underscore.string": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", + "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "dev": true, + "dependencies": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/webworkify": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", + "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==" + }, + "node_modules/webworkify-webpack": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz", + "integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==" + }, + "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/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/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/widest-line/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/widest-line/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "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/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrap-ansi/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "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/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/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.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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/yargs/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/yargs/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "dev": true, + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "requires": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==" + }, + "@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "requires": { + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "requires": { + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "requires": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "requires": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", + "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.0", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "requires": { + "jsesc": "~0.5.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "requires": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + } + }, + "@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "requires": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "requires": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "requires": { + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "requires": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "requires": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + } + }, + "@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==" + }, + "@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==" + }, + "@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==" + }, + "@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "requires": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + } + }, + "@babel/helpers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "requires": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" + } + }, + "@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "requires": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + } + }, + "@babel/parser": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", + "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==" + }, + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.0.tgz", + "integrity": "sha512-dG0aApncVQwAUJa8tP1VHTnmU67BeIQvKafd3raEx315H54FfkZSz3B/TT+33ZQAjatGJA79gZqTtqL5QZUKXw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + } + }, + "@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + } + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "requires": {} + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", + "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "requires": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", + "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.0", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "requires": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "requires": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "requires": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "requires": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "requires": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "requires": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "requires": { - "@babel/highlight": "^7.12.13" + "@babel/helper-plugin-utils": "^7.24.7" } }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true + "@babel/plugin-transform-runtime": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "requires": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.8" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + } + }, + "@babel/preset-env": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.2.tgz", + "integrity": "sha512-Y2Vkwy3ITW4id9c6KXshVV/x5yCGK7VdJmKkzOzNsDZMojRKfSA/033rRbLqlRozmhRXCejxWHLSJOg/wUHfzw==", + "requires": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.0", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.0", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.0", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" }, "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, - "@babel/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q==", - "dev": true + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "@babel/runtime": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", - "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", - "dev": true, + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + } + }, + "@babel/traverse": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.2.tgz", + "integrity": "sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==", + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "requires": { - "regenerator-runtime": "^0.13.4" + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" } }, "@colors/colors": { @@ -8303,93 +11007,25 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, "@jridgewell/source-map": { "version": "0.3.2", @@ -8402,19 +11038,17 @@ } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", - "dev": true, + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@npmcli/fs": { @@ -8426,11 +11060,23 @@ "semver": "^7.3.5" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -8452,10 +11098,24 @@ }, "dependencies": { "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } }, "which": { "version": "3.0.0", @@ -8538,12 +11198,26 @@ } } }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true + "@rollup/plugin-babel": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", + "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@rollup/pluginutils": "^5.0.1" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + } + } }, "@rollup/plugin-buble": { "version": "1.0.0", @@ -8557,15 +11231,15 @@ } }, "@rollup/plugin-commonjs": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", - "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", "dev": true, "requires": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", - "glob": "^10.4.1", + "glob": "^8.0.3", "is-reference": "1.2.1", "magic-string": "^0.30.3" }, @@ -8591,41 +11265,35 @@ } }, "glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" } }, "magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, "requires": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true } } }, @@ -8667,9 +11335,9 @@ } }, "@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "@tootallnate/once": { "version": "2.0.0", @@ -8692,9 +11360,9 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", "requires": { "@types/node": "*" } @@ -8702,8 +11370,7 @@ "@types/estree": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" }, "@types/linkify-it": { "version": "3.0.2", @@ -8843,9 +11510,9 @@ } }, "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-escapes": { @@ -8855,16 +11522,15 @@ "dev": true }, "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -8937,6 +11603,40 @@ "lodash": "^4.17.14" } }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -9071,9 +11771,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -9170,12 +11870,12 @@ } }, "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "fill-range": "^7.1.1" + "fill-range": "^7.0.1" } }, "brotli-size": { @@ -9193,6 +11893,17 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "requires": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + } + }, "buble": { "version": "0.20.0", "resolved": "https://registry.npmjs.org/buble/-/buble-0.20.0.tgz", @@ -9229,11 +11940,23 @@ "semver": "^7.0.0" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -9319,6 +12042,11 @@ "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001645", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001645.tgz", + "integrity": "sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==" + }, "catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -9352,7 +12080,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -9461,9 +12188,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "emoji-regex": { @@ -9504,7 +12231,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -9512,8 +12238,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-support": { "version": "1.1.3", @@ -9592,11 +12317,24 @@ "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", "dev": true }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, "cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, + "core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "requires": { + "browserslist": "^4.23.0" + } + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -9655,9 +12393,9 @@ "dev": true }, "debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -9720,9 +12458,9 @@ "dev": true }, "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "doctrine": { @@ -9789,18 +12527,17 @@ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -9836,9 +12573,9 @@ } }, "engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz", + "integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==", "requires": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -9848,14 +12585,14 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" } }, "engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==" + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==" }, "ent": { "version": "2.2.0", @@ -9891,10 +12628,9 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==" }, "escape-html": { "version": "1.0.3", @@ -9905,8 +12641,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { "version": "5.16.0", @@ -9953,9 +12688,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "cross-spawn": { @@ -10106,14 +12841,12 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "eventemitter2": { "version": "6.4.5", @@ -10121,9 +12854,10 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" }, "eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true }, "exit": { "version": "0.1.2", @@ -10209,9 +12943,9 @@ "dev": true }, "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -10345,24 +13079,6 @@ "for-in": "^1.0.1" } }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - } - } - }, "fs-extra": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", @@ -10399,8 +13115,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -10473,6 +13188,11 @@ "globule": "^1.0.0" } }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -10480,9 +13200,9 @@ "dev": true }, "get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, "get-intrinsic": { @@ -10563,8 +13283,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "globule": { "version": "1.3.2", @@ -10989,7 +13708,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -10997,8 +13715,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.3", @@ -11102,14 +13819,6 @@ "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" - }, - "dependencies": { - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - } } }, "http-proxy-agent": { @@ -11263,23 +13972,11 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, - "ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "requires": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - } - } + "ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true }, "is-absolute": { "version": "1.0.0", @@ -11313,7 +14010,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -11444,16 +14140,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, "jest-worker": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", @@ -11482,6 +14168,11 @@ } } }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -11501,12 +14192,6 @@ "xmlcreate": "^2.0.4" } }, - "jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true - }, "jsdoc": { "version": "3.6.11", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", @@ -11553,8 +14238,7 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" }, "json-parse-even-better-errors": { "version": "3.0.0", @@ -11574,6 +14258,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -11753,6 +14442,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -11968,12 +14662,26 @@ "yallist": "^4.0.0" } }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "ssri": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", @@ -12284,31 +14992,31 @@ "dev": true }, "mocha": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", - "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, + "requires": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "dependencies": { "argparse": { @@ -12352,9 +15060,9 @@ } }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -12440,6 +15148,15 @@ "which": "^2.0.2" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -12450,13 +15167,21 @@ } }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, + "node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -12478,11 +15203,23 @@ "validate-npm-package-license": "^3.0.4" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -12510,11 +15247,23 @@ "semver": "^7.1.1" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -12536,11 +15285,23 @@ "validate-npm-package-name": "^5.0.0" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -12565,11 +15326,23 @@ "semver": "^7.3.5" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -12899,8 +15672,7 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-root": { "version": "0.1.1", @@ -12917,41 +15689,21 @@ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, - "path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "dev": true - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pngparse": { "version": "2.0.1", @@ -13127,8 +15879,7 @@ "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { "version": "8.2.0", @@ -13140,10 +15891,17 @@ } }, "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "requires": { + "@babel/runtime": "^7.8.4" + } }, "regexpp": { "version": "2.0.1", @@ -13205,7 +15963,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -13263,7 +16020,7 @@ "version": "2.79.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz", "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==", - "dev": true, + "devOptional": true, "requires": { "fsevents": "~2.3.2" } @@ -13365,15 +16122,15 @@ "dev": true }, "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -13488,44 +16245,42 @@ "dev": true }, "socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", - "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.4.1", "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" + "socket.io-parser": "~4.2.1" } }, "socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", "requires": { - "debug": "~4.3.4", - "ws": "~8.17.1" + "ws": "~8.11.0" } }, "socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz", + "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, "socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, "requires": { - "ip-address": "^9.0.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" } }, @@ -13652,9 +16407,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "strip-ansi": { @@ -13668,46 +16423,6 @@ } } }, - "string-width-cjs": { - "version": "npm:string-width@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" - }, - "dependencies": { - "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 - }, - "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 - }, - "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 - }, - "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" - } - } - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -13717,23 +16432,6 @@ "ansi-regex": "^4.1.0" } }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@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" - }, - "dependencies": { - "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 - } - } - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -13744,7 +16442,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -13752,8 +16449,7 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "table": { "version": "5.4.6", @@ -13783,18 +16479,18 @@ "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "dev": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", + "minipass": "^4.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -13819,12 +16515,6 @@ } } } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true } } }, @@ -13855,9 +16545,9 @@ "dev": true }, "three": { - "version": "0.89.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.89.0.tgz", - "integrity": "sha512-Evv3JolLQtag/lCWu1o3cgz2E5UYCSZHbh9lfBjeLz7nlK8DMmASID680Odl++ZPYk63rrZjPAMq88IrMP3GCA==" + "version": "0.167.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.167.0.tgz", + "integrity": "sha512-9Y1a66fpjqF3rhq7ivKTaKtjQLZ97Hj/lZ00DmZWaKHaQFH4uzYT1znwRDWQOcgMmCcOloQzo61gDmqO8l9xmA==" }, "through": { "version": "2.3.8", @@ -13899,6 +16589,11 @@ "os-tmpdir": "~1.0.2" } }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -14102,6 +16797,15 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "requires": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -14217,9 +16921,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "emoji-regex": { @@ -14263,9 +16967,9 @@ "dev": true }, "workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", "dev": true }, "wrap-ansi": { @@ -14280,9 +16984,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -14343,81 +17047,6 @@ } } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@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" - }, - "dependencies": { - "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" - } - }, - "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 - }, - "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 - }, - "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 - }, - "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" - } - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -14445,9 +17074,9 @@ } }, "ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "requires": {} }, "xmlcreate": { @@ -14484,9 +17113,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "emoji-regex": { @@ -14524,9 +17153,9 @@ } }, "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==", + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true }, "yargs-unparser": { diff --git a/package.json b/package.json index 411fbf4e..9ee45c4c 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,18 @@ "main": "./build/ros3d.cjs.js", "module": "./build/ros3d.esm.js", "dependencies": { - "eventemitter3": "^5.0.1", + "@babel/core": "^7.25.2", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/preset-env": "^7.25.2", + "@babel/runtime": "^7.25.0", + "@rollup/plugin-babel": "^6.0.4", + "eventemitter2": "^6.4.0", "roslib": "^1.0.0", - "three": "^0.89.0" + "three": "^0.167.0" }, "devDependencies": { "@rollup/plugin-buble": "^1.0.0", - "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.0.0", "chai": "^4.3.0", "debug": "^4.3.0", diff --git a/rollup.config.js b/rollup.config.js index 349f5f41..befaf40d 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,15 +1,15 @@ const rollup = require('rollup'); -// plugin that transpiles output into commonjs format +// Plugin that transpiles output into commonjs format const commonjs = require('@rollup/plugin-commonjs'); -// plugin that transpiles es6 to es5 for legacy platforms -const buble = require('@rollup/plugin-buble'); -// plugin that shows output file info +// Plugin that shows output file info const filesize = require('rollup-plugin-filesize'); -/// plugin that resolves node module imports +// Plugin that resolves node module imports const { nodeResolve } = require('@rollup/plugin-node-resolve'); -// plugin that minifies and obfuscates code +// Plugin that minifies and obfuscates code const { terser } = require('rollup-plugin-terser'); +// Plugin that transpiles ES6+ code to ES5 +const babel = require('@rollup/plugin-babel').babel; const pkg = require('./package.json'); const input = 'src-esm/index.js'; @@ -46,8 +46,13 @@ export default [ ], plugins: [ nodeResolve({ browser: true }), - commonjs(), - buble(), + commonjs({ transformMixedEsModules: true }), + babel({ + babelHelpers: 'runtime', + exclude: 'node_modules/**', // only transpile our source code + presets: ['@babel/preset-env'], + plugins: ['@babel/plugin-transform-runtime'] + }), filesize(), ], }, @@ -67,8 +72,13 @@ export default [ ], plugins: [ nodeResolve({ browser: true }), - commonjs(), - buble(), + commonjs({ transformMixedEsModules: true }), + babel({ + babelHelpers: 'runtime', + exclude: 'node_modules/**', // only transpile our source code + presets: ['@babel/preset-env'], + plugins: ['@babel/plugin-transform-runtime'] + }), filesize(), ], }, @@ -90,7 +100,13 @@ export default [ ], plugins: [ nodeResolve({ browser: true }), - commonjs(), + commonjs({ transformMixedEsModules: true }), + babel({ + babelHelpers: 'runtime', + exclude: 'node_modules/**', // only transpile our source code + presets: ['@babel/preset-env'], + plugins: ['@babel/plugin-transform-runtime'] + }), filesize(), ], }, @@ -113,8 +129,14 @@ export default [ plugins: [ nodeResolve({ browser: true }), commonjs(), + babel({ + babelHelpers: 'runtime', + exclude: 'node_modules/**', // only transpile our source code + presets: ['@babel/preset-env'], + plugins: ['@babel/plugin-transform-runtime'] + }), filesize(), terser(), ], }, -]; +]; \ No newline at end of file diff --git a/shims/three/ColladaLoader.js b/shims/three/ColladaLoader.js index 049b27fe..215c8242 100644 --- a/shims/three/ColladaLoader.js +++ b/shims/three/ColladaLoader.js @@ -1,3478 +1,4117 @@ -/** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - * @Modified by Jihoon Lee from ColladerLoader.js@r88 - * To support rviz compatible collada viewing. - * See: #202 why it is forked. - * - * It is a fork from ColladerLoader.js in three.js. It follows three.js license. - */ +import { + AmbientLight, + AnimationClip, + Bone, + BufferGeometry, + ClampToEdgeWrapping, + Color, + DirectionalLight, + DoubleSide, + FileLoader, + Float32BufferAttribute, + FrontSide, + Group, + Line, + LineBasicMaterial, + LineSegments, + Loader, + LoaderUtils, + MathUtils, + Matrix4, + Mesh, + MeshBasicMaterial, + MeshLambertMaterial, + MeshPhongMaterial, + OrthographicCamera, + PerspectiveCamera, + PointLight, + Quaternion, + QuaternionKeyframeTrack, + RepeatWrapping, + Scene, + Skeleton, + SkinnedMesh, + SpotLight, + TextureLoader, + Vector2, + Vector3, + VectorKeyframeTrack, + SRGBColorSpace +} from 'three'; +import { TGALoader } from 'three/examples/jsm/loaders/TGALoader.js'; -import THREE from './core' -THREE.ColladaLoader = function (manager) { +class ColladaLoader extends Loader { - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; + load( url, onLoad, onProgress, onError ) { -}; + const scope = this; -THREE.ColladaLoader.prototype = { + const path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; - constructor: THREE.ColladaLoader, + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( text ) { - crossOrigin: 'Anonymous', + try { - load: function (url, onLoad, onProgress, onError) { + onLoad( scope.parse( text, path ) ); - var scope = this; + } catch ( e ) { - var path = THREE.Loader.prototype.extractUrlBase(url); + if ( onError ) { - var loader = new THREE.FileLoader(scope.manager); - loader.load(url, function (text) { + onError( e ); - onLoad(scope.parse(text, path)); + } else { - }, onProgress, onError); + console.error( e ); - }, + } - options: { + scope.manager.itemError( url ); - set convertUpAxis(value) { + } - console.warn('THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.'); + }, onProgress, onError ); - } + } - }, + parse( text, path ) { - setCrossOrigin: function (value) { + function getElementsByTagName( xml, name ) { - this.crossOrigin = value; + // Non recursive xml.getElementsByTagName() ... - }, + const array = []; + const childNodes = xml.childNodes; - parse: function (text, path) { + for ( let i = 0, l = childNodes.length; i < l; i ++ ) { - function getElementsByTagName(xml, name) { + const child = childNodes[ i ]; - // Non recursive xml.getElementsByTagName() ... + if ( child.nodeName === name ) { - var array = []; - var childNodes = xml.childNodes; + array.push( child ); - for (var i = 0, l = childNodes.length; i < l; i++) { + } - var child = childNodes[i]; + } - if (child.nodeName === name) { + return array; - array.push(child); + } - } + function parseStrings( text ) { - } + if ( text.length === 0 ) return []; - return array; + const parts = text.trim().split( /\s+/ ); + const array = new Array( parts.length ); - } + for ( let i = 0, l = parts.length; i < l; i ++ ) { - function parseStrings(text) { + array[ i ] = parts[ i ]; - if (text.length === 0) return []; + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + return array; - for (var i = 0, l = parts.length; i < l; i++) { + } - array[i] = parts[i]; + function parseFloats( text ) { - } + if ( text.length === 0 ) return []; - return array; + const parts = text.trim().split( /\s+/ ); + const array = new Array( parts.length ); - } + for ( let i = 0, l = parts.length; i < l; i ++ ) { - function parseFloats(text) { + array[ i ] = parseFloat( parts[ i ] ); - if (text.length === 0) return []; + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + return array; - for (var i = 0, l = parts.length; i < l; i++) { + } - array[i] = parseFloat(parts[i]); + function parseInts( text ) { - } + if ( text.length === 0 ) return []; - return array; + const parts = text.trim().split( /\s+/ ); + const array = new Array( parts.length ); - } + for ( let i = 0, l = parts.length; i < l; i ++ ) { - function parseInts(text) { + array[ i ] = parseInt( parts[ i ] ); - if (text.length === 0) return []; + } - var parts = text.trim().split(/\s+/); - var array = new Array(parts.length); + return array; - for (var i = 0, l = parts.length; i < l; i++) { + } - array[i] = parseInt(parts[i]); + function parseId( text ) { - } + return text.substring( 1 ); - return array; + } - } + function generateId() { - function parseId(text) { + return 'three_default_' + ( count ++ ); - return text.substring(1); + } - } + function isEmpty( object ) { - function generateId() { + return Object.keys( object ).length === 0; - return 'three_default_' + (count++); + } - } + // asset - function isEmpty(object) { + function parseAsset( xml ) { - return Object.keys(object).length === 0; + return { + unit: parseAssetUnit( getElementsByTagName( xml, 'unit' )[ 0 ] ), + upAxis: parseAssetUpAxis( getElementsByTagName( xml, 'up_axis' )[ 0 ] ) + }; - } + } - // asset + function parseAssetUnit( xml ) { - function parseAsset(xml) { + if ( ( xml !== undefined ) && ( xml.hasAttribute( 'meter' ) === true ) ) { - return { - unit: parseAssetUnit(getElementsByTagName(xml, 'unit')[0]), - upAxis: parseAssetUpAxis(getElementsByTagName(xml, 'up_axis')[0]) - }; + return parseFloat( xml.getAttribute( 'meter' ) ); - } + } else { - function parseAssetUnit(xml) { + return 1; // default 1 meter - return xml !== undefined ? parseFloat(xml.getAttribute('meter')) : 1; + } - } + } - function parseAssetUpAxis(xml) { + function parseAssetUpAxis( xml ) { - return xml !== undefined ? xml.textContent : 'Y_UP'; + return xml !== undefined ? xml.textContent : 'Y_UP'; - } + } - // library + // library - function parseLibrary(xml, libraryName, nodeName, parser) { + function parseLibrary( xml, libraryName, nodeName, parser ) { - var library = getElementsByTagName(xml, libraryName)[0]; + const library = getElementsByTagName( xml, libraryName )[ 0 ]; - if (library !== undefined) { + if ( library !== undefined ) { - var elements = getElementsByTagName(library, nodeName); + const elements = getElementsByTagName( library, nodeName ); - for (var i = 0; i < elements.length; i++) { + for ( let i = 0; i < elements.length; i ++ ) { - parser(elements[i]); + parser( elements[ i ] ); - } + } - } + } - } + } - function buildLibrary(data, builder) { + function buildLibrary( data, builder ) { - for (var name in data) { + for ( const name in data ) { - var object = data[name]; - object.build = builder(data[name]); + const object = data[ name ]; + object.build = builder( data[ name ] ); - } + } - } + } - // get + // get - function getBuild(data, builder) { + function getBuild( data, builder ) { - if (data.build !== undefined) return data.build; + if ( data.build !== undefined ) return data.build; - data.build = builder(data); + data.build = builder( data ); - return data.build; + return data.build; - } + } - // animation + // animation - function parseAnimation(xml) { + function parseAnimation( xml ) { - var data = { - sources: {}, - samplers: {}, - channels: {} - }; + const data = { + sources: {}, + samplers: {}, + channels: {} + }; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + let hasChildren = false; - var child = xml.childNodes[i]; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - if (child.nodeType !== 1) continue; + const child = xml.childNodes[ i ]; - var id; + if ( child.nodeType !== 1 ) continue; - switch (child.nodeName) { + let id; - case 'source': - id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; + switch ( child.nodeName ) { - case 'sampler': - id = child.getAttribute('id'); - data.samplers[id] = parseAnimationSampler(child); - break; + case 'source': + id = child.getAttribute( 'id' ); + data.sources[ id ] = parseSource( child ); + break; - case 'channel': - id = child.getAttribute('target'); - data.channels[id] = parseAnimationChannel(child); - break; + case 'sampler': + id = child.getAttribute( 'id' ); + data.samplers[ id ] = parseAnimationSampler( child ); + break; - default: - console.log(child); + case 'channel': + id = child.getAttribute( 'target' ); + data.channels[ id ] = parseAnimationChannel( child ); + break; - } + case 'animation': + // hierarchy of related animations + parseAnimation( child ); + hasChildren = true; + break; - } + default: + console.log( child ); - library.animations[xml.getAttribute('id')] = data; + } - } + } - function parseAnimationSampler(xml) { + if ( hasChildren === false ) { - var data = { - inputs: {}, - }; + // since 'id' attributes can be optional, it's necessary to generate a UUID for unqiue assignment - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + library.animations[ xml.getAttribute( 'id' ) || MathUtils.generateUUID() ] = data; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function parseAnimationSampler( xml ) { - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - data.inputs[semantic] = id; - break; + const data = { + inputs: {}, + }; - } + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - return data; + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - function parseAnimationChannel(xml) { + case 'input': + const id = parseId( child.getAttribute( 'source' ) ); + const semantic = child.getAttribute( 'semantic' ); + data.inputs[ semantic ] = id; + break; - var data = {}; + } - var target = xml.getAttribute('target'); + } - // parsing SID Addressing Syntax + return data; - var parts = target.split('/'); + } - var id = parts.shift(); - var sid = parts.shift(); + function parseAnimationChannel( xml ) { - // check selection syntax + const data = {}; - var arraySyntax = (sid.indexOf('(') !== - 1); - var memberSyntax = (sid.indexOf('.') !== - 1); + const target = xml.getAttribute( 'target' ); - if (memberSyntax) { + // parsing SID Addressing Syntax - // member selection access + let parts = target.split( '/' ); - parts = sid.split('.'); - sid = parts.shift(); - data.member = parts.shift(); + const id = parts.shift(); + let sid = parts.shift(); - } else if (arraySyntax) { + // check selection syntax - // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. + const arraySyntax = ( sid.indexOf( '(' ) !== - 1 ); + const memberSyntax = ( sid.indexOf( '.' ) !== - 1 ); - var indices = sid.split('('); - sid = indices.shift(); + if ( memberSyntax ) { - for (var i = 0; i < indices.length; i++) { + // member selection access - indices[i] = parseInt(indices[i].replace(/\)/, '')); + parts = sid.split( '.' ); + sid = parts.shift(); + data.member = parts.shift(); - } + } else if ( arraySyntax ) { - data.indices = indices; + // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. - } + const indices = sid.split( '(' ); + sid = indices.shift(); - data.id = id; - data.sid = sid; + for ( let i = 0; i < indices.length; i ++ ) { - data.arraySyntax = arraySyntax; - data.memberSyntax = memberSyntax; + indices[ i ] = parseInt( indices[ i ].replace( /\)/, '' ) ); - data.sampler = parseId(xml.getAttribute('source')); + } - return data; + data.indices = indices; - } + } - function buildAnimation(data) { + data.id = id; + data.sid = sid; - var tracks = []; + data.arraySyntax = arraySyntax; + data.memberSyntax = memberSyntax; - var channels = data.channels; - var samplers = data.samplers; - var sources = data.sources; + data.sampler = parseId( xml.getAttribute( 'source' ) ); - for (var target in channels) { + return data; - if (channels.hasOwnProperty(target)) { + } - var channel = channels[target]; - var sampler = samplers[channel.sampler]; + function buildAnimation( data ) { - var inputId = sampler.inputs.INPUT; - var outputId = sampler.inputs.OUTPUT; + const tracks = []; - var inputSource = sources[inputId]; - var outputSource = sources[outputId]; + const channels = data.channels; + const samplers = data.samplers; + const sources = data.sources; - var animation = buildAnimationChannel(channel, inputSource, outputSource); + for ( const target in channels ) { - createKeyframeTracks(animation, tracks); + if ( channels.hasOwnProperty( target ) ) { - } + const channel = channels[ target ]; + const sampler = samplers[ channel.sampler ]; - } + const inputId = sampler.inputs.INPUT; + const outputId = sampler.inputs.OUTPUT; - return tracks; + const inputSource = sources[ inputId ]; + const outputSource = sources[ outputId ]; - } + const animation = buildAnimationChannel( channel, inputSource, outputSource ); - function getAnimation(id) { + createKeyframeTracks( animation, tracks ); - return getBuild(library.animations[id], buildAnimation); + } - } + } - function buildAnimationChannel(channel, inputSource, outputSource) { + return tracks; - var node = library.nodes[channel.id]; - var object3D = getNode(node.id); + } - var transform = node.transforms[channel.sid]; - var defaultMatrix = node.matrix.clone().transpose(); + function getAnimation( id ) { - var time, stride; - var i, il, j, jl; + return getBuild( library.animations[ id ], buildAnimation ); - var data = {}; + } - // the collada spec allows the animation of data in various ways. - // depending on the transform type (matrix, translate, rotate, scale), we execute different logic + function buildAnimationChannel( channel, inputSource, outputSource ) { - switch (transform) { + const node = library.nodes[ channel.id ]; + const object3D = getNode( node.id ); - case 'matrix': + const transform = node.transforms[ channel.sid ]; + const defaultMatrix = node.matrix.clone().transpose(); - for (i = 0, il = inputSource.array.length; i < il; i++) { + let time, stride; + let i, il, j, jl; - time = inputSource.array[i]; - stride = i * outputSource.stride; + const data = {}; - if (data[time] === undefined) data[time] = {}; + // the collada spec allows the animation of data in various ways. + // depending on the transform type (matrix, translate, rotate, scale), we execute different logic - if (channel.arraySyntax === true) { + switch ( transform ) { - var value = outputSource.array[stride]; - var index = channel.indices[0] + 4 * channel.indices[1]; + case 'matrix': - data[time][index] = value; + for ( i = 0, il = inputSource.array.length; i < il; i ++ ) { - } else { + time = inputSource.array[ i ]; + stride = i * outputSource.stride; - for (j = 0, jl = outputSource.stride; j < jl; j++) { + if ( data[ time ] === undefined ) data[ time ] = {}; - data[time][j] = outputSource.array[stride + j]; + if ( channel.arraySyntax === true ) { - } + const value = outputSource.array[ stride ]; + const index = channel.indices[ 0 ] + 4 * channel.indices[ 1 ]; - } + data[ time ][ index ] = value; - } + } else { - break; + for ( j = 0, jl = outputSource.stride; j < jl; j ++ ) { - case 'translate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + data[ time ][ j ] = outputSource.array[ stride + j ]; - case 'rotate': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + } - case 'scale': - console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform); - break; + } - } + } - var keyframes = prepareAnimationData(data, defaultMatrix); + break; - var animation = { - name: object3D.uuid, - keyframes: keyframes - }; + case 'translate': + console.warn( 'THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform ); + break; - return animation; + case 'rotate': + console.warn( 'THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform ); + break; - } + case 'scale': + console.warn( 'THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform ); + break; - function prepareAnimationData(data, defaultMatrix) { + } - var keyframes = []; + const keyframes = prepareAnimationData( data, defaultMatrix ); - // transfer data into a sortable array + const animation = { + name: object3D.uuid, + keyframes: keyframes + }; - for (var time in data) { + return animation; - keyframes.push({ time: parseFloat(time), value: data[time] }); + } - } + function prepareAnimationData( data, defaultMatrix ) { - // ensure keyframes are sorted by time + const keyframes = []; - keyframes.sort(ascending); + // transfer data into a sortable array - // now we clean up all animation data, so we can use them for keyframe tracks + for ( const time in data ) { - for (var i = 0; i < 16; i++) { + keyframes.push( { time: parseFloat( time ), value: data[ time ] } ); - transformAnimationData(keyframes, i, defaultMatrix.elements[i]); + } - } + // ensure keyframes are sorted by time - return keyframes; + keyframes.sort( ascending ); - // array sort function + // now we clean up all animation data, so we can use them for keyframe tracks - function ascending(a, b) { + for ( let i = 0; i < 16; i ++ ) { - return a.time - b.time; + transformAnimationData( keyframes, i, defaultMatrix.elements[ i ] ); - } + } - } + return keyframes; - var position = new THREE.Vector3(); - var scale = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); + // array sort function - function createKeyframeTracks(animation, tracks) { + function ascending( a, b ) { - var keyframes = animation.keyframes; - var name = animation.name; + return a.time - b.time; - var times = []; - var positionData = []; - var quaternionData = []; - var scaleData = []; + } - for (var i = 0, l = keyframes.length; i < l; i++) { + } - var keyframe = keyframes[i]; + const position = new Vector3(); + const scale = new Vector3(); + const quaternion = new Quaternion(); - var time = keyframe.time; - var value = keyframe.value; + function createKeyframeTracks( animation, tracks ) { - matrix.fromArray(value).transpose(); - matrix.decompose(position, quaternion, scale); + const keyframes = animation.keyframes; + const name = animation.name; - times.push(time); - positionData.push(position.x, position.y, position.z); - quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w); - scaleData.push(scale.x, scale.y, scale.z); + const times = []; + const positionData = []; + const quaternionData = []; + const scaleData = []; - } + for ( let i = 0, l = keyframes.length; i < l; i ++ ) { - if (positionData.length > 0) tracks.push(new THREE.VectorKeyframeTrack(name + '.position', times, positionData)); - if (quaternionData.length > 0) tracks.push(new THREE.QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData)); - if (scaleData.length > 0) tracks.push(new THREE.VectorKeyframeTrack(name + '.scale', times, scaleData)); + const keyframe = keyframes[ i ]; - return tracks; + const time = keyframe.time; + const value = keyframe.value; - } + matrix.fromArray( value ).transpose(); + matrix.decompose( position, quaternion, scale ); - function transformAnimationData(keyframes, property, defaultValue) { + times.push( time ); + positionData.push( position.x, position.y, position.z ); + quaternionData.push( quaternion.x, quaternion.y, quaternion.z, quaternion.w ); + scaleData.push( scale.x, scale.y, scale.z ); - var keyframe; + } - var empty = true; - var i, l; + if ( positionData.length > 0 ) tracks.push( new VectorKeyframeTrack( name + '.position', times, positionData ) ); + if ( quaternionData.length > 0 ) tracks.push( new QuaternionKeyframeTrack( name + '.quaternion', times, quaternionData ) ); + if ( scaleData.length > 0 ) tracks.push( new VectorKeyframeTrack( name + '.scale', times, scaleData ) ); - // check, if values of a property are missing in our keyframes + return tracks; - for (i = 0, l = keyframes.length; i < l; i++) { + } - keyframe = keyframes[i]; + function transformAnimationData( keyframes, property, defaultValue ) { - if (keyframe.value[property] === undefined) { + let keyframe; - keyframe.value[property] = null; // mark as missing + let empty = true; + let i, l; - } else { + // check, if values of a property are missing in our keyframes - empty = false; + for ( i = 0, l = keyframes.length; i < l; i ++ ) { - } + keyframe = keyframes[ i ]; - } + if ( keyframe.value[ property ] === undefined ) { - if (empty === true) { + keyframe.value[ property ] = null; // mark as missing - // no values at all, so we set a default value + } else { - for (i = 0, l = keyframes.length; i < l; i++) { + empty = false; - keyframe = keyframes[i]; + } - keyframe.value[property] = defaultValue; + } - } + if ( empty === true ) { - } else { + // no values at all, so we set a default value - // filling gaps + for ( i = 0, l = keyframes.length; i < l; i ++ ) { - createMissingKeyframes(keyframes, property); + keyframe = keyframes[ i ]; - } + keyframe.value[ property ] = defaultValue; - } + } - function createMissingKeyframes(keyframes, property) { + } else { - var prev, next; + // filling gaps - for (var i = 0, l = keyframes.length; i < l; i++) { + createMissingKeyframes( keyframes, property ); - var keyframe = keyframes[i]; + } - if (keyframe.value[property] === null) { + } - prev = getPrev(keyframes, i, property); - next = getNext(keyframes, i, property); + function createMissingKeyframes( keyframes, property ) { - if (prev === null) { + let prev, next; - keyframe.value[property] = next.value[property]; - continue; + for ( let i = 0, l = keyframes.length; i < l; i ++ ) { - } + const keyframe = keyframes[ i ]; - if (next === null) { + if ( keyframe.value[ property ] === null ) { - keyframe.value[property] = prev.value[property]; - continue; + prev = getPrev( keyframes, i, property ); + next = getNext( keyframes, i, property ); - } + if ( prev === null ) { - interpolate(keyframe, prev, next, property); + keyframe.value[ property ] = next.value[ property ]; + continue; - } + } - } + if ( next === null ) { - } + keyframe.value[ property ] = prev.value[ property ]; + continue; - function getPrev(keyframes, i, property) { + } - while (i >= 0) { + interpolate( keyframe, prev, next, property ); - var keyframe = keyframes[i]; + } - if (keyframe.value[property] !== null) return keyframe; + } - i--; + } - } + function getPrev( keyframes, i, property ) { - return null; + while ( i >= 0 ) { - } + const keyframe = keyframes[ i ]; - function getNext(keyframes, i, property) { + if ( keyframe.value[ property ] !== null ) return keyframe; - while (i < keyframes.length) { + i --; - var keyframe = keyframes[i]; + } - if (keyframe.value[property] !== null) return keyframe; + return null; - i++; + } - } + function getNext( keyframes, i, property ) { - return null; + while ( i < keyframes.length ) { - } + const keyframe = keyframes[ i ]; - function interpolate(key, prev, next, property) { + if ( keyframe.value[ property ] !== null ) return keyframe; - if ((next.time - prev.time) === 0) { + i ++; - key.value[property] = prev.value[property]; - return; + } - } + return null; - key.value[property] = ((key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time)) + prev.value[property]; + } - } + function interpolate( key, prev, next, property ) { - // animation clips + if ( ( next.time - prev.time ) === 0 ) { - function parseAnimationClip(xml) { + key.value[ property ] = prev.value[ property ]; + return; - var data = { - name: xml.getAttribute('id') || 'default', - start: parseFloat(xml.getAttribute('start') || 0), - end: parseFloat(xml.getAttribute('end') || 0), - animations: [] - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + key.value[ property ] = ( ( key.time - prev.time ) * ( next.value[ property ] - prev.value[ property ] ) / ( next.time - prev.time ) ) + prev.value[ property ]; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + // animation clips - switch (child.nodeName) { + function parseAnimationClip( xml ) { - case 'instance_animation': - data.animations.push(parseId(child.getAttribute('url'))); - break; + const data = { + name: xml.getAttribute( 'id' ) || 'default', + start: parseFloat( xml.getAttribute( 'start' ) || 0 ), + end: parseFloat( xml.getAttribute( 'end' ) || 0 ), + animations: [] + }; - } + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - library.clips[xml.getAttribute('id')] = data; + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - function buildAnimationClip(data) { + case 'instance_animation': + data.animations.push( parseId( child.getAttribute( 'url' ) ) ); + break; - var tracks = []; + } - var name = data.name; - var duration = (data.end - data.start) || - 1; - var animations = data.animations; + } - for (var i = 0, il = animations.length; i < il; i++) { + library.clips[ xml.getAttribute( 'id' ) ] = data; - var animationTracks = getAnimation(animations[i]); + } - for (var j = 0, jl = animationTracks.length; j < jl; j++) { + function buildAnimationClip( data ) { - tracks.push(animationTracks[j]); + const tracks = []; - } + const name = data.name; + const duration = ( data.end - data.start ) || - 1; + const animations = data.animations; - } + for ( let i = 0, il = animations.length; i < il; i ++ ) { - return new THREE.AnimationClip(name, duration, tracks); + const animationTracks = getAnimation( animations[ i ] ); - } + for ( let j = 0, jl = animationTracks.length; j < jl; j ++ ) { - function getAnimationClip(id) { + tracks.push( animationTracks[ j ] ); - return getBuild(library.clips[id], buildAnimationClip); + } - } + } - // controller + return new AnimationClip( name, duration, tracks ); - function parseController(xml) { + } - var data = {}; + function getAnimationClip( id ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + return getBuild( library.clips[ id ], buildAnimationClip ); - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + // controller - switch (child.nodeName) { + function parseController( xml ) { - case 'skin': - // there is exactly one skin per controller - data.id = parseId(child.getAttribute('source')); - data.skin = parseSkin(child); - break; + const data = {}; - case 'morph': - data.id = parseId(child.getAttribute('source')); - console.warn('THREE.ColladaLoader: Morph target animation not supported yet.'); - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - library.controllers[xml.getAttribute('id')] = data; + switch ( child.nodeName ) { - } + case 'skin': + // there is exactly one skin per controller + data.id = parseId( child.getAttribute( 'source' ) ); + data.skin = parseSkin( child ); + break; - function parseSkin(xml) { + case 'morph': + data.id = parseId( child.getAttribute( 'source' ) ); + console.warn( 'THREE.ColladaLoader: Morph target animation not supported yet.' ); + break; - var data = { - sources: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + library.controllers[ xml.getAttribute( 'id' ) ] = data; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function parseSkin( xml ) { - case 'bind_shape_matrix': - data.bindShapeMatrix = parseFloats(child.textContent); - break; + const data = { + sources: {} + }; - case 'source': - var id = child.getAttribute('id'); - data.sources[id] = parseSource(child); - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - case 'joints': - data.joints = parseJoints(child); - break; + const child = xml.childNodes[ i ]; - case 'vertex_weights': - data.vertexWeights = parseVertexWeights(child); - break; + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - } + case 'bind_shape_matrix': + data.bindShapeMatrix = parseFloats( child.textContent ); + break; - return data; + case 'source': + const id = child.getAttribute( 'id' ); + data.sources[ id ] = parseSource( child ); + break; - } + case 'joints': + data.joints = parseJoints( child ); + break; - function parseJoints(xml) { + case 'vertex_weights': + data.vertexWeights = parseVertexWeights( child ); + break; - var data = { - inputs: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + return data; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function parseJoints( xml ) { - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - data.inputs[semantic] = id; - break; + const data = { + inputs: {} + }; - } + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - return data; + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - function parseVertexWeights(xml) { + case 'input': + const semantic = child.getAttribute( 'semantic' ); + const id = parseId( child.getAttribute( 'source' ) ); + data.inputs[ semantic ] = id; + break; - var data = { - inputs: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + return data; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function parseVertexWeights( xml ) { - case 'input': - var semantic = child.getAttribute('semantic'); - var id = parseId(child.getAttribute('source')); - var offset = parseInt(child.getAttribute('offset')); - data.inputs[semantic] = { id: id, offset: offset }; - break; + const data = { + inputs: {} + }; - case 'vcount': - data.vcount = parseInts(child.textContent); - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - case 'v': - data.v = parseInts(child.textContent); - break; + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - return data; + case 'input': + const semantic = child.getAttribute( 'semantic' ); + const id = parseId( child.getAttribute( 'source' ) ); + const offset = parseInt( child.getAttribute( 'offset' ) ); + data.inputs[ semantic ] = { id: id, offset: offset }; + break; - } + case 'vcount': + data.vcount = parseInts( child.textContent ); + break; - function buildController(data) { + case 'v': + data.v = parseInts( child.textContent ); + break; - var build = { - id: data.id - }; + } - var geometry = library.geometries[build.id]; + } - if (data.skin !== undefined) { + return data; - build.skin = buildSkin(data.skin); + } - // we enhance the 'sources' property of the corresponding geometry with our skin data + function buildController( data ) { - geometry.sources.skinIndices = build.skin.indices; - geometry.sources.skinWeights = build.skin.weights; + const build = { + id: data.id + }; - } + const geometry = library.geometries[ build.id ]; - return build; + if ( data.skin !== undefined ) { - } + build.skin = buildSkin( data.skin ); - function buildSkin(data) { + // we enhance the 'sources' property of the corresponding geometry with our skin data - var BONE_LIMIT = 4; + geometry.sources.skinIndices = build.skin.indices; + geometry.sources.skinWeights = build.skin.weights; - var build = { - joints: [], // this must be an array to preserve the joint order - indices: { - array: [], - stride: BONE_LIMIT - }, - weights: { - array: [], - stride: BONE_LIMIT - } - }; + } - var sources = data.sources; - var vertexWeights = data.vertexWeights; + return build; - var vcount = vertexWeights.vcount; - var v = vertexWeights.v; - var jointOffset = vertexWeights.inputs.JOINT.offset; - var weightOffset = vertexWeights.inputs.WEIGHT.offset; + } - var jointSource = data.sources[data.joints.inputs.JOINT]; - var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX]; + function buildSkin( data ) { - var weights = sources[vertexWeights.inputs.WEIGHT.id].array; - var stride = 0; + const BONE_LIMIT = 4; - var i, j, l; + const build = { + joints: [], // this must be an array to preserve the joint order + indices: { + array: [], + stride: BONE_LIMIT + }, + weights: { + array: [], + stride: BONE_LIMIT + } + }; - // procces skin data for each vertex + const sources = data.sources; + const vertexWeights = data.vertexWeights; - for (i = 0, l = vcount.length; i < l; i++) { + const vcount = vertexWeights.vcount; + const v = vertexWeights.v; + const jointOffset = vertexWeights.inputs.JOINT.offset; + const weightOffset = vertexWeights.inputs.WEIGHT.offset; - var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex - var vertexSkinData = []; + const jointSource = data.sources[ data.joints.inputs.JOINT ]; + const inverseSource = data.sources[ data.joints.inputs.INV_BIND_MATRIX ]; - for (j = 0; j < jointCount; j++) { + const weights = sources[ vertexWeights.inputs.WEIGHT.id ].array; + let stride = 0; - var skinIndex = v[stride + jointOffset]; - var weightId = v[stride + weightOffset]; - var skinWeight = weights[weightId]; + let i, j, l; - vertexSkinData.push({ index: skinIndex, weight: skinWeight }); + // process skin data for each vertex - stride += 2; + for ( i = 0, l = vcount.length; i < l; i ++ ) { - } + const jointCount = vcount[ i ]; // this is the amount of joints that affect a single vertex + const vertexSkinData = []; - // we sort the joints in descending order based on the weights. - // this ensures, we only procced the most important joints of the vertex + for ( j = 0; j < jointCount; j ++ ) { - vertexSkinData.sort(descending); + const skinIndex = v[ stride + jointOffset ]; + const weightId = v[ stride + weightOffset ]; + const skinWeight = weights[ weightId ]; - // now we provide for each vertex a set of four index and weight values. - // the order of the skin data matches the order of vertices + vertexSkinData.push( { index: skinIndex, weight: skinWeight } ); - for (j = 0; j < BONE_LIMIT; j++) { + stride += 2; - var d = vertexSkinData[j]; + } - if (d !== undefined) { + // we sort the joints in descending order based on the weights. + // this ensures, we only procced the most important joints of the vertex - build.indices.array.push(d.index); - build.weights.array.push(d.weight); + vertexSkinData.sort( descending ); - } else { + // now we provide for each vertex a set of four index and weight values. + // the order of the skin data matches the order of vertices - build.indices.array.push(0); - build.weights.array.push(0); + for ( j = 0; j < BONE_LIMIT; j ++ ) { - } + const d = vertexSkinData[ j ]; - } + if ( d !== undefined ) { - } + build.indices.array.push( d.index ); + build.weights.array.push( d.weight ); - // setup bind matrix + } else { - build.bindMatrix = new THREE.Matrix4().fromArray(data.bindShapeMatrix).transpose(); + build.indices.array.push( 0 ); + build.weights.array.push( 0 ); - // process bones and inverse bind matrix data + } - for (i = 0, l = jointSource.array.length; i < l; i++) { + } - var name = jointSource.array[i]; - var boneInverse = new THREE.Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose(); + } - build.joints.push({ name: name, boneInverse: boneInverse }); + // setup bind matrix - } + if ( data.bindShapeMatrix ) { - return build; + build.bindMatrix = new Matrix4().fromArray( data.bindShapeMatrix ).transpose(); - // array sort function + } else { - function descending(a, b) { + build.bindMatrix = new Matrix4().identity(); - return b.weight - a.weight; + } - } + // process bones and inverse bind matrix data - } + for ( i = 0, l = jointSource.array.length; i < l; i ++ ) { - function getController(id) { + const name = jointSource.array[ i ]; + const boneInverse = new Matrix4().fromArray( inverseSource.array, i * inverseSource.stride ).transpose(); - return getBuild(library.controllers[id], buildController); + build.joints.push( { name: name, boneInverse: boneInverse } ); - } + } - // image + return build; - function parseImage(xml) { + // array sort function - var data = { - init_from: getElementsByTagName(xml, 'init_from')[0].textContent - }; + function descending( a, b ) { - library.images[xml.getAttribute('id')] = data; + return b.weight - a.weight; - } + } - function buildImage(data) { + } - if (data.build !== undefined) return data.build; + function getController( id ) { - return data.init_from; + return getBuild( library.controllers[ id ], buildController ); - } + } - function getImage(id) { + // image - return getBuild(library.images[id], buildImage); + function parseImage( xml ) { - } + const data = { + init_from: getElementsByTagName( xml, 'init_from' )[ 0 ].textContent + }; - // effect + library.images[ xml.getAttribute( 'id' ) ] = data; - function parseEffect(xml) { + } - var data = {}; + function buildImage( data ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + if ( data.build !== undefined ) return data.build; - var child = xml.childNodes[i]; + return data.init_from; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function getImage( id ) { - case 'profile_COMMON': - data.profile = parseEffectProfileCOMMON(child); - break; + const data = library.images[ id ]; - } + if ( data !== undefined ) { - } + return getBuild( data, buildImage ); - library.effects[xml.getAttribute('id')] = data; + } - } + console.warn( 'THREE.ColladaLoader: Couldn\'t find image with ID:', id ); - function parseEffectProfileCOMMON(xml) { + return null; - var data = { - surfaces: {}, - samplers: {} - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // effect - var child = xml.childNodes[i]; + function parseEffect( xml ) { - if (child.nodeType !== 1) continue; + const data = {}; - switch (child.nodeName) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - case 'newparam': - parseEffectNewparam(child, data); - break; + const child = xml.childNodes[ i ]; - case 'technique': - data.technique = parseEffectTechnique(child); - break; + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - } + case 'profile_COMMON': + data.profile = parseEffectProfileCOMMON( child ); + break; - return data; + } - } + } - function parseEffectNewparam(xml, data) { + library.effects[ xml.getAttribute( 'id' ) ] = data; - var sid = xml.getAttribute('sid'); + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + function parseEffectProfileCOMMON( xml ) { - var child = xml.childNodes[i]; + const data = { + surfaces: {}, + samplers: {} + }; - if (child.nodeType !== 1) continue; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - switch (child.nodeName) { + const child = xml.childNodes[ i ]; - case 'surface': - data.surfaces[sid] = parseEffectSurface(child); - break; + if ( child.nodeType !== 1 ) continue; - case 'sampler2D': - data.samplers[sid] = parseEffectSampler(child); - break; + switch ( child.nodeName ) { - } + case 'newparam': + parseEffectNewparam( child, data ); + break; - } + case 'technique': + data.technique = parseEffectTechnique( child ); + break; - } + case 'extra': + data.extra = parseEffectExtra( child ); + break; - function parseEffectSurface(xml) { + } - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + return data; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + function parseEffectNewparam( xml, data ) { - switch (child.nodeName) { + const sid = xml.getAttribute( 'sid' ); - case 'init_from': - data.init_from = child.textContent; - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - return data; + switch ( child.nodeName ) { - } + case 'surface': + data.surfaces[ sid ] = parseEffectSurface( child ); + break; - function parseEffectSampler(xml) { + case 'sampler2D': + data.samplers[ sid ] = parseEffectSampler( child ); + break; - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + function parseEffectSurface( xml ) { - switch (child.nodeName) { + const data = {}; - case 'source': - data.source = child.textContent; - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - return data; + switch ( child.nodeName ) { - } + case 'init_from': + data.init_from = child.textContent; + break; - function parseEffectTechnique(xml) { + } - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + return data; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + function parseEffectSampler( xml ) { - switch (child.nodeName) { + const data = {}; - case 'constant': - case 'lambert': - case 'blinn': - case 'phong': - data.type = child.nodeName; - data.parameters = parseEffectParameters(child); - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - return data; + switch ( child.nodeName ) { - } + case 'source': + data.source = child.textContent; + break; - function parseEffectParameters(xml) { + } - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + return data; - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + function parseEffectTechnique( xml ) { - switch (child.nodeName) { + const data = {}; - case 'emission': - case 'diffuse': - case 'specular': - case 'shininess': - case 'transparent': - case 'transparency': - data[child.nodeName] = parseEffectParameter(child); - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - return data; + switch ( child.nodeName ) { - } + case 'constant': + case 'lambert': + case 'blinn': + case 'phong': + data.type = child.nodeName; + data.parameters = parseEffectParameters( child ); + break; - function parseEffectParameter(xml) { + case 'extra': + data.extra = parseEffectExtra( child ); + break; - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + return data; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function parseEffectParameters( xml ) { - case 'color': - data[child.nodeName] = parseFloats(child.textContent); - break; + const data = {}; - case 'float': - data[child.nodeName] = parseFloat(child.textContent); - break; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - case 'texture': - data[child.nodeName] = { id: child.getAttribute('texture'), extra: parseEffectParameterTexture(child) }; - break; + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - return data; + case 'emission': + case 'diffuse': + case 'specular': + case 'bump': + case 'ambient': + case 'shininess': + case 'transparency': + data[ child.nodeName ] = parseEffectParameter( child ); + break; + case 'transparent': + data[ child.nodeName ] = { + opaque: child.hasAttribute( 'opaque' ) ? child.getAttribute( 'opaque' ) : 'A_ONE', + data: parseEffectParameter( child ) + }; + break; - } + } - function parseEffectParameterTexture(xml) { + } - var data = { - technique: {} - }; + return data; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + function parseEffectParameter( xml ) { - if (child.nodeType !== 1) continue; + const data = {}; - switch (child.nodeName) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - case 'extra': - parseEffectParameterTextureExtra(child, data); - break; + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - return data; + case 'color': + data[ child.nodeName ] = parseFloats( child.textContent ); + break; - } + case 'float': + data[ child.nodeName ] = parseFloat( child.textContent ); + break; - function parseEffectParameterTextureExtra(xml, data) { + case 'texture': + data[ child.nodeName ] = { id: child.getAttribute( 'texture' ), extra: parseEffectParameterTexture( child ) }; + break; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + return data; - switch (child.nodeName) { + } - case 'technique': - parseEffectParameterTextureExtraTechnique(child, data); - break; + function parseEffectParameterTexture( xml ) { - } + const data = { + technique: {} + }; - } + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - function parseEffectParameterTextureExtraTechnique(xml, data) { + if ( child.nodeType !== 1 ) continue; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + switch ( child.nodeName ) { - var child = xml.childNodes[i]; + case 'extra': + parseEffectParameterTextureExtra( child, data ); + break; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + } - case 'repeatU': - case 'repeatV': - case 'offsetU': - case 'offsetV': - data.technique[child.nodeName] = parseFloat(child.textContent); - break; + return data; - case 'wrapU': - case 'wrapV': + } - // some files have values for wrapU/wrapV which become NaN via parseInt + function parseEffectParameterTextureExtra( xml, data ) { - if (child.textContent.toUpperCase() === 'TRUE') { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - data.technique[child.nodeName] = 1; + const child = xml.childNodes[ i ]; - } else if (child.textContent.toUpperCase() === 'FALSE') { + if ( child.nodeType !== 1 ) continue; - data.technique[child.nodeName] = 0; + switch ( child.nodeName ) { - } else { + case 'technique': + parseEffectParameterTextureExtraTechnique( child, data ); + break; - data.technique[child.nodeName] = parseInt(child.textContent); + } - } + } - break; + } - } + function parseEffectParameterTextureExtraTechnique( xml, data ) { - } + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - } + const child = xml.childNodes[ i ]; - function buildEffect(data) { + if ( child.nodeType !== 1 ) continue; - return data; + switch ( child.nodeName ) { - } + case 'repeatU': + case 'repeatV': + case 'offsetU': + case 'offsetV': + data.technique[ child.nodeName ] = parseFloat( child.textContent ); + break; - function getEffect(id) { + case 'wrapU': + case 'wrapV': - return getBuild(library.effects[id], buildEffect); + // some files have values for wrapU/wrapV which become NaN via parseInt - } + if ( child.textContent.toUpperCase() === 'TRUE' ) { - // material + data.technique[ child.nodeName ] = 1; - function parseMaterial(xml) { + } else if ( child.textContent.toUpperCase() === 'FALSE' ) { - var data = { - name: xml.getAttribute('name') - }; + data.technique[ child.nodeName ] = 0; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + } else { - var child = xml.childNodes[i]; + data.technique[ child.nodeName ] = parseInt( child.textContent ); - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + break; - case 'instance_effect': - data.url = parseId(child.getAttribute('url')); - break; + case 'bump': + data[ child.nodeName ] = parseEffectExtraTechniqueBump( child ); + break; - } + } - } + } - library.materials[xml.getAttribute('id')] = data; + } - } + function parseEffectExtra( xml ) { - function buildMaterial(data) { + const data = {}; - var effect = getEffect(data.url); - var technique = effect.profile.technique; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var material; + const child = xml.childNodes[ i ]; - switch (technique.type) { + if ( child.nodeType !== 1 ) continue; - case 'phong': - case 'blinn': - material = new THREE.MeshPhongMaterial(); - break; + switch ( child.nodeName ) { - case 'lambert': - material = new THREE.MeshLambertMaterial(); - break; + case 'technique': + data.technique = parseEffectExtraTechnique( child ); + break; - default: - material = new THREE.MeshBasicMaterial(); - break; + } - } + } - material.name = data.name; + return data; - function getTexture(textureObject) { + } - var sampler = effect.profile.samplers[textureObject.id]; + function parseEffectExtraTechnique( xml ) { - if (sampler !== undefined) { + const data = {}; - var surface = effect.profile.surfaces[sampler.source]; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var texture = textureLoader.load(getImage(surface.init_from)); + const child = xml.childNodes[ i ]; - var extra = textureObject.extra; + if ( child.nodeType !== 1 ) continue; - if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) { + switch ( child.nodeName ) { - var technique = extra.technique; + case 'double_sided': + data[ child.nodeName ] = parseInt( child.textContent ); + break; - texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; - texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; + case 'bump': + data[ child.nodeName ] = parseEffectExtraTechniqueBump( child ); + break; - texture.offset.set(technique.offsetU || 0, technique.offsetV || 0); - texture.repeat.set(technique.repeatU || 1, technique.repeatV || 1); + } - } else { + } - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; + return data; - } + } - return texture; + function parseEffectExtraTechniqueBump( xml ) { - } + const data = {}; - console.error('THREE.ColladaLoader: Undefined sampler', textureObject.id); + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - return null; + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - var parameters = technique.parameters; + switch ( child.nodeName ) { - for (var key in parameters) { + case 'texture': + data[ child.nodeName ] = { id: child.getAttribute( 'texture' ), texcoord: child.getAttribute( 'texcoord' ), extra: parseEffectParameterTexture( child ) }; + break; - var parameter = parameters[key]; + } - switch (key) { + } - case 'diffuse': - if (parameter.color) material.color.fromArray(parameter.color); - if (parameter.texture) material.map = getTexture(parameter.texture); - break; - case 'specular': - if (parameter.color && material.specular) material.specular.fromArray(parameter.color); - if (parameter.texture) material.specularMap = getTexture(parameter.texture); - break; - case 'shininess': - if (parameter.float && material.shininess) - material.shininess = parameter.float; - break; - case 'emission': - if (parameter.color && material.emissive) - material.emissive.fromArray(parameter.color); - break; - case 'transparent': - // if ( parameter.texture ) material.alphaMap = getTexture( parameter.texture ); - material.transparent = true; - break; - case 'transparency': - if (parameter.float !== undefined) material.opacity = parameter.float; - material.transparent = true; - break; + return data; - } + } - } + function buildEffect( data ) { - return material; + return data; - } + } - function getMaterial(id) { + function getEffect( id ) { - return getBuild(library.materials[id], buildMaterial); + return getBuild( library.effects[ id ], buildEffect ); - } + } - // camera + // material - function parseCamera(xml) { + function parseMaterial( xml ) { - var data = { - name: xml.getAttribute('name') - }; + const data = { + name: xml.getAttribute( 'name' ) + }; - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[i]; + const child = xml.childNodes[ i ]; - if (child.nodeType !== 1) continue; + if ( child.nodeType !== 1 ) continue; - switch (child.nodeName) { + switch ( child.nodeName ) { - case 'optics': - data.optics = parseCameraOptics(child); - break; + case 'instance_effect': + data.url = parseId( child.getAttribute( 'url' ) ); + break; - } + } - } + } - library.cameras[xml.getAttribute('id')] = data; + library.materials[ xml.getAttribute( 'id' ) ] = data; - } + } - function parseCameraOptics(xml) { + function getTextureLoader( image ) { - for (var i = 0; i < xml.childNodes.length; i++) { + let loader; - var child = xml.childNodes[i]; + let extension = image.slice( ( image.lastIndexOf( '.' ) - 1 >>> 0 ) + 2 ); // http://www.jstips.co/en/javascript/get-file-extension/ + extension = extension.toLowerCase(); - switch (child.nodeName) { + switch ( extension ) { - case 'technique_common': - return parseCameraTechnique(child); + case 'tga': + loader = tgaLoader; + break; - } + default: + loader = textureLoader; - } + } - return {}; + return loader; - } + } - function parseCameraTechnique(xml) { + function buildMaterial( data ) { - var data = {}; + const effect = getEffect( data.url ); + const technique = effect.profile.technique; - for (var i = 0; i < xml.childNodes.length; i++) { + let material; - var child = xml.childNodes[i]; + switch ( technique.type ) { - switch (child.nodeName) { + case 'phong': + case 'blinn': + material = new MeshPhongMaterial(); + break; - case 'perspective': - case 'orthographic': + case 'lambert': + material = new MeshLambertMaterial(); + break; - data.technique = child.nodeName; - data.parameters = parseCameraParameters(child); + default: + material = new MeshBasicMaterial(); + break; - break; + } - } + material.name = data.name || ''; - } + function getTexture( textureObject, colorSpace = null ) { - return data; + const sampler = effect.profile.samplers[ textureObject.id ]; + let image = null; - } + // get image - function parseCameraParameters(xml) { + if ( sampler !== undefined ) { - var data = {}; + const surface = effect.profile.surfaces[ sampler.source ]; + image = getImage( surface.init_from ); - for (var i = 0; i < xml.childNodes.length; i++) { + } else { - var child = xml.childNodes[i]; + console.warn( 'THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530).' ); + image = getImage( textureObject.id ); - switch (child.nodeName) { + } - case 'xfov': - case 'yfov': - case 'xmag': - case 'ymag': - case 'znear': - case 'zfar': - case 'aspect_ratio': - data[child.nodeName] = parseFloat(child.textContent); - break; + // create texture if image is avaiable - } + if ( image !== null ) { - } + const loader = getTextureLoader( image ); - return data; + if ( loader !== undefined ) { - } + const texture = loader.load( image ); - function buildCamera(data) { + const extra = textureObject.extra; - var camera; + if ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) { - switch (data.optics.technique) { + const technique = extra.technique; - case 'perspective': - camera = new THREE.PerspectiveCamera( - data.optics.parameters.yfov, - data.optics.parameters.aspect_ratio, - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + texture.wrapS = technique.wrapU ? RepeatWrapping : ClampToEdgeWrapping; + texture.wrapT = technique.wrapV ? RepeatWrapping : ClampToEdgeWrapping; - case 'orthographic': - var ymag = data.optics.parameters.ymag; - var xmag = data.optics.parameters.xmag; - var aspectRatio = data.optics.parameters.aspect_ratio; + texture.offset.set( technique.offsetU || 0, technique.offsetV || 0 ); + texture.repeat.set( technique.repeatU || 1, technique.repeatV || 1 ); - xmag = (xmag === undefined) ? (ymag * aspectRatio) : xmag; - ymag = (ymag === undefined) ? (xmag / aspectRatio) : ymag; + } else { - xmag *= 0.5; - ymag *= 0.5; + texture.wrapS = RepeatWrapping; + texture.wrapT = RepeatWrapping; - camera = new THREE.OrthographicCamera( - - xmag, xmag, ymag, - ymag, // left, right, top, bottom - data.optics.parameters.znear, - data.optics.parameters.zfar - ); - break; + } - default: - camera = new THREE.PerspectiveCamera(); - break; + if ( colorSpace !== null ) { - } + texture.colorSpace = colorSpace; - camera.name = data.name; + } - return camera; + return texture; - } + } else { - function getCamera(id) { - var data = library.cameras[id]; - if (data !== undefined) { - return getBuild(data, buildCamera); - } - return null; - } + console.warn( 'THREE.ColladaLoader: Loader for texture %s not found.', image ); - // light + return null; - function parseLight(xml) { + } - var data = {}; + } else { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + console.warn( 'THREE.ColladaLoader: Couldn\'t create texture with ID:', textureObject.id ); - var child = xml.childNodes[i]; + return null; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + } - case 'technique_common': - data = parseLightTechnique(child); - break; + const parameters = technique.parameters; - } + for ( const key in parameters ) { - } + const parameter = parameters[ key ]; - library.lights[xml.getAttribute('id')] = data; + switch ( key ) { - } + case 'diffuse': + if ( parameter.color ) material.color.fromArray( parameter.color ); + if ( parameter.texture ) material.map = getTexture( parameter.texture, SRGBColorSpace ); + break; + case 'specular': + if ( parameter.color && material.specular ) material.specular.fromArray( parameter.color ); + if ( parameter.texture ) material.specularMap = getTexture( parameter.texture ); + break; + case 'bump': + if ( parameter.texture ) material.normalMap = getTexture( parameter.texture ); + break; + case 'ambient': + if ( parameter.texture ) material.lightMap = getTexture( parameter.texture, SRGBColorSpace ); + break; + case 'shininess': + if ( parameter.float && material.shininess ) material.shininess = parameter.float; + break; + case 'emission': + if ( parameter.color && material.emissive ) material.emissive.fromArray( parameter.color ); + if ( parameter.texture ) material.emissiveMap = getTexture( parameter.texture, SRGBColorSpace ); + break; - function parseLightTechnique(xml) { + } - var data = {}; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + material.color.convertSRGBToLinear(); + if ( material.specular ) material.specular.convertSRGBToLinear(); + if ( material.emissive ) material.emissive.convertSRGBToLinear(); - var child = xml.childNodes[i]; + // - if (child.nodeType !== 1) continue; + let transparent = parameters[ 'transparent' ]; + let transparency = parameters[ 'transparency' ]; - switch (child.nodeName) { + // does not exist but - case 'directional': - case 'point': - case 'spot': - case 'ambient': + if ( transparency === undefined && transparent ) { - data.technique = child.nodeName; - data.parameters = parseLightParameters(child); + transparency = { + float: 1 + }; - } + } - } + // does not exist but - return data; + if ( transparent === undefined && transparency ) { - } + transparent = { + opaque: 'A_ONE', + data: { + color: [ 1, 1, 1, 1 ] + } }; - function parseLightParameters(xml) { + } - var data = {}; + if ( transparent && transparency ) { - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + // handle case if a texture exists but no color - var child = xml.childNodes[i]; + if ( transparent.data.texture ) { - if (child.nodeType !== 1) continue; + // we do not set an alpha map (see #13792) - switch (child.nodeName) { + material.transparent = true; - case 'color': - var array = parseFloats(child.textContent); - data.color = new THREE.Color().fromArray(array); - break; + } else { - case 'falloff_angle': - data.falloffAngle = parseFloat(child.textContent); - break; + const color = transparent.data.color; - case 'quadratic_attenuation': - var f = parseFloat(child.textContent); - data.distance = f ? Math.sqrt(1 / f) : 0; - break; + switch ( transparent.opaque ) { - } + case 'A_ONE': + material.opacity = color[ 3 ] * transparency.float; + break; + case 'RGB_ZERO': + material.opacity = 1 - ( color[ 0 ] * transparency.float ); + break; + case 'A_ZERO': + material.opacity = 1 - ( color[ 3 ] * transparency.float ); + break; + case 'RGB_ONE': + material.opacity = color[ 0 ] * transparency.float; + break; + default: + console.warn( 'THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.', transparent.opaque ); - } + } - return data; + if ( material.opacity < 1 ) material.transparent = true; - } + } - function buildLight(data) { + } - var light; + // - switch (data.technique) { - case 'directional': - light = new THREE.DirectionalLight(); - break; + if ( technique.extra !== undefined && technique.extra.technique !== undefined ) { - case 'point': - light = new THREE.PointLight(); - break; + const techniques = technique.extra.technique; - case 'spot': - light = new THREE.SpotLight(); - break; + for ( const k in techniques ) { - case 'ambient': - light = new THREE.AmbientLight(); - break; + const v = techniques[ k ]; - } + switch ( k ) { - if (data.parameters.color) light.color.copy(data.parameters.color); - if (data.parameters.distance) light.distance = data.parameters.distance; + case 'double_sided': + material.side = ( v === 1 ? DoubleSide : FrontSide ); + break; - return light; + case 'bump': + material.normalMap = getTexture( v.texture ); + material.normalScale = new Vector2( 1, 1 ); + break; - } + } - function getLight(id) { - var data = library.lights[id]; + } - if (data !== undefined) { + } - return getBuild(data, buildLight); + return material; - } + } - return null; - } + function getMaterial( id ) { - // geometry + return getBuild( library.materials[ id ], buildMaterial ); - function parseGeometry(xml) { + } - var data = { - name: xml.getAttribute('name'), - sources: {}, - vertices: {}, - primitives: [] - }; + // camera - var mesh = getElementsByTagName(xml, 'mesh')[0]; + function parseCamera( xml ) { - for (var i = 0; i < mesh.childNodes.length; i++) { + const data = { + name: xml.getAttribute( 'name' ) + }; - var child = mesh.childNodes[i]; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - if (child.nodeType !== 1) continue; + const child = xml.childNodes[ i ]; - var id = child.getAttribute('id'); + if ( child.nodeType !== 1 ) continue; - switch (child.nodeName) { + switch ( child.nodeName ) { - case 'source': - data.sources[id] = parseSource(child); - break; + case 'optics': + data.optics = parseCameraOptics( child ); + break; - case 'vertices': - // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; - data.vertices = parseGeometryVertices(child); - break; + } - case 'polygons': - console.warn('THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName); - break; + } - case 'lines': - case 'linestrips': - case 'polylist': - case 'triangles': - data.primitives.push(parseGeometryPrimitive(child)); - break; + library.cameras[ xml.getAttribute( 'id' ) ] = data; - default: - console.log(child); + } - } + function parseCameraOptics( xml ) { - } + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - library.geometries[xml.getAttribute('id')] = data; + const child = xml.childNodes[ i ]; - } + switch ( child.nodeName ) { - function parseSource(xml) { + case 'technique_common': + return parseCameraTechnique( child ); - var data = { - array: [], - stride: 3 - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + return {}; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function parseCameraTechnique( xml ) { - case 'float_array': - data.array = parseFloats(child.textContent); - break; + const data = {}; - case 'Name_array': - data.array = parseStrings(child.textContent); - break; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - case 'technique_common': - var accessor = getElementsByTagName(child, 'accessor')[0]; + const child = xml.childNodes[ i ]; - if (accessor !== undefined) { + switch ( child.nodeName ) { - data.stride = parseInt(accessor.getAttribute('stride')); + case 'perspective': + case 'orthographic': - } - break; + data.technique = child.nodeName; + data.parameters = parseCameraParameters( child ); - } + break; - } + } - return data; + } - } + return data; - function parseGeometryVertices(xml) { + } - var data = {}; + function parseCameraParameters( xml ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const data = {}; - var child = xml.childNodes[i]; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - if (child.nodeType !== 1) continue; + const child = xml.childNodes[ i ]; - data[child.getAttribute('semantic')] = parseId(child.getAttribute('source')); + switch ( child.nodeName ) { - } + case 'xfov': + case 'yfov': + case 'xmag': + case 'ymag': + case 'znear': + case 'zfar': + case 'aspect_ratio': + data[ child.nodeName ] = parseFloat( child.textContent ); + break; - return data; + } - } + } - function parseGeometryPrimitive(xml) { + return data; - var primitive = { - type: xml.nodeName, - material: xml.getAttribute('material'), - count: parseInt(xml.getAttribute('count')), - inputs: {}, - stride: 0 - }; + } - for (var i = 0, l = xml.childNodes.length; i < l; i++) { + function buildCamera( data ) { - var child = xml.childNodes[i]; + let camera; - if (child.nodeType !== 1) continue; + switch ( data.optics.technique ) { - switch (child.nodeName) { + case 'perspective': + camera = new PerspectiveCamera( + data.optics.parameters.yfov, + data.optics.parameters.aspect_ratio, + data.optics.parameters.znear, + data.optics.parameters.zfar + ); + break; - case 'input': - var id = parseId(child.getAttribute('source')); - var semantic = child.getAttribute('semantic'); - var offset = parseInt(child.getAttribute('offset')); - primitive.inputs[semantic] = { id: id, offset: offset }; - primitive.stride = Math.max(primitive.stride, offset + 1); - break; + case 'orthographic': + let ymag = data.optics.parameters.ymag; + let xmag = data.optics.parameters.xmag; + const aspectRatio = data.optics.parameters.aspect_ratio; - case 'vcount': - primitive.vcount = parseInts(child.textContent); - break; + xmag = ( xmag === undefined ) ? ( ymag * aspectRatio ) : xmag; + ymag = ( ymag === undefined ) ? ( xmag / aspectRatio ) : ymag; - case 'p': - primitive.p = parseInts(child.textContent); - break; + xmag *= 0.5; + ymag *= 0.5; - } + camera = new OrthographicCamera( + - xmag, xmag, ymag, - ymag, // left, right, top, bottom + data.optics.parameters.znear, + data.optics.parameters.zfar + ); + break; - } + default: + camera = new PerspectiveCamera(); + break; - return primitive; + } - } + camera.name = data.name || ''; - function groupPrimitives(primitives) { + return camera; - var build = {}; + } - for (var i = 0; i < primitives.length; i++) { + function getCamera( id ) { - var primitive = primitives[i]; + const data = library.cameras[ id ]; - if (build[primitive.type] === undefined) build[primitive.type] = []; + if ( data !== undefined ) { - build[primitive.type].push(primitive); + return getBuild( data, buildCamera ); - } + } - return build; + console.warn( 'THREE.ColladaLoader: Couldn\'t find camera with ID:', id ); - } + return null; - function buildGeometry(data) { + } - var build = {}; + // light - var sources = data.sources; - var vertices = data.vertices; - var primitives = data.primitives; + function parseLight( xml ) { - if (primitives.length === 0) return {}; + let data = {}; - // our goal is to create one buffer geoemtry for a single type of primitives - // first, we group all primitives by their type + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var groupedPrimitives = groupPrimitives(primitives); + const child = xml.childNodes[ i ]; - for (var type in groupedPrimitives) { + if ( child.nodeType !== 1 ) continue; - // second, we create for each type of primitives (polylist,triangles or lines) a buffer geometry + switch ( child.nodeName ) { - build[type] = buildGeometryType(groupedPrimitives[type], sources, vertices); + case 'technique_common': + data = parseLightTechnique( child ); + break; - } + } - return build; + } - } + library.lights[ xml.getAttribute( 'id' ) ] = data; - function buildGeometryType(primitives, sources, vertices) { + } - var build = {}; + function parseLightTechnique( xml ) { - var position = { array: [], stride: 0 }; - var normal = { array: [], stride: 0 }; - var uv = { array: [], stride: 0 }; - var color = { array: [], stride: 0 }; + const data = {}; - var skinIndex = { array: [], stride: 4 }; - var skinWeight = { array: [], stride: 4 }; + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var geometry = new THREE.BufferGeometry(); + const child = xml.childNodes[ i ]; - var materialKeys = []; + if ( child.nodeType !== 1 ) continue; - var start = 0, count = 0; + switch ( child.nodeName ) { - for (var p = 0; p < primitives.length; p++) { + case 'directional': + case 'point': + case 'spot': + case 'ambient': - var primitive = primitives[p]; - var inputs = primitive.inputs; - var triangleCount = 1; + data.technique = child.nodeName; + data.parameters = parseLightParameters( child ); - if (primitive.vcount && primitive.vcount[0] === 4) { + } - triangleCount = 2; // one quad -> two triangles + } - } + return data; - // groups + } - if (primitive.type === 'lines' || primitive.type === 'linestrips') { + function parseLightParameters( xml ) { - count = primitive.count * 2; + const data = {}; - } else { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - count = primitive.count * 3 * triangleCount; + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - geometry.addGroup(start, count, p); - start += count; + switch ( child.nodeName ) { - // material + case 'color': + const array = parseFloats( child.textContent ); + data.color = new Color().fromArray( array ).convertSRGBToLinear(); + break; - if (primitive.material) { + case 'falloff_angle': + data.falloffAngle = parseFloat( child.textContent ); + break; - materialKeys.push(primitive.material); + case 'quadratic_attenuation': + const f = parseFloat( child.textContent ); + data.distance = f ? Math.sqrt( 1 / f ) : 0; + break; - } + } - // geometry data + } - for (var name in inputs) { + return data; - var input = inputs[name]; + } - switch (name) { + function buildLight( data ) { - case 'VERTEX': - for (var key in vertices) { + let light; - var id = vertices[key]; + switch ( data.technique ) { - switch (key) { + case 'directional': + light = new DirectionalLight(); + break; - case 'POSITION': - buildGeometryData(primitive, sources[id], input.offset, position.array); - position.stride = sources[id].stride; + case 'point': + light = new PointLight(); + break; - if (sources.skinWeights && sources.skinIndices) { + case 'spot': + light = new SpotLight(); + break; - buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array); - buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array); + case 'ambient': + light = new AmbientLight(); + break; - } - break; + } - case 'NORMAL': - buildGeometryData(primitive, sources[id], input.offset, normal.array); - normal.stride = sources[id].stride; - break; + if ( data.parameters.color ) light.color.copy( data.parameters.color ); + if ( data.parameters.distance ) light.distance = data.parameters.distance; - case 'COLOR': - buildGeometryData(primitive, sources[id], input.offset, color.array); - color.stride = sources[id].stride; - break; + return light; - case 'TEXCOORD': - buildGeometryData(primitive, sources[id], input.offset, uv.array); - uv.stride = sources[id].stride; - break; + } - default: - console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key); + function getLight( id ) { - } + const data = library.lights[ id ]; - } - break; + if ( data !== undefined ) { - case 'NORMAL': - buildGeometryData(primitive, sources[input.id], input.offset, normal.array); - normal.stride = sources[input.id].stride; - break; + return getBuild( data, buildLight ); - case 'COLOR': - buildGeometryData(primitive, sources[input.id], input.offset, color.array); - color.stride = sources[input.id].stride; - break; + } - case 'TEXCOORD': - buildGeometryData(primitive, sources[input.id], input.offset, uv.array); - uv.stride = sources[input.id].stride; - break; + console.warn( 'THREE.ColladaLoader: Couldn\'t find light with ID:', id ); - } + return null; - } + } - } + // geometry - // build geometry + function parseGeometry( xml ) { - if (position.array.length > 0) geometry.addAttribute('position', new THREE.Float32BufferAttribute(position.array, position.stride)); - if (normal.array.length > 0) geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normal.array, normal.stride)); - if (color.array.length > 0) geometry.addAttribute('color', new THREE.Float32BufferAttribute(color.array, color.stride)); - if (uv.array.length > 0) geometry.addAttribute('uv', new THREE.Float32BufferAttribute(uv.array, uv.stride)); + const data = { + name: xml.getAttribute( 'name' ), + sources: {}, + vertices: {}, + primitives: [] + }; - if (skinIndex.array.length > 0) geometry.addAttribute('skinIndex', new THREE.Float32BufferAttribute(skinIndex.array, skinIndex.stride)); - if (skinWeight.array.length > 0) geometry.addAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeight.array, skinWeight.stride)); + const mesh = getElementsByTagName( xml, 'mesh' )[ 0 ]; - build.data = geometry; - build.type = primitives[0].type; - build.materialKeys = materialKeys; + // the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep + if ( mesh === undefined ) return; - return build; + for ( let i = 0; i < mesh.childNodes.length; i ++ ) { - } + const child = mesh.childNodes[ i ]; - function buildGeometryData(primitive, source, offset, array) { + if ( child.nodeType !== 1 ) continue; - var indices = primitive.p; - var stride = primitive.stride; - var vcount = primitive.vcount; + const id = child.getAttribute( 'id' ); - function pushVector(i) { + switch ( child.nodeName ) { - var index = indices[i + offset] * sourceStride; - var length = index + sourceStride; + case 'source': + data.sources[ id ] = parseSource( child ); + break; - for (; index < length; index++) { + case 'vertices': + // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ]; + data.vertices = parseGeometryVertices( child ); + break; - array.push(sourceArray[index]); + case 'polygons': + console.warn( 'THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName ); + break; - } + case 'lines': + case 'linestrips': + case 'polylist': + case 'triangles': + data.primitives.push( parseGeometryPrimitive( child ) ); + break; - } + default: + console.log( child ); - var maxcount = 0; + } - var sourceArray = source.array; - var sourceStride = source.stride; + } - if (primitive.vcount !== undefined) { + library.geometries[ xml.getAttribute( 'id' ) ] = data; - var index = 0; + } - for (var i = 0, l = vcount.length; i < l; i++) { + function parseSource( xml ) { - var count = vcount[i]; + const data = { + array: [], + stride: 3 + }; - if (count === 4) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; - var d = index + stride * 3; + const child = xml.childNodes[ i ]; - pushVector(a); pushVector(b); pushVector(d); - pushVector(b); pushVector(c); pushVector(d); + if ( child.nodeType !== 1 ) continue; - } else if (count === 3) { + switch ( child.nodeName ) { - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; + case 'float_array': + data.array = parseFloats( child.textContent ); + break; - pushVector(a); pushVector(b); pushVector(c); + case 'Name_array': + data.array = parseStrings( child.textContent ); + break; - } else { + case 'technique_common': + const accessor = getElementsByTagName( child, 'accessor' )[ 0 ]; - maxcount = Math.max(maxcount, count); + if ( accessor !== undefined ) { - } + data.stride = parseInt( accessor.getAttribute( 'stride' ) ); - index += stride * count; + } - } + break; - if (maxcount > 0) { + } - console.log('THREE.ColladaLoader: Geometry has faces with more than 4 vertices.'); + } - } + return data; - } else { + } - for (var i = 0, l = indices.length; i < l; i += stride) { + function parseGeometryVertices( xml ) { - pushVector(i); + const data = {}; - } + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - function getGeometry(id) { + data[ child.getAttribute( 'semantic' ) ] = parseId( child.getAttribute( 'source' ) ); - return getBuild(library.geometries[id], buildGeometry); + } - } + return data; - // kinematics + } - function parseKinematicsModel(xml) { + function parseGeometryPrimitive( xml ) { - var data = { - name: xml.getAttribute('name') || '', - joints: {}, - links: [] - }; + const primitive = { + type: xml.nodeName, + material: xml.getAttribute( 'material' ), + count: parseInt( xml.getAttribute( 'count' ) ), + inputs: {}, + stride: 0, + hasUV: false + }; - for (var i = 0; i < xml.childNodes.length; i++) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[i]; + const child = xml.childNodes[ i ]; - if (child.nodeType !== 1) continue; + if ( child.nodeType !== 1 ) continue; - switch (child.nodeName) { + switch ( child.nodeName ) { - case 'technique_common': - parseKinematicsTechniqueCommon(child, data); - break; + case 'input': + const id = parseId( child.getAttribute( 'source' ) ); + const semantic = child.getAttribute( 'semantic' ); + const offset = parseInt( child.getAttribute( 'offset' ) ); + const set = parseInt( child.getAttribute( 'set' ) ); + const inputname = ( set > 0 ? semantic + set : semantic ); + primitive.inputs[ inputname ] = { id: id, offset: offset }; + primitive.stride = Math.max( primitive.stride, offset + 1 ); + if ( semantic === 'TEXCOORD' ) primitive.hasUV = true; + break; - } + case 'vcount': + primitive.vcount = parseInts( child.textContent ); + break; - } + case 'p': + primitive.p = parseInts( child.textContent ); + break; - library.kinematicsModels[xml.getAttribute('id')] = data; + } - } + } - function buildKinematicsModel(data) { + return primitive; - if (data.build !== undefined) return data.build; + } - return data; + function groupPrimitives( primitives ) { - } + const build = {}; - function getKinematicsModel(id) { + for ( let i = 0; i < primitives.length; i ++ ) { - return getBuild(library.kinematicsModels[id], buildKinematicsModel); + const primitive = primitives[ i ]; - } + if ( build[ primitive.type ] === undefined ) build[ primitive.type ] = []; - function parseKinematicsTechniqueCommon(xml, data) { + build[ primitive.type ].push( primitive ); - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + return build; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + function checkUVCoordinates( primitives ) { - case 'joint': - data.joints[child.getAttribute('sid')] = parseKinematicsJoint(child); - break; + let count = 0; - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + for ( let i = 0, l = primitives.length; i < l; i ++ ) { - } + const primitive = primitives[ i ]; - } + if ( primitive.hasUV === true ) { - } + count ++; - function parseKinematicsJoint(xml) { + } - var data; + } - for (var i = 0; i < xml.childNodes.length; i++) { + if ( count > 0 && count < primitives.length ) { - var child = xml.childNodes[i]; + primitives.uvsNeedsFix = true; - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + } - case 'prismatic': - case 'revolute': - data = parseKinematicsJointParameter(child); - break; + function buildGeometry( data ) { - } + const build = {}; - } + const sources = data.sources; + const vertices = data.vertices; + const primitives = data.primitives; - return data; + if ( primitives.length === 0 ) return {}; - } + // our goal is to create one buffer geometry for a single type of primitives + // first, we group all primitives by their type - function parseKinematicsJointParameter(xml, data) { + const groupedPrimitives = groupPrimitives( primitives ); - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - axis: new THREE.Vector3(), - limits: { - min: 0, - max: 0 - }, - type: xml.nodeName, - static: false, - zeroPosition: 0, - middlePosition: 0 - }; + for ( const type in groupedPrimitives ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const primitiveType = groupedPrimitives[ type ]; - var child = xml.childNodes[i]; + // second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines) - if (child.nodeType !== 1) continue; + checkUVCoordinates( primitiveType ); - switch (child.nodeName) { + // third, create a buffer geometry for each type of primitives - case 'axis': - var array = parseFloats(child.textContent); - data.axis.fromArray(array); - break; - case 'limits': - var max = child.getElementsByTagName('max')[0]; - var min = child.getElementsByTagName('min')[0]; + build[ type ] = buildGeometryType( primitiveType, sources, vertices ); - data.limits.max = parseFloat(max.textContent); - data.limits.min = parseFloat(min.textContent); - break; + } - } + return build; - } + } - // if min is equal to or greater than max, consider the joint static + function buildGeometryType( primitives, sources, vertices ) { - if (data.limits.min >= data.limits.max) { + const build = {}; - data.static = true; + const position = { array: [], stride: 0 }; + const normal = { array: [], stride: 0 }; + const uv = { array: [], stride: 0 }; + const uv1 = { array: [], stride: 0 }; + const color = { array: [], stride: 0 }; - } + const skinIndex = { array: [], stride: 4 }; + const skinWeight = { array: [], stride: 4 }; - // calculate middle position + const geometry = new BufferGeometry(); - data.middlePosition = (data.limits.min + data.limits.max) / 2.0; + const materialKeys = []; - return data; + let start = 0; - } + for ( let p = 0; p < primitives.length; p ++ ) { - function parseKinematicsLink(xml) { + const primitive = primitives[ p ]; + const inputs = primitive.inputs; - var data = { - sid: xml.getAttribute('sid'), - name: xml.getAttribute('name') || '', - attachments: [], - transforms: [] - }; + // groups - for (var i = 0; i < xml.childNodes.length; i++) { + let count = 0; - var child = xml.childNodes[i]; + switch ( primitive.type ) { - if (child.nodeType !== 1) continue; + case 'lines': + case 'linestrips': + count = primitive.count * 2; + break; - switch (child.nodeName) { + case 'triangles': + count = primitive.count * 3; + break; - case 'attachment_full': - data.attachments.push(parseKinematicsAttachment(child)); - break; + case 'polylist': - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + for ( let g = 0; g < primitive.count; g ++ ) { - } + const vc = primitive.vcount[ g ]; - } + switch ( vc ) { - return data; + case 3: + count += 3; // single triangle + break; - } + case 4: + count += 6; // quad, subdivided into two triangles + break; - function parseKinematicsAttachment(xml) { + default: + count += ( vc - 2 ) * 3; // polylist with more than four vertices + break; - var data = { - joint: xml.getAttribute('joint').split('/').pop(), - transforms: [], - links: [] - }; + } - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + break; - if (child.nodeType !== 1) continue; + default: + console.warn( 'THREE.ColladaLoader: Unknow primitive type:', primitive.type ); - switch (child.nodeName) { + } - case 'link': - data.links.push(parseKinematicsLink(child)); - break; + geometry.addGroup( start, count, p ); + start += count; - case 'matrix': - case 'translate': - case 'rotate': - data.transforms.push(parseKinematicsTransform(child)); - break; + // material - } + if ( primitive.material ) { - } + materialKeys.push( primitive.material ); - return data; + } - } + // geometry data - function parseKinematicsTransform(xml) { + for ( const name in inputs ) { - var data = { - type: xml.nodeName - }; + const input = inputs[ name ]; - var array = parseFloats(xml.textContent); + switch ( name ) { - switch (data.type) { + case 'VERTEX': + for ( const key in vertices ) { - case 'matrix': - data.obj = new THREE.Matrix4(); - data.obj.fromArray(array).transpose(); - break; + const id = vertices[ key ]; - case 'translate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - break; + switch ( key ) { - case 'rotate': - data.obj = new THREE.Vector3(); - data.obj.fromArray(array); - data.angle = THREE.Math.degToRad(array[3]); - break; + case 'POSITION': + const prevLength = position.array.length; + buildGeometryData( primitive, sources[ id ], input.offset, position.array ); + position.stride = sources[ id ].stride; - } + if ( sources.skinWeights && sources.skinIndices ) { - return data; + buildGeometryData( primitive, sources.skinIndices, input.offset, skinIndex.array ); + buildGeometryData( primitive, sources.skinWeights, input.offset, skinWeight.array ); - } + } - function parseKinematicsScene(xml) { + // see #3803 - var data = { - bindJointAxis: [] - }; + if ( primitive.hasUV === false && primitives.uvsNeedsFix === true ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const count = ( position.array.length - prevLength ) / position.stride; - var child = xml.childNodes[i]; + for ( let i = 0; i < count; i ++ ) { - if (child.nodeType !== 1) continue; + // fill missing uv coordinates - switch (child.nodeName) { + uv.array.push( 0, 0 ); - case 'bind_joint_axis': - data.bindJointAxis.push(parseKinematicsBindJointAxis(child)); - break; + } - } + } - } + break; - library.kinematicsScenes[parseId(xml.getAttribute('url'))] = data; + case 'NORMAL': + buildGeometryData( primitive, sources[ id ], input.offset, normal.array ); + normal.stride = sources[ id ].stride; + break; - } + case 'COLOR': + buildGeometryData( primitive, sources[ id ], input.offset, color.array ); + color.stride = sources[ id ].stride; + break; - function parseKinematicsBindJointAxis(xml) { + case 'TEXCOORD': + buildGeometryData( primitive, sources[ id ], input.offset, uv.array ); + uv.stride = sources[ id ].stride; + break; - var data = { - target: xml.getAttribute('target').split('/').pop() - }; + case 'TEXCOORD1': + buildGeometryData( primitive, sources[ id ], input.offset, uv1.array ); + uv.stride = sources[ id ].stride; + break; - for (var i = 0; i < xml.childNodes.length; i++) { + default: + console.warn( 'THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key ); - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + } - switch (child.nodeName) { + break; - case 'axis': - var param = child.getElementsByTagName('param')[0]; - data.axis = param.textContent; - var tmpJointIndex = data.axis.split('inst_').pop().split('axis')[0]; - data.jointIndex = tmpJointIndex.substr(0, tmpJointIndex.length - 1); - break; + case 'NORMAL': + buildGeometryData( primitive, sources[ input.id ], input.offset, normal.array ); + normal.stride = sources[ input.id ].stride; + break; - } + case 'COLOR': + buildGeometryData( primitive, sources[ input.id ], input.offset, color.array, true ); + color.stride = sources[ input.id ].stride; + break; - } + case 'TEXCOORD': + buildGeometryData( primitive, sources[ input.id ], input.offset, uv.array ); + uv.stride = sources[ input.id ].stride; + break; - return data; + case 'TEXCOORD1': + buildGeometryData( primitive, sources[ input.id ], input.offset, uv1.array ); + uv1.stride = sources[ input.id ].stride; + break; - } + } - function buildKinematicsScene(data) { + } - if (data.build !== undefined) return data.build; + } - return data; + // build geometry - } + if ( position.array.length > 0 ) geometry.setAttribute( 'position', new Float32BufferAttribute( position.array, position.stride ) ); + if ( normal.array.length > 0 ) geometry.setAttribute( 'normal', new Float32BufferAttribute( normal.array, normal.stride ) ); + if ( color.array.length > 0 ) geometry.setAttribute( 'color', new Float32BufferAttribute( color.array, color.stride ) ); + if ( uv.array.length > 0 ) geometry.setAttribute( 'uv', new Float32BufferAttribute( uv.array, uv.stride ) ); + if ( uv1.array.length > 0 ) geometry.setAttribute( 'uv1', new Float32BufferAttribute( uv1.array, uv1.stride ) ); - function getKinematicsScene(id) { + if ( skinIndex.array.length > 0 ) geometry.setAttribute( 'skinIndex', new Float32BufferAttribute( skinIndex.array, skinIndex.stride ) ); + if ( skinWeight.array.length > 0 ) geometry.setAttribute( 'skinWeight', new Float32BufferAttribute( skinWeight.array, skinWeight.stride ) ); - return getBuild(library.kinematicsScenes[id], buildKinematicsScene); + build.data = geometry; + build.type = primitives[ 0 ].type; + build.materialKeys = materialKeys; - } + return build; - function setupKinematics() { + } - var kinematicsModelId = Object.keys(library.kinematicsModels)[0]; - var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0]; - var visualSceneId = Object.keys(library.visualScenes)[0]; + function buildGeometryData( primitive, source, offset, array, isColor = false ) { - if (kinematicsModelId === undefined || kinematicsSceneId === undefined) return; + const indices = primitive.p; + const stride = primitive.stride; + const vcount = primitive.vcount; - var kinematicsModel = getKinematicsModel(kinematicsModelId); - var kinematicsScene = getKinematicsScene(kinematicsSceneId); - var visualScene = getVisualScene(visualSceneId); + function pushVector( i ) { - var bindJointAxis = kinematicsScene.bindJointAxis; - var jointMap = {}; + let index = indices[ i + offset ] * sourceStride; + const length = index + sourceStride; - for (var i = 0, l = bindJointAxis.length; i < l; i++) { + for ( ; index < length; index ++ ) { - var axis = bindJointAxis[i]; + array.push( sourceArray[ index ] ); - // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' + } - var targetElement = collada.querySelector('[sid="' + axis.target + '"]'); + if ( isColor ) { - if (targetElement) { + // convert the vertex colors from srgb to linear if present + const startIndex = array.length - sourceStride - 1; + tempColor.setRGB( + array[ startIndex + 0 ], + array[ startIndex + 1 ], + array[ startIndex + 2 ] + ).convertSRGBToLinear(); - // get the parent of the transfrom element + array[ startIndex + 0 ] = tempColor.r; + array[ startIndex + 1 ] = tempColor.g; + array[ startIndex + 2 ] = tempColor.b; - var parentVisualElement = targetElement.parentElement; + } - // connect the joint of the kinematics model with the element in the visual scene + } - connect(axis.jointIndex, parentVisualElement); + const sourceArray = source.array; + const sourceStride = source.stride; - } + if ( primitive.vcount !== undefined ) { - } + let index = 0; - function connect(jointIndex, visualElement) { + for ( let i = 0, l = vcount.length; i < l; i ++ ) { - var visualElementName = visualElement.getAttribute('name'); - var joint = kinematicsModel.joints[jointIndex]; + const count = vcount[ i ]; - visualScene.traverse(function (object) { + if ( count === 4 ) { - if (object.name === visualElementName) { + const a = index + stride * 0; + const b = index + stride * 1; + const c = index + stride * 2; + const d = index + stride * 3; - jointMap[jointIndex] = { - object: object, - transforms: buildTransformList(visualElement), - joint: joint, - position: joint.zeroPosition - }; + pushVector( a ); pushVector( b ); pushVector( d ); + pushVector( b ); pushVector( c ); pushVector( d ); - } + } else if ( count === 3 ) { - }); + const a = index + stride * 0; + const b = index + stride * 1; + const c = index + stride * 2; - } + pushVector( a ); pushVector( b ); pushVector( c ); - var m0 = new THREE.Matrix4(); + } else if ( count > 4 ) { - kinematics = { + for ( let k = 1, kl = ( count - 2 ); k <= kl; k ++ ) { - joints: kinematicsModel && kinematicsModel.joints, + const a = index + stride * 0; + const b = index + stride * k; + const c = index + stride * ( k + 1 ); - getJointValue: function (jointIndex) { + pushVector( a ); pushVector( b ); pushVector( c ); - var jointData = jointMap[jointIndex]; + } - if (jointData) { + } - return jointData.position; + index += stride * count; - } else { + } - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.'); + } else { - } + for ( let i = 0, l = indices.length; i < l; i += stride ) { - }, + pushVector( i ); - setJointValue: function (jointIndex, value) { + } - var jointData = jointMap[jointIndex]; + } - if (jointData) { + } - var joint = jointData.joint; + function getGeometry( id ) { - if (value > joint.limits.max || value < joint.limits.min) { + return getBuild( library.geometries[ id ], buildGeometry ); - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').'); + } - } else if (joint.static) { + // kinematics - console.warn('THREE.ColladaLoader: Joint ' + jointIndex + ' is static.'); + function parseKinematicsModel( xml ) { - } else { + const data = { + name: xml.getAttribute( 'name' ) || '', + joints: {}, + links: [] + }; - var object = jointData.object; - var axis = joint.axis; - var transforms = jointData.transforms; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - matrix.identity(); + const child = xml.childNodes[ i ]; - // each update, we have to apply all transforms in the correct order + if ( child.nodeType !== 1 ) continue; - for (var i = 0; i < transforms.length; i++) { + switch ( child.nodeName ) { - var transform = transforms[i]; + case 'technique_common': + parseKinematicsTechniqueCommon( child, data ); + break; - // if there is a connection of the transform node with a joint, apply the joint value + } - if (transform.sid && transform.sid.indexOf(jointIndex) !== - 1) { + } - switch (joint.type) { + library.kinematicsModels[ xml.getAttribute( 'id' ) ] = data; - case 'revolute': - matrix.multiply(m0.makeRotationAxis(axis, THREE.Math.degToRad(value))); - break; + } - case 'prismatic': - matrix.multiply(m0.makeTranslation(axis.x * value, axis.y * value, axis.z * value)); - break; + function buildKinematicsModel( data ) { - default: - console.warn('THREE.ColladaLoader: Unknown joint type: ' + joint.type); - break; + if ( data.build !== undefined ) return data.build; - } + return data; - } else { + } - switch (transform.type) { + function getKinematicsModel( id ) { - case 'matrix': - matrix.multiply(transform.obj); - break; + return getBuild( library.kinematicsModels[ id ], buildKinematicsModel ); - case 'translate': - matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z)); - break; + } - case 'scale': - matrix.scale(transform.obj); - break; + function parseKinematicsTechniqueCommon( xml, data ) { - case 'rotate': - matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle)); - break; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + case 'joint': + data.joints[ child.getAttribute( 'sid' ) ] = parseKinematicsJoint( child ); + break; - jointMap[jointIndex].position = value; + case 'link': + data.links.push( parseKinematicsLink( child ) ); + break; - } + } - } else { + } - console.log('THREE.ColladaLoader: ' + jointIndex + ' does not exist.'); + } - } + function parseKinematicsJoint( xml ) { - } + let data; - }; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - function buildTransformList(node) { + if ( child.nodeType !== 1 ) continue; - var transforms = []; + switch ( child.nodeName ) { - var xml = collada.querySelector('[id="' + node.id + '"]'); + case 'prismatic': + case 'revolute': + data = parseKinematicsJointParameter( child ); + break; - for (var i = 0; i < xml.childNodes.length; i++) { + } - var child = xml.childNodes[i]; + } - if (child.nodeType !== 1) continue; + return data; - switch (child.nodeName) { + } - case 'matrix': - var array = parseFloats(child.textContent); - var matrix = new THREE.Matrix4().fromArray(array).transpose(); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: matrix - }); - break; + function parseKinematicsJointParameter( xml ) { - case 'translate': - case 'scale': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector - }); - break; + const data = { + sid: xml.getAttribute( 'sid' ), + name: xml.getAttribute( 'name' ) || '', + axis: new Vector3(), + limits: { + min: 0, + max: 0 + }, + type: xml.nodeName, + static: false, + zeroPosition: 0, + middlePosition: 0 + }; - case 'rotate': - var array = parseFloats(child.textContent); - var vector = new THREE.Vector3().fromArray(array); - var angle = THREE.Math.degToRad(array[3]); - transforms.push({ - sid: child.getAttribute('sid'), - type: child.nodeName, - obj: vector, - angle: angle - }); - break; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - return transforms; + switch ( child.nodeName ) { - } + case 'axis': + const array = parseFloats( child.textContent ); + data.axis.fromArray( array ); + break; + case 'limits': + const max = child.getElementsByTagName( 'max' )[ 0 ]; + const min = child.getElementsByTagName( 'min' )[ 0 ]; - // nodes + data.limits.max = parseFloat( max.textContent ); + data.limits.min = parseFloat( min.textContent ); + break; - function prepareNodes(xml) { + } - var elements = xml.getElementsByTagName('node'); + } - // ensure all node elements have id attributes + // if min is equal to or greater than max, consider the joint static - for (var i = 0; i < elements.length; i++) { + if ( data.limits.min >= data.limits.max ) { - var element = elements[i]; + data.static = true; - if (element.hasAttribute('id') === false) { + } - element.setAttribute('id', generateId()); + // calculate middle position - } + data.middlePosition = ( data.limits.min + data.limits.max ) / 2.0; - } + return data; - } + } - var matrix = new THREE.Matrix4(); - var vector = new THREE.Vector3(); + function parseKinematicsLink( xml ) { - function parseNode(xml) { + const data = { + sid: xml.getAttribute( 'sid' ), + name: xml.getAttribute( 'name' ) || '', + attachments: [], + transforms: [] + }; - var data = { - name: xml.getAttribute('name') || '', - type: xml.getAttribute('type'), - id: xml.getAttribute('id'), - sid: xml.getAttribute('sid'), - matrix: new THREE.Matrix4(), - nodes: [], - instanceCameras: [], - instanceControllers: [], - instanceLights: [], - instanceGeometries: [], - instanceNodes: [], - transforms: {} - }; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - for (var i = 0; i < xml.childNodes.length; i++) { + const child = xml.childNodes[ i ]; - var child = xml.childNodes[i]; + if ( child.nodeType !== 1 ) continue; - if (child.nodeType !== 1) continue; + switch ( child.nodeName ) { - switch (child.nodeName) { + case 'attachment_full': + data.attachments.push( parseKinematicsAttachment( child ) ); + break; - case 'node': - data.nodes.push(child.getAttribute('id')); - parseNode(child); - break; + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push( parseKinematicsTransform( child ) ); + break; - case 'instance_camera': - data.instanceCameras.push(parseId(child.getAttribute('url'))); - break; + } - case 'instance_controller': - data.instanceControllers.push(parseNodeInstance(child)); - break; + } - case 'instance_light': - data.instanceLights.push(parseId(child.getAttribute('url'))); - break; + return data; - case 'instance_geometry': - data.instanceGeometries.push(parseNodeInstance(child)); - break; + } - case 'instance_node': - data.instanceNodes.push(parseId(child.getAttribute('url'))); - break; + function parseKinematicsAttachment( xml ) { - case 'matrix': - var array = parseFloats(child.textContent); - data.matrix.multiply(matrix.fromArray(array).transpose()); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + const data = { + joint: xml.getAttribute( 'joint' ).split( '/' ).pop(), + transforms: [], + links: [] + }; - case 'translate': - var array = parseFloats(child.textContent); - vector.fromArray(array); - data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - case 'rotate': - var array = parseFloats(child.textContent); - var angle = THREE.Math.degToRad(array[3]); - data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + const child = xml.childNodes[ i ]; - case 'scale': - var array = parseFloats(child.textContent); - data.matrix.scale(vector.fromArray(array)); - data.transforms[child.getAttribute('sid')] = child.nodeName; - break; + if ( child.nodeType !== 1 ) continue; - case 'extra': - break; + switch ( child.nodeName ) { - default: - console.log(child); + case 'link': + data.links.push( parseKinematicsLink( child ) ); + break; - } + case 'matrix': + case 'translate': + case 'rotate': + data.transforms.push( parseKinematicsTransform( child ) ); + break; - } + } - library.nodes[data.id] = data; + } - return data; + return data; - } + } - function parseNodeInstance(xml) { + function parseKinematicsTransform( xml ) { - var data = { - id: parseId(xml.getAttribute('url')), - materials: {}, - skeletons: [] - }; + const data = { + type: xml.nodeName + }; - for (var i = 0; i < xml.childNodes.length; i++) { + const array = parseFloats( xml.textContent ); - var child = xml.childNodes[i]; + switch ( data.type ) { - switch (child.nodeName) { + case 'matrix': + data.obj = new Matrix4(); + data.obj.fromArray( array ).transpose(); + break; - case 'bind_material': - var instances = child.getElementsByTagName('instance_material'); + case 'translate': + data.obj = new Vector3(); + data.obj.fromArray( array ); + break; - for (var j = 0; j < instances.length; j++) { + case 'rotate': + data.obj = new Vector3(); + data.obj.fromArray( array ); + data.angle = MathUtils.degToRad( array[ 3 ] ); + break; - var instance = instances[j]; - var symbol = instance.getAttribute('symbol'); - var target = instance.getAttribute('target'); + } - data.materials[symbol] = parseId(target); + return data; - } + } - break; + // physics - case 'skeleton': - data.skeletons.push(parseId(child.textContent)); - break; + function parsePhysicsModel( xml ) { - default: - break; + const data = { + name: xml.getAttribute( 'name' ) || '', + rigidBodies: {} + }; - } + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - return data; + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - function buildSkeleton(skeletons, joints) { + case 'rigid_body': + data.rigidBodies[ child.getAttribute( 'name' ) ] = {}; + parsePhysicsRigidBody( child, data.rigidBodies[ child.getAttribute( 'name' ) ] ); + break; - var boneData = []; - var sortedBoneData = []; + } - var i, j, data; + } - // a skeleton can have multiple root bones. collada expresses this - // situtation with multiple "skeleton" tags per controller instance + library.physicsModels[ xml.getAttribute( 'id' ) ] = data; - for (i = 0; i < skeletons.length; i++) { + } - var skeleton = skeletons[i]; - var root = getNode(skeleton); + function parsePhysicsRigidBody( xml, data ) { - // setup bone data for a single bone hierarchy + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - buildBoneHierarchy(root, joints, boneData); + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - // sort bone data (the order is defined in the corresponding controller) + switch ( child.nodeName ) { - for (i = 0; i < joints.length; i++) { + case 'technique_common': + parsePhysicsTechniqueCommon( child, data ); + break; - for (j = 0; j < boneData.length; j++) { + } - data = boneData[j]; + } - if (data.bone.name === joints[i].name) { + } - sortedBoneData[i] = data; - data.processed = true; - break; + function parsePhysicsTechniqueCommon( xml, data ) { - } + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - } + if ( child.nodeType !== 1 ) continue; - // add unprocessed bone data at the end of the list + switch ( child.nodeName ) { - for (i = 0; i < boneData.length; i++) { + case 'inertia': + data.inertia = parseFloats( child.textContent ); + break; - data = boneData[i]; + case 'mass': + data.mass = parseFloats( child.textContent )[ 0 ]; + break; - if (data.processed === false) { + } - sortedBoneData.push(data); - data.processed = true; + } - } + } - } + // scene - // setup arrays for skeleton creation + function parseKinematicsScene( xml ) { - var bones = []; - var boneInverses = []; + const data = { + bindJointAxis: [] + }; - for (i = 0; i < sortedBoneData.length; i++) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - data = sortedBoneData[i]; + const child = xml.childNodes[ i ]; - bones.push(data.bone); - boneInverses.push(data.boneInverse); + if ( child.nodeType !== 1 ) continue; - } + switch ( child.nodeName ) { - return new THREE.Skeleton(bones, boneInverses); + case 'bind_joint_axis': + data.bindJointAxis.push( parseKinematicsBindJointAxis( child ) ); + break; - } + } - function buildBoneHierarchy(root, joints, boneData) { + } - // setup bone data from visual scene + library.kinematicsScenes[ parseId( xml.getAttribute( 'url' ) ) ] = data; - root.traverse(function (object) { + } - if (object.isBone === true) { + function parseKinematicsBindJointAxis( xml ) { - var boneInverse; + const data = { + target: xml.getAttribute( 'target' ).split( '/' ).pop() + }; - // retrieve the boneInverse from the controller data + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - for (var i = 0; i < joints.length; i++) { + const child = xml.childNodes[ i ]; - var joint = joints[i]; + if ( child.nodeType !== 1 ) continue; - if (joint.name === object.name) { + switch ( child.nodeName ) { - boneInverse = joint.boneInverse; - break; + case 'axis': + const param = child.getElementsByTagName( 'param' )[ 0 ]; + data.axis = param.textContent; + const tmpJointIndex = data.axis.split( 'inst_' ).pop().split( 'axis' )[ 0 ]; + data.jointIndex = tmpJointIndex.substring( 0, tmpJointIndex.length - 1 ); + break; - } + } - } + } - if (boneInverse === undefined) { + return data; - // Unfortunately, there can be joints in the visual scene that are not part of the - // corresponding controller. In this case, we have to create a dummy boneInverse matrix - // for the respective bone. This bone won't affect any vertices, because there are no skin indices - // and weights defined for it. But we still have to add the bone to the sorted bone list in order to - // ensure a correct animation of the model. + } - boneInverse = new THREE.Matrix4(); + function buildKinematicsScene( data ) { - } + if ( data.build !== undefined ) return data.build; - boneData.push({ bone: object, boneInverse: boneInverse, processed: false }); + return data; - } + } - }); + function getKinematicsScene( id ) { - } + return getBuild( library.kinematicsScenes[ id ], buildKinematicsScene ); - function buildNode(data) { + } - var objects = []; + function setupKinematics() { - var matrix = data.matrix; - var nodes = data.nodes; - var type = data.type; - var instanceCameras = data.instanceCameras; - var instanceControllers = data.instanceControllers; - var instanceLights = data.instanceLights; - var instanceGeometries = data.instanceGeometries; - var instanceNodes = data.instanceNodes; + const kinematicsModelId = Object.keys( library.kinematicsModels )[ 0 ]; + const kinematicsSceneId = Object.keys( library.kinematicsScenes )[ 0 ]; + const visualSceneId = Object.keys( library.visualScenes )[ 0 ]; - // nodes + if ( kinematicsModelId === undefined || kinematicsSceneId === undefined ) return; - for (var i = 0, l = nodes.length; i < l; i++) { + const kinematicsModel = getKinematicsModel( kinematicsModelId ); + const kinematicsScene = getKinematicsScene( kinematicsSceneId ); + const visualScene = getVisualScene( visualSceneId ); - objects.push(getNode(nodes[i])); + const bindJointAxis = kinematicsScene.bindJointAxis; + const jointMap = {}; - } + for ( let i = 0, l = bindJointAxis.length; i < l; i ++ ) { - // instance cameras + const axis = bindJointAxis[ i ]; - for (var i = 0, l = instanceCameras.length; i < l; i++) { + // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' - var instanceCamera = getCamera(instanceCameras[i]); + const targetElement = collada.querySelector( '[sid="' + axis.target + '"]' ); - if (instanceCamera !== null) { + if ( targetElement ) { - objects.push(instanceCamera.clone()); + // get the parent of the transform element - } + const parentVisualElement = targetElement.parentElement; + // connect the joint of the kinematics model with the element in the visual scene - } + connect( axis.jointIndex, parentVisualElement ); - // instance controllers + } - for (var i = 0, l = instanceControllers.length; i < l; i++) { + } - var instance = instanceControllers[i]; - var controller = getController(instance.id); - var geometries = getGeometry(controller.id); - var newObjects = buildObjects(geometries, instance.materials); + function connect( jointIndex, visualElement ) { - var skeletons = instance.skeletons; - var joints = controller.skin.joints; + const visualElementName = visualElement.getAttribute( 'name' ); + const joint = kinematicsModel.joints[ jointIndex ]; - var skeleton = buildSkeleton(skeletons, joints); + visualScene.traverse( function ( object ) { - for (var j = 0, jl = newObjects.length; j < jl; j++) { + if ( object.name === visualElementName ) { - var object = newObjects[j]; + jointMap[ jointIndex ] = { + object: object, + transforms: buildTransformList( visualElement ), + joint: joint, + position: joint.zeroPosition + }; - if (object.isSkinnedMesh) { + } - object.bind(skeleton, controller.skin.bindMatrix); - object.normalizeSkinWeights(); + } ); - } + } - objects.push(object); + const m0 = new Matrix4(); - } + kinematics = { - } + joints: kinematicsModel && kinematicsModel.joints, - // instance lights + getJointValue: function ( jointIndex ) { - for (var i = 0, l = instanceLights.length; i < l; i++) { - var instanceCamera = getCamera(instanceCameras[i]); + const jointData = jointMap[ jointIndex ]; - if (instanceCamera !== null) { + if ( jointData ) { - objects.push(instanceCamera.clone()); + return jointData.position; - } + } else { - } + console.warn( 'THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\'t exist.' ); - // instance geometries + } - for (var i = 0, l = instanceGeometries.length; i < l; i++) { + }, - var instance = instanceGeometries[i]; + setJointValue: function ( jointIndex, value ) { - // a single geometry instance in collada can lead to multiple object3Ds. - // this is the case when primitives are combined like triangles and lines + const jointData = jointMap[ jointIndex ]; - var geometries = getGeometry(instance.id); - var newObjects = buildObjects(geometries, instance.materials); + if ( jointData ) { - for (var j = 0, jl = newObjects.length; j < jl; j++) { + const joint = jointData.joint; - objects.push(newObjects[j]); + if ( value > joint.limits.max || value < joint.limits.min ) { - } + console.warn( 'THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').' ); - } + } else if ( joint.static ) { - // instance nodes + console.warn( 'THREE.ColladaLoader: Joint ' + jointIndex + ' is static.' ); - for (var i = 0, l = instanceNodes.length; i < l; i++) { + } else { - objects.push(getNode(instanceNodes[i]).clone()); + const object = jointData.object; + const axis = joint.axis; + const transforms = jointData.transforms; - } + matrix.identity(); - var object; + // each update, we have to apply all transforms in the correct order - if (nodes.length === 0 && objects.length === 1) { + for ( let i = 0; i < transforms.length; i ++ ) { - object = objects[0]; + const transform = transforms[ i ]; - } else { + // if there is a connection of the transform node with a joint, apply the joint value - object = (type === 'JOINT') ? new THREE.Bone() : new THREE.Object3D(); + if ( transform.sid && transform.sid.indexOf( jointIndex ) !== - 1 ) { - for (var i = 0; i < objects.length; i++) { + switch ( joint.type ) { - object.add(objects[i]); + case 'revolute': + matrix.multiply( m0.makeRotationAxis( axis, MathUtils.degToRad( value ) ) ); + break; - } + case 'prismatic': + matrix.multiply( m0.makeTranslation( axis.x * value, axis.y * value, axis.z * value ) ); + break; - } + default: + console.warn( 'THREE.ColladaLoader: Unknown joint type: ' + joint.type ); + break; - object.name = (type === 'JOINT') ? data.sid : data.name; - object.matrix.copy(matrix); - object.matrix.decompose(object.position, object.quaternion, object.scale); + } - return object; + } else { - } + switch ( transform.type ) { - function resolveMaterialBinding(keys, instanceMaterials) { + case 'matrix': + matrix.multiply( transform.obj ); + break; - var materials = []; + case 'translate': + matrix.multiply( m0.makeTranslation( transform.obj.x, transform.obj.y, transform.obj.z ) ); + break; - for (var i = 0, l = keys.length; i < l; i++) { + case 'scale': + matrix.scale( transform.obj ); + break; - var id = instanceMaterials[keys[i]]; - materials.push(getMaterial(id)); + case 'rotate': + matrix.multiply( m0.makeRotationAxis( transform.obj, transform.angle ) ); + break; - } + } - return materials; + } - } + } - function buildObjects(geometries, instanceMaterials) { + object.matrix.copy( matrix ); + object.matrix.decompose( object.position, object.quaternion, object.scale ); - var objects = []; + jointMap[ jointIndex ].position = value; - for (var type in geometries) { + } - var geometry = geometries[type]; + } else { - var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); + console.log( 'THREE.ColladaLoader: ' + jointIndex + ' does not exist.' ); - // handle case if no materials are defined + } - if (materials.length === 0) { + } - if (type === 'lines' || type === 'linestrips') { + }; - materials.push(new THREE.LineBasicMaterial()); + } - } else { + function buildTransformList( node ) { - materials.push(new THREE.MeshPhongMaterial()); + const transforms = []; - } + const xml = collada.querySelector( '[id="' + node.id + '"]' ); - } + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - // regard skinning + const child = xml.childNodes[ i ]; - var skinning = (geometry.data.attributes.skinIndex !== undefined); + if ( child.nodeType !== 1 ) continue; - if (skinning) { + let array, vector; - for (var i = 0, l = materials.length; i < l; i++) { + switch ( child.nodeName ) { - materials[i].skinning = true; + case 'matrix': + array = parseFloats( child.textContent ); + const matrix = new Matrix4().fromArray( array ).transpose(); + transforms.push( { + sid: child.getAttribute( 'sid' ), + type: child.nodeName, + obj: matrix + } ); + break; - } + case 'translate': + case 'scale': + array = parseFloats( child.textContent ); + vector = new Vector3().fromArray( array ); + transforms.push( { + sid: child.getAttribute( 'sid' ), + type: child.nodeName, + obj: vector + } ); + break; - } + case 'rotate': + array = parseFloats( child.textContent ); + vector = new Vector3().fromArray( array ); + const angle = MathUtils.degToRad( array[ 3 ] ); + transforms.push( { + sid: child.getAttribute( 'sid' ), + type: child.nodeName, + obj: vector, + angle: angle + } ); + break; - // choose between a single or multi materials (material array) + } - var material = (materials.length === 1) ? materials[0] : materials; + } - // now create a specific 3D object + return transforms; - var object; + } - switch (type) { + // nodes - case 'lines': - object = new THREE.LineSegments(geometry.data, material); - break; + function prepareNodes( xml ) { - case 'linestrips': - object = new THREE.Line(geometry.data, material); - break; + const elements = xml.getElementsByTagName( 'node' ); - case 'triangles': - case 'polylist': - if (skinning) { + // ensure all node elements have id attributes - object = new THREE.SkinnedMesh(geometry.data, material); + for ( let i = 0; i < elements.length; i ++ ) { - } else { + const element = elements[ i ]; - object = new THREE.Mesh(geometry.data, material); + if ( element.hasAttribute( 'id' ) === false ) { - } - break; + element.setAttribute( 'id', generateId() ); - } + } - objects.push(object); + } - } + } - return objects; + const matrix = new Matrix4(); + const vector = new Vector3(); - } + function parseNode( xml ) { - function getNode(id) { + const data = { + name: xml.getAttribute( 'name' ) || '', + type: xml.getAttribute( 'type' ), + id: xml.getAttribute( 'id' ), + sid: xml.getAttribute( 'sid' ), + matrix: new Matrix4(), + nodes: [], + instanceCameras: [], + instanceControllers: [], + instanceLights: [], + instanceGeometries: [], + instanceNodes: [], + transforms: {} + }; - return getBuild(library.nodes[id], buildNode); + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - } + const child = xml.childNodes[ i ]; - // visual scenes + if ( child.nodeType !== 1 ) continue; - function parseVisualScene(xml) { + let array; - var data = { - name: xml.getAttribute('name'), - children: [] - }; + switch ( child.nodeName ) { - prepareNodes(xml); + case 'node': + data.nodes.push( child.getAttribute( 'id' ) ); + parseNode( child ); + break; - var elements = getElementsByTagName(xml, 'node'); + case 'instance_camera': + data.instanceCameras.push( parseId( child.getAttribute( 'url' ) ) ); + break; - for (var i = 0; i < elements.length; i++) { + case 'instance_controller': + data.instanceControllers.push( parseNodeInstance( child ) ); + break; - data.children.push(parseNode(elements[i])); + case 'instance_light': + data.instanceLights.push( parseId( child.getAttribute( 'url' ) ) ); + break; - } + case 'instance_geometry': + data.instanceGeometries.push( parseNodeInstance( child ) ); + break; - library.visualScenes[xml.getAttribute('id')] = data; + case 'instance_node': + data.instanceNodes.push( parseId( child.getAttribute( 'url' ) ) ); + break; - } + case 'matrix': + array = parseFloats( child.textContent ); + data.matrix.multiply( matrix.fromArray( array ).transpose() ); + data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; + break; - function buildVisualScene(data) { + case 'translate': + array = parseFloats( child.textContent ); + vector.fromArray( array ); + data.matrix.multiply( matrix.makeTranslation( vector.x, vector.y, vector.z ) ); + data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; + break; - var group = new THREE.Object3D(); - group.name = data.name; + case 'rotate': + array = parseFloats( child.textContent ); + const angle = MathUtils.degToRad( array[ 3 ] ); + data.matrix.multiply( matrix.makeRotationAxis( vector.fromArray( array ), angle ) ); + data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; + break; - var children = data.children; + case 'scale': + array = parseFloats( child.textContent ); + data.matrix.scale( vector.fromArray( array ) ); + data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; + break; - for (var i = 0; i < children.length; i++) { + case 'extra': + break; - var child = children[i]; + default: + console.log( child ); - if (child.id === null) { + } - group.add(buildNode(child)); + } - } else { + if ( hasNode( data.id ) ) { - // if there is an ID, let's try to get the finished build (e.g. joints are already build) + console.warn( 'THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id ); - group.add(getNode(child.id)); + } else { - } + library.nodes[ data.id ] = data; - } + } - return group; + return data; - } + } - function getVisualScene(id) { + function parseNodeInstance( xml ) { - return getBuild(library.visualScenes[id], buildVisualScene); + const data = { + id: parseId( xml.getAttribute( 'url' ) ), + materials: {}, + skeletons: [] + }; - } + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - // scenes + const child = xml.childNodes[ i ]; - function parseScene(xml) { + switch ( child.nodeName ) { - var instance = getElementsByTagName(xml, 'instance_visual_scene')[0]; - return getVisualScene(parseId(instance.getAttribute('url'))); + case 'bind_material': + const instances = child.getElementsByTagName( 'instance_material' ); - } + for ( let j = 0; j < instances.length; j ++ ) { - function setupAnimations() { + const instance = instances[ j ]; + const symbol = instance.getAttribute( 'symbol' ); + const target = instance.getAttribute( 'target' ); - var clips = library.clips; + data.materials[ symbol ] = parseId( target ); - if (isEmpty(clips) === true) { + } - if (isEmpty(library.animations) === false) { + break; - // if there are animations but no clips, we create a default clip for playback + case 'skeleton': + data.skeletons.push( parseId( child.textContent ) ); + break; - var tracks = []; + default: + break; - for (var id in library.animations) { + } - var animationTracks = getAnimation(id); + } - for (var i = 0, l = animationTracks.length; i < l; i++) { + return data; - tracks.push(animationTracks[i]); + } - } + function buildSkeleton( skeletons, joints ) { - } + const boneData = []; + const sortedBoneData = []; - animations.push(new THREE.AnimationClip('default', - 1, tracks)); + let i, j, data; - } + // a skeleton can have multiple root bones. collada expresses this + // situtation with multiple "skeleton" tags per controller instance - } else { + for ( i = 0; i < skeletons.length; i ++ ) { - for (var id in clips) { + const skeleton = skeletons[ i ]; - animations.push(getAnimationClip(id)); + let root; - } + if ( hasNode( skeleton ) ) { - } + root = getNode( skeleton ); + buildBoneHierarchy( root, joints, boneData ); - } + } else if ( hasVisualScene( skeleton ) ) { - console.time('THREE.ColladaLoader'); + // handle case where the skeleton refers to the visual scene (#13335) - if (text.length === 0) { + const visualScene = library.visualScenes[ skeleton ]; + const children = visualScene.children; - return { scene: new THREE.Scene() }; + for ( let j = 0; j < children.length; j ++ ) { - } + const child = children[ j ]; - console.time('THREE.ColladaLoader: DOMParser'); + if ( child.type === 'JOINT' ) { - var xml = new DOMParser().parseFromString(text, 'application/xml'); + const root = getNode( child.id ); + buildBoneHierarchy( root, joints, boneData ); - console.timeEnd('THREE.ColladaLoader: DOMParser'); + } - var collada = getElementsByTagName(xml, 'COLLADA')[0]; + } - // metadata + } else { - var version = collada.getAttribute('version'); - console.log('THREE.ColladaLoader: File version', version); + console.error( 'THREE.ColladaLoader: Unable to find root bone of skeleton with ID:', skeleton ); - var asset = parseAsset(getElementsByTagName(collada, 'asset')[0]); - var textureLoader = new THREE.TextureLoader(this.manager); - textureLoader.setPath(path).setCrossOrigin(this.crossOrigin); + } - // + } - var animations = []; - var kinematics = {}; - var count = 0; + // sort bone data (the order is defined in the corresponding controller) - // + for ( i = 0; i < joints.length; i ++ ) { - var library = { - animations: {}, - clips: {}, - controllers: {}, - images: {}, - effects: {}, - materials: {}, - cameras: {}, - lights: {}, - geometries: {}, - nodes: {}, - visualScenes: {}, - kinematicsModels: {}, - kinematicsScenes: {} - }; + for ( j = 0; j < boneData.length; j ++ ) { - console.time('THREE.ColladaLoader: Parse'); + data = boneData[ j ]; - parseLibrary(collada, 'library_animations', 'animation', parseAnimation); - parseLibrary(collada, 'library_animation_clips', 'animation_clip', parseAnimationClip); - parseLibrary(collada, 'library_controllers', 'controller', parseController); - parseLibrary(collada, 'library_images', 'image', parseImage); - parseLibrary(collada, 'library_effects', 'effect', parseEffect); - parseLibrary(collada, 'library_materials', 'material', parseMaterial); - parseLibrary(collada, 'library_cameras', 'camera', parseCamera); - parseLibrary(collada, 'library_lights', 'light', parseLight); - parseLibrary(collada, 'library_geometries', 'geometry', parseGeometry); - parseLibrary(collada, 'library_nodes', 'node', parseNode); - parseLibrary(collada, 'library_visual_scenes', 'visual_scene', parseVisualScene); - parseLibrary(collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel); - parseLibrary(collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene); + if ( data.bone.name === joints[ i ].name ) { - console.timeEnd('THREE.ColladaLoader: Parse'); + sortedBoneData[ i ] = data; + data.processed = true; + break; - console.time('THREE.ColladaLoader: Build'); + } - buildLibrary(library.animations, buildAnimation); - buildLibrary(library.clips, buildAnimationClip); - buildLibrary(library.controllers, buildController); - buildLibrary(library.images, buildImage); - buildLibrary(library.effects, buildEffect); - buildLibrary(library.materials, buildMaterial); - buildLibrary(library.cameras, buildCamera); - buildLibrary(library.lights, buildLight); - buildLibrary(library.geometries, buildGeometry); - buildLibrary(library.visualScenes, buildVisualScene); + } - console.timeEnd('THREE.ColladaLoader: Build'); + } - setupAnimations(); - setupKinematics(); + // add unprocessed bone data at the end of the list - var scene = parseScene(getElementsByTagName(collada, 'scene')[0]); + for ( i = 0; i < boneData.length; i ++ ) { - /* - * up_axis of some robot models in ROS world aren't properly set because - * rviz ignores this field. Thus, ignores Z_UP to show urdfs just like rviz. - * See https://github.com/ros-visualization/rviz/issues/1045 for the detail - if ( asset.upAxis === 'Z_UP' ) { + data = boneData[ i ]; - scene.rotation.x = - Math.PI / 2; + if ( data.processed === false ) { - } - */ + sortedBoneData.push( data ); + data.processed = true; - scene.scale.multiplyScalar(asset.unit); + } - console.timeEnd('THREE.ColladaLoader'); + } - return { - animations: animations, - kinematics: kinematics, - library: library, - scene: scene - }; + // setup arrays for skeleton creation - } + const bones = []; + const boneInverses = []; -}; + for ( i = 0; i < sortedBoneData.length; i ++ ) { + + data = sortedBoneData[ i ]; + + bones.push( data.bone ); + boneInverses.push( data.boneInverse ); + + } + + return new Skeleton( bones, boneInverses ); + + } + + function buildBoneHierarchy( root, joints, boneData ) { + + // setup bone data from visual scene + + root.traverse( function ( object ) { + + if ( object.isBone === true ) { + + let boneInverse; + + // retrieve the boneInverse from the controller data + + for ( let i = 0; i < joints.length; i ++ ) { + + const joint = joints[ i ]; + + if ( joint.name === object.name ) { + + boneInverse = joint.boneInverse; + break; + + } + + } + + if ( boneInverse === undefined ) { + + // Unfortunately, there can be joints in the visual scene that are not part of the + // corresponding controller. In this case, we have to create a dummy boneInverse matrix + // for the respective bone. This bone won't affect any vertices, because there are no skin indices + // and weights defined for it. But we still have to add the bone to the sorted bone list in order to + // ensure a correct animation of the model. + + boneInverse = new Matrix4(); + + } + + boneData.push( { bone: object, boneInverse: boneInverse, processed: false } ); + + } + + } ); + + } + + function buildNode( data ) { + + const objects = []; + + const matrix = data.matrix; + const nodes = data.nodes; + const type = data.type; + const instanceCameras = data.instanceCameras; + const instanceControllers = data.instanceControllers; + const instanceLights = data.instanceLights; + const instanceGeometries = data.instanceGeometries; + const instanceNodes = data.instanceNodes; + + // nodes + + for ( let i = 0, l = nodes.length; i < l; i ++ ) { + + objects.push( getNode( nodes[ i ] ) ); + + } + + // instance cameras + + for ( let i = 0, l = instanceCameras.length; i < l; i ++ ) { + + const instanceCamera = getCamera( instanceCameras[ i ] ); + + if ( instanceCamera !== null ) { + + objects.push( instanceCamera.clone() ); + + } + + } + + // instance controllers + + for ( let i = 0, l = instanceControllers.length; i < l; i ++ ) { + + const instance = instanceControllers[ i ]; + const controller = getController( instance.id ); + const geometries = getGeometry( controller.id ); + const newObjects = buildObjects( geometries, instance.materials ); + + const skeletons = instance.skeletons; + const joints = controller.skin.joints; + + const skeleton = buildSkeleton( skeletons, joints ); + + for ( let j = 0, jl = newObjects.length; j < jl; j ++ ) { + + const object = newObjects[ j ]; + + if ( object.isSkinnedMesh ) { + + object.bind( skeleton, controller.skin.bindMatrix ); + object.normalizeSkinWeights(); + + } + + objects.push( object ); + + } + + } + + // instance lights + + for ( let i = 0, l = instanceLights.length; i < l; i ++ ) { + + const instanceLight = getLight( instanceLights[ i ] ); + + if ( instanceLight !== null ) { + + objects.push( instanceLight.clone() ); + + } + + } + + // instance geometries + + for ( let i = 0, l = instanceGeometries.length; i < l; i ++ ) { + + const instance = instanceGeometries[ i ]; + + // a single geometry instance in collada can lead to multiple object3Ds. + // this is the case when primitives are combined like triangles and lines + + const geometries = getGeometry( instance.id ); + const newObjects = buildObjects( geometries, instance.materials ); + + for ( let j = 0, jl = newObjects.length; j < jl; j ++ ) { + + objects.push( newObjects[ j ] ); + + } + + } + + // instance nodes + + for ( let i = 0, l = instanceNodes.length; i < l; i ++ ) { + + objects.push( getNode( instanceNodes[ i ] ).clone() ); + + } + + let object; + + if ( nodes.length === 0 && objects.length === 1 ) { + + object = objects[ 0 ]; + + } else { + + object = ( type === 'JOINT' ) ? new Bone() : new Group(); + + for ( let i = 0; i < objects.length; i ++ ) { + + object.add( objects[ i ] ); + + } + + } + + object.name = ( type === 'JOINT' ) ? data.sid : data.name; + object.matrix.copy( matrix ); + object.matrix.decompose( object.position, object.quaternion, object.scale ); + + return object; + + } + + const fallbackMaterial = new MeshBasicMaterial( { + name: Loader.DEFAULT_MATERIAL_NAME, + color: 0xff00ff + } ); + + function resolveMaterialBinding( keys, instanceMaterials ) { + + const materials = []; + + for ( let i = 0, l = keys.length; i < l; i ++ ) { + + const id = instanceMaterials[ keys[ i ] ]; + + if ( id === undefined ) { + + console.warn( 'THREE.ColladaLoader: Material with key %s not found. Apply fallback material.', keys[ i ] ); + materials.push( fallbackMaterial ); + + } else { + + materials.push( getMaterial( id ) ); + + } + + } + + return materials; + + } + + function buildObjects( geometries, instanceMaterials ) { + + const objects = []; + + for ( const type in geometries ) { + + const geometry = geometries[ type ]; + + const materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials ); + + // handle case if no materials are defined + + if ( materials.length === 0 ) { + + if ( type === 'lines' || type === 'linestrips' ) { + + materials.push( new LineBasicMaterial() ); + + } else { + + materials.push( new MeshPhongMaterial() ); + + } + + } + + // Collada allows to use phong and lambert materials with lines. Replacing these cases with LineBasicMaterial. + + if ( type === 'lines' || type === 'linestrips' ) { + + for ( let i = 0, l = materials.length; i < l; i ++ ) { + + const material = materials[ i ]; + + if ( material.isMeshPhongMaterial === true || material.isMeshLambertMaterial === true ) { + + const lineMaterial = new LineBasicMaterial(); + + // copy compatible properties + + lineMaterial.color.copy( material.color ); + lineMaterial.opacity = material.opacity; + lineMaterial.transparent = material.transparent; + + // replace material + + materials[ i ] = lineMaterial; + + } + + } + + } + + // regard skinning + + const skinning = ( geometry.data.attributes.skinIndex !== undefined ); + + // choose between a single or multi materials (material array) + + const material = ( materials.length === 1 ) ? materials[ 0 ] : materials; + + // now create a specific 3D object + + let object; + + switch ( type ) { + + case 'lines': + object = new LineSegments( geometry.data, material ); + break; + + case 'linestrips': + object = new Line( geometry.data, material ); + break; + + case 'triangles': + case 'polylist': + if ( skinning ) { + + object = new SkinnedMesh( geometry.data, material ); + + } else { + + object = new Mesh( geometry.data, material ); + + } + + break; + + } + + objects.push( object ); + + } + + return objects; + + } + + function hasNode( id ) { + + return library.nodes[ id ] !== undefined; + + } + + function getNode( id ) { + + return getBuild( library.nodes[ id ], buildNode ); + + } + + // visual scenes + + function parseVisualScene( xml ) { + + const data = { + name: xml.getAttribute( 'name' ), + children: [] + }; + + prepareNodes( xml ); + + const elements = getElementsByTagName( xml, 'node' ); + + for ( let i = 0; i < elements.length; i ++ ) { + + data.children.push( parseNode( elements[ i ] ) ); + + } + + library.visualScenes[ xml.getAttribute( 'id' ) ] = data; + + } + + function buildVisualScene( data ) { + + const group = new Group(); + group.name = data.name; + + const children = data.children; + + for ( let i = 0; i < children.length; i ++ ) { + + const child = children[ i ]; + + group.add( getNode( child.id ) ); + + } + + return group; + + } + + function hasVisualScene( id ) { + + return library.visualScenes[ id ] !== undefined; + + } + + function getVisualScene( id ) { + + return getBuild( library.visualScenes[ id ], buildVisualScene ); + + } + + // scenes + + function parseScene( xml ) { + + const instance = getElementsByTagName( xml, 'instance_visual_scene' )[ 0 ]; + return getVisualScene( parseId( instance.getAttribute( 'url' ) ) ); + + } + + function setupAnimations() { + + const clips = library.clips; + + if ( isEmpty( clips ) === true ) { + + if ( isEmpty( library.animations ) === false ) { + + // if there are animations but no clips, we create a default clip for playback + + const tracks = []; + + for ( const id in library.animations ) { + + const animationTracks = getAnimation( id ); + + for ( let i = 0, l = animationTracks.length; i < l; i ++ ) { + + tracks.push( animationTracks[ i ] ); + + } + + } + + animations.push( new AnimationClip( 'default', - 1, tracks ) ); + + } + + } else { + + for ( const id in clips ) { + + animations.push( getAnimationClip( id ) ); + + } + + } + + } + + // convert the parser error element into text with each child elements text + // separated by new lines. + + function parserErrorToText( parserError ) { + + let result = ''; + const stack = [ parserError ]; + + while ( stack.length ) { + + const node = stack.shift(); + + if ( node.nodeType === Node.TEXT_NODE ) { + + result += node.textContent; + + } else { + + result += '\n'; + stack.push.apply( stack, node.childNodes ); + + } + + } + + return result.trim(); + + } + + if ( text.length === 0 ) { + + return { scene: new Scene() }; + + } + + const xml = new DOMParser().parseFromString( text, 'application/xml' ); + + const collada = getElementsByTagName( xml, 'COLLADA' )[ 0 ]; + + const parserError = xml.getElementsByTagName( 'parsererror' )[ 0 ]; + if ( parserError !== undefined ) { + + // Chrome will return parser error with a div in it + + const errorElement = getElementsByTagName( parserError, 'div' )[ 0 ]; + let errorText; + + if ( errorElement ) { + + errorText = errorElement.textContent; + + } else { + + errorText = parserErrorToText( parserError ); + + } + + console.error( 'THREE.ColladaLoader: Failed to parse collada file.\n', errorText ); + + return null; + + } + + // metadata + + const version = collada.getAttribute( 'version' ); + console.debug( 'THREE.ColladaLoader: File version', version ); + + const asset = parseAsset( getElementsByTagName( collada, 'asset' )[ 0 ] ); + const textureLoader = new TextureLoader( this.manager ); + textureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); + + let tgaLoader; + + if ( TGALoader ) { + + tgaLoader = new TGALoader( this.manager ); + tgaLoader.setPath( this.resourcePath || path ); + + } + + // + + const tempColor = new Color(); + const animations = []; + let kinematics = {}; + let count = 0; + + // + + const library = { + animations: {}, + clips: {}, + controllers: {}, + images: {}, + effects: {}, + materials: {}, + cameras: {}, + lights: {}, + geometries: {}, + nodes: {}, + visualScenes: {}, + kinematicsModels: {}, + physicsModels: {}, + kinematicsScenes: {} + }; + + parseLibrary( collada, 'library_animations', 'animation', parseAnimation ); + parseLibrary( collada, 'library_animation_clips', 'animation_clip', parseAnimationClip ); + parseLibrary( collada, 'library_controllers', 'controller', parseController ); + parseLibrary( collada, 'library_images', 'image', parseImage ); + parseLibrary( collada, 'library_effects', 'effect', parseEffect ); + parseLibrary( collada, 'library_materials', 'material', parseMaterial ); + parseLibrary( collada, 'library_cameras', 'camera', parseCamera ); + parseLibrary( collada, 'library_lights', 'light', parseLight ); + parseLibrary( collada, 'library_geometries', 'geometry', parseGeometry ); + parseLibrary( collada, 'library_nodes', 'node', parseNode ); + parseLibrary( collada, 'library_visual_scenes', 'visual_scene', parseVisualScene ); + parseLibrary( collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel ); + parseLibrary( collada, 'library_physics_models', 'physics_model', parsePhysicsModel ); + parseLibrary( collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene ); + + buildLibrary( library.animations, buildAnimation ); + buildLibrary( library.clips, buildAnimationClip ); + buildLibrary( library.controllers, buildController ); + buildLibrary( library.images, buildImage ); + buildLibrary( library.effects, buildEffect ); + buildLibrary( library.materials, buildMaterial ); + buildLibrary( library.cameras, buildCamera ); + buildLibrary( library.lights, buildLight ); + buildLibrary( library.geometries, buildGeometry ); + buildLibrary( library.visualScenes, buildVisualScene ); + + setupAnimations(); + setupKinematics(); + + const scene = parseScene( getElementsByTagName( collada, 'scene' )[ 0 ] ); + scene.animations = animations; + + // if ( asset.upAxis === 'Z_UP' ) { + + // console.warn( 'THREE.ColladaLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted, see #24289.' ); + // scene.rotation.set( - Math.PI / 2, 0, 0 ); + + // } + + scene.scale.multiplyScalar( asset.unit ); + + return { + get animations() { + + console.warn( 'THREE.ColladaLoader: Please access animations over scene.animations now.' ); + return animations; + + }, + kinematics: kinematics, + library: library, + scene: scene + }; + + } + +} + +export { ColladaLoader }; diff --git a/shims/three/ColladaTest.html b/shims/three/ColladaTest.html new file mode 100644 index 00000000..b0140135 --- /dev/null +++ b/shims/three/ColladaTest.html @@ -0,0 +1,62 @@ + + + + + Three.js Collada Example + + + + + + + + \ No newline at end of file diff --git a/shims/three/MTLLoader.js b/shims/three/MTLLoader.js deleted file mode 100644 index ba36aea3..00000000 --- a/shims/three/MTLLoader.js +++ /dev/null @@ -1,588 +0,0 @@ -/** - * @fileOverview - * Loads a Wavefront .mtl file specifying materials - * - * @author angelxuanchang - */ - -import THREE from './core' - -THREE.MTLLoader = function ( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - -}; - -THREE.MTLLoader.prototype = { - - constructor: THREE.MTLLoader, - - crossOrigin: 'anonymous', - - /** - * Loads and parses a MTL asset from a URL. - * - * @param {String} url - URL to the MTL file. - * @param {Function} [onLoad] - Callback invoked with the loaded object. - * @param {Function} [onProgress] - Callback for download progress. - * @param {Function} [onError] - Callback for download errors. - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to load. - */ - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var path = ( this.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path; - - var loader = new THREE.FileLoader( this.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text, path ) ); - - }, onProgress, onError ); - - }, - - /** - * Set base path for resolving references. - * If set this path will be prepended to each loaded and found reference. - * - * @see setResourcePath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setPath: function ( path ) { - - this.path = path; - return this; - - }, - - /** - * Set base path for additional resources like textures. - * - * @see setPath - * @param {String} path - * @return {THREE.MTLLoader} - * - * @example - * mtlLoader.setPath( 'assets/obj/' ); - * mtlLoader.setResourcePath( 'assets/textures/' ); - * mtlLoader.load( 'my.mtl', ... ); - */ - setResourcePath: function ( path ) { - - this.resourcePath = path; - return this; - - }, - - setTexturePath: function ( path ) { - - console.warn( 'THREE.MTLLoader: .setTexturePath() has been renamed to .setResourcePath().' ); - return this.setResourcePath( path ); - - }, - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setMaterialOptions: function ( value ) { - - this.materialOptions = value; - return this; - - }, - - /** - * Parses a MTL file. - * - * @param {String} text - Content of MTL file - * @return {THREE.MTLLoader.MaterialCreator} - * - * @see setPath setResourcePath - * - * @note In order for relative texture references to resolve correctly - * you must call setResourcePath() explicitly prior to parse. - */ - parse: function ( text, path ) { - - var lines = text.split( '\n' ); - var info = {}; - var delimiter_pattern = /\s+/; - var materialsInfo = {}; - - for ( var i = 0; i < lines.length; i ++ ) { - - var line = lines[ i ]; - line = line.trim(); - - if ( line.length === 0 || line.charAt( 0 ) === '#' ) { - - // Blank line or comment ignore - continue; - - } - - var pos = line.indexOf( ' ' ); - - var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; - key = key.toLowerCase(); - - var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; - value = value.trim(); - - if ( key === 'newmtl' ) { - - // New material - - info = { name: value }; - materialsInfo[ value ] = info; - - } else { - - if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { - - var ss = value.split( delimiter_pattern, 3 ); - info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; - - } else { - - info[ key ] = value; - - } - - } - - } - - var materialCreator = new THREE.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions ); - materialCreator.setCrossOrigin( this.crossOrigin ); - materialCreator.setManager( this.manager ); - materialCreator.setMaterials( materialsInfo ); - return materialCreator; - - } - -}; - -/** - * Create a new THREE-MTLLoader.MaterialCreator - * @param baseUrl - Url relative to which textures are loaded - * @param options - Set of options on how to construct the materials - * side: Which side to apply the material - * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide - * wrap: What type of wrapping to apply for textures - * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping - * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 - * Default: false, assumed to be already normalized - * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's - * Default: false - * @constructor - */ - -THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) { - - this.baseUrl = baseUrl || ''; - this.options = options; - this.materialsInfo = {}; - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; - - this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide; - this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping; - -}; - -THREE.MTLLoader.MaterialCreator.prototype = { - - constructor: THREE.MTLLoader.MaterialCreator, - - crossOrigin: 'anonymous', - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setManager: function ( value ) { - - this.manager = value; - - }, - - setMaterials: function ( materialsInfo ) { - - this.materialsInfo = this.convert( materialsInfo ); - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; - - }, - - convert: function ( materialsInfo ) { - - if ( ! this.options ) return materialsInfo; - - var converted = {}; - - for ( var mn in materialsInfo ) { - - // Convert materials info into normalized form based on options - - var mat = materialsInfo[ mn ]; - - var covmat = {}; - - converted[ mn ] = covmat; - - for ( var prop in mat ) { - - var save = true; - var value = mat[ prop ]; - var lprop = prop.toLowerCase(); - - switch ( lprop ) { - - case 'kd': - case 'ka': - case 'ks': - - // Diffuse color (color under white light) using RGB values - - if ( this.options && this.options.normalizeRGB ) { - - value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; - - } - - if ( this.options && this.options.ignoreZeroRGBs ) { - - if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { - - // ignore - - save = false; - - } - - } - - break; - - default: - - break; - - } - - if ( save ) { - - covmat[ lprop ] = value; - - } - - } - - } - - return converted; - - }, - - preload: function () { - - for ( var mn in this.materialsInfo ) { - - this.create( mn ); - - } - - }, - - getIndex: function ( materialName ) { - - return this.nameLookup[ materialName ]; - - }, - - getAsArray: function () { - - var index = 0; - - for ( var mn in this.materialsInfo ) { - - this.materialsArray[ index ] = this.create( mn ); - this.nameLookup[ mn ] = index; - index ++; - - } - - return this.materialsArray; - - }, - - create: function ( materialName ) { - - if ( this.materials[ materialName ] === undefined ) { - - this.createMaterial_( materialName ); - - } - - return this.materials[ materialName ]; - - }, - - createMaterial_: function ( materialName ) { - - // Create material - - var scope = this; - var mat = this.materialsInfo[ materialName ]; - var params = { - - name: materialName, - side: this.side - - }; - - function resolveURL( baseUrl, url ) { - - if ( typeof url !== 'string' || url === '' ) - return ''; - - // Absolute URL - if ( /^https?:\/\//i.test( url ) ) return url; - - return baseUrl + url; - - } - - function setMapForType( mapType, value ) { - - if ( params[ mapType ] ) return; // Keep the first encountered texture - - var texParams = scope.getTextureParams( value, params ); - var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); - - map.repeat.copy( texParams.scale ); - map.offset.copy( texParams.offset ); - - map.wrapS = scope.wrap; - map.wrapT = scope.wrap; - - params[ mapType ] = map; - - } - - for ( var prop in mat ) { - - var value = mat[ prop ]; - var n; - - if ( value === '' ) continue; - - switch ( prop.toLowerCase() ) { - - // Ns is material specular exponent - - case 'kd': - - // Diffuse color (color under white light) using RGB values - - params.color = new THREE.Color().fromArray( value ); - - break; - - case 'ks': - - // Specular color (color when light is reflected from shiny surface) using RGB values - params.specular = new THREE.Color().fromArray( value ); - - break; - - case 'ke': - - // Emissive using RGB values - params.emissive = new THREE.Color().fromArray( value ); - - break; - - case 'map_kd': - - // Diffuse texture map - - setMapForType( "map", value ); - - break; - - case 'map_ks': - - // Specular map - - setMapForType( "specularMap", value ); - - break; - - case 'map_ke': - - // Emissive map - - setMapForType( "emissiveMap", value ); - - break; - - case 'norm': - - setMapForType( "normalMap", value ); - - break; - - case 'map_bump': - case 'bump': - - // Bump texture map - - setMapForType( "bumpMap", value ); - - break; - - case 'map_d': - - // Alpha map - - setMapForType( "alphaMap", value ); - params.transparent = true; - - break; - - case 'ns': - - // The specular exponent (defines the focus of the specular highlight) - // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. - - params.shininess = parseFloat( value ); - - break; - - case 'd': - n = parseFloat( value ); - - if ( n < 1 ) { - - params.opacity = n; - params.transparent = true; - - } - - break; - - case 'tr': - n = parseFloat( value ); - - if ( this.options && this.options.invertTrProperty ) n = 1 - n; - - if ( n > 0 ) { - - params.opacity = 1 - n; - params.transparent = true; - - } - - break; - - default: - break; - - } - - } - - this.materials[ materialName ] = new THREE.MeshPhongMaterial( params ); - return this.materials[ materialName ]; - - }, - - getTextureParams: function ( value, matParams ) { - - var texParams = { - - scale: new THREE.Vector2( 1, 1 ), - offset: new THREE.Vector2( 0, 0 ) - - }; - - var items = value.split( /\s+/ ); - var pos; - - pos = items.indexOf( '-bm' ); - - if ( pos >= 0 ) { - - matParams.bumpScale = parseFloat( items[ pos + 1 ] ); - items.splice( pos, 2 ); - - } - - pos = items.indexOf( '-s' ); - - if ( pos >= 0 ) { - - texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! - - } - - pos = items.indexOf( '-o' ); - - if ( pos >= 0 ) { - - texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); - items.splice( pos, 4 ); // we expect 3 parameters here! - - } - - texParams.url = items.join( ' ' ).trim(); - return texParams; - - }, - - loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { - - var texture; - var loader = THREE.Loader.Handlers.get( url ); - var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager; - - if ( loader === null ) { - - loader = new THREE.TextureLoader( manager ); - - } - - if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); - texture = loader.load( url, onLoad, onProgress, onError ); - - if ( mapping !== undefined ) texture.mapping = mapping; - - return texture; - - } - -}; diff --git a/shims/three/OBJLoader.js b/shims/three/OBJLoader.js deleted file mode 100644 index 57bd98ab..00000000 --- a/shims/three/OBJLoader.js +++ /dev/null @@ -1,795 +0,0 @@ -/** - * @fileOverview - * @author mrdoob / http://mrdoob.com/ - * - * @Modified by Jose Rojas from OBJLoader.js@r106 - * - */ - -import THREE from './core' - -// o object_name | g group_name -var object_pattern = /^[og]\s*(.+)?/; -// mtllib file_reference -var material_library_pattern = /^mtllib /; -// usemtl material_name -var material_use_pattern = /^usemtl /; - -function ParserState() { - - var state = { - objects: [], - object: {}, - - vertices: [], - normals: [], - colors: [], - uvs: [], - - materialLibraries: [], - - startObject: function ( name, fromDeclaration ) { - - // If the current object (initial from reset) is not from a g/o declaration in the parsed - // file. We need to use it for the first parsed g/o to keep things in sync. - if ( this.object && this.object.fromDeclaration === false ) { - - this.object.name = name; - this.object.fromDeclaration = ( fromDeclaration !== false ); - return; - - } - - var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); - - if ( this.object && typeof this.object._finalize === 'function' ) { - - this.object._finalize( true ); - - } - - this.object = { - name: name || '', - fromDeclaration: ( fromDeclaration !== false ), - - geometry: { - vertices: [], - normals: [], - colors: [], - uvs: [] - }, - materials: [], - smooth: true, - - startMaterial: function ( name, libraries ) { - - var previous = this._finalize( false ); - - // New usemtl declaration overwrites an inherited material, except if faces were declared - // after the material, then it must be preserved for proper MultiMaterial continuation. - if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { - - this.materials.splice( previous.index, 1 ); - - } - - var material = { - index: this.materials.length, - name: name || '', - mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), - smooth: ( previous !== undefined ? previous.smooth : this.smooth ), - groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), - groupEnd: - 1, - groupCount: - 1, - inherited: false, - - clone: function ( index ) { - - var cloned = { - index: ( typeof index === 'number' ? index : this.index ), - name: this.name, - mtllib: this.mtllib, - smooth: this.smooth, - groupStart: 0, - groupEnd: - 1, - groupCount: - 1, - inherited: false - }; - cloned.clone = this.clone.bind( cloned ); - return cloned; - - } - }; - - this.materials.push( material ); - - return material; - - }, - - currentMaterial: function () { - - if ( this.materials.length > 0 ) { - - return this.materials[ this.materials.length - 1 ]; - - } - - return undefined; - - }, - - _finalize: function ( end ) { - - var lastMultiMaterial = this.currentMaterial(); - if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { - - lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; - lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; - lastMultiMaterial.inherited = false; - - } - - // Ignore objects tail materials if no face declarations followed them before a new o/g started. - if ( end && this.materials.length > 1 ) { - - for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { - - if ( this.materials[ mi ].groupCount <= 0 ) { - - this.materials.splice( mi, 1 ); - - } - - } - - } - - // Guarantee at least one empty material, this makes the creation later more straight forward. - if ( end && this.materials.length === 0 ) { - - this.materials.push( { - name: '', - smooth: this.smooth - } ); - - } - - return lastMultiMaterial; - - } - }; - - // Inherit previous objects material. - // Spec tells us that a declared material must be set to all objects until a new material is declared. - // If a usemtl declaration is encountered while this new object is being parsed, it will - // overwrite the inherited material. Exception being that there was already face declarations - // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - - if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - - var declared = previousMaterial.clone( 0 ); - declared.inherited = true; - this.object.materials.push( declared ); - - } - - this.objects.push( this.object ); - - }, - - finalize: function () { - - if ( this.object && typeof this.object._finalize === 'function' ) { - - this.object._finalize( true ); - - } - - }, - - parseVertexIndex: function ( value, len ) { - - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - - }, - - parseNormalIndex: function ( value, len ) { - - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - - }, - - parseUVIndex: function ( value, len ) { - - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; - - }, - - addVertex: function ( a, b, c ) { - - var src = this.vertices; - var dst = this.object.geometry.vertices; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - - }, - - addVertexPoint: function ( a ) { - - var src = this.vertices; - var dst = this.object.geometry.vertices; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - - }, - - addVertexLine: function ( a ) { - - var src = this.vertices; - var dst = this.object.geometry.vertices; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - - }, - - addNormal: function ( a, b, c ) { - - var src = this.normals; - var dst = this.object.geometry.normals; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - - }, - - addColor: function ( a, b, c ) { - - var src = this.colors; - var dst = this.object.geometry.colors; - - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - - }, - - addUV: function ( a, b, c ) { - - var src = this.uvs; - var dst = this.object.geometry.uvs; - - dst.push( src[ a + 0 ], src[ a + 1 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ] ); - - }, - - addUVLine: function ( a ) { - - var src = this.uvs; - var dst = this.object.geometry.uvs; - - dst.push( src[ a + 0 ], src[ a + 1 ] ); - - }, - - addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { - - var vLen = this.vertices.length; - - var ia = this.parseVertexIndex( a, vLen ); - var ib = this.parseVertexIndex( b, vLen ); - var ic = this.parseVertexIndex( c, vLen ); - - this.addVertex( ia, ib, ic ); - - if ( ua !== undefined && ua !== '' ) { - - var uvLen = this.uvs.length; - ia = this.parseUVIndex( ua, uvLen ); - ib = this.parseUVIndex( ub, uvLen ); - ic = this.parseUVIndex( uc, uvLen ); - this.addUV( ia, ib, ic ); - - } - - if ( na !== undefined && na !== '' ) { - - // Normals are many times the same. If so, skip function call and parseInt. - var nLen = this.normals.length; - ia = this.parseNormalIndex( na, nLen ); - - ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); - ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); - - this.addNormal( ia, ib, ic ); - - } - - if ( this.colors.length > 0 ) { - - this.addColor( ia, ib, ic ); - - } - - }, - - addPointGeometry: function ( vertices ) { - - this.object.geometry.type = 'Points'; - - var vLen = this.vertices.length; - - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { - - this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); - - } - - }, - - addLineGeometry: function ( vertices, uvs ) { - - this.object.geometry.type = 'Line'; - - var vLen = this.vertices.length; - var uvLen = this.uvs.length; - - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { - - this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); - - } - - for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { - - this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); - - } - - } - - }; - - state.startObject( '', false ); - - return state; - -} - -THREE.OBJLoader = function( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - - this.materials = null; - -} - -THREE.OBJLoader.prototype = { - - constructor: THREE.OBJLoader, - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new THREE.FileLoader( scope.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text ) ); - - }, onProgress, onError ); - - }, - - setPath: function ( value ) { - - this.path = value; - - return this; - - }, - - setMaterials: function ( materials ) { - - this.materials = materials; - - return this; - - }, - - parse: function ( text ) { - - console.time( 'OBJLoader' ); - - var state = new ParserState(); - - if ( text.indexOf( '\r\n' ) !== - 1 ) { - - // This is faster than String.split with regex that splits on both - text = text.replace( /\r\n/g, '\n' ); - - } - - if ( text.indexOf( '\\\n' ) !== - 1 ) { - - // join lines separated by a line continuation character (\) - text = text.replace( /\\\n/g, '' ); - - } - - var lines = text.split( '\n' ); - var line = '', lineFirstChar = ''; - var lineLength = 0; - var result = []; - - // Faster to just trim left side of the line. Use if available. - var trimLeft = ( typeof ''.trimLeft === 'function' ); - - for ( var i = 0, l = lines.length; i < l; i ++ ) { - - line = lines[ i ]; - - line = trimLeft ? line.trimLeft() : line.trim(); - - lineLength = line.length; - - if ( lineLength === 0 ) continue; - - lineFirstChar = line.charAt( 0 ); - - // @todo invoke passed in handler if any - if ( lineFirstChar === '#' ) continue; - - if ( lineFirstChar === 'v' ) { - - var data = line.split( /\s+/ ); - - switch ( data[ 0 ] ) { - - case 'v': - state.vertices.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - if ( data.length === 8 ) { - - state.colors.push( - parseFloat( data[ 4 ] ), - parseFloat( data[ 5 ] ), - parseFloat( data[ 6 ] ) - - ); - - } - break; - case 'vn': - state.normals.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - break; - case 'vt': - state.uvs.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ) - ); - break; - - } - - } else if ( lineFirstChar === 'f' ) { - - var lineData = line.substr( 1 ).trim(); - var vertexData = lineData.split( /\s+/ ); - var faceVertices = []; - - // Parse the face vertex data into an easy to work with format - - for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { - - var vertex = vertexData[ j ]; - - if ( vertex.length > 0 ) { - - var vertexParts = vertex.split( '/' ); - faceVertices.push( vertexParts ); - - } - - } - - // Draw an edge between the first vertex and all subsequent vertices to form an n-gon - - var v1 = faceVertices[ 0 ]; - - for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { - - var v2 = faceVertices[ j ]; - var v3 = faceVertices[ j + 1 ]; - - state.addFace( - v1[ 0 ], v2[ 0 ], v3[ 0 ], - v1[ 1 ], v2[ 1 ], v3[ 1 ], - v1[ 2 ], v2[ 2 ], v3[ 2 ] - ); - - } - - } else if ( lineFirstChar === 'l' ) { - - var lineParts = line.substring( 1 ).trim().split( " " ); - var lineVertices = [], lineUVs = []; - - if ( line.indexOf( "/" ) === - 1 ) { - - lineVertices = lineParts; - - } else { - - for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { - - var parts = lineParts[ li ].split( "/" ); - - if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); - if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); - - } - - } - state.addLineGeometry( lineVertices, lineUVs ); - - } else if ( lineFirstChar === 'p' ) { - - var lineData = line.substr( 1 ).trim(); - var pointData = lineData.split( " " ); - - state.addPointGeometry( pointData ); - - } else if ( ( result = object_pattern.exec( line ) ) !== null ) { - - // o object_name - // or - // g group_name - - // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 - // var name = result[ 0 ].substr( 1 ).trim(); - var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); - - state.startObject( name ); - - } else if ( material_use_pattern.test( line ) ) { - - // material - - state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); - - } else if ( material_library_pattern.test( line ) ) { - - // mtl file - - state.materialLibraries.push( line.substring( 7 ).trim() ); - - } else if ( lineFirstChar === 's' ) { - - result = line.split( ' ' ); - - // smooth shading - - // @todo Handle files that have varying smooth values for a set of faces inside one geometry, - // but does not define a usemtl for each face set. - // This should be detected and a dummy material created (later MultiMaterial and geometry groups). - // This requires some care to not create extra material on each smooth value for "normal" obj files. - // where explicit usemtl defines geometry groups. - // Example asset: examples/models/obj/cerberus/Cerberus.obj - - /* - * http://paulbourke.net/dataformats/obj/ - * or - * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf - * - * From chapter "Grouping" Syntax explanation "s group_number": - * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. - * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form - * surfaces, smoothing groups are either turned on or off; there is no difference between values greater - * than 0." - */ - if ( result.length > 1 ) { - - var value = result[ 1 ].trim().toLowerCase(); - state.object.smooth = ( value !== '0' && value !== 'off' ); - - } else { - - // ZBrush can produce "s" lines #11707 - state.object.smooth = true; - - } - var material = state.object.currentMaterial(); - if ( material ) material.smooth = state.object.smooth; - - } else { - - // Handle null terminated files without exception - if ( line === '\0' ) continue; - - throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); - - } - - } - - state.finalize(); - - var container = new THREE.Object3D(); - container.materialLibraries = [].concat( state.materialLibraries ); - - for ( var i = 0, l = state.objects.length; i < l; i ++ ) { - - var object = state.objects[ i ]; - var geometry = object.geometry; - var materials = object.materials; - var isLine = ( geometry.type === 'Line' ); - var isPoints = ( geometry.type === 'Points' ); - var hasVertexColors = false; - - // Skip o/g line declarations that did not follow with any faces - if ( geometry.vertices.length === 0 ) continue; - - var buffergeometry = new THREE.BufferGeometry(); - - buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); - - if ( geometry.normals.length > 0 ) { - - buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); - - } else { - - buffergeometry.computeVertexNormals(); - - } - - if ( geometry.colors.length > 0 ) { - - hasVertexColors = true; - buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); - - } - - if ( geometry.uvs.length > 0 ) { - - buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); - - } - - // Create materials - - var createdMaterials = []; - - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - - var sourceMaterial = materials[ mi ]; - var material = undefined; - - if ( this.materials !== null ) { - - material = this.materials.create( sourceMaterial.name ); - - // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. - if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { - - var materialLine = new THREE.LineBasicMaterial(); - THREE.Material.prototype.copy.call( materialLine, material ); - materialLine.color.copy( material.color ); - materialLine.lights = false; - material = materialLine; - - } else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { - - var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); - THREE.Material.prototype.copy.call( materialPoints, material ); - materialPoints.color.copy( material.color ); - materialPoints.map = material.map; - materialPoints.lights = false; - material = materialPoints; - - } - - } - - if ( ! material ) { - - if ( isLine ) { - - material = new THREE.LineBasicMaterial(); - - } else if ( isPoints ) { - - material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); - - } else { - - material = new THREE.MeshPhongMaterial(); - - } - - material.name = sourceMaterial.name; - - } - - material.flatShading = sourceMaterial.smooth ? false : true; - material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; - - createdMaterials.push( material ); - - } - - // Create mesh - - var mesh; - - if ( createdMaterials.length > 1 ) { - - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - - var sourceMaterial = materials[ mi ]; - buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); - - } - - if ( isLine ) { - - mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); - - } else if ( isPoints ) { - - mesh = new THREE.Points( buffergeometry, createdMaterials ); - - } else { - - mesh = new THREE.Mesh( buffergeometry, createdMaterials ); - - } - - } else { - - if ( isLine ) { - - mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); - - } else if ( isPoints ) { - - mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); - - } else { - - mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); - - } - - } - - mesh.name = object.name; - - container.add( mesh ); - - } - - console.timeEnd( 'OBJLoader' ); - - return container; - - } - -}; diff --git a/shims/three/STLLoader.js b/shims/three/STLLoader.js deleted file mode 100644 index 79150812..00000000 --- a/shims/three/STLLoader.js +++ /dev/null @@ -1,325 +0,0 @@ -/** - * @fileOverview - * @author aleeper / http://adamleeper.com/ - * @author mrdoob / http://mrdoob.com/ - * @author gero3 / https://github.com/gero3 - * @author Mugen87 / https://github.com/Mugen87 - * - * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. - * - * Supports both binary and ASCII encoded files, with automatic detection of type. - * - * The loader returns a non-indexed buffer geometry. - * - * Limitations: - * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). - * There is perhaps some question as to how valid it is to always assume little-endian-ness. - * ASCII decoding assumes file is UTF-8. - * - * Usage: - * var loader = new THREE.STLLoader(); - * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { - * scene.add( new THREE.Mesh( geometry ) ); - * }); - * - * For binary STLs geometry might contain colors for vertices. To use it: - * // use the same code to load STL as above - * if (geometry.hasColors) { - * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors }); - * } else { .... } - * var mesh = new THREE.Mesh( geometry, material ); - */ - -import THREE from './core' - -THREE.STLLoader = function (manager) { - - this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; - -}; - -THREE.STLLoader.prototype = { - - constructor: THREE.STLLoader, - - load: function (url, onLoad, onProgress, onError) { - - var scope = this; - - var loader = new THREE.FileLoader(scope.manager); - loader.setResponseType('arraybuffer'); - loader.load(url, function (text) { - - onLoad(scope.parse(text)); - - }, onProgress, onError); - - }, - - parse: function (data) { - - function isBinary(data) { - - var expect, face_size, n_faces, reader; - reader = new DataView(data); - face_size = (32 / 8 * 3) + ((32 / 8 * 3) * 3) + (16 / 8); - n_faces = reader.getUint32(80, true); - expect = 80 + (32 / 8) + (n_faces * face_size); - - if (expect === reader.byteLength) { - - return true; - - } - - // An ASCII STL data must begin with 'solid ' as the first six bytes. - // However, ASCII STLs lacking the SPACE after the 'd' are known to be - // plentiful. So, check the first 5 bytes for 'solid'. - - // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' - - var solid = [115, 111, 108, 105, 100]; - - for (var i = 0; i < 5; i++) { - - // If solid[ i ] does not match the i-th byte, then it is not an - // ASCII STL; hence, it is binary and return true. - - if (solid[i] != reader.getUint8(i, false)) return true; - - } - - // First 5 bytes read "solid"; declare it to be an ASCII STL - - return false; - - } - - function parseBinary(data) { - - var reader = new DataView(data); - var faces = reader.getUint32(80, true); - - var r, g, b, hasColors = false, colors; - var defaultR, defaultG, defaultB, alpha; - - // process STL header - // check for default color in header ("COLOR=rgba" sequence). - - for (var index = 0; index < 80 - 10; index++) { - - if ((reader.getUint32(index, false) == 0x434F4C4F /*COLO*/) && - (reader.getUint8(index + 4) == 0x52 /*'R'*/) && - (reader.getUint8(index + 5) == 0x3D /*'='*/)) { - - hasColors = true; - colors = []; - - defaultR = reader.getUint8(index + 6) / 255; - defaultG = reader.getUint8(index + 7) / 255; - defaultB = reader.getUint8(index + 8) / 255; - alpha = reader.getUint8(index + 9) / 255; - - } - - } - - var dataOffset = 84; - var faceLength = 12 * 4 + 2; - - var geometry = new THREE.BufferGeometry(); - - var vertices = []; - var normals = []; - - for (var face = 0; face < faces; face++) { - - var start = dataOffset + face * faceLength; - var normalX = reader.getFloat32(start, true); - var normalY = reader.getFloat32(start + 4, true); - var normalZ = reader.getFloat32(start + 8, true); - - if (hasColors) { - - var packedColor = reader.getUint16(start + 48, true); - - if ((packedColor & 0x8000) === 0) { - - // facet has its own unique color - - r = (packedColor & 0x1F) / 31; - g = ((packedColor >> 5) & 0x1F) / 31; - b = ((packedColor >> 10) & 0x1F) / 31; - - } else { - - r = defaultR; - g = defaultG; - b = defaultB; - - } - - } - - for (var i = 1; i <= 3; i++) { - - var vertexstart = start + i * 12; - - vertices.push(reader.getFloat32(vertexstart, true)); - vertices.push(reader.getFloat32(vertexstart + 4, true)); - vertices.push(reader.getFloat32(vertexstart + 8, true)); - - normals.push(normalX, normalY, normalZ); - - if (hasColors) { - - colors.push(r, g, b); - - } - - } - - } - - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); - geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); - - if (hasColors) { - - geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); - geometry.hasColors = true; - geometry.alpha = alpha; - - } - - return geometry; - - } - - function parseASCII(data) { - - var geometry = new THREE.BufferGeometry(); - var patternFace = /facet([\s\S]*?)endfacet/g; - var faceCounter = 0; - - var patternFloat = /[\s]+([+-]?(?:\d+.\d+|\d+.|\d+|.\d+)(?:[eE][+-]?\d+)?)/.source; - var patternVertex = new RegExp('vertex' + patternFloat + patternFloat + patternFloat, 'g'); - var patternNormal = new RegExp('normal' + patternFloat + patternFloat + patternFloat, 'g'); - - var vertices = []; - var normals = []; - - var normal = new THREE.Vector3(); - - var result; - - while ((result = patternFace.exec(data)) !== null) { - - var vertexCountPerFace = 0; - var normalCountPerFace = 0; - - var text = result[0]; - - while ((result = patternNormal.exec(text)) !== null) { - - normal.x = parseFloat(result[1]); - normal.y = parseFloat(result[2]); - normal.z = parseFloat(result[3]); - normalCountPerFace++; - - } - - while ((result = patternVertex.exec(text)) !== null) { - - vertices.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])); - normals.push(normal.x, normal.y, normal.z); - vertexCountPerFace++; - - } - - // every face have to own ONE valid normal - - if (normalCountPerFace !== 1) { - - console.error('THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter); - - } - - // each face have to own THREE valid vertices - - if (vertexCountPerFace !== 3) { - - console.error('THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter); - - } - - faceCounter++; - - } - - geometry.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); - geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normals, 3)); - - return geometry; - - } - - function ensureString(buffer) { - - if (typeof buffer !== 'string') { - - var array_buffer = new Uint8Array(buffer); - - if (window.TextDecoder !== undefined) { - - return new TextDecoder().decode(array_buffer); - - } - - var str = ''; - - for (var i = 0, il = buffer.byteLength; i < il; i++) { - - str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian - - } - - return str; - - } else { - - return buffer; - - } - - } - - function ensureBinary(buffer) { - - if (typeof buffer === 'string') { - - var array_buffer = new Uint8Array(buffer.length); - for (var i = 0; i < buffer.length; i++) { - - array_buffer[i] = buffer.charCodeAt(i) & 0xff; // implicitly assumes little-endian - - } - return array_buffer.buffer || array_buffer; - - } else { - - return buffer; - - } - - } - - // start - - var binData = ensureBinary(data); - - return isBinary(binData) ? parseBinary(binData) : parseASCII(ensureString(data)); - - } - -}; diff --git a/shims/three/core.js b/shims/three/core.js index 8a6bbac3..0813aae7 100644 --- a/shims/three/core.js +++ b/shims/three/core.js @@ -1,3 +1,3 @@ -import * as THREE from 'three'; +// import * as THREE from 'three'; -export default Object.assign({}, THREE) +// export default Object.assign({}, THREE) diff --git a/src/depthcloud/DepthCloud.js b/src/depthcloud/DepthCloud.js index 438ac584..c2f667aa 100644 --- a/src/depthcloud/DepthCloud.js +++ b/src/depthcloud/DepthCloud.js @@ -237,7 +237,7 @@ ROS3D.DepthCloud.prototype.initStreamer = function() { if (this.metaLoaded) { this.texture = new THREE.Texture(this.video); - this.geometry = new THREE.Geometry(); + this.geometry = new THREE.BufferGeometry(); for (var i = 0, l = this.width * this.height; i < l; i++) { @@ -295,7 +295,7 @@ ROS3D.DepthCloud.prototype.initStreamer = function() { fragmentShader : this.fragment_shader }); - this.mesh = new THREE.ParticleSystem(this.geometry, this.material); + this.mesh = new THREE.Points(this.geometry, this.material); this.mesh.position.x = 0; this.mesh.position.y = 0; this.add(this.mesh); diff --git a/src/interactivemarkers/InteractiveMarkerHandle.js b/src/interactivemarkers/InteractiveMarkerHandle.js index af2ed1d4..c9c75484 100644 --- a/src/interactivemarkers/InteractiveMarkerHandle.js +++ b/src/interactivemarkers/InteractiveMarkerHandle.js @@ -43,7 +43,7 @@ ROS3D.InteractiveMarkerHandle = function(options) { this.setPoseFromServer(this.message.pose); this.tfUpdateBound = this.tfUpdate.bind(this); }; -ROS3D.InteractiveMarkerHandle.prototype.__proto__ = EventEmitter3.prototype; +ROS3D.InteractiveMarkerHandle.prototype.__proto__ = EventEmitter2.prototype; /** * Subscribe to the TF associated with this interactive marker. diff --git a/src/markers/Marker.js b/src/markers/Marker.js index 99b60cb7..d36b981e 100644 --- a/src/markers/Marker.js +++ b/src/markers/Marker.js @@ -98,7 +98,7 @@ ROS3D.Marker = function(options) { this.add(cylinderMesh); break; case ROS3D.MARKER_LINE_STRIP: - var lineStripGeom = new THREE.Geometry(); + var lineStripGeom = new THREE.BufferGeometry(); var lineStripMaterial = new THREE.LineBasicMaterial({ linewidth : message.scale.x }); @@ -129,7 +129,7 @@ ROS3D.Marker = function(options) { this.add(new THREE.Line(lineStripGeom, lineStripMaterial)); break; case ROS3D.MARKER_LINE_LIST: - var lineListGeom = new THREE.Geometry(); + var lineListGeom = new THREE.BufferGeometry(); var lineListMaterial = new THREE.LineBasicMaterial({ linewidth : message.scale.x }); @@ -225,7 +225,7 @@ ROS3D.Marker = function(options) { break; case ROS3D.MARKER_POINTS: // for now, use a particle system for the lists - var geometry = new THREE.Geometry(); + var geometry = new THREE.BufferGeometry(); var material = new THREE.PointsMaterial({ size : message.scale.x }); diff --git a/src/markers/MarkerArrayClient.js b/src/markers/MarkerArrayClient.js index 00be1831..6353c176 100644 --- a/src/markers/MarkerArrayClient.js +++ b/src/markers/MarkerArrayClient.js @@ -35,7 +35,7 @@ ROS3D.MarkerArrayClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.MarkerArrayClient.prototype.__proto__ = EventEmitter3.prototype; +ROS3D.MarkerArrayClient.prototype.__proto__ = EventEmitter2.prototype; ROS3D.MarkerArrayClient.prototype.subscribe = function(){ this.unsubscribe(); diff --git a/src/markers/MarkerClient.js b/src/markers/MarkerClient.js index 9cb5d4ed..896f01f4 100644 --- a/src/markers/MarkerClient.js +++ b/src/markers/MarkerClient.js @@ -37,7 +37,7 @@ ROS3D.MarkerClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.MarkerClient.prototype.__proto__ = EventEmitter3.prototype; +ROS3D.MarkerClient.prototype.__proto__ = EventEmitter2.prototype; ROS3D.MarkerClient.prototype.unsubscribe = function(){ if(this.rosTopic){ diff --git a/src/models/Grid.js b/src/models/Grid.js index 1d302ae7..f83f42ac 100644 --- a/src/models/Grid.js +++ b/src/models/Grid.js @@ -14,6 +14,7 @@ * * lineWidth (optional) - the width of the lines in the grid * * cellSize (optional) - The length, in meters, of the side of each cell */ + ROS3D.Grid = function(options) { options = options || {}; var num_cells = options.num_cells || 10; @@ -28,22 +29,32 @@ ROS3D.Grid = function(options) { linewidth: lineWidth }); + var edges = []; + for (var i = 0; i <= num_cells; ++i) { var edge = cellSize * num_cells / 2; var position = edge - (i * cellSize); - var geometryH = new THREE.Geometry(); - geometryH.vertices.push( - new THREE.Vector3( -edge, position, 0 ), - new THREE.Vector3( edge, position, 0 ) + + // Horizontal lines + edges.push( + new THREE.Vector3(-edge, position, 0), + new THREE.Vector3(edge, position, 0) ); - var geometryV = new THREE.Geometry(); - geometryV.vertices.push( - new THREE.Vector3( position, -edge, 0 ), - new THREE.Vector3( position, edge, 0 ) + + // Vertical lines + edges.push( + new THREE.Vector3(position, -edge, 0), + new THREE.Vector3(position, edge, 0) ); - this.add(new THREE.Line(geometryH, material)); - this.add(new THREE.Line(geometryV, material)); } + + + var geometry = new THREE.BufferGeometry().setFromPoints(edges); + + // Define lines with the geometry + var lineSegments = new THREE.LineSegments(geometry, material); + + this.add(lineSegments); }; ROS3D.Grid.prototype.__proto__ = THREE.Object3D.prototype; diff --git a/src/models/MeshLoader.js b/src/models/MeshLoader.js index 5bb3a126..928b57a7 100644 --- a/src/models/MeshLoader.js +++ b/src/models/MeshLoader.js @@ -2,131 +2,126 @@ * @fileOverview * @author Jose Rojas - jrojas@redlinesolutions.co */ +/** + * MeshLoader is a singleton factory class for using various helper classes to + * load mesh files of different types. + * + * It consists of one dictionary property 'loaders'. The dictionary keys consist + * of the file extension for each supported loader type. The dictionary values + * are functions used to construct the loader objects. The functions have the + * following parameters: + * + * * meshRes - the MeshResource that will contain the loaded mesh + * * uri - the uri path to the mesh file + * @returns loader object + */ +import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'; +import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; +import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js'; +import { ColladaLoader } from '../../shims/three/ColladaLoader.js'; + - /** - * MeshLoader is a singleton factory class for using various helper classes to - * load mesh files of different types. - * - * It consists of one dictionary property 'loaders'. The dictionary keys consist - * of the file extension for each supported loader type. The dictionary values - * are functions used to construct the loader objects. The functions have the - * following parameters: - * - * * meshRes - the MeshResource that will contain the loaded mesh - * * uri - the uri path to the mesh file - * @returns loader object - */ ROS3D.MeshLoader = { - onError: function(error) { - console.error(error); - }, - loaders: { - 'dae': function(meshRes, uri, options) { - const material = options.material; - const loader = new THREE.ColladaLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; - loader.load( - uri, - function colladaReady(collada) { - // check for a scale factor in ColladaLoader2 - // add a texture to anything that is missing one - if(material !== null) { - collada.scene.traverse(function(child) { - if(child instanceof THREE.Mesh) { - if(child.material === undefined) { - child.material = material; - } - } - }); - } + onError: function (error) { + console.error(error); + }, + loaders: { + 'dae': function (meshRes, uri, options) { - meshRes.add(collada.scene); - }, - /*onProgress=*/null, - ROS3D.MeshLoader.onError); - return loader; - }, + const loader = new ColladaLoader(options.loader); + + console.log('Loading collada: ' + uri) + loader.load(uri, function (collada_mesh) { + let model = collada_mesh.scene; + meshRes.add (model) + console.log('Done loading collada'); + }); + + + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + return loader; + }, - 'obj': function(meshRes, uri, options) { - const material = options.material; - const loader = new THREE.OBJLoader(options.loader); - loader.log = function(message) { - if (meshRes.warnings) { - console.warn(message); - } - }; + 'obj': function (meshRes, uri, options) { + const material = options.material; + const loader = new OBJLoader(options.loader); + loader.log = function (message) { + if (meshRes.warnings) { + console.warn(message); + } + }; - //Reload the mesh again after materials have been loaded - // @todo: this should be improved so that the file doesn't need to be - // reloaded however that would involve more changes within the OBJLoader. - function onMaterialsLoaded(loader, materials) { - loader. - setMaterials(materials). - load( - uri, - function OBJMaterialsReady(obj) { - // add the container group - meshRes.add(obj); - }, - null, - ROS3D.MeshLoader.onError); - } + //Reload the mesh again after materials have been loaded + // @todo: this should be improved so that the file doesn't need to be + // reloaded however that would involve more changes within the OBJLoader. + function onMaterialsLoaded(loader, materials) { + loader. + setMaterials(materials). + load( + uri, + function OBJMaterialsReady(obj) { + // add the container group + meshRes.add(obj); + }, + null, + ROS3D.MeshLoader.onError); + } - loader.load( - uri, - function OBJFileReady(obj) { + loader.load( + uri, + function OBJFileReady(obj) { - const baseUri = THREE.LoaderUtils.extractUrlBase( uri ); + const baseUri = THREE.LoaderUtils.extractUrlBase(uri); - if (obj.materialLibraries.length) { - // load the material libraries - const materialUri = obj.materialLibraries[0]; - new THREE.MTLLoader(options.loader).setPath(baseUri).load( - materialUri, - function(materials) { - materials.preload(); - onMaterialsLoaded(loader, materials); - }, - null, - ROS3D.MeshLoader.onError - ); - } else { - // add the container group - meshRes.add(obj); - } + if (obj.materialLibraries.length) { + // load the material libraries + const materialUri = obj.materialLibraries[0]; + new MTLLoader(options.loader).setPath(baseUri).load( + materialUri, + function (materials) { + materials.preload(); + onMaterialsLoaded(loader, materials); + }, + null, + ROS3D.MeshLoader.onError + ); + } else { + // add the container group + meshRes.add(obj); + } - }, + }, /*onProgress=*/null, - ROS3D.MeshLoader.onError - ); - return loader; - }, + ROS3D.MeshLoader.onError + ); + return loader; + }, - 'stl': function(meshRes, uri, options) { - const material = options.material; - const loader = new THREE.STLLoader(options.loader); - { - loader.load(uri, - function ( geometry ) { - geometry.computeFaceNormals(); - var mesh; - if(material !== null) { - mesh = new THREE.Mesh( geometry, material ); - } else { - mesh = new THREE.Mesh( geometry, - new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); - } - meshRes.add(mesh); - }, + 'stl': function (meshRes, uri, options) { + const material = options.material; + const loader = new STLLoader(options.loader); + { + loader.load(uri, + function (geometry) { + geometry.computeVertexNormals(); + var mesh; + if (material !== null) { + mesh = new THREE.Mesh(geometry, material); + } else { + mesh = new THREE.Mesh(geometry, + new THREE.MeshBasicMaterial({ color: 0x999999 })); + } + meshRes.add(mesh); + }, /*onProgress=*/null, - ROS3D.MeshLoader.onError); - } - return loader; - } + ROS3D.MeshLoader.onError); + } + return loader; + } - } - }; + } +}; diff --git a/src/models/TriangleList.js b/src/models/TriangleList.js index c2138f88..ea3733f4 100644 --- a/src/models/TriangleList.js +++ b/src/models/TriangleList.js @@ -13,7 +13,7 @@ * * vertices - the array of vertices to use * * colors - the associated array of colors to use */ -ROS3D.TriangleList = function(options) { +ROS3D.TriangleList = function (options) { options = options || {}; var material = options.material || new THREE.MeshBasicMaterial(); var vertices = options.vertices; @@ -24,40 +24,52 @@ ROS3D.TriangleList = function(options) { // set the material to be double sided material.side = THREE.DoubleSide; - // construct the geometry - var geometry = new THREE.Geometry(); - for (i = 0; i < vertices.length; i++) { - geometry.vertices.push(new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)); + + // Construct the geometry + let geometry = new THREE.BufferGeometry(); + let verticesArray = new Float32Array(vertices.length * 3); + for (let i = 0; i < vertices.length; i++) { + verticesArray[i * 3] = vertices[i].x; + verticesArray[i * 3 + 1] = vertices[i].y; + verticesArray[i * 3 + 2] = vertices[i].z; } + geometry.setAttribute('position', new THREE.BufferAttribute(verticesArray, 3)); - // set the colors - var i, j; + // Set the colors + let i, j; if (colors.length === vertices.length) { - // use per-vertex color - for (i = 0; i < vertices.length; i += 3) { - var faceVert = new THREE.Face3(i, i + 1, i + 2); - for (j = i * 3; j < i * 3 + 3; i++) { - var color = new THREE.Color(); - color.setRGB(colors[i].r, colors[i].g, colors[i].b); - faceVert.vertexColors.push(color); - } - geometry.faces.push(faceVert); + // Use per-vertex color + let vertexColors = new Float32Array(colors.length * 3); + for (i = 0; i < colors.length; i++) { + vertexColors[i * 3] = colors[i].r; + vertexColors[i * 3 + 1] = colors[i].g; + vertexColors[i * 3 + 2] = colors[i].b; } - material.vertexColors = THREE.VertexColors; + geometry.setAttribute('color', new THREE.BufferAttribute(vertexColors, 3)); + material.vertexColors = true; } else if (colors.length === vertices.length / 3) { - // use per-triangle color - for (i = 0; i < vertices.length; i += 3) { - var faceTri = new THREE.Face3(i, i + 1, i + 2); - faceTri.color.setRGB(colors[i / 3].r, colors[i / 3].g, colors[i / 3].b); - geometry.faces.push(faceTri); + // Use per-triangle color + let faceColors = new Float32Array(vertices.length); + for (i = 0; i < colors.length; i++) { + let color = new THREE.Color(colors[i].r, colors[i].g, colors[i].b); + for (j = 0; j < 9; j += 3) { + faceColors[i * 9 + j] = color.r; + faceColors[i * 9 + j + 1] = color.g; + faceColors[i * 9 + j + 2] = color.b; + } } - material.vertexColors = THREE.FaceColors; + geometry.setAttribute('color', new THREE.BufferAttribute(faceColors, 3)); + material.vertexColors = true; } else { - // use marker color + // Use marker color + let defaultColor = new THREE.Color(1, 1, 1); // Default color + let faceColors = new Float32Array(vertices.length); for (i = 0; i < vertices.length; i += 3) { - var face = new THREE.Face3(i, i + 1, i + 2); - geometry.faces.push(face); + faceColors[i * 3] = defaultColor.r; + faceColors[i * 3 + 1] = defaultColor.g; + faceColors[i * 3 + 2] = defaultColor.b; } + geometry.setAttribute('color', new THREE.BufferAttribute(faceColors, 3)); } geometry.computeBoundingBox(); @@ -73,6 +85,6 @@ ROS3D.TriangleList.prototype.__proto__ = THREE.Object3D.prototype; * * @param hex - the hex value of the color to set */ -ROS3D.TriangleList.prototype.setColor = function(hex) { +ROS3D.TriangleList.prototype.setColor = function (hex) { this.mesh.material.color.setHex(hex); }; diff --git a/src/navigation/OcTreeBase.js b/src/navigation/OcTreeBase.js index ac4c77cf..c46fcc33 100644 --- a/src/navigation/OcTreeBase.js +++ b/src/navigation/OcTreeBase.js @@ -403,7 +403,7 @@ ROS3D.OcTreeBase.prototype.buildGeometry = function () { const material = new THREE.MeshBasicMaterial({ color: 'white', flatShading: true, - vertexColors: THREE.VertexColors, + vertexColors: true, transparent: this.opacity < 1.0, opacity: this.opacity }); diff --git a/src/navigation/OcTreeClient.js b/src/navigation/OcTreeClient.js index 722e1dad..1983b2b0 100644 --- a/src/navigation/OcTreeClient.js +++ b/src/navigation/OcTreeClient.js @@ -30,7 +30,7 @@ */ ROS3D.OcTreeClient = function(options) { - EventEmitter3.call(this); + EventEmitter2.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/octomap'; @@ -60,7 +60,7 @@ ROS3D.OcTreeClient = function(options) { this.subscribe(); }; -ROS3D.OcTreeClient.prototype.__proto__ = EventEmitter3.prototype; +ROS3D.OcTreeClient.prototype.__proto__ = EventEmitter2.prototype; ROS3D.OcTreeClient.prototype.unsubscribe = function () { if (this.rosTopic) { diff --git a/src/navigation/OccupancyGrid.js b/src/navigation/OccupancyGrid.js index 41ca98a7..a75ee832 100644 --- a/src/navigation/OccupancyGrid.js +++ b/src/navigation/OccupancyGrid.js @@ -24,7 +24,8 @@ ROS3D.OccupancyGrid = function(options) { var origin = info.origin; var width = info.width; var height = info.height; - var geom = new THREE.PlaneBufferGeometry(width, height); + var geom = new THREE.PlaneGeometry(width, height); + // create the color material var imageData = new Uint8Array(width * height * 4); diff --git a/src/navigation/OccupancyGridClient.js b/src/navigation/OccupancyGridClient.js index 011e69d4..493831e2 100644 --- a/src/navigation/OccupancyGridClient.js +++ b/src/navigation/OccupancyGridClient.js @@ -24,7 +24,7 @@ * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) */ ROS3D.OccupancyGridClient = function(options) { - EventEmitter3.call(this); + EventEmitter2.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/map'; @@ -44,7 +44,7 @@ ROS3D.OccupancyGridClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter3.prototype; +ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter2.prototype; ROS3D.OccupancyGridClient.prototype.unsubscribe = function(){ if(this.rosTopic){ diff --git a/src/navigation/Path.js b/src/navigation/Path.js index 2b26d0d0..e5aa3b74 100644 --- a/src/navigation/Path.js +++ b/src/navigation/Path.js @@ -59,7 +59,7 @@ ROS3D.Path.prototype.processMessage = function(message){ this.rootObject.remove(this.sn); } - var lineGeometry = new THREE.Geometry(); + var lineGeometry = new THREE.BufferGeometry(); for(var i=0; i Date: Wed, 24 Jul 2024 12:06:30 +0200 Subject: [PATCH 4/8] change to "eventemitter3": "^5.0.1" --- build/ros3d.cjs.js | 1648 +---------------- build/ros3d.esm.js | 1648 +---------------- build/ros3d.js | 1648 +---------------- build/ros3d.min.js | 9 +- package-lock.json | 30 +- package.json | 2 +- .../InteractiveMarkerHandle.js | 2 +- src/markers/MarkerArrayClient.js | 2 +- src/markers/MarkerClient.js | 2 +- src/navigation/OcTreeClient.js | 4 +- src/navigation/OccupancyGridClient.js | 4 +- 11 files changed, 45 insertions(+), 4954 deletions(-) diff --git a/build/ros3d.cjs.js b/build/ros3d.cjs.js index 2a8c74da..4fa00b66 100644 --- a/build/ros3d.cjs.js +++ b/build/ros3d.cjs.js @@ -43610,1644 +43610,6 @@ var InteractiveMarker = /*#__PURE__*/function (_THREE$Object3D) { }]); }(Object3D); -function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; -} - -var eventemitter2 = {exports: {}}; - -/*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */ -eventemitter2.exports; - -(function (module, exports) { -!function(undefined$1) { - var hasOwnProperty= Object.hasOwnProperty; - var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - var defaultMaxListeners = 10; - var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; - var symbolsSupported= typeof Symbol==='function'; - var reflectSupported= typeof Reflect === 'object'; - var setImmediateSupported= typeof setImmediate === 'function'; - var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; - var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ - var arr= Object.getOwnPropertyNames(obj); - arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); - return arr; - }) : Object.keys; - - function init() { - this._events = {}; - if (this._conf) { - configure.call(this, this._conf); - } - } - - function configure(conf) { - if (conf) { - this._conf = conf; - - conf.delimiter && (this.delimiter = conf.delimiter); - - if(conf.maxListeners!==undefined$1){ - this._maxListeners= conf.maxListeners; - } - - conf.wildcard && (this.wildcard = conf.wildcard); - conf.newListener && (this._newListener = conf.newListener); - conf.removeListener && (this._removeListener = conf.removeListener); - conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); - conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); - - if (this.wildcard) { - this.listenerTree = {}; - } - } - } - - function logPossibleMemoryLeak(count, eventName) { - var errorMsg = '(node) warning: possible EventEmitter memory ' + - 'leak detected. ' + count + ' listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.'; - - if(this.verboseMemoryLeak){ - errorMsg += ' Event name: ' + eventName + '.'; - } - - if(typeof process !== 'undefined' && process.emitWarning){ - var e = new Error(errorMsg); - e.name = 'MaxListenersExceededWarning'; - e.emitter = this; - e.count = count; - process.emitWarning(e); - } else { - console.error(errorMsg); - - if (console.trace){ - console.trace(); - } - } - } - - var toArray = function (a, b, c) { - var n = arguments.length; - switch (n) { - case 0: - return []; - case 1: - return [a]; - case 2: - return [a, b]; - case 3: - return [a, b, c]; - default: - var arr = new Array(n); - while (n--) { - arr[n] = arguments[n]; - } - return arr; - } - }; - - function toObject(keys, values) { - var obj = {}; - var key; - var len = keys.length; - var valuesCount = values ? value.length : 0; - for (var i = 0; i < len; i++) { - key = keys[i]; - obj[key] = i < valuesCount ? values[i] : undefined$1; - } - return obj; - } - - function TargetObserver(emitter, target, options) { - this._emitter = emitter; - this._target = target; - this._listeners = {}; - this._listenersCount = 0; - - var on, off; - - if (options.on || options.off) { - on = options.on; - off = options.off; - } - - if (target.addEventListener) { - on = target.addEventListener; - off = target.removeEventListener; - } else if (target.addListener) { - on = target.addListener; - off = target.removeListener; - } else if (target.on) { - on = target.on; - off = target.off; - } - - if (!on && !off) { - throw Error('target does not implement any known event API'); - } - - if (typeof on !== 'function') { - throw TypeError('on method must be a function'); - } - - if (typeof off !== 'function') { - throw TypeError('off method must be a function'); - } - - this._on = on; - this._off = off; - - var _observers= emitter._observers; - if(_observers){ - _observers.push(this); - }else { - emitter._observers= [this]; - } - } - - Object.assign(TargetObserver.prototype, { - subscribe: function(event, localEvent, reducer){ - var observer= this; - var target= this._target; - var emitter= this._emitter; - var listeners= this._listeners; - var handler= function(){ - var args= toArray.apply(null, arguments); - var eventObj= { - data: args, - name: localEvent, - original: event - }; - if(reducer){ - var result= reducer.call(target, eventObj); - if(result!==false){ - emitter.emit.apply(emitter, [eventObj.name].concat(args)); - } - return; - } - emitter.emit.apply(emitter, [localEvent].concat(args)); - }; - - - if(listeners[event]){ - throw Error('Event \'' + event + '\' is already listening'); - } - - this._listenersCount++; - - if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ - - this._onNewListener = function (_event) { - if (_event === localEvent && listeners[event] === null) { - listeners[event] = handler; - observer._on.call(target, event, handler); - } - }; - - emitter.on('newListener', this._onNewListener); - - this._onRemoveListener= function(_event){ - if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ - listeners[event]= null; - observer._off.call(target, event, handler); - } - }; - - listeners[event]= null; - - emitter.on('removeListener', this._onRemoveListener); - }else { - listeners[event]= handler; - observer._on.call(target, event, handler); - } - }, - - unsubscribe: function(event){ - var observer= this; - var listeners= this._listeners; - var emitter= this._emitter; - var handler; - var events; - var off= this._off; - var target= this._target; - var i; - - if(event && typeof event!=='string'){ - throw TypeError('event must be a string'); - } - - function clearRefs(){ - if(observer._onNewListener){ - emitter.off('newListener', observer._onNewListener); - emitter.off('removeListener', observer._onRemoveListener); - observer._onNewListener= null; - observer._onRemoveListener= null; - } - var index= findTargetIndex.call(emitter, observer); - emitter._observers.splice(index, 1); - } - - if(event){ - handler= listeners[event]; - if(!handler) return; - off.call(target, event, handler); - delete listeners[event]; - if(!--this._listenersCount){ - clearRefs(); - } - }else { - events= ownKeys(listeners); - i= events.length; - while(i-->0){ - event= events[i]; - off.call(target, event, listeners[event]); - } - this._listeners= {}; - this._listenersCount= 0; - clearRefs(); - } - } - }); - - function resolveOptions(options, schema, reducers, allowUnknown) { - var computedOptions = Object.assign({}, schema); - - if (!options) return computedOptions; - - if (typeof options !== 'object') { - throw TypeError('options must be an object') - } - - var keys = Object.keys(options); - var length = keys.length; - var option, value; - var reducer; - - function reject(reason) { - throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) - } - - for (var i = 0; i < length; i++) { - option = keys[i]; - if (!allowUnknown && !hasOwnProperty.call(schema, option)) { - throw Error('Unknown "' + option + '" option'); - } - value = options[option]; - if (value !== undefined$1) { - reducer = reducers[option]; - computedOptions[option] = reducer ? reducer(value, reject) : value; - } - } - return computedOptions; - } - - function constructorReducer(value, reject) { - if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { - reject('value must be a constructor'); - } - return value; - } - - function makeTypeReducer(types) { - var message= 'value must be type of ' + types.join('|'); - var len= types.length; - var firstType= types[0]; - var secondType= types[1]; - - if (len === 1) { - return function (v, reject) { - if (typeof v === firstType) { - return v; - } - reject(message); - } - } - - if (len === 2) { - return function (v, reject) { - var kind= typeof v; - if (kind === firstType || kind === secondType) return v; - reject(message); - } - } - - return function (v, reject) { - var kind = typeof v; - var i = len; - while (i-- > 0) { - if (kind === types[i]) return v; - } - reject(message); - } - } - - var functionReducer= makeTypeReducer(['function']); - - var objectFunctionReducer= makeTypeReducer(['object', 'function']); - - function makeCancelablePromise(Promise, executor, options) { - var isCancelable; - var callbacks; - var timer= 0; - var subscriptionClosed; - - var promise = new Promise(function (resolve, reject, onCancel) { - options= resolveOptions(options, { - timeout: 0, - overload: false - }, { - timeout: function(value, reject){ - value*= 1; - if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { - reject('timeout must be a positive number'); - } - return value; - } - }); - - isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; - - function cleanup() { - if (callbacks) { - callbacks = null; - } - if (timer) { - clearTimeout(timer); - timer = 0; - } - } - - var _resolve= function(value){ - cleanup(); - resolve(value); - }; - - var _reject= function(err){ - cleanup(); - reject(err); - }; - - if (isCancelable) { - executor(_resolve, _reject, onCancel); - } else { - callbacks = [function(reason){ - _reject(reason || Error('canceled')); - }]; - executor(_resolve, _reject, function (cb) { - if (subscriptionClosed) { - throw Error('Unable to subscribe on cancel event asynchronously') - } - if (typeof cb !== 'function') { - throw TypeError('onCancel callback must be a function'); - } - callbacks.push(cb); - }); - subscriptionClosed= true; - } - - if (options.timeout > 0) { - timer= setTimeout(function(){ - var reason= Error('timeout'); - reason.code = 'ETIMEDOUT'; - timer= 0; - promise.cancel(reason); - reject(reason); - }, options.timeout); - } - }); - - if (!isCancelable) { - promise.cancel = function (reason) { - if (!callbacks) { - return; - } - var length = callbacks.length; - for (var i = 1; i < length; i++) { - callbacks[i](reason); - } - // internal callback to reject the promise - callbacks[0](reason); - callbacks = null; - }; - } - - return promise; - } - - function findTargetIndex(observer) { - var observers = this._observers; - if(!observers){ - return -1; - } - var len = observers.length; - for (var i = 0; i < len; i++) { - if (observers[i]._target === observer) return i; - } - return -1; - } - - // Attention, function return type now is array, always ! - // It has zero elements if no any matches found and one or more - // elements (leafs) if there are matches - // - function searchListenerTree(handlers, type, tree, i, typeLength) { - if (!tree) { - return null; - } - - if (i === 0) { - var kind = typeof type; - if (kind === 'string') { - var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; - if ((n = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[l++] = type.slice(j, n); - j = n + dl; - } while ((n = type.indexOf(delimiter, j)) !== -1); - - ns[l++] = type.slice(j); - type = ns; - typeLength = l; - } else { - type = [type]; - typeLength = 1; - } - } else if (kind === 'object') { - typeLength = type.length; - } else { - type = [type]; - typeLength = 1; - } - } - - var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], - nextType = type[i + 1], branches, _listeners; - - if (i === typeLength) { - // - // If at the end of the event(s) list and the tree has listeners - // invoke those listeners. - // - - if(tree._listeners) { - if (typeof tree._listeners === 'function') { - handlers && handlers.push(tree._listeners); - listeners = [tree]; - } else { - handlers && handlers.push.apply(handlers, tree._listeners); - listeners = [tree]; - } - } - } else { - - if (currentType === '*') { - // - // If the event emitted is '*' at this part - // or there is a concrete match at this patch - // - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (currentType === '**') { - endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); - if (endReached && tree._listeners) { - // The next element has a _listeners, add it to the handlers. - listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); - } - - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - if (branch === '*' || branch === '**') { - if (tree[branch]._listeners && !endReached) { - _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } else if (branch === nextType) { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); - } else { - // No match on this one, shift into the tree but not in the type array. - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (tree[currentType]) { - listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); - } - } - - xTree = tree['*']; - if (xTree) { - // - // If the listener tree will allow any match for this part, - // then recursively explore all branches of the tree - // - searchListenerTree(handlers, type, xTree, i + 1, typeLength); - } - - xxTree = tree['**']; - if (xxTree) { - if (i < typeLength) { - if (xxTree._listeners) { - // If we have a listener on a '**', it will catch all, so add its handler. - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } - - // Build arrays of matching next branches and others. - branches= ownKeys(xxTree); - n= branches.length; - while(n-->0){ - branch= branches[n]; - if (branch !== '_listeners') { - if (branch === nextType) { - // We know the next element will match, so jump twice. - searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); - } else if (branch === currentType) { - // Current node matches, move into the tree. - searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); - } else { - isolatedBranch = {}; - isolatedBranch[branch] = xxTree[branch]; - searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); - } - } - } - } else if (xxTree._listeners) { - // We have reached the end and still on a '**' - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } else if (xxTree['*'] && xxTree['*']._listeners) { - searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); - } - } - - return listeners; - } - - function growListenerTree(type, listener, prepend) { - var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; - - if(typeof type==='string') { - if ((i = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[len++] = type.slice(j, i); - j = i + dl; - } while ((i = type.indexOf(delimiter, j)) !== -1); - - ns[len++] = type.slice(j); - }else { - ns= [type]; - len= 1; - } - }else { - ns= type; - len= type.length; - } - - // - // Looks for two consecutive '**', if so, don't add the event at all. - // - if (len > 1) { - for (i = 0; i + 1 < len; i++) { - if (ns[i] === '**' && ns[i + 1] === '**') { - return; - } - } - } - - - - var tree = this.listenerTree, name; - - for (i = 0; i < len; i++) { - name = ns[i]; - - tree = tree[name] || (tree[name] = {}); - - if (i === len - 1) { - if (!tree._listeners) { - tree._listeners = listener; - } else { - if (typeof tree._listeners === 'function') { - tree._listeners = [tree._listeners]; - } - - if (prepend) { - tree._listeners.unshift(listener); - } else { - tree._listeners.push(listener); - } - - if ( - !tree._listeners.warned && - this._maxListeners > 0 && - tree._listeners.length > this._maxListeners - ) { - tree._listeners.warned = true; - logPossibleMemoryLeak.call(this, tree._listeners.length, name); - } - } - return true; - } - } - - return true; - } - - function collectTreeEvents(tree, events, root, asArray){ - var branches= ownKeys(tree); - var i= branches.length; - var branch, branchName, path; - var hasListeners= tree['_listeners']; - var isArrayPath; - - while(i-->0){ - branchName= branches[i]; - - branch= tree[branchName]; - - if(branchName==='_listeners'){ - path= root; - }else { - path = root ? root.concat(branchName) : [branchName]; - } - - isArrayPath= asArray || typeof branchName==='symbol'; - - hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); - - if(typeof branch==='object'){ - collectTreeEvents.call(this, branch, events, path, isArrayPath); - } - } - - return events; - } - - function recursivelyGarbageCollect(root) { - var keys = ownKeys(root); - var i= keys.length; - var obj, key, flag; - while(i-->0){ - key = keys[i]; - obj = root[key]; - - if(obj){ - flag= true; - if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ - delete root[key]; - } - } - } - - return flag; - } - - function Listener(emitter, event, listener){ - this.emitter= emitter; - this.event= event; - this.listener= listener; - } - - Listener.prototype.off= function(){ - this.emitter.off(this.event, this.listener); - return this; - }; - - function setupListener(event, listener, options){ - if (options === true) { - promisify = true; - } else if (options === false) { - async = true; - } else { - if (!options || typeof options !== 'object') { - throw TypeError('options should be an object or true'); - } - var async = options.async; - var promisify = options.promisify; - var nextTick = options.nextTick; - var objectify = options.objectify; - } - - if (async || nextTick || promisify) { - var _listener = listener; - var _origin = listener._origin || listener; - - if (nextTick && !nextTickSupported) { - throw Error('process.nextTick is not supported'); - } - - if (promisify === undefined$1) { - promisify = listener.constructor.name === 'AsyncFunction'; - } - - listener = function () { - var args = arguments; - var context = this; - var event = this.event; - - return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { - _setImmediate(resolve); - }).then(function () { - context.event = event; - return _listener.apply(context, args) - })) : (nextTick ? process.nextTick : _setImmediate)(function () { - context.event = event; - _listener.apply(context, args); - }); - }; - - listener._async = true; - listener._origin = _origin; - } - - return [listener, objectify? new Listener(this, event, listener): this]; - } - - function EventEmitter(conf) { - this._events = {}; - this._newListener = false; - this._removeListener = false; - this.verboseMemoryLeak = false; - configure.call(this, conf); - } - - EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property - - EventEmitter.prototype.listenTo= function(target, events, options){ - if(typeof target!=='object'){ - throw TypeError('target musts be an object'); - } - - var emitter= this; - - options = resolveOptions(options, { - on: undefined$1, - off: undefined$1, - reducers: undefined$1 - }, { - on: functionReducer, - off: functionReducer, - reducers: objectFunctionReducer - }); - - function listen(events){ - if(typeof events!=='object'){ - throw TypeError('events must be an object'); - } - - var reducers= options.reducers; - var index= findTargetIndex.call(emitter, target); - var observer; - - if(index===-1){ - observer= new TargetObserver(emitter, target, options); - }else { - observer= emitter._observers[index]; - } - - var keys= ownKeys(events); - var len= keys.length; - var event; - var isSingleReducer= typeof reducers==='function'; - - for(var i=0; i 0) { - observer = observers[i]; - if (!target || observer._target === target) { - observer.unsubscribe(event); - matched= true; - } - } - - return matched; - }; - - // By default EventEmitters will print a warning if more than - // 10 listeners are added to it. This is a useful default which - // helps finding memory leaks. - // - // Obviously not all Emitters should be limited to 10. This function allows - // that to be increased. Set to zero for unlimited. - - EventEmitter.prototype.delimiter = '.'; - - EventEmitter.prototype.setMaxListeners = function(n) { - if (n !== undefined$1) { - this._maxListeners = n; - if (!this._conf) this._conf = {}; - this._conf.maxListeners = n; - } - }; - - EventEmitter.prototype.getMaxListeners = function() { - return this._maxListeners; - }; - - EventEmitter.prototype.event = ''; - - EventEmitter.prototype.once = function(event, fn, options) { - return this._once(event, fn, false, options); - }; - - EventEmitter.prototype.prependOnceListener = function(event, fn, options) { - return this._once(event, fn, true, options); - }; - - EventEmitter.prototype._once = function(event, fn, prepend, options) { - return this._many(event, 1, fn, prepend, options); - }; - - EventEmitter.prototype.many = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, false, options); - }; - - EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, true, options); - }; - - EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { - var self = this; - - if (typeof fn !== 'function') { - throw new Error('many only accepts instances of Function'); - } - - function listener() { - if (--ttl === 0) { - self.off(event, listener); - } - return fn.apply(this, arguments); - } - - listener._origin = fn; - - return this._on(event, listener, prepend, options); - }; - - EventEmitter.prototype.emit = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], ns, wildcard= this.wildcard; - var args,l,i,j, containsSymbol; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { - return false; - } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var al = arguments.length; - var handler; - - if (this._all && this._all.length) { - handler = this._all.slice(); - - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this, type); - break; - case 2: - handler[i].call(this, type, arguments[1]); - break; - case 3: - handler[i].call(this, type, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, arguments); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); - } else { - handler = this._events[type]; - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - handler.apply(this, args); - } - return true; - } else if (handler) { - // need to make copy of handlers because list can change in the middle - // of emit call - handler = handler.slice(); - } - } - - if (handler && handler.length) { - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this); - break; - case 2: - handler[i].call(this, arguments[1]); - break; - case 3: - handler[i].call(this, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, args); - } - } - return true; - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - } - - return !!this._all; - }; - - EventEmitter.prototype.emitAsync = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; - var args,l,i,j; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { return Promise.resolve([false]); } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var promises= []; - - var al = arguments.length; - var handler; - - if (this._all) { - for (i = 0, l = this._all.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(this._all[i].call(this, type)); - break; - case 2: - promises.push(this._all[i].call(this, type, arguments[1])); - break; - case 3: - promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); - break; - default: - promises.push(this._all[i].apply(this, arguments)); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0); - } else { - handler = this._events[type]; - } - - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - promises.push(handler.call(this)); - break; - case 2: - promises.push(handler.call(this, arguments[1])); - break; - case 3: - promises.push(handler.call(this, arguments[1], arguments[2])); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - promises.push(handler.apply(this, args)); - } - } else if (handler && handler.length) { - handler = handler.slice(); - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(handler[i].call(this)); - break; - case 2: - promises.push(handler[i].call(this, arguments[1])); - break; - case 3: - promises.push(handler[i].call(this, arguments[1], arguments[2])); - break; - default: - promises.push(handler[i].apply(this, args)); - } - } - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - return Promise.reject(arguments[1]); // Unhandled 'error' event - } else { - return Promise.reject("Uncaught, unspecified 'error' event."); - } - } - - return Promise.all(promises); - }; - - EventEmitter.prototype.on = function(type, listener, options) { - return this._on(type, listener, false, options); - }; - - EventEmitter.prototype.prependListener = function(type, listener, options) { - return this._on(type, listener, true, options); - }; - - EventEmitter.prototype.onAny = function(fn) { - return this._onAny(fn, false); - }; - - EventEmitter.prototype.prependAny = function(fn) { - return this._onAny(fn, true); - }; - - EventEmitter.prototype.addListener = EventEmitter.prototype.on; - - EventEmitter.prototype._onAny = function(fn, prepend){ - if (typeof fn !== 'function') { - throw new Error('onAny only accepts instances of Function'); - } - - if (!this._all) { - this._all = []; - } - - // Add the function to the event listener collection. - if(prepend){ - this._all.unshift(fn); - }else { - this._all.push(fn); - } - - return this; - }; - - EventEmitter.prototype._on = function(type, listener, prepend, options) { - if (typeof type === 'function') { - this._onAny(type, listener); - return this; - } - - if (typeof listener !== 'function') { - throw new Error('on only accepts instances of Function'); - } - this._events || init.call(this); - - var returnValue= this, temp; - - if (options !== undefined$1) { - temp = setupListener.call(this, type, listener, options); - listener = temp[0]; - returnValue = temp[1]; - } - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._newListener) { - this.emit('newListener', type, listener); - } - - if (this.wildcard) { - growListenerTree.call(this, type, listener, prepend); - return returnValue; - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else { - if (typeof this._events[type] === 'function') { - // Change to array. - this._events[type] = [this._events[type]]; - } - - // If we've already got an array, just add - if(prepend){ - this._events[type].unshift(listener); - }else { - this._events[type].push(listener); - } - - // Check for listener leak - if ( - !this._events[type].warned && - this._maxListeners > 0 && - this._events[type].length > this._maxListeners - ) { - this._events[type].warned = true; - logPossibleMemoryLeak.call(this, this._events[type].length, type); - } - } - - return returnValue; - }; - - EventEmitter.prototype.off = function(type, listener) { - if (typeof listener !== 'function') { - throw new Error('removeListener only takes instances of Function'); - } - - var handlers,leafs=[]; - - if(this.wildcard) { - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); - if(!leafs) return this; - } else { - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events[type]) return this; - handlers = this._events[type]; - leafs.push({_listeners:handlers}); - } - - for (var iLeaf=0; iLeaf 0) { - fns = this._all; - for(i = 0, l = fns.length; i < l; i++) { - if(fn === fns[i]) { - fns.splice(i, 1); - if (this._removeListener) - this.emit("removeListenerAny", fn); - return this; - } - } - } else { - fns = this._all; - if (this._removeListener) { - for(i = 0, l = fns.length; i < l; i++) - this.emit("removeListenerAny", fns[i]); - } - this._all = []; - } - return this; - }; - - EventEmitter.prototype.removeListener = EventEmitter.prototype.off; - - EventEmitter.prototype.removeAllListeners = function (type) { - if (type === undefined$1) { - !this._events || init.call(this); - return this; - } - - if (this.wildcard) { - var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; - if (!leafs) return this; - for (i = 0; i < leafs.length; i++) { - leaf = leafs[i]; - leaf._listeners = null; - } - this.listenerTree && recursivelyGarbageCollect(this.listenerTree); - } else if (this._events) { - this._events[type] = null; - } - return this; - }; - - EventEmitter.prototype.listeners = function (type) { - var _events = this._events; - var keys, listeners, allListeners; - var i; - var listenerTree; - - if (type === undefined$1) { - if (this.wildcard) { - throw Error('event name required for wildcard emitter'); - } - - if (!_events) { - return []; - } - - keys = ownKeys(_events); - i = keys.length; - allListeners = []; - while (i-- > 0) { - listeners = _events[keys[i]]; - if (typeof listeners === 'function') { - allListeners.push(listeners); - } else { - allListeners.push.apply(allListeners, listeners); - } - } - return allListeners; - } else { - if (this.wildcard) { - listenerTree= this.listenerTree; - if(!listenerTree) return []; - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, listenerTree, 0); - return handlers; - } - - if (!_events) { - return []; - } - - listeners = _events[type]; - - if (!listeners) { - return []; - } - return typeof listeners === 'function' ? [listeners] : listeners; - } - }; - - EventEmitter.prototype.eventNames = function(nsAsArray){ - var _events= this._events; - return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); - }; - - EventEmitter.prototype.listenerCount = function(type) { - return this.listeners(type).length; - }; - - EventEmitter.prototype.hasListeners = function (type) { - if (this.wildcard) { - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); - return handlers.length > 0; - } - - var _events = this._events; - var _all = this._all; - - return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); - }; - - EventEmitter.prototype.listenersAny = function() { - - if(this._all) { - return this._all; - } - else { - return []; - } - - }; - - EventEmitter.prototype.waitFor = function (event, options) { - var self = this; - var type = typeof options; - if (type === 'number') { - options = {timeout: options}; - } else if (type === 'function') { - options = {filter: options}; - } - - options= resolveOptions(options, { - timeout: 0, - filter: undefined$1, - handleError: false, - Promise: Promise, - overload: false - }, { - filter: functionReducer, - Promise: constructorReducer - }); - - return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { - function listener() { - var filter= options.filter; - if (filter && !filter.apply(self, arguments)) { - return; - } - self.off(event, listener); - if (options.handleError) { - var err = arguments[0]; - err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); - } else { - resolve(toArray.apply(null, arguments)); - } - } - - onCancel(function(){ - self.off(event, listener); - }); - - self._on(event, listener, false); - }, { - timeout: options.timeout, - overload: options.overload - }) - }; - - function once(emitter, name, options) { - options= resolveOptions(options, { - Promise: Promise, - timeout: 0, - overload: false - }, { - Promise: constructorReducer - }); - - var _Promise= options.Promise; - - return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ - var handler; - if (typeof emitter.addEventListener === 'function') { - handler= function () { - resolve(toArray.apply(null, arguments)); - }; - - onCancel(function(){ - emitter.removeEventListener(name, handler); - }); - - emitter.addEventListener( - name, - handler, - {once: true} - ); - return; - } - - var eventListener = function(){ - errorListener && emitter.removeListener('error', errorListener); - resolve(toArray.apply(null, arguments)); - }; - - var errorListener; - - if (name !== 'error') { - errorListener = function (err){ - emitter.removeListener(name, eventListener); - reject(err); - }; - - emitter.once('error', errorListener); - } - - onCancel(function(){ - errorListener && emitter.removeListener('error', errorListener); - emitter.removeListener(name, eventListener); - }); - - emitter.once(name, eventListener); - }, { - timeout: options.timeout, - overload: options.overload - }); - } - - var prototype= EventEmitter.prototype; - - Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - get: function () { - return prototype._maxListeners; - }, - set: function (n) { - if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { - throw TypeError('n must be a non-negative number') - } - prototype._maxListeners = n; - }, - enumerable: true - }, - once: { - value: once, - writable: true, - configurable: true - } - }); - - Object.defineProperties(prototype, { - _maxListeners: { - value: defaultMaxListeners, - writable: true, - configurable: true - }, - _observers: {value: null, writable: true, configurable: true} - }); - - if (typeof undefined$1 === 'function' && undefined$1.amd) { - // AMD. Register as an anonymous module. - undefined$1(function() { - return EventEmitter; - }); - } else { - // CommonJS - module.exports = EventEmitter; - } - }(); -} (eventemitter2, eventemitter2.exports)); - -var eventemitter2Exports = eventemitter2.exports; -var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); - function _callSuper$q(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$q() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$q() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$q = function _isNativeReflectConstruct() { return !!t; })(); } @@ -45465,7 +43827,7 @@ var InteractiveMarkerHandle = /*#__PURE__*/function (_EventEmitter) { this.feedbackTopic.publish(feedback); } }]); -}(EventEmitter2); +}(EventEmitter3); /** * @fileOverview @@ -45889,7 +44251,7 @@ var MarkerArrayClient = /*#__PURE__*/function (_EventEmitter) { delete this.markers[key]; } }]); -}(EventEmitter2); +}(EventEmitter3); function _callSuper$n(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$n() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$n() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$n = function _isNativeReflectConstruct() { return !!t; })(); } @@ -46015,7 +44377,7 @@ var MarkerClient = /*#__PURE__*/function (_EventEmitter) { delete this.markers[key]; } }]); -}(EventEmitter2); +}(EventEmitter3); function _callSuper$m(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$m() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$m() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$m = function _isNativeReflectConstruct() { return !!t; })(); } @@ -46493,7 +44855,7 @@ var OccupancyGridClient = /*#__PURE__*/function (_EventEmitter) { } } }]); -}(EventEmitter2); +}(EventEmitter3); function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); @@ -47413,7 +45775,7 @@ var OcTreeClient = /*#__PURE__*/function (_EventEmitter) { }.bind(this)); } }]); -}(EventEmitter2); +}(EventEmitter3); function _callSuper$e(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$e() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$e() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$e = function _isNativeReflectConstruct() { return !!t; })(); } diff --git a/build/ros3d.esm.js b/build/ros3d.esm.js index 1870b0bb..d177b7bc 100644 --- a/build/ros3d.esm.js +++ b/build/ros3d.esm.js @@ -43586,1644 +43586,6 @@ var InteractiveMarker = /*#__PURE__*/function (_THREE$Object3D) { }]); }(Object3D); -function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; -} - -var eventemitter2 = {exports: {}}; - -/*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */ -eventemitter2.exports; - -(function (module, exports) { -!function(undefined$1) { - var hasOwnProperty= Object.hasOwnProperty; - var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - var defaultMaxListeners = 10; - var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; - var symbolsSupported= typeof Symbol==='function'; - var reflectSupported= typeof Reflect === 'object'; - var setImmediateSupported= typeof setImmediate === 'function'; - var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; - var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ - var arr= Object.getOwnPropertyNames(obj); - arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); - return arr; - }) : Object.keys; - - function init() { - this._events = {}; - if (this._conf) { - configure.call(this, this._conf); - } - } - - function configure(conf) { - if (conf) { - this._conf = conf; - - conf.delimiter && (this.delimiter = conf.delimiter); - - if(conf.maxListeners!==undefined$1){ - this._maxListeners= conf.maxListeners; - } - - conf.wildcard && (this.wildcard = conf.wildcard); - conf.newListener && (this._newListener = conf.newListener); - conf.removeListener && (this._removeListener = conf.removeListener); - conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); - conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); - - if (this.wildcard) { - this.listenerTree = {}; - } - } - } - - function logPossibleMemoryLeak(count, eventName) { - var errorMsg = '(node) warning: possible EventEmitter memory ' + - 'leak detected. ' + count + ' listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.'; - - if(this.verboseMemoryLeak){ - errorMsg += ' Event name: ' + eventName + '.'; - } - - if(typeof process !== 'undefined' && process.emitWarning){ - var e = new Error(errorMsg); - e.name = 'MaxListenersExceededWarning'; - e.emitter = this; - e.count = count; - process.emitWarning(e); - } else { - console.error(errorMsg); - - if (console.trace){ - console.trace(); - } - } - } - - var toArray = function (a, b, c) { - var n = arguments.length; - switch (n) { - case 0: - return []; - case 1: - return [a]; - case 2: - return [a, b]; - case 3: - return [a, b, c]; - default: - var arr = new Array(n); - while (n--) { - arr[n] = arguments[n]; - } - return arr; - } - }; - - function toObject(keys, values) { - var obj = {}; - var key; - var len = keys.length; - var valuesCount = values ? value.length : 0; - for (var i = 0; i < len; i++) { - key = keys[i]; - obj[key] = i < valuesCount ? values[i] : undefined$1; - } - return obj; - } - - function TargetObserver(emitter, target, options) { - this._emitter = emitter; - this._target = target; - this._listeners = {}; - this._listenersCount = 0; - - var on, off; - - if (options.on || options.off) { - on = options.on; - off = options.off; - } - - if (target.addEventListener) { - on = target.addEventListener; - off = target.removeEventListener; - } else if (target.addListener) { - on = target.addListener; - off = target.removeListener; - } else if (target.on) { - on = target.on; - off = target.off; - } - - if (!on && !off) { - throw Error('target does not implement any known event API'); - } - - if (typeof on !== 'function') { - throw TypeError('on method must be a function'); - } - - if (typeof off !== 'function') { - throw TypeError('off method must be a function'); - } - - this._on = on; - this._off = off; - - var _observers= emitter._observers; - if(_observers){ - _observers.push(this); - }else { - emitter._observers= [this]; - } - } - - Object.assign(TargetObserver.prototype, { - subscribe: function(event, localEvent, reducer){ - var observer= this; - var target= this._target; - var emitter= this._emitter; - var listeners= this._listeners; - var handler= function(){ - var args= toArray.apply(null, arguments); - var eventObj= { - data: args, - name: localEvent, - original: event - }; - if(reducer){ - var result= reducer.call(target, eventObj); - if(result!==false){ - emitter.emit.apply(emitter, [eventObj.name].concat(args)); - } - return; - } - emitter.emit.apply(emitter, [localEvent].concat(args)); - }; - - - if(listeners[event]){ - throw Error('Event \'' + event + '\' is already listening'); - } - - this._listenersCount++; - - if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ - - this._onNewListener = function (_event) { - if (_event === localEvent && listeners[event] === null) { - listeners[event] = handler; - observer._on.call(target, event, handler); - } - }; - - emitter.on('newListener', this._onNewListener); - - this._onRemoveListener= function(_event){ - if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ - listeners[event]= null; - observer._off.call(target, event, handler); - } - }; - - listeners[event]= null; - - emitter.on('removeListener', this._onRemoveListener); - }else { - listeners[event]= handler; - observer._on.call(target, event, handler); - } - }, - - unsubscribe: function(event){ - var observer= this; - var listeners= this._listeners; - var emitter= this._emitter; - var handler; - var events; - var off= this._off; - var target= this._target; - var i; - - if(event && typeof event!=='string'){ - throw TypeError('event must be a string'); - } - - function clearRefs(){ - if(observer._onNewListener){ - emitter.off('newListener', observer._onNewListener); - emitter.off('removeListener', observer._onRemoveListener); - observer._onNewListener= null; - observer._onRemoveListener= null; - } - var index= findTargetIndex.call(emitter, observer); - emitter._observers.splice(index, 1); - } - - if(event){ - handler= listeners[event]; - if(!handler) return; - off.call(target, event, handler); - delete listeners[event]; - if(!--this._listenersCount){ - clearRefs(); - } - }else { - events= ownKeys(listeners); - i= events.length; - while(i-->0){ - event= events[i]; - off.call(target, event, listeners[event]); - } - this._listeners= {}; - this._listenersCount= 0; - clearRefs(); - } - } - }); - - function resolveOptions(options, schema, reducers, allowUnknown) { - var computedOptions = Object.assign({}, schema); - - if (!options) return computedOptions; - - if (typeof options !== 'object') { - throw TypeError('options must be an object') - } - - var keys = Object.keys(options); - var length = keys.length; - var option, value; - var reducer; - - function reject(reason) { - throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) - } - - for (var i = 0; i < length; i++) { - option = keys[i]; - if (!allowUnknown && !hasOwnProperty.call(schema, option)) { - throw Error('Unknown "' + option + '" option'); - } - value = options[option]; - if (value !== undefined$1) { - reducer = reducers[option]; - computedOptions[option] = reducer ? reducer(value, reject) : value; - } - } - return computedOptions; - } - - function constructorReducer(value, reject) { - if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { - reject('value must be a constructor'); - } - return value; - } - - function makeTypeReducer(types) { - var message= 'value must be type of ' + types.join('|'); - var len= types.length; - var firstType= types[0]; - var secondType= types[1]; - - if (len === 1) { - return function (v, reject) { - if (typeof v === firstType) { - return v; - } - reject(message); - } - } - - if (len === 2) { - return function (v, reject) { - var kind= typeof v; - if (kind === firstType || kind === secondType) return v; - reject(message); - } - } - - return function (v, reject) { - var kind = typeof v; - var i = len; - while (i-- > 0) { - if (kind === types[i]) return v; - } - reject(message); - } - } - - var functionReducer= makeTypeReducer(['function']); - - var objectFunctionReducer= makeTypeReducer(['object', 'function']); - - function makeCancelablePromise(Promise, executor, options) { - var isCancelable; - var callbacks; - var timer= 0; - var subscriptionClosed; - - var promise = new Promise(function (resolve, reject, onCancel) { - options= resolveOptions(options, { - timeout: 0, - overload: false - }, { - timeout: function(value, reject){ - value*= 1; - if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { - reject('timeout must be a positive number'); - } - return value; - } - }); - - isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; - - function cleanup() { - if (callbacks) { - callbacks = null; - } - if (timer) { - clearTimeout(timer); - timer = 0; - } - } - - var _resolve= function(value){ - cleanup(); - resolve(value); - }; - - var _reject= function(err){ - cleanup(); - reject(err); - }; - - if (isCancelable) { - executor(_resolve, _reject, onCancel); - } else { - callbacks = [function(reason){ - _reject(reason || Error('canceled')); - }]; - executor(_resolve, _reject, function (cb) { - if (subscriptionClosed) { - throw Error('Unable to subscribe on cancel event asynchronously') - } - if (typeof cb !== 'function') { - throw TypeError('onCancel callback must be a function'); - } - callbacks.push(cb); - }); - subscriptionClosed= true; - } - - if (options.timeout > 0) { - timer= setTimeout(function(){ - var reason= Error('timeout'); - reason.code = 'ETIMEDOUT'; - timer= 0; - promise.cancel(reason); - reject(reason); - }, options.timeout); - } - }); - - if (!isCancelable) { - promise.cancel = function (reason) { - if (!callbacks) { - return; - } - var length = callbacks.length; - for (var i = 1; i < length; i++) { - callbacks[i](reason); - } - // internal callback to reject the promise - callbacks[0](reason); - callbacks = null; - }; - } - - return promise; - } - - function findTargetIndex(observer) { - var observers = this._observers; - if(!observers){ - return -1; - } - var len = observers.length; - for (var i = 0; i < len; i++) { - if (observers[i]._target === observer) return i; - } - return -1; - } - - // Attention, function return type now is array, always ! - // It has zero elements if no any matches found and one or more - // elements (leafs) if there are matches - // - function searchListenerTree(handlers, type, tree, i, typeLength) { - if (!tree) { - return null; - } - - if (i === 0) { - var kind = typeof type; - if (kind === 'string') { - var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; - if ((n = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[l++] = type.slice(j, n); - j = n + dl; - } while ((n = type.indexOf(delimiter, j)) !== -1); - - ns[l++] = type.slice(j); - type = ns; - typeLength = l; - } else { - type = [type]; - typeLength = 1; - } - } else if (kind === 'object') { - typeLength = type.length; - } else { - type = [type]; - typeLength = 1; - } - } - - var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], - nextType = type[i + 1], branches, _listeners; - - if (i === typeLength) { - // - // If at the end of the event(s) list and the tree has listeners - // invoke those listeners. - // - - if(tree._listeners) { - if (typeof tree._listeners === 'function') { - handlers && handlers.push(tree._listeners); - listeners = [tree]; - } else { - handlers && handlers.push.apply(handlers, tree._listeners); - listeners = [tree]; - } - } - } else { - - if (currentType === '*') { - // - // If the event emitted is '*' at this part - // or there is a concrete match at this patch - // - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (currentType === '**') { - endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); - if (endReached && tree._listeners) { - // The next element has a _listeners, add it to the handlers. - listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); - } - - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - if (branch === '*' || branch === '**') { - if (tree[branch]._listeners && !endReached) { - _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } else if (branch === nextType) { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); - } else { - // No match on this one, shift into the tree but not in the type array. - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (tree[currentType]) { - listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); - } - } - - xTree = tree['*']; - if (xTree) { - // - // If the listener tree will allow any match for this part, - // then recursively explore all branches of the tree - // - searchListenerTree(handlers, type, xTree, i + 1, typeLength); - } - - xxTree = tree['**']; - if (xxTree) { - if (i < typeLength) { - if (xxTree._listeners) { - // If we have a listener on a '**', it will catch all, so add its handler. - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } - - // Build arrays of matching next branches and others. - branches= ownKeys(xxTree); - n= branches.length; - while(n-->0){ - branch= branches[n]; - if (branch !== '_listeners') { - if (branch === nextType) { - // We know the next element will match, so jump twice. - searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); - } else if (branch === currentType) { - // Current node matches, move into the tree. - searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); - } else { - isolatedBranch = {}; - isolatedBranch[branch] = xxTree[branch]; - searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); - } - } - } - } else if (xxTree._listeners) { - // We have reached the end and still on a '**' - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } else if (xxTree['*'] && xxTree['*']._listeners) { - searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); - } - } - - return listeners; - } - - function growListenerTree(type, listener, prepend) { - var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; - - if(typeof type==='string') { - if ((i = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[len++] = type.slice(j, i); - j = i + dl; - } while ((i = type.indexOf(delimiter, j)) !== -1); - - ns[len++] = type.slice(j); - }else { - ns= [type]; - len= 1; - } - }else { - ns= type; - len= type.length; - } - - // - // Looks for two consecutive '**', if so, don't add the event at all. - // - if (len > 1) { - for (i = 0; i + 1 < len; i++) { - if (ns[i] === '**' && ns[i + 1] === '**') { - return; - } - } - } - - - - var tree = this.listenerTree, name; - - for (i = 0; i < len; i++) { - name = ns[i]; - - tree = tree[name] || (tree[name] = {}); - - if (i === len - 1) { - if (!tree._listeners) { - tree._listeners = listener; - } else { - if (typeof tree._listeners === 'function') { - tree._listeners = [tree._listeners]; - } - - if (prepend) { - tree._listeners.unshift(listener); - } else { - tree._listeners.push(listener); - } - - if ( - !tree._listeners.warned && - this._maxListeners > 0 && - tree._listeners.length > this._maxListeners - ) { - tree._listeners.warned = true; - logPossibleMemoryLeak.call(this, tree._listeners.length, name); - } - } - return true; - } - } - - return true; - } - - function collectTreeEvents(tree, events, root, asArray){ - var branches= ownKeys(tree); - var i= branches.length; - var branch, branchName, path; - var hasListeners= tree['_listeners']; - var isArrayPath; - - while(i-->0){ - branchName= branches[i]; - - branch= tree[branchName]; - - if(branchName==='_listeners'){ - path= root; - }else { - path = root ? root.concat(branchName) : [branchName]; - } - - isArrayPath= asArray || typeof branchName==='symbol'; - - hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); - - if(typeof branch==='object'){ - collectTreeEvents.call(this, branch, events, path, isArrayPath); - } - } - - return events; - } - - function recursivelyGarbageCollect(root) { - var keys = ownKeys(root); - var i= keys.length; - var obj, key, flag; - while(i-->0){ - key = keys[i]; - obj = root[key]; - - if(obj){ - flag= true; - if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ - delete root[key]; - } - } - } - - return flag; - } - - function Listener(emitter, event, listener){ - this.emitter= emitter; - this.event= event; - this.listener= listener; - } - - Listener.prototype.off= function(){ - this.emitter.off(this.event, this.listener); - return this; - }; - - function setupListener(event, listener, options){ - if (options === true) { - promisify = true; - } else if (options === false) { - async = true; - } else { - if (!options || typeof options !== 'object') { - throw TypeError('options should be an object or true'); - } - var async = options.async; - var promisify = options.promisify; - var nextTick = options.nextTick; - var objectify = options.objectify; - } - - if (async || nextTick || promisify) { - var _listener = listener; - var _origin = listener._origin || listener; - - if (nextTick && !nextTickSupported) { - throw Error('process.nextTick is not supported'); - } - - if (promisify === undefined$1) { - promisify = listener.constructor.name === 'AsyncFunction'; - } - - listener = function () { - var args = arguments; - var context = this; - var event = this.event; - - return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { - _setImmediate(resolve); - }).then(function () { - context.event = event; - return _listener.apply(context, args) - })) : (nextTick ? process.nextTick : _setImmediate)(function () { - context.event = event; - _listener.apply(context, args); - }); - }; - - listener._async = true; - listener._origin = _origin; - } - - return [listener, objectify? new Listener(this, event, listener): this]; - } - - function EventEmitter(conf) { - this._events = {}; - this._newListener = false; - this._removeListener = false; - this.verboseMemoryLeak = false; - configure.call(this, conf); - } - - EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property - - EventEmitter.prototype.listenTo= function(target, events, options){ - if(typeof target!=='object'){ - throw TypeError('target musts be an object'); - } - - var emitter= this; - - options = resolveOptions(options, { - on: undefined$1, - off: undefined$1, - reducers: undefined$1 - }, { - on: functionReducer, - off: functionReducer, - reducers: objectFunctionReducer - }); - - function listen(events){ - if(typeof events!=='object'){ - throw TypeError('events must be an object'); - } - - var reducers= options.reducers; - var index= findTargetIndex.call(emitter, target); - var observer; - - if(index===-1){ - observer= new TargetObserver(emitter, target, options); - }else { - observer= emitter._observers[index]; - } - - var keys= ownKeys(events); - var len= keys.length; - var event; - var isSingleReducer= typeof reducers==='function'; - - for(var i=0; i 0) { - observer = observers[i]; - if (!target || observer._target === target) { - observer.unsubscribe(event); - matched= true; - } - } - - return matched; - }; - - // By default EventEmitters will print a warning if more than - // 10 listeners are added to it. This is a useful default which - // helps finding memory leaks. - // - // Obviously not all Emitters should be limited to 10. This function allows - // that to be increased. Set to zero for unlimited. - - EventEmitter.prototype.delimiter = '.'; - - EventEmitter.prototype.setMaxListeners = function(n) { - if (n !== undefined$1) { - this._maxListeners = n; - if (!this._conf) this._conf = {}; - this._conf.maxListeners = n; - } - }; - - EventEmitter.prototype.getMaxListeners = function() { - return this._maxListeners; - }; - - EventEmitter.prototype.event = ''; - - EventEmitter.prototype.once = function(event, fn, options) { - return this._once(event, fn, false, options); - }; - - EventEmitter.prototype.prependOnceListener = function(event, fn, options) { - return this._once(event, fn, true, options); - }; - - EventEmitter.prototype._once = function(event, fn, prepend, options) { - return this._many(event, 1, fn, prepend, options); - }; - - EventEmitter.prototype.many = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, false, options); - }; - - EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, true, options); - }; - - EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { - var self = this; - - if (typeof fn !== 'function') { - throw new Error('many only accepts instances of Function'); - } - - function listener() { - if (--ttl === 0) { - self.off(event, listener); - } - return fn.apply(this, arguments); - } - - listener._origin = fn; - - return this._on(event, listener, prepend, options); - }; - - EventEmitter.prototype.emit = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], ns, wildcard= this.wildcard; - var args,l,i,j, containsSymbol; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { - return false; - } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var al = arguments.length; - var handler; - - if (this._all && this._all.length) { - handler = this._all.slice(); - - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this, type); - break; - case 2: - handler[i].call(this, type, arguments[1]); - break; - case 3: - handler[i].call(this, type, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, arguments); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); - } else { - handler = this._events[type]; - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - handler.apply(this, args); - } - return true; - } else if (handler) { - // need to make copy of handlers because list can change in the middle - // of emit call - handler = handler.slice(); - } - } - - if (handler && handler.length) { - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this); - break; - case 2: - handler[i].call(this, arguments[1]); - break; - case 3: - handler[i].call(this, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, args); - } - } - return true; - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - } - - return !!this._all; - }; - - EventEmitter.prototype.emitAsync = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; - var args,l,i,j; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { return Promise.resolve([false]); } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var promises= []; - - var al = arguments.length; - var handler; - - if (this._all) { - for (i = 0, l = this._all.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(this._all[i].call(this, type)); - break; - case 2: - promises.push(this._all[i].call(this, type, arguments[1])); - break; - case 3: - promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); - break; - default: - promises.push(this._all[i].apply(this, arguments)); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0); - } else { - handler = this._events[type]; - } - - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - promises.push(handler.call(this)); - break; - case 2: - promises.push(handler.call(this, arguments[1])); - break; - case 3: - promises.push(handler.call(this, arguments[1], arguments[2])); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - promises.push(handler.apply(this, args)); - } - } else if (handler && handler.length) { - handler = handler.slice(); - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(handler[i].call(this)); - break; - case 2: - promises.push(handler[i].call(this, arguments[1])); - break; - case 3: - promises.push(handler[i].call(this, arguments[1], arguments[2])); - break; - default: - promises.push(handler[i].apply(this, args)); - } - } - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - return Promise.reject(arguments[1]); // Unhandled 'error' event - } else { - return Promise.reject("Uncaught, unspecified 'error' event."); - } - } - - return Promise.all(promises); - }; - - EventEmitter.prototype.on = function(type, listener, options) { - return this._on(type, listener, false, options); - }; - - EventEmitter.prototype.prependListener = function(type, listener, options) { - return this._on(type, listener, true, options); - }; - - EventEmitter.prototype.onAny = function(fn) { - return this._onAny(fn, false); - }; - - EventEmitter.prototype.prependAny = function(fn) { - return this._onAny(fn, true); - }; - - EventEmitter.prototype.addListener = EventEmitter.prototype.on; - - EventEmitter.prototype._onAny = function(fn, prepend){ - if (typeof fn !== 'function') { - throw new Error('onAny only accepts instances of Function'); - } - - if (!this._all) { - this._all = []; - } - - // Add the function to the event listener collection. - if(prepend){ - this._all.unshift(fn); - }else { - this._all.push(fn); - } - - return this; - }; - - EventEmitter.prototype._on = function(type, listener, prepend, options) { - if (typeof type === 'function') { - this._onAny(type, listener); - return this; - } - - if (typeof listener !== 'function') { - throw new Error('on only accepts instances of Function'); - } - this._events || init.call(this); - - var returnValue= this, temp; - - if (options !== undefined$1) { - temp = setupListener.call(this, type, listener, options); - listener = temp[0]; - returnValue = temp[1]; - } - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._newListener) { - this.emit('newListener', type, listener); - } - - if (this.wildcard) { - growListenerTree.call(this, type, listener, prepend); - return returnValue; - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else { - if (typeof this._events[type] === 'function') { - // Change to array. - this._events[type] = [this._events[type]]; - } - - // If we've already got an array, just add - if(prepend){ - this._events[type].unshift(listener); - }else { - this._events[type].push(listener); - } - - // Check for listener leak - if ( - !this._events[type].warned && - this._maxListeners > 0 && - this._events[type].length > this._maxListeners - ) { - this._events[type].warned = true; - logPossibleMemoryLeak.call(this, this._events[type].length, type); - } - } - - return returnValue; - }; - - EventEmitter.prototype.off = function(type, listener) { - if (typeof listener !== 'function') { - throw new Error('removeListener only takes instances of Function'); - } - - var handlers,leafs=[]; - - if(this.wildcard) { - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); - if(!leafs) return this; - } else { - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events[type]) return this; - handlers = this._events[type]; - leafs.push({_listeners:handlers}); - } - - for (var iLeaf=0; iLeaf 0) { - fns = this._all; - for(i = 0, l = fns.length; i < l; i++) { - if(fn === fns[i]) { - fns.splice(i, 1); - if (this._removeListener) - this.emit("removeListenerAny", fn); - return this; - } - } - } else { - fns = this._all; - if (this._removeListener) { - for(i = 0, l = fns.length; i < l; i++) - this.emit("removeListenerAny", fns[i]); - } - this._all = []; - } - return this; - }; - - EventEmitter.prototype.removeListener = EventEmitter.prototype.off; - - EventEmitter.prototype.removeAllListeners = function (type) { - if (type === undefined$1) { - !this._events || init.call(this); - return this; - } - - if (this.wildcard) { - var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; - if (!leafs) return this; - for (i = 0; i < leafs.length; i++) { - leaf = leafs[i]; - leaf._listeners = null; - } - this.listenerTree && recursivelyGarbageCollect(this.listenerTree); - } else if (this._events) { - this._events[type] = null; - } - return this; - }; - - EventEmitter.prototype.listeners = function (type) { - var _events = this._events; - var keys, listeners, allListeners; - var i; - var listenerTree; - - if (type === undefined$1) { - if (this.wildcard) { - throw Error('event name required for wildcard emitter'); - } - - if (!_events) { - return []; - } - - keys = ownKeys(_events); - i = keys.length; - allListeners = []; - while (i-- > 0) { - listeners = _events[keys[i]]; - if (typeof listeners === 'function') { - allListeners.push(listeners); - } else { - allListeners.push.apply(allListeners, listeners); - } - } - return allListeners; - } else { - if (this.wildcard) { - listenerTree= this.listenerTree; - if(!listenerTree) return []; - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, listenerTree, 0); - return handlers; - } - - if (!_events) { - return []; - } - - listeners = _events[type]; - - if (!listeners) { - return []; - } - return typeof listeners === 'function' ? [listeners] : listeners; - } - }; - - EventEmitter.prototype.eventNames = function(nsAsArray){ - var _events= this._events; - return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); - }; - - EventEmitter.prototype.listenerCount = function(type) { - return this.listeners(type).length; - }; - - EventEmitter.prototype.hasListeners = function (type) { - if (this.wildcard) { - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); - return handlers.length > 0; - } - - var _events = this._events; - var _all = this._all; - - return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); - }; - - EventEmitter.prototype.listenersAny = function() { - - if(this._all) { - return this._all; - } - else { - return []; - } - - }; - - EventEmitter.prototype.waitFor = function (event, options) { - var self = this; - var type = typeof options; - if (type === 'number') { - options = {timeout: options}; - } else if (type === 'function') { - options = {filter: options}; - } - - options= resolveOptions(options, { - timeout: 0, - filter: undefined$1, - handleError: false, - Promise: Promise, - overload: false - }, { - filter: functionReducer, - Promise: constructorReducer - }); - - return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { - function listener() { - var filter= options.filter; - if (filter && !filter.apply(self, arguments)) { - return; - } - self.off(event, listener); - if (options.handleError) { - var err = arguments[0]; - err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); - } else { - resolve(toArray.apply(null, arguments)); - } - } - - onCancel(function(){ - self.off(event, listener); - }); - - self._on(event, listener, false); - }, { - timeout: options.timeout, - overload: options.overload - }) - }; - - function once(emitter, name, options) { - options= resolveOptions(options, { - Promise: Promise, - timeout: 0, - overload: false - }, { - Promise: constructorReducer - }); - - var _Promise= options.Promise; - - return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ - var handler; - if (typeof emitter.addEventListener === 'function') { - handler= function () { - resolve(toArray.apply(null, arguments)); - }; - - onCancel(function(){ - emitter.removeEventListener(name, handler); - }); - - emitter.addEventListener( - name, - handler, - {once: true} - ); - return; - } - - var eventListener = function(){ - errorListener && emitter.removeListener('error', errorListener); - resolve(toArray.apply(null, arguments)); - }; - - var errorListener; - - if (name !== 'error') { - errorListener = function (err){ - emitter.removeListener(name, eventListener); - reject(err); - }; - - emitter.once('error', errorListener); - } - - onCancel(function(){ - errorListener && emitter.removeListener('error', errorListener); - emitter.removeListener(name, eventListener); - }); - - emitter.once(name, eventListener); - }, { - timeout: options.timeout, - overload: options.overload - }); - } - - var prototype= EventEmitter.prototype; - - Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - get: function () { - return prototype._maxListeners; - }, - set: function (n) { - if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { - throw TypeError('n must be a non-negative number') - } - prototype._maxListeners = n; - }, - enumerable: true - }, - once: { - value: once, - writable: true, - configurable: true - } - }); - - Object.defineProperties(prototype, { - _maxListeners: { - value: defaultMaxListeners, - writable: true, - configurable: true - }, - _observers: {value: null, writable: true, configurable: true} - }); - - if (typeof undefined$1 === 'function' && undefined$1.amd) { - // AMD. Register as an anonymous module. - undefined$1(function() { - return EventEmitter; - }); - } else { - // CommonJS - module.exports = EventEmitter; - } - }(); -} (eventemitter2, eventemitter2.exports)); - -var eventemitter2Exports = eventemitter2.exports; -var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); - function _callSuper$q(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$q() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$q() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$q = function _isNativeReflectConstruct() { return !!t; })(); } @@ -45441,7 +43803,7 @@ var InteractiveMarkerHandle = /*#__PURE__*/function (_EventEmitter) { this.feedbackTopic.publish(feedback); } }]); -}(EventEmitter2); +}(EventEmitter3); /** * @fileOverview @@ -45865,7 +44227,7 @@ var MarkerArrayClient = /*#__PURE__*/function (_EventEmitter) { delete this.markers[key]; } }]); -}(EventEmitter2); +}(EventEmitter3); function _callSuper$n(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$n() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$n() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$n = function _isNativeReflectConstruct() { return !!t; })(); } @@ -45991,7 +44353,7 @@ var MarkerClient = /*#__PURE__*/function (_EventEmitter) { delete this.markers[key]; } }]); -}(EventEmitter2); +}(EventEmitter3); function _callSuper$m(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$m() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$m() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$m = function _isNativeReflectConstruct() { return !!t; })(); } @@ -46469,7 +44831,7 @@ var OccupancyGridClient = /*#__PURE__*/function (_EventEmitter) { } } }]); -}(EventEmitter2); +}(EventEmitter3); function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); @@ -47389,7 +45751,7 @@ var OcTreeClient = /*#__PURE__*/function (_EventEmitter) { }.bind(this)); } }]); -}(EventEmitter2); +}(EventEmitter3); function _callSuper$e(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$e() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$e() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$e = function _isNativeReflectConstruct() { return !!t; })(); } diff --git a/build/ros3d.js b/build/ros3d.js index 9f4d9e0c..8a809f6e 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -43607,1644 +43607,6 @@ void main() { }]); }(Object3D); - function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; - } - - var eventemitter2 = {exports: {}}; - - /*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */ - eventemitter2.exports; - - (function (module, exports) { - !function(undefined$1) { - var hasOwnProperty= Object.hasOwnProperty; - var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]"; - }; - var defaultMaxListeners = 10; - var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function'; - var symbolsSupported= typeof Symbol==='function'; - var reflectSupported= typeof Reflect === 'object'; - var setImmediateSupported= typeof setImmediate === 'function'; - var _setImmediate= setImmediateSupported ? setImmediate : setTimeout; - var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){ - var arr= Object.getOwnPropertyNames(obj); - arr.push.apply(arr, Object.getOwnPropertySymbols(obj)); - return arr; - }) : Object.keys; - - function init() { - this._events = {}; - if (this._conf) { - configure.call(this, this._conf); - } - } - - function configure(conf) { - if (conf) { - this._conf = conf; - - conf.delimiter && (this.delimiter = conf.delimiter); - - if(conf.maxListeners!==undefined$1){ - this._maxListeners= conf.maxListeners; - } - - conf.wildcard && (this.wildcard = conf.wildcard); - conf.newListener && (this._newListener = conf.newListener); - conf.removeListener && (this._removeListener = conf.removeListener); - conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); - conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors); - - if (this.wildcard) { - this.listenerTree = {}; - } - } - } - - function logPossibleMemoryLeak(count, eventName) { - var errorMsg = '(node) warning: possible EventEmitter memory ' + - 'leak detected. ' + count + ' listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.'; - - if(this.verboseMemoryLeak){ - errorMsg += ' Event name: ' + eventName + '.'; - } - - if(typeof process !== 'undefined' && process.emitWarning){ - var e = new Error(errorMsg); - e.name = 'MaxListenersExceededWarning'; - e.emitter = this; - e.count = count; - process.emitWarning(e); - } else { - console.error(errorMsg); - - if (console.trace){ - console.trace(); - } - } - } - - var toArray = function (a, b, c) { - var n = arguments.length; - switch (n) { - case 0: - return []; - case 1: - return [a]; - case 2: - return [a, b]; - case 3: - return [a, b, c]; - default: - var arr = new Array(n); - while (n--) { - arr[n] = arguments[n]; - } - return arr; - } - }; - - function toObject(keys, values) { - var obj = {}; - var key; - var len = keys.length; - var valuesCount = values ? value.length : 0; - for (var i = 0; i < len; i++) { - key = keys[i]; - obj[key] = i < valuesCount ? values[i] : undefined$1; - } - return obj; - } - - function TargetObserver(emitter, target, options) { - this._emitter = emitter; - this._target = target; - this._listeners = {}; - this._listenersCount = 0; - - var on, off; - - if (options.on || options.off) { - on = options.on; - off = options.off; - } - - if (target.addEventListener) { - on = target.addEventListener; - off = target.removeEventListener; - } else if (target.addListener) { - on = target.addListener; - off = target.removeListener; - } else if (target.on) { - on = target.on; - off = target.off; - } - - if (!on && !off) { - throw Error('target does not implement any known event API'); - } - - if (typeof on !== 'function') { - throw TypeError('on method must be a function'); - } - - if (typeof off !== 'function') { - throw TypeError('off method must be a function'); - } - - this._on = on; - this._off = off; - - var _observers= emitter._observers; - if(_observers){ - _observers.push(this); - }else { - emitter._observers= [this]; - } - } - - Object.assign(TargetObserver.prototype, { - subscribe: function(event, localEvent, reducer){ - var observer= this; - var target= this._target; - var emitter= this._emitter; - var listeners= this._listeners; - var handler= function(){ - var args= toArray.apply(null, arguments); - var eventObj= { - data: args, - name: localEvent, - original: event - }; - if(reducer){ - var result= reducer.call(target, eventObj); - if(result!==false){ - emitter.emit.apply(emitter, [eventObj.name].concat(args)); - } - return; - } - emitter.emit.apply(emitter, [localEvent].concat(args)); - }; - - - if(listeners[event]){ - throw Error('Event \'' + event + '\' is already listening'); - } - - this._listenersCount++; - - if(emitter._newListener && emitter._removeListener && !observer._onNewListener){ - - this._onNewListener = function (_event) { - if (_event === localEvent && listeners[event] === null) { - listeners[event] = handler; - observer._on.call(target, event, handler); - } - }; - - emitter.on('newListener', this._onNewListener); - - this._onRemoveListener= function(_event){ - if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){ - listeners[event]= null; - observer._off.call(target, event, handler); - } - }; - - listeners[event]= null; - - emitter.on('removeListener', this._onRemoveListener); - }else { - listeners[event]= handler; - observer._on.call(target, event, handler); - } - }, - - unsubscribe: function(event){ - var observer= this; - var listeners= this._listeners; - var emitter= this._emitter; - var handler; - var events; - var off= this._off; - var target= this._target; - var i; - - if(event && typeof event!=='string'){ - throw TypeError('event must be a string'); - } - - function clearRefs(){ - if(observer._onNewListener){ - emitter.off('newListener', observer._onNewListener); - emitter.off('removeListener', observer._onRemoveListener); - observer._onNewListener= null; - observer._onRemoveListener= null; - } - var index= findTargetIndex.call(emitter, observer); - emitter._observers.splice(index, 1); - } - - if(event){ - handler= listeners[event]; - if(!handler) return; - off.call(target, event, handler); - delete listeners[event]; - if(!--this._listenersCount){ - clearRefs(); - } - }else { - events= ownKeys(listeners); - i= events.length; - while(i-->0){ - event= events[i]; - off.call(target, event, listeners[event]); - } - this._listeners= {}; - this._listenersCount= 0; - clearRefs(); - } - } - }); - - function resolveOptions(options, schema, reducers, allowUnknown) { - var computedOptions = Object.assign({}, schema); - - if (!options) return computedOptions; - - if (typeof options !== 'object') { - throw TypeError('options must be an object') - } - - var keys = Object.keys(options); - var length = keys.length; - var option, value; - var reducer; - - function reject(reason) { - throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : '')) - } - - for (var i = 0; i < length; i++) { - option = keys[i]; - if (!allowUnknown && !hasOwnProperty.call(schema, option)) { - throw Error('Unknown "' + option + '" option'); - } - value = options[option]; - if (value !== undefined$1) { - reducer = reducers[option]; - computedOptions[option] = reducer ? reducer(value, reject) : value; - } - } - return computedOptions; - } - - function constructorReducer(value, reject) { - if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) { - reject('value must be a constructor'); - } - return value; - } - - function makeTypeReducer(types) { - var message= 'value must be type of ' + types.join('|'); - var len= types.length; - var firstType= types[0]; - var secondType= types[1]; - - if (len === 1) { - return function (v, reject) { - if (typeof v === firstType) { - return v; - } - reject(message); - } - } - - if (len === 2) { - return function (v, reject) { - var kind= typeof v; - if (kind === firstType || kind === secondType) return v; - reject(message); - } - } - - return function (v, reject) { - var kind = typeof v; - var i = len; - while (i-- > 0) { - if (kind === types[i]) return v; - } - reject(message); - } - } - - var functionReducer= makeTypeReducer(['function']); - - var objectFunctionReducer= makeTypeReducer(['object', 'function']); - - function makeCancelablePromise(Promise, executor, options) { - var isCancelable; - var callbacks; - var timer= 0; - var subscriptionClosed; - - var promise = new Promise(function (resolve, reject, onCancel) { - options= resolveOptions(options, { - timeout: 0, - overload: false - }, { - timeout: function(value, reject){ - value*= 1; - if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) { - reject('timeout must be a positive number'); - } - return value; - } - }); - - isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function'; - - function cleanup() { - if (callbacks) { - callbacks = null; - } - if (timer) { - clearTimeout(timer); - timer = 0; - } - } - - var _resolve= function(value){ - cleanup(); - resolve(value); - }; - - var _reject= function(err){ - cleanup(); - reject(err); - }; - - if (isCancelable) { - executor(_resolve, _reject, onCancel); - } else { - callbacks = [function(reason){ - _reject(reason || Error('canceled')); - }]; - executor(_resolve, _reject, function (cb) { - if (subscriptionClosed) { - throw Error('Unable to subscribe on cancel event asynchronously') - } - if (typeof cb !== 'function') { - throw TypeError('onCancel callback must be a function'); - } - callbacks.push(cb); - }); - subscriptionClosed= true; - } - - if (options.timeout > 0) { - timer= setTimeout(function(){ - var reason= Error('timeout'); - reason.code = 'ETIMEDOUT'; - timer= 0; - promise.cancel(reason); - reject(reason); - }, options.timeout); - } - }); - - if (!isCancelable) { - promise.cancel = function (reason) { - if (!callbacks) { - return; - } - var length = callbacks.length; - for (var i = 1; i < length; i++) { - callbacks[i](reason); - } - // internal callback to reject the promise - callbacks[0](reason); - callbacks = null; - }; - } - - return promise; - } - - function findTargetIndex(observer) { - var observers = this._observers; - if(!observers){ - return -1; - } - var len = observers.length; - for (var i = 0; i < len; i++) { - if (observers[i]._target === observer) return i; - } - return -1; - } - - // Attention, function return type now is array, always ! - // It has zero elements if no any matches found and one or more - // elements (leafs) if there are matches - // - function searchListenerTree(handlers, type, tree, i, typeLength) { - if (!tree) { - return null; - } - - if (i === 0) { - var kind = typeof type; - if (kind === 'string') { - var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length; - if ((n = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[l++] = type.slice(j, n); - j = n + dl; - } while ((n = type.indexOf(delimiter, j)) !== -1); - - ns[l++] = type.slice(j); - type = ns; - typeLength = l; - } else { - type = [type]; - typeLength = 1; - } - } else if (kind === 'object') { - typeLength = type.length; - } else { - type = [type]; - typeLength = 1; - } - } - - var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i], - nextType = type[i + 1], branches, _listeners; - - if (i === typeLength) { - // - // If at the end of the event(s) list and the tree has listeners - // invoke those listeners. - // - - if(tree._listeners) { - if (typeof tree._listeners === 'function') { - handlers && handlers.push(tree._listeners); - listeners = [tree]; - } else { - handlers && handlers.push.apply(handlers, tree._listeners); - listeners = [tree]; - } - } - } else { - - if (currentType === '*') { - // - // If the event emitted is '*' at this part - // or there is a concrete match at this patch - // - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (currentType === '**') { - endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*')); - if (endReached && tree._listeners) { - // The next element has a _listeners, add it to the handlers. - listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength); - } - - branches = ownKeys(tree); - n = branches.length; - while (n-- > 0) { - branch = branches[n]; - if (branch !== '_listeners') { - if (branch === '*' || branch === '**') { - if (tree[branch]._listeners && !endReached) { - _listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength); - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } else if (branch === nextType) { - _listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength); - } else { - // No match on this one, shift into the tree but not in the type array. - _listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength); - } - if (_listeners) { - if (listeners) { - listeners.push.apply(listeners, _listeners); - } else { - listeners = _listeners; - } - } - } - } - return listeners; - } else if (tree[currentType]) { - listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength); - } - } - - xTree = tree['*']; - if (xTree) { - // - // If the listener tree will allow any match for this part, - // then recursively explore all branches of the tree - // - searchListenerTree(handlers, type, xTree, i + 1, typeLength); - } - - xxTree = tree['**']; - if (xxTree) { - if (i < typeLength) { - if (xxTree._listeners) { - // If we have a listener on a '**', it will catch all, so add its handler. - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } - - // Build arrays of matching next branches and others. - branches= ownKeys(xxTree); - n= branches.length; - while(n-->0){ - branch= branches[n]; - if (branch !== '_listeners') { - if (branch === nextType) { - // We know the next element will match, so jump twice. - searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength); - } else if (branch === currentType) { - // Current node matches, move into the tree. - searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength); - } else { - isolatedBranch = {}; - isolatedBranch[branch] = xxTree[branch]; - searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength); - } - } - } - } else if (xxTree._listeners) { - // We have reached the end and still on a '**' - searchListenerTree(handlers, type, xxTree, typeLength, typeLength); - } else if (xxTree['*'] && xxTree['*']._listeners) { - searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength); - } - } - - return listeners; - } - - function growListenerTree(type, listener, prepend) { - var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns; - - if(typeof type==='string') { - if ((i = type.indexOf(delimiter)) !== -1) { - ns = new Array(5); - do { - ns[len++] = type.slice(j, i); - j = i + dl; - } while ((i = type.indexOf(delimiter, j)) !== -1); - - ns[len++] = type.slice(j); - }else { - ns= [type]; - len= 1; - } - }else { - ns= type; - len= type.length; - } - - // - // Looks for two consecutive '**', if so, don't add the event at all. - // - if (len > 1) { - for (i = 0; i + 1 < len; i++) { - if (ns[i] === '**' && ns[i + 1] === '**') { - return; - } - } - } - - - - var tree = this.listenerTree, name; - - for (i = 0; i < len; i++) { - name = ns[i]; - - tree = tree[name] || (tree[name] = {}); - - if (i === len - 1) { - if (!tree._listeners) { - tree._listeners = listener; - } else { - if (typeof tree._listeners === 'function') { - tree._listeners = [tree._listeners]; - } - - if (prepend) { - tree._listeners.unshift(listener); - } else { - tree._listeners.push(listener); - } - - if ( - !tree._listeners.warned && - this._maxListeners > 0 && - tree._listeners.length > this._maxListeners - ) { - tree._listeners.warned = true; - logPossibleMemoryLeak.call(this, tree._listeners.length, name); - } - } - return true; - } - } - - return true; - } - - function collectTreeEvents(tree, events, root, asArray){ - var branches= ownKeys(tree); - var i= branches.length; - var branch, branchName, path; - var hasListeners= tree['_listeners']; - var isArrayPath; - - while(i-->0){ - branchName= branches[i]; - - branch= tree[branchName]; - - if(branchName==='_listeners'){ - path= root; - }else { - path = root ? root.concat(branchName) : [branchName]; - } - - isArrayPath= asArray || typeof branchName==='symbol'; - - hasListeners && events.push(isArrayPath? path : path.join(this.delimiter)); - - if(typeof branch==='object'){ - collectTreeEvents.call(this, branch, events, path, isArrayPath); - } - } - - return events; - } - - function recursivelyGarbageCollect(root) { - var keys = ownKeys(root); - var i= keys.length; - var obj, key, flag; - while(i-->0){ - key = keys[i]; - obj = root[key]; - - if(obj){ - flag= true; - if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){ - delete root[key]; - } - } - } - - return flag; - } - - function Listener(emitter, event, listener){ - this.emitter= emitter; - this.event= event; - this.listener= listener; - } - - Listener.prototype.off= function(){ - this.emitter.off(this.event, this.listener); - return this; - }; - - function setupListener(event, listener, options){ - if (options === true) { - promisify = true; - } else if (options === false) { - async = true; - } else { - if (!options || typeof options !== 'object') { - throw TypeError('options should be an object or true'); - } - var async = options.async; - var promisify = options.promisify; - var nextTick = options.nextTick; - var objectify = options.objectify; - } - - if (async || nextTick || promisify) { - var _listener = listener; - var _origin = listener._origin || listener; - - if (nextTick && !nextTickSupported) { - throw Error('process.nextTick is not supported'); - } - - if (promisify === undefined$1) { - promisify = listener.constructor.name === 'AsyncFunction'; - } - - listener = function () { - var args = arguments; - var context = this; - var event = this.event; - - return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) { - _setImmediate(resolve); - }).then(function () { - context.event = event; - return _listener.apply(context, args) - })) : (nextTick ? process.nextTick : _setImmediate)(function () { - context.event = event; - _listener.apply(context, args); - }); - }; - - listener._async = true; - listener._origin = _origin; - } - - return [listener, objectify? new Listener(this, event, listener): this]; - } - - function EventEmitter(conf) { - this._events = {}; - this._newListener = false; - this._removeListener = false; - this.verboseMemoryLeak = false; - configure.call(this, conf); - } - - EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property - - EventEmitter.prototype.listenTo= function(target, events, options){ - if(typeof target!=='object'){ - throw TypeError('target musts be an object'); - } - - var emitter= this; - - options = resolveOptions(options, { - on: undefined$1, - off: undefined$1, - reducers: undefined$1 - }, { - on: functionReducer, - off: functionReducer, - reducers: objectFunctionReducer - }); - - function listen(events){ - if(typeof events!=='object'){ - throw TypeError('events must be an object'); - } - - var reducers= options.reducers; - var index= findTargetIndex.call(emitter, target); - var observer; - - if(index===-1){ - observer= new TargetObserver(emitter, target, options); - }else { - observer= emitter._observers[index]; - } - - var keys= ownKeys(events); - var len= keys.length; - var event; - var isSingleReducer= typeof reducers==='function'; - - for(var i=0; i 0) { - observer = observers[i]; - if (!target || observer._target === target) { - observer.unsubscribe(event); - matched= true; - } - } - - return matched; - }; - - // By default EventEmitters will print a warning if more than - // 10 listeners are added to it. This is a useful default which - // helps finding memory leaks. - // - // Obviously not all Emitters should be limited to 10. This function allows - // that to be increased. Set to zero for unlimited. - - EventEmitter.prototype.delimiter = '.'; - - EventEmitter.prototype.setMaxListeners = function(n) { - if (n !== undefined$1) { - this._maxListeners = n; - if (!this._conf) this._conf = {}; - this._conf.maxListeners = n; - } - }; - - EventEmitter.prototype.getMaxListeners = function() { - return this._maxListeners; - }; - - EventEmitter.prototype.event = ''; - - EventEmitter.prototype.once = function(event, fn, options) { - return this._once(event, fn, false, options); - }; - - EventEmitter.prototype.prependOnceListener = function(event, fn, options) { - return this._once(event, fn, true, options); - }; - - EventEmitter.prototype._once = function(event, fn, prepend, options) { - return this._many(event, 1, fn, prepend, options); - }; - - EventEmitter.prototype.many = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, false, options); - }; - - EventEmitter.prototype.prependMany = function(event, ttl, fn, options) { - return this._many(event, ttl, fn, true, options); - }; - - EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) { - var self = this; - - if (typeof fn !== 'function') { - throw new Error('many only accepts instances of Function'); - } - - function listener() { - if (--ttl === 0) { - self.off(event, listener); - } - return fn.apply(this, arguments); - } - - listener._origin = fn; - - return this._on(event, listener, prepend, options); - }; - - EventEmitter.prototype.emit = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], ns, wildcard= this.wildcard; - var args,l,i,j, containsSymbol; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { - return false; - } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var al = arguments.length; - var handler; - - if (this._all && this._all.length) { - handler = this._all.slice(); - - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this, type); - break; - case 2: - handler[i].call(this, type, arguments[1]); - break; - case 3: - handler[i].call(this, type, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, arguments); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l); - } else { - handler = this._events[type]; - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - handler.apply(this, args); - } - return true; - } else if (handler) { - // need to make copy of handlers because list can change in the middle - // of emit call - handler = handler.slice(); - } - } - - if (handler && handler.length) { - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - handler[i].call(this); - break; - case 2: - handler[i].call(this, arguments[1]); - break; - case 3: - handler[i].call(this, arguments[1], arguments[2]); - break; - default: - handler[i].apply(this, args); - } - } - return true; - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - } - - return !!this._all; - }; - - EventEmitter.prototype.emitAsync = function() { - if (!this._events && !this._all) { - return false; - } - - this._events || init.call(this); - - var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol; - var args,l,i,j; - - if (type === 'newListener' && !this._newListener) { - if (!this._events.newListener) { return Promise.resolve([false]); } - } - - if (wildcard) { - ns= type; - if(type!=='newListener' && type!=='removeListener'){ - if (typeof type === 'object') { - l = type.length; - if (symbolsSupported) { - for (i = 0; i < l; i++) { - if (typeof type[i] === 'symbol') { - containsSymbol = true; - break; - } - } - } - if (!containsSymbol) { - type = type.join(this.delimiter); - } - } - } - } - - var promises= []; - - var al = arguments.length; - var handler; - - if (this._all) { - for (i = 0, l = this._all.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(this._all[i].call(this, type)); - break; - case 2: - promises.push(this._all[i].call(this, type, arguments[1])); - break; - case 3: - promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); - break; - default: - promises.push(this._all[i].apply(this, arguments)); - } - } - } - - if (wildcard) { - handler = []; - searchListenerTree.call(this, handler, ns, this.listenerTree, 0); - } else { - handler = this._events[type]; - } - - if (typeof handler === 'function') { - this.event = type; - switch (al) { - case 1: - promises.push(handler.call(this)); - break; - case 2: - promises.push(handler.call(this, arguments[1])); - break; - case 3: - promises.push(handler.call(this, arguments[1], arguments[2])); - break; - default: - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - promises.push(handler.apply(this, args)); - } - } else if (handler && handler.length) { - handler = handler.slice(); - if (al > 3) { - args = new Array(al - 1); - for (j = 1; j < al; j++) args[j - 1] = arguments[j]; - } - for (i = 0, l = handler.length; i < l; i++) { - this.event = type; - switch (al) { - case 1: - promises.push(handler[i].call(this)); - break; - case 2: - promises.push(handler[i].call(this, arguments[1])); - break; - case 3: - promises.push(handler[i].call(this, arguments[1], arguments[2])); - break; - default: - promises.push(handler[i].apply(this, args)); - } - } - } else if (!this.ignoreErrors && !this._all && type === 'error') { - if (arguments[1] instanceof Error) { - return Promise.reject(arguments[1]); // Unhandled 'error' event - } else { - return Promise.reject("Uncaught, unspecified 'error' event."); - } - } - - return Promise.all(promises); - }; - - EventEmitter.prototype.on = function(type, listener, options) { - return this._on(type, listener, false, options); - }; - - EventEmitter.prototype.prependListener = function(type, listener, options) { - return this._on(type, listener, true, options); - }; - - EventEmitter.prototype.onAny = function(fn) { - return this._onAny(fn, false); - }; - - EventEmitter.prototype.prependAny = function(fn) { - return this._onAny(fn, true); - }; - - EventEmitter.prototype.addListener = EventEmitter.prototype.on; - - EventEmitter.prototype._onAny = function(fn, prepend){ - if (typeof fn !== 'function') { - throw new Error('onAny only accepts instances of Function'); - } - - if (!this._all) { - this._all = []; - } - - // Add the function to the event listener collection. - if(prepend){ - this._all.unshift(fn); - }else { - this._all.push(fn); - } - - return this; - }; - - EventEmitter.prototype._on = function(type, listener, prepend, options) { - if (typeof type === 'function') { - this._onAny(type, listener); - return this; - } - - if (typeof listener !== 'function') { - throw new Error('on only accepts instances of Function'); - } - this._events || init.call(this); - - var returnValue= this, temp; - - if (options !== undefined$1) { - temp = setupListener.call(this, type, listener, options); - listener = temp[0]; - returnValue = temp[1]; - } - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._newListener) { - this.emit('newListener', type, listener); - } - - if (this.wildcard) { - growListenerTree.call(this, type, listener, prepend); - return returnValue; - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else { - if (typeof this._events[type] === 'function') { - // Change to array. - this._events[type] = [this._events[type]]; - } - - // If we've already got an array, just add - if(prepend){ - this._events[type].unshift(listener); - }else { - this._events[type].push(listener); - } - - // Check for listener leak - if ( - !this._events[type].warned && - this._maxListeners > 0 && - this._events[type].length > this._maxListeners - ) { - this._events[type].warned = true; - logPossibleMemoryLeak.call(this, this._events[type].length, type); - } - } - - return returnValue; - }; - - EventEmitter.prototype.off = function(type, listener) { - if (typeof listener !== 'function') { - throw new Error('removeListener only takes instances of Function'); - } - - var handlers,leafs=[]; - - if(this.wildcard) { - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); - if(!leafs) return this; - } else { - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events[type]) return this; - handlers = this._events[type]; - leafs.push({_listeners:handlers}); - } - - for (var iLeaf=0; iLeaf 0) { - fns = this._all; - for(i = 0, l = fns.length; i < l; i++) { - if(fn === fns[i]) { - fns.splice(i, 1); - if (this._removeListener) - this.emit("removeListenerAny", fn); - return this; - } - } - } else { - fns = this._all; - if (this._removeListener) { - for(i = 0, l = fns.length; i < l; i++) - this.emit("removeListenerAny", fns[i]); - } - this._all = []; - } - return this; - }; - - EventEmitter.prototype.removeListener = EventEmitter.prototype.off; - - EventEmitter.prototype.removeAllListeners = function (type) { - if (type === undefined$1) { - !this._events || init.call(this); - return this; - } - - if (this.wildcard) { - var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i; - if (!leafs) return this; - for (i = 0; i < leafs.length; i++) { - leaf = leafs[i]; - leaf._listeners = null; - } - this.listenerTree && recursivelyGarbageCollect(this.listenerTree); - } else if (this._events) { - this._events[type] = null; - } - return this; - }; - - EventEmitter.prototype.listeners = function (type) { - var _events = this._events; - var keys, listeners, allListeners; - var i; - var listenerTree; - - if (type === undefined$1) { - if (this.wildcard) { - throw Error('event name required for wildcard emitter'); - } - - if (!_events) { - return []; - } - - keys = ownKeys(_events); - i = keys.length; - allListeners = []; - while (i-- > 0) { - listeners = _events[keys[i]]; - if (typeof listeners === 'function') { - allListeners.push(listeners); - } else { - allListeners.push.apply(allListeners, listeners); - } - } - return allListeners; - } else { - if (this.wildcard) { - listenerTree= this.listenerTree; - if(!listenerTree) return []; - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, listenerTree, 0); - return handlers; - } - - if (!_events) { - return []; - } - - listeners = _events[type]; - - if (!listeners) { - return []; - } - return typeof listeners === 'function' ? [listeners] : listeners; - } - }; - - EventEmitter.prototype.eventNames = function(nsAsArray){ - var _events= this._events; - return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []); - }; - - EventEmitter.prototype.listenerCount = function(type) { - return this.listeners(type).length; - }; - - EventEmitter.prototype.hasListeners = function (type) { - if (this.wildcard) { - var handlers = []; - var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); - searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); - return handlers.length > 0; - } - - var _events = this._events; - var _all = this._all; - - return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type])); - }; - - EventEmitter.prototype.listenersAny = function() { - - if(this._all) { - return this._all; - } - else { - return []; - } - - }; - - EventEmitter.prototype.waitFor = function (event, options) { - var self = this; - var type = typeof options; - if (type === 'number') { - options = {timeout: options}; - } else if (type === 'function') { - options = {filter: options}; - } - - options= resolveOptions(options, { - timeout: 0, - filter: undefined$1, - handleError: false, - Promise: Promise, - overload: false - }, { - filter: functionReducer, - Promise: constructorReducer - }); - - return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) { - function listener() { - var filter= options.filter; - if (filter && !filter.apply(self, arguments)) { - return; - } - self.off(event, listener); - if (options.handleError) { - var err = arguments[0]; - err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1)); - } else { - resolve(toArray.apply(null, arguments)); - } - } - - onCancel(function(){ - self.off(event, listener); - }); - - self._on(event, listener, false); - }, { - timeout: options.timeout, - overload: options.overload - }) - }; - - function once(emitter, name, options) { - options= resolveOptions(options, { - Promise: Promise, - timeout: 0, - overload: false - }, { - Promise: constructorReducer - }); - - var _Promise= options.Promise; - - return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){ - var handler; - if (typeof emitter.addEventListener === 'function') { - handler= function () { - resolve(toArray.apply(null, arguments)); - }; - - onCancel(function(){ - emitter.removeEventListener(name, handler); - }); - - emitter.addEventListener( - name, - handler, - {once: true} - ); - return; - } - - var eventListener = function(){ - errorListener && emitter.removeListener('error', errorListener); - resolve(toArray.apply(null, arguments)); - }; - - var errorListener; - - if (name !== 'error') { - errorListener = function (err){ - emitter.removeListener(name, eventListener); - reject(err); - }; - - emitter.once('error', errorListener); - } - - onCancel(function(){ - errorListener && emitter.removeListener('error', errorListener); - emitter.removeListener(name, eventListener); - }); - - emitter.once(name, eventListener); - }, { - timeout: options.timeout, - overload: options.overload - }); - } - - var prototype= EventEmitter.prototype; - - Object.defineProperties(EventEmitter, { - defaultMaxListeners: { - get: function () { - return prototype._maxListeners; - }, - set: function (n) { - if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { - throw TypeError('n must be a non-negative number') - } - prototype._maxListeners = n; - }, - enumerable: true - }, - once: { - value: once, - writable: true, - configurable: true - } - }); - - Object.defineProperties(prototype, { - _maxListeners: { - value: defaultMaxListeners, - writable: true, - configurable: true - }, - _observers: {value: null, writable: true, configurable: true} - }); - - if (typeof undefined$1 === 'function' && undefined$1.amd) { - // AMD. Register as an anonymous module. - undefined$1(function() { - return EventEmitter; - }); - } else { - // CommonJS - module.exports = EventEmitter; - } - }(); - } (eventemitter2, eventemitter2.exports)); - - var eventemitter2Exports = eventemitter2.exports; - var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports); - function _callSuper$q(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$q() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$q() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$q = function _isNativeReflectConstruct() { return !!t; })(); } @@ -45462,7 +43824,7 @@ void main() { this.feedbackTopic.publish(feedback); } }]); - }(EventEmitter2); + }(EventEmitter3); /** * @fileOverview @@ -45886,7 +44248,7 @@ void main() { delete this.markers[key]; } }]); - }(EventEmitter2); + }(EventEmitter3); function _callSuper$n(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$n() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$n() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$n = function _isNativeReflectConstruct() { return !!t; })(); } @@ -46012,7 +44374,7 @@ void main() { delete this.markers[key]; } }]); - }(EventEmitter2); + }(EventEmitter3); function _callSuper$m(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$m() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$m() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$m = function _isNativeReflectConstruct() { return !!t; })(); } @@ -46490,7 +44852,7 @@ void main() { } } }]); - }(EventEmitter2); + }(EventEmitter3); function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); @@ -47410,7 +45772,7 @@ void main() { }.bind(this)); } }]); - }(EventEmitter2); + }(EventEmitter3); function _callSuper$e(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct$e() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct$e() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct$e = function _isNativeReflectConstruct() { return !!t; })(); } diff --git a/build/ros3d.min.js b/build/ros3d.min.js index bf13095f..e7e03f5e 100644 --- a/build/ros3d.min.js +++ b/build/ros3d.min.js @@ -3,11 +3,4 @@ var ROS3D=function(e,t){"use strict";function n(e){if(e&&e.__esModule)return e;v * @license * Copyright 2010-2024 Three.js Authors * SPDX-License-Identifier: MIT - */const r="167",a=100,s=204,o=205,l="attached",c=301,h=302,u=306,d=1e3,p=1001,f=1002,m=1003,g=1005,v=1006,_=1007,y=1008,x=1009,b=1010,M=1011,S=1012,E=1013,w=1014,T=1015,A=1016,R=1017,C=1018,L=1020,P=35902,I=1023,N=1026,U=1027,D=1029,O=1031,F=1033,k=33776,B=33777,z=33778,H=33779,V=35840,G=35841,W=35842,j=35843,X=36196,q=37492,Y=37496,K=37808,Z=37809,J=37810,Q=37811,$=37812,ee=37813,te=37814,ne=37815,ie=37816,re=37817,ae=37818,se=37819,oe=37820,le=37821,ce=36492,he=36494,ue=36495,de=36284,pe=36285,fe=36286,me=2300,ge=2301,ve=2302,_e="",ye="srgb",xe="srgb-linear",be="display-p3",Me="display-p3-linear",Se="linear",Ee="srgb",we="rec709",Te="p3",Ae=7680,Re=35044,Ce="300 es",Le=2e3,Pe=2001;class Ie{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[e]&&(n[e]=[]),-1===n[e].indexOf(t)&&n[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[e]&&-1!==n[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;const n=this._listeners[e];if(void 0!==n){const e=n.indexOf(t);-1!==e&&n.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;const t=this._listeners[e.type];if(void 0!==t){e.target=this;const n=t.slice(0);for(let t=0,i=n.length;t>8&255]+Ne[e>>16&255]+Ne[e>>24&255]+"-"+Ne[255&t]+Ne[t>>8&255]+"-"+Ne[t>>16&15|64]+Ne[t>>24&255]+"-"+Ne[63&n|128]+Ne[n>>8&255]+"-"+Ne[n>>16&255]+Ne[n>>24&255]+Ne[255&i]+Ne[i>>8&255]+Ne[i>>16&255]+Ne[i>>24&255]).toLowerCase()}function ke(e,t,n){return Math.max(t,Math.min(n,e))}function Be(e,t){return(e%t+t)%t}function ze(e,t,n){return(1-n)*e+n*t}function He(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw new Error("Invalid component type.")}}function Ve(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw new Error("Invalid component type.")}}const Ge={DEG2RAD:De,RAD2DEG:Oe,generateUUID:Fe,clamp:ke,euclideanModulo:Be,mapLinear:function(e,t,n,i,r){return i+(e-t)*(r-i)/(n-t)},inverseLerp:function(e,t,n){return e!==t?(n-e)/(t-e):0},lerp:ze,damp:function(e,t,n,i){return ze(e,t,1-Math.exp(-n*i))},pingpong:function(e,t=1){return t-Math.abs(Be(e,2*t)-t)},smoothstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*(3-2*e)},smootherstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},seededRandom:function(e){void 0!==e&&(Ue=e);let t=Ue+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296},degToRad:function(e){return e*De},radToDeg:function(e){return e*Oe},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,n,i,r){const a=Math.cos,s=Math.sin,o=a(n/2),l=s(n/2),c=a((t+i)/2),h=s((t+i)/2),u=a((t-i)/2),d=s((t-i)/2),p=a((i-t)/2),f=s((i-t)/2);switch(r){case"XYX":e.set(o*h,l*u,l*d,o*c);break;case"YZY":e.set(l*d,o*h,l*u,o*c);break;case"ZXZ":e.set(l*u,l*d,o*h,o*c);break;case"XZX":e.set(o*h,l*f,l*p,o*c);break;case"YXY":e.set(l*p,o*h,l*f,o*c);break;case"ZYZ":e.set(l*f,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Ve,denormalize:He};class We{constructor(e=0,t=0){We.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,n=this.y,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6],this.y=i[1]*t+i[4]*n+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.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(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(ke(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const n=Math.cos(t),i=Math.sin(t),r=this.x-e.x,a=this.y-e.y;return this.x=r*n-a*i+e.x,this.y=r*i+a*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class je{constructor(e,t,n,i,r,a,s,o,l){je.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,n,i,r,a,s,o,l)}set(e,t,n,i,r,a,s,o,l){const c=this.elements;return c[0]=e,c[1]=i,c[2]=s,c[3]=t,c[4]=r,c[5]=o,c[6]=n,c[7]=a,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,i=t.elements,r=this.elements,a=n[0],s=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],f=i[0],m=i[3],g=i[6],v=i[1],_=i[4],y=i[7],x=i[2],b=i[5],M=i[8];return r[0]=a*f+s*v+o*x,r[3]=a*m+s*_+o*b,r[6]=a*g+s*y+o*M,r[1]=l*f+c*v+h*x,r[4]=l*m+c*_+h*b,r[7]=l*g+c*y+h*M,r[2]=u*f+d*v+p*x,r[5]=u*m+d*_+p*b,r[8]=u*g+d*y+p*M,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8];return t*a*c-t*s*l-n*r*c+n*s*o+i*r*l-i*a*o}invert(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8],h=c*a-s*l,u=s*o-c*r,d=l*r-a*o,p=t*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const f=1/p;return e[0]=h*f,e[1]=(i*l-c*n)*f,e[2]=(s*n-i*a)*f,e[3]=u*f,e[4]=(c*t-i*o)*f,e[5]=(i*r-s*t)*f,e[6]=d*f,e[7]=(n*o-l*t)*f,e[8]=(a*t-n*r)*f,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,i,r,a,s){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*a+l*s)+a+e,-i*l,i*o,-i*(-l*a+o*s)+s+t,0,0,1),this}scale(e,t){return this.premultiply(Xe.makeScale(e,t)),this}rotate(e){return this.premultiply(Xe.makeRotation(-e)),this}translate(e,t){return this.premultiply(Xe.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,n=e.elements;for(let e=0;e<9;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return(new this.constructor).fromArray(this.elements)}}const Xe=new je;function qe(e){for(let t=e.length-1;t>=0;--t)if(e[t]>=65535)return!0;return!1}function Ye(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}function Ke(){const e=Ye("canvas");return e.style.display="block",e}const Ze={};function Je(e){e in Ze||(Ze[e]=!0,console.warn(e))}const Qe=(new je).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),$e=(new je).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),et={[xe]:{transfer:Se,primaries:we,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[ye]:{transfer:Ee,primaries:we,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[Me]:{transfer:Se,primaries:Te,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3($e),fromReference:e=>e.applyMatrix3(Qe)},[be]:{transfer:Ee,primaries:Te,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3($e),fromReference:e=>e.applyMatrix3(Qe).convertLinearToSRGB()}},tt=new Set([xe,Me]),nt={enabled:!0,_workingColorSpace:xe,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!tt.has(e))throw new Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,n){if(!1===this.enabled||t===n||!t||!n)return e;const i=et[t].toReference;return(0,et[n].fromReference)(i(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return et[e].primaries},getTransfer:function(e){return e===_e?Se:et[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(et[t].luminanceCoefficients)}};function it(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function rt(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let at;let st=0;class ot{constructor(e=null){this.isSource=!0,Object.defineProperty(this,"id",{value:st++}),this.uuid=Fe(),this.data=e,this.dataReady=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}toJSON(e){const t=void 0===e||"string"==typeof e;if(!t&&void 0!==e.images[this.uuid])return e.images[this.uuid];const n={uuid:this.uuid,url:""},i=this.data;if(null!==i){let e;if(Array.isArray(i)){e=[];for(let t=0,n=i.length;t2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){const t=Ye("canvas");t.width=e.width,t.height=e.height;const n=t.getContext("2d");n.drawImage(e,0,0,e.width,e.height);const i=n.getImageData(0,0,e.width,e.height),r=i.data;for(let e=0;e0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(300!==this.mapping)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case d:e.x=e.x-Math.floor(e.x);break;case p:e.x=e.x<0?0:1;break;case f:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case d:e.y=e.y-Math.floor(e.y);break;case p:e.y=e.y<0?0:1;break;case f:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){!0===e&&this.pmremVersion++}}ht.DEFAULT_IMAGE=null,ht.DEFAULT_MAPPING=300,ht.DEFAULT_ANISOTROPY=1;class ut{constructor(e=0,t=0,n=0,i=1){ut.prototype.isVector4=!0,this.x=e,this.y=t,this.z=n,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,i){return this.x=e,this.y=t,this.z=n,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){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: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,n=this.y,i=this.z,r=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*t+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*t+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*t+a[7]*n+a[11]*i+a[15]*r,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,n,i,r;const a=.01,s=.1,o=e.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],f=o[2],m=o[6],g=o[10];if(Math.abs(c-u)o&&e>v?ev?o=0?1:-1,i=1-t*t;if(i>Number.EPSILON){const r=Math.sqrt(i),a=Math.atan2(r,t*n);e=Math.sin(e*a)/r,s=Math.sin(s*a)/r}const r=s*n;if(o=o*e+u*r,l=l*e+d*r,c=c*e+p*r,h=h*e+f*r,e===1-s){const e=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=e,l*=e,c*=e,h*=e}}e[t]=o,e[t+1]=l,e[t+2]=c,e[t+3]=h}static multiplyQuaternionsFlat(e,t,n,i,r,a){const s=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[a],u=r[a+1],d=r[a+2],p=r[a+3];return e[t]=s*p+c*h+o*d-l*u,e[t+1]=o*p+c*u+l*h-s*d,e[t+2]=l*p+c*d+s*u-o*h,e[t+3]=c*p-s*h-o*u-l*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const n=e._x,i=e._y,r=e._z,a=e._order,s=Math.cos,o=Math.sin,l=s(n/2),c=s(i/2),h=s(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(a){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return!0===t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const n=t/2,i=Math.sin(n);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,n=t[0],i=t[4],r=t[8],a=t[1],s=t[5],o=t[9],l=t[2],c=t[6],h=t[10],u=n+s+h;if(u>0){const e=.5/Math.sqrt(u+1);this._w=.25/e,this._x=(c-o)*e,this._y=(r-l)*e,this._z=(a-i)*e}else if(n>s&&n>h){const e=2*Math.sqrt(1+n-s-h);this._w=(c-o)/e,this._x=.25*e,this._y=(i+a)/e,this._z=(r+l)/e}else if(s>h){const e=2*Math.sqrt(1+s-n-h);this._w=(r-l)/e,this._x=(i+a)/e,this._y=.25*e,this._z=(o+c)/e}else{const e=2*Math.sqrt(1+h-n-s);this._w=(a-i)/e,this._x=(r+l)/e,this._y=(o+c)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return nMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(ke(this.dot(e),-1,1)))}rotateTowards(e,t){const n=this.angleTo(e);if(0===n)return this;const i=Math.min(1,t/n);return this.slerp(e,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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 e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const n=e._x,i=e._y,r=e._z,a=e._w,s=t._x,o=t._y,l=t._z,c=t._w;return this._x=n*c+a*s+i*l-r*o,this._y=i*c+a*o+r*s-n*l,this._z=r*c+a*l+n*o-i*s,this._w=a*c-n*s-i*o-r*l,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);const n=this._x,i=this._y,r=this._z,a=this._w;let s=a*e._w+n*e._x+i*e._y+r*e._z;if(s<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,s=-s):this.copy(e),s>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;const o=1-s*s;if(o<=Number.EPSILON){const e=1-t;return this._w=e*a+t*this._w,this._x=e*n+t*this._x,this._y=e*i+t*this._y,this._z=e*r+t*this._z,this.normalize(),this}const l=Math.sqrt(o),c=Math.atan2(l,s),h=Math.sin((1-t)*c)/l,u=Math.sin(t*c)/l;return this._w=a*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),i=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(i*Math.sin(e),i*Math.cos(e),r*Math.sin(t),r*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class vt{constructor(e=0,t=0,n=0){vt.prototype.isVector3=!0,this.x=e,this.y=t,this.z=n}set(e,t,n){return void 0===n&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(yt.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(yt.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6]*i,this.y=r[1]*t+r[4]*n+r[7]*i,this.z=r[2]*t+r[5]*n+r[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,n=this.y,i=this.z,r=e.elements,a=1/(r[3]*t+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*t+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*t+r[6]*n+r[10]*i+r[14])*a,this}applyQuaternion(e){const t=this.x,n=this.y,i=this.z,r=e.x,a=e.y,s=e.z,o=e.w,l=2*(a*i-s*n),c=2*(s*t-r*i),h=2*(r*n-a*t);return this.x=t+o*l+a*h-s*c,this.y=n+o*c+s*l-r*h,this.z=i+o*h+r*c-a*l,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*n+r[8]*i,this.y=r[1]*t+r[5]*n+r[9]*i,this.z=r[2]*t+r[6]*n+r[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.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(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const n=e.x,i=e.y,r=e.z,a=t.x,s=t.y,o=t.z;return this.x=i*o-r*s,this.y=r*a-n*o,this.z=n*s-i*a,this}projectOnVector(e){const t=e.lengthSq();if(0===t)return this.set(0,0,0);const n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return _t.copy(this).projectOnVector(e),this.sub(_t)}reflect(e){return this.sub(_t.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(ke(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y,i=this.z-e.z;return t*t+n*n+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){const i=Math.sin(t)*e;return this.x=i*Math.sin(n),this.y=Math.cos(t)*e,this.z=i*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=2*Math.random()-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const _t=new vt,yt=new gt;class xt{constructor(e=new vt(1/0,1/0,1/0),t=new vt(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Mt),Mt.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Lt),Pt.subVectors(this.max,Lt),Et.subVectors(e.a,Lt),wt.subVectors(e.b,Lt),Tt.subVectors(e.c,Lt),At.subVectors(wt,Et),Rt.subVectors(Tt,wt),Ct.subVectors(Et,Tt);let t=[0,-At.z,At.y,0,-Rt.z,Rt.y,0,-Ct.z,Ct.y,At.z,0,-At.x,Rt.z,0,-Rt.x,Ct.z,0,-Ct.x,-At.y,At.x,0,-Rt.y,Rt.x,0,-Ct.y,Ct.x,0];return!!Ut(t,Et,wt,Tt,Pt)&&(t=[1,0,0,0,1,0,0,0,1],!!Ut(t,Et,wt,Tt,Pt)&&(It.crossVectors(At,Rt),t=[It.x,It.y,It.z],Ut(t,Et,wt,Tt,Pt)))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Mt).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Mt).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(bt[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),bt[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),bt[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),bt[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),bt[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),bt[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),bt[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),bt[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(bt)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const bt=[new vt,new vt,new vt,new vt,new vt,new vt,new vt,new vt],Mt=new vt,St=new xt,Et=new vt,wt=new vt,Tt=new vt,At=new vt,Rt=new vt,Ct=new vt,Lt=new vt,Pt=new vt,It=new vt,Nt=new vt;function Ut(e,t,n,i,r){for(let a=0,s=e.length-3;a<=s;a+=3){Nt.fromArray(e,a);const s=r.x*Math.abs(Nt.x)+r.y*Math.abs(Nt.y)+r.z*Math.abs(Nt.z),o=t.dot(Nt),l=n.dot(Nt),c=i.dot(Nt);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>s)return!1}return!0}const Dt=new xt,Ot=new vt,Ft=new vt;class kt{constructor(e=new vt,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const n=this.center;void 0!==t?n.copy(t):Dt.setFromPoints(e).getCenter(n);let i=0;for(let t=0,r=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Ot.subVectors(e,this.center);const t=Ot.lengthSq();if(t>this.radius*this.radius){const e=Math.sqrt(t),n=.5*(e-this.radius);this.center.addScaledVector(Ot,n/e),this.radius+=n}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(Ft.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Ot.copy(e.center).add(Ft)),this.expandByPoint(Ot.copy(e.center).sub(Ft))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Bt=new vt,zt=new vt,Ht=new vt,Vt=new vt,Gt=new vt,Wt=new vt,jt=new vt;class Xt{constructor(e=new vt,t=new vt(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Bt)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=Bt.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Bt.copy(this.origin).addScaledVector(this.direction,t),Bt.distanceToSquared(e))}distanceSqToSegment(e,t,n,i){zt.copy(e).add(t).multiplyScalar(.5),Ht.copy(t).sub(e).normalize(),Vt.copy(this.origin).sub(zt);const r=.5*e.distanceTo(t),a=-this.direction.dot(Ht),s=Vt.dot(this.direction),o=-Vt.dot(Ht),l=Vt.lengthSq(),c=Math.abs(1-a*a);let h,u,d,p;if(c>0)if(h=a*o-s,u=a*s-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const e=1/c;h*=e,u*=e,d=h*(h+a*u+2*s)+u*(a*h+u+2*o)+l}else u=r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-a*r+s)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(a*r+s)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=a>0?-r:r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(zt).addScaledVector(Ht,u),d}intersectSphere(e,t){Bt.subVectors(e.center,this.origin);const n=Bt.dot(this.direction),i=Bt.dot(Bt)-n*n,r=e.radius*e.radius;if(i>r)return null;const a=Math.sqrt(r-i),s=n-a,o=n+a;return o<0?null:s<0?this.at(o,t):this.at(s,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){const n=this.distanceToPlane(e);return null===n?null:this.at(n,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);if(0===t)return!0;return e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,i,r,a,s,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(e.min.x-u.x)*l,i=(e.max.x-u.x)*l):(n=(e.max.x-u.x)*l,i=(e.min.x-u.x)*l),c>=0?(r=(e.min.y-u.y)*c,a=(e.max.y-u.y)*c):(r=(e.max.y-u.y)*c,a=(e.min.y-u.y)*c),n>a||r>i?null:((r>n||isNaN(n))&&(n=r),(a=0?(s=(e.min.z-u.z)*h,o=(e.max.z-u.z)*h):(s=(e.max.z-u.z)*h,o=(e.min.z-u.z)*h),n>o||s>i?null:((s>n||n!=n)&&(n=s),(o=0?n:i,t)))}intersectsBox(e){return null!==this.intersectBox(e,Bt)}intersectTriangle(e,t,n,i,r){Gt.subVectors(t,e),Wt.subVectors(n,e),jt.crossVectors(Gt,Wt);let a,s=this.direction.dot(jt);if(s>0){if(i)return null;a=1}else{if(!(s<0))return null;a=-1,s=-s}Vt.subVectors(this.origin,e);const o=a*this.direction.dot(Wt.crossVectors(Vt,Wt));if(o<0)return null;const l=a*this.direction.dot(Gt.cross(Vt));if(l<0)return null;if(o+l>s)return null;const c=-a*Vt.dot(jt);return c<0?null:this.at(c/s,r)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class qt{constructor(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m){qt.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m)}set(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m){const g=this.elements;return g[0]=e,g[4]=t,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=s,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=f,g[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new qt).fromArray(this.elements)}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this}copyPosition(e){const t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,n=e.elements,i=1/Yt.setFromMatrixColumn(e,0).length(),r=1/Yt.setFromMatrixColumn(e,1).length(),a=1/Yt.setFromMatrixColumn(e,2).length();return t[0]=n[0]*i,t[1]=n[1]*i,t[2]=n[2]*i,t[3]=0,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,n=e.x,i=e.y,r=e.z,a=Math.cos(n),s=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===e.order){const e=a*c,n=a*h,i=s*c,r=s*h;t[0]=o*c,t[4]=-o*h,t[8]=l,t[1]=n+i*l,t[5]=e-r*l,t[9]=-s*o,t[2]=r-e*l,t[6]=i+n*l,t[10]=a*o}else if("YXZ"===e.order){const e=o*c,n=o*h,i=l*c,r=l*h;t[0]=e+r*s,t[4]=i*s-n,t[8]=a*l,t[1]=a*h,t[5]=a*c,t[9]=-s,t[2]=n*s-i,t[6]=r+e*s,t[10]=a*o}else if("ZXY"===e.order){const e=o*c,n=o*h,i=l*c,r=l*h;t[0]=e-r*s,t[4]=-a*h,t[8]=i+n*s,t[1]=n+i*s,t[5]=a*c,t[9]=r-e*s,t[2]=-a*l,t[6]=s,t[10]=a*o}else if("ZYX"===e.order){const e=a*c,n=a*h,i=s*c,r=s*h;t[0]=o*c,t[4]=i*l-n,t[8]=e*l+r,t[1]=o*h,t[5]=r*l+e,t[9]=n*l-i,t[2]=-l,t[6]=s*o,t[10]=a*o}else if("YZX"===e.order){const e=a*o,n=a*l,i=s*o,r=s*l;t[0]=o*c,t[4]=r-e*h,t[8]=i*h+n,t[1]=h,t[5]=a*c,t[9]=-s*c,t[2]=-l*c,t[6]=n*h+i,t[10]=e-r*h}else if("XZY"===e.order){const e=a*o,n=a*l,i=s*o,r=s*l;t[0]=o*c,t[4]=-h,t[8]=l*c,t[1]=e*h+r,t[5]=a*c,t[9]=n*h-i,t[2]=i*h-n,t[6]=s*c,t[10]=r*h+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(Zt,e,Jt)}lookAt(e,t,n){const i=this.elements;return en.subVectors(e,t),0===en.lengthSq()&&(en.z=1),en.normalize(),Qt.crossVectors(n,en),0===Qt.lengthSq()&&(1===Math.abs(n.z)?en.x+=1e-4:en.z+=1e-4,en.normalize(),Qt.crossVectors(n,en)),Qt.normalize(),$t.crossVectors(en,Qt),i[0]=Qt.x,i[4]=$t.x,i[8]=en.x,i[1]=Qt.y,i[5]=$t.y,i[9]=en.y,i[2]=Qt.z,i[6]=$t.z,i[10]=en.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,i=t.elements,r=this.elements,a=n[0],s=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],f=n[6],m=n[10],g=n[14],v=n[3],_=n[7],y=n[11],x=n[15],b=i[0],M=i[4],S=i[8],E=i[12],w=i[1],T=i[5],A=i[9],R=i[13],C=i[2],L=i[6],P=i[10],I=i[14],N=i[3],U=i[7],D=i[11],O=i[15];return r[0]=a*b+s*w+o*C+l*N,r[4]=a*M+s*T+o*L+l*U,r[8]=a*S+s*A+o*P+l*D,r[12]=a*E+s*R+o*I+l*O,r[1]=c*b+h*w+u*C+d*N,r[5]=c*M+h*T+u*L+d*U,r[9]=c*S+h*A+u*P+d*D,r[13]=c*E+h*R+u*I+d*O,r[2]=p*b+f*w+m*C+g*N,r[6]=p*M+f*T+m*L+g*U,r[10]=p*S+f*A+m*P+g*D,r[14]=p*E+f*R+m*I+g*O,r[3]=v*b+_*w+y*C+x*N,r[7]=v*M+_*T+y*L+x*U,r[11]=v*S+_*A+y*P+x*D,r[15]=v*E+_*R+y*I+x*O,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[4],i=e[8],r=e[12],a=e[1],s=e[5],o=e[9],l=e[13],c=e[2],h=e[6],u=e[10],d=e[14];return e[3]*(+r*o*h-i*l*h-r*s*u+n*l*u+i*s*d-n*o*d)+e[7]*(+t*o*d-t*l*u+r*a*u-i*a*d+i*l*c-r*o*c)+e[11]*(+t*l*h-t*s*d-r*a*h+n*a*d+r*s*c-n*l*c)+e[15]*(-i*s*c-t*o*h+t*s*u+i*a*h-n*a*u+n*o*c)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,n){const i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=n),this}invert(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8],h=e[9],u=e[10],d=e[11],p=e[12],f=e[13],m=e[14],g=e[15],v=h*m*l-f*u*l+f*o*d-s*m*d-h*o*g+s*u*g,_=p*u*l-c*m*l-p*o*d+a*m*d+c*o*g-a*u*g,y=c*f*l-p*h*l+p*s*d-a*f*d-c*s*g+a*h*g,x=p*h*o-c*f*o-p*s*u+a*f*u+c*s*m-a*h*m,b=t*v+n*_+i*y+r*x;if(0===b)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const M=1/b;return e[0]=v*M,e[1]=(f*u*r-h*m*r-f*i*d+n*m*d+h*i*g-n*u*g)*M,e[2]=(s*m*r-f*o*r+f*i*l-n*m*l-s*i*g+n*o*g)*M,e[3]=(h*o*r-s*u*r-h*i*l+n*u*l+s*i*d-n*o*d)*M,e[4]=_*M,e[5]=(c*m*r-p*u*r+p*i*d-t*m*d-c*i*g+t*u*g)*M,e[6]=(p*o*r-a*m*r-p*i*l+t*m*l+a*i*g-t*o*g)*M,e[7]=(a*u*r-c*o*r+c*i*l-t*u*l-a*i*d+t*o*d)*M,e[8]=y*M,e[9]=(p*h*r-c*f*r-p*n*d+t*f*d+c*n*g-t*h*g)*M,e[10]=(a*f*r-p*s*r+p*n*l-t*f*l-a*n*g+t*s*g)*M,e[11]=(c*s*r-a*h*r-c*n*l+t*h*l+a*n*d-t*s*d)*M,e[12]=x*M,e[13]=(c*f*i-p*h*i+p*n*u-t*f*u-c*n*m+t*h*m)*M,e[14]=(p*s*i-a*f*i-p*n*o+t*f*o+a*n*m-t*s*m)*M,e[15]=(a*h*i-c*s*i+c*n*o-t*h*o-a*n*u+t*s*u)*M,this}scale(e){const t=this.elements,n=e.x,i=e.y,r=e.z;return t[0]*=n,t[4]*=i,t[8]*=r,t[1]*=n,t[5]*=i,t[9]*=r,t[2]*=n,t[6]*=i,t[10]*=r,t[3]*=n,t[7]*=i,t[11]*=r,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,i))}makeTranslation(e,t,n){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const n=Math.cos(t),i=Math.sin(t),r=1-n,a=e.x,s=e.y,o=e.z,l=r*a,c=r*s;return this.set(l*a+n,l*s-i*o,l*o+i*s,0,l*s+i*o,c*s+n,c*o-i*a,0,l*o-i*s,c*o+i*a,r*o*o+n,0,0,0,0,1),this}makeScale(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this}makeShear(e,t,n,i,r,a){return this.set(1,n,r,0,e,1,a,0,t,i,1,0,0,0,0,1),this}compose(e,t,n){const i=this.elements,r=t._x,a=t._y,s=t._z,o=t._w,l=r+r,c=a+a,h=s+s,u=r*l,d=r*c,p=r*h,f=a*c,m=a*h,g=s*h,v=o*l,_=o*c,y=o*h,x=n.x,b=n.y,M=n.z;return i[0]=(1-(f+g))*x,i[1]=(d+y)*x,i[2]=(p-_)*x,i[3]=0,i[4]=(d-y)*b,i[5]=(1-(u+g))*b,i[6]=(m+v)*b,i[7]=0,i[8]=(p+_)*M,i[9]=(m-v)*M,i[10]=(1-(u+f))*M,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this}decompose(e,t,n){const i=this.elements;let r=Yt.set(i[0],i[1],i[2]).length();const a=Yt.set(i[4],i[5],i[6]).length(),s=Yt.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],Kt.copy(this);const o=1/r,l=1/a,c=1/s;return Kt.elements[0]*=o,Kt.elements[1]*=o,Kt.elements[2]*=o,Kt.elements[4]*=l,Kt.elements[5]*=l,Kt.elements[6]*=l,Kt.elements[8]*=c,Kt.elements[9]*=c,Kt.elements[10]*=c,t.setFromRotationMatrix(Kt),n.x=r,n.y=a,n.z=s,this}makePerspective(e,t,n,i,r,a,s=2e3){const o=this.elements,l=2*r/(t-e),c=2*r/(n-i),h=(t+e)/(t-e),u=(n+i)/(n-i);let d,p;if(s===Le)d=-(a+r)/(a-r),p=-2*a*r/(a-r);else{if(s!==Pe)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+s);d=-a/(a-r),p=-a*r/(a-r)}return o[0]=l,o[4]=0,o[8]=h,o[12]=0,o[1]=0,o[5]=c,o[9]=u,o[13]=0,o[2]=0,o[6]=0,o[10]=d,o[14]=p,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this}makeOrthographic(e,t,n,i,r,a,s=2e3){const o=this.elements,l=1/(t-e),c=1/(n-i),h=1/(a-r),u=(t+e)*l,d=(n+i)*c;let p,f;if(s===Le)p=(a+r)*h,f=-2*h;else{if(s!==Pe)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+s);p=r*h,f=-1*h}return o[0]=2*l,o[4]=0,o[8]=0,o[12]=-u,o[1]=0,o[5]=2*c,o[9]=0,o[13]=-d,o[2]=0,o[6]=0,o[10]=f,o[14]=-p,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this}equals(e){const t=this.elements,n=e.elements;for(let e=0;e<16;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<16;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}}const Yt=new vt,Kt=new qt,Zt=new vt(0,0,0),Jt=new vt(1,1,1),Qt=new vt,$t=new vt,en=new vt,tn=new qt,nn=new gt;class rn{constructor(e=0,t=0,n=0,i=rn.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=n,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,n,i=this._order){return this._x=e,this._y=t,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,n=!0){const i=e.elements,r=i[0],a=i[4],s=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(t){case"XYZ":this._y=Math.asin(ke(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-a,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-ke(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(s,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(ke(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-a,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-ke(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-a,l));break;case"YZX":this._z=Math.asin(ke(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(s,d));break;case"XZY":this._z=Math.asin(-ke(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(s,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===n&&this._onChangeCallback(),this}setFromQuaternion(e,t,n){return tn.makeRotationFromQuaternion(e),this.setFromRotationMatrix(tn,t,n)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return nn.setFromEuler(this),this.setFromQuaternion(nn,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}rn.DEFAULT_ORDER="XYZ";class an{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(e),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(e)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(e.geometries,this.geometry);const t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){const n=t.shapes;if(Array.isArray(n))for(let t=0,i=n.length;t0){i.children=[];for(let t=0;t0){i.animations=[];for(let t=0;t0&&(n.geometries=t),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),s.length>0&&(n.images=s),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function a(e){const t=[];for(const n in e){const i=e[n];delete i.metadata,t.push(i)}return t}}clone(e){return(new this.constructor).copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(e,t,n,i,r){Mn.subVectors(i,t),Sn.subVectors(n,t),En.subVectors(e,t);const a=Mn.dot(Mn),s=Mn.dot(Sn),o=Mn.dot(En),l=Sn.dot(Sn),c=Sn.dot(En),h=a*l-s*s;if(0===h)return r.set(0,0,0),null;const u=1/h,d=(l*o-s*c)*u,p=(a*c-s*o)*u;return r.set(1-d-p,p,d)}static containsPoint(e,t,n,i){return null!==this.getBarycoord(e,t,n,i,wn)&&(wn.x>=0&&wn.y>=0&&wn.x+wn.y<=1)}static getInterpolation(e,t,n,i,r,a,s,o){return null===this.getBarycoord(e,t,n,i,wn)?(o.x=0,o.y=0,"z"in o&&(o.z=0),"w"in o&&(o.w=0),null):(o.setScalar(0),o.addScaledVector(r,wn.x),o.addScaledVector(a,wn.y),o.addScaledVector(s,wn.z),o)}static isFrontFacing(e,t,n,i){return Mn.subVectors(n,t),Sn.subVectors(e,t),Mn.cross(Sn).dot(i)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,i){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,n,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,i),this}clone(){return(new this.constructor).copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Mn.subVectors(this.c,this.b),Sn.subVectors(this.a,this.b),.5*Mn.cross(Sn).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return In.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return In.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,n,i,r){return In.getInterpolation(e,this.a,this.b,this.c,t,n,i,r)}containsPoint(e){return In.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return In.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const n=this.a,i=this.b,r=this.c;let a,s;Tn.subVectors(i,n),An.subVectors(r,n),Cn.subVectors(e,n);const o=Tn.dot(Cn),l=An.dot(Cn);if(o<=0&&l<=0)return t.copy(n);Ln.subVectors(e,i);const c=Tn.dot(Ln),h=An.dot(Ln);if(c>=0&&h<=c)return t.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return a=o/(o-c),t.copy(n).addScaledVector(Tn,a);Pn.subVectors(e,r);const d=Tn.dot(Pn),p=An.dot(Pn);if(p>=0&&d<=p)return t.copy(r);const f=d*l-o*p;if(f<=0&&l>=0&&p<=0)return s=l/(l-p),t.copy(n).addScaledVector(An,s);const m=c*p-d*h;if(m<=0&&h-c>=0&&d-p>=0)return Rn.subVectors(r,i),s=(h-c)/(h-c+(d-p)),t.copy(i).addScaledVector(Rn,s);const g=1/(m+f+u);return a=f*g,s=u*g,t.copy(n).addScaledVector(Tn,a).addScaledVector(An,s)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const Nn={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},Un={h:0,s:0,l:0},Dn={h:0,s:0,l:0};function On(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+6*(t-e)*(2/3-n):e}class Fn{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(void 0===t&&void 0===n){const t=e;t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t="srgb"){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,nt.toWorkingColorSpace(this,t),this}setRGB(e,t,n,i=nt.workingColorSpace){return this.r=e,this.g=t,this.b=n,nt.toWorkingColorSpace(this,i),this}setHSL(e,t,n,i=nt.workingColorSpace){if(e=Be(e,1),t=ke(t,0,1),n=ke(n,0,1),0===t)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+t):n+t-n*t,r=2*n-i;this.r=On(r,i,e+1/3),this.g=On(r,i,e),this.b=On(r,i,e-1/3)}return nt.toWorkingColorSpace(this,i),this}setStyle(e,t="srgb"){function n(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let r;const a=i[1],s=i[2];switch(a){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,t);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,t);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,t);if(6===r)return this.setHex(parseInt(n,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t="srgb"){const n=Nn[e.toLowerCase()];return void 0!==n?this.setHex(n,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=it(e.r),this.g=it(e.g),this.b=it(e.b),this}copyLinearToSRGB(e){return this.r=rt(e.r),this.g=rt(e.g),this.b=rt(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e="srgb"){return nt.fromWorkingColorSpace(kn.copy(this),e),65536*Math.round(ke(255*kn.r,0,255))+256*Math.round(ke(255*kn.g,0,255))+Math.round(ke(255*kn.b,0,255))}getHexString(e="srgb"){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=nt.workingColorSpace){nt.fromWorkingColorSpace(kn.copy(this),t);const n=kn.r,i=kn.g,r=kn.b,a=Math.max(n,i,r),s=Math.min(n,i,r);let o,l;const c=(s+a)/2;if(s===a)o=0,l=0;else{const e=a-s;switch(l=c<=.5?e/(a+s):e/(2-a-s),a){case n:o=(i-r)/e+(i0!=e>0&&this.version++,this._alphaTest=e}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(const t in e){const n=e[t];if(void 0===n){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const i=this[t];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[t]=n:console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`)}}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(e){const t=[];for(const n in e){const i=e[n];delete i.metadata,t.push(i)}return t}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(n.dispersion=this.dispersion),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapRotation&&(n.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),0!==this.side&&(n.side=this.side),!0===this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=!0),this.blendSrc!==s&&(n.blendSrc=this.blendSrc),this.blendDst!==o&&(n.blendDst=this.blendDst),this.blendEquation!==a&&(n.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(n.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(n.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(n.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(n.depthFunc=this.depthFunc),!1===this.depthTest&&(n.depthTest=this.depthTest),!1===this.depthWrite&&(n.depthWrite=this.depthWrite),!1===this.colorWrite&&(n.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(n.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(n.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(n.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==Ae&&(n.stencilFail=this.stencilFail),this.stencilZFail!==Ae&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==Ae&&(n.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(n.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaHash&&(n.alphaHash=!0),!0===this.alphaToCoverage&&(n.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=!0),!0===this.forceSinglePass&&(n.forceSinglePass=!0),!0===this.wireframe&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),t){const t=i(e.textures),r=i(e.images);t.length>0&&(n.textures=t),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let n=null;if(null!==t){const e=t.length;n=new Array(e);for(let i=0;i!==e;++i)n[i]=t[i].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}onBeforeRender(){console.warn("Material: onBeforeRender() has been removed.")}}class Hn extends zn{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Fn(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.envMapRotation=new rn,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const Vn=new vt,Gn=new We;class Wn{constructor(e,t,n=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=n,this.usage=Re,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.gpuType=T,this.version=0}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return Je("THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let i=0,r=this.itemSize;i0&&(e.userData=this.userData),void 0!==this.parameters){const t=this.parameters;for(const n in t)void 0!==t[n]&&(e[n]=t[n]);return e}e.data={attributes:{}};const t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const n=this.attributes;for(const t in n){const i=n[t];e.data.attributes[t]=i.toJSON(e.data)}const i={};let r=!1;for(const t in this.morphAttributes){const n=this.morphAttributes[t],a=[];for(let t=0,i=n.length;t0&&(i[t]=a,r=!0)}r&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(e.data.groups=JSON.parse(JSON.stringify(a)));const s=this.boundingSphere;return null!==s&&(e.data.boundingSphere={center:s.center.toArray(),radius:s.radius}),e}clone(){return(new this.constructor).copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const n=e.index;null!==n&&this.setIndex(n.clone(t));const i=e.attributes;for(const e in i){const n=i[e];this.setAttribute(e,n.clone(t))}const r=e.morphAttributes;for(const e in r){const n=[],i=r[e];for(let e=0,r=i.length;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;e(e.far-e.near)**2)return}ni.copy(r).invert(),ii.copy(e.ray).applyMatrix4(ni),null!==n.boundingBox&&!1===ii.intersectsBox(n.boundingBox)||this._computeIntersections(e,t,ii)}}_computeIntersections(e,t,n){let i;const r=this.geometry,a=this.material,s=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==s)if(Array.isArray(a))for(let r=0,o=u.length;rn.far?null:{distance:c,point:_i.clone(),object:e}}(e,t,n,i,si,oi,li,vi);if(h){r&&(ui.fromBufferAttribute(r,o),di.fromBufferAttribute(r,l),pi.fromBufferAttribute(r,c),h.uv=In.getInterpolation(vi,si,oi,li,ui,di,pi,new We)),a&&(ui.fromBufferAttribute(a,o),di.fromBufferAttribute(a,l),pi.fromBufferAttribute(a,c),h.uv1=In.getInterpolation(vi,si,oi,li,ui,di,pi,new We)),s&&(fi.fromBufferAttribute(s,o),mi.fromBufferAttribute(s,l),gi.fromBufferAttribute(s,c),h.normal=In.getInterpolation(vi,si,oi,li,fi,mi,gi,new vt),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const e={a:o,b:l,c:c,normal:new vt,materialIndex:0};In.getNormal(si,oi,li,e.normal),h.face=e}return h}class bi extends ti{constructor(e=1,t=1,n=1,i=1,r=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:n,widthSegments:i,heightSegments:r,depthSegments:a};const s=this;i=Math.floor(i),r=Math.floor(r),a=Math.floor(a);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(e,t,n,i,r,a,p,f,m,g,v){const _=a/m,y=p/g,x=a/2,b=p/2,M=f/2,S=m+1,E=g+1;let w=0,T=0;const A=new vt;for(let a=0;a0?1:-1,c.push(A.x,A.y,A.z),h.push(o/m),h.push(1-a/g),w+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const n={};for(const e in this.extensions)!0===this.extensions[e]&&(n[e]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}}class Ai extends bn{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new qt,this.projectionMatrix=new qt,this.projectionMatrixInverse=new qt,this.coordinateSystem=Le}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Ri=new vt,Ci=new We,Li=new We;class Pi extends Ai{constructor(e=50,t=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=2*Oe*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(.5*De*this.fov);return.5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*Oe*Math.atan(Math.tan(.5*De*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,n){Ri.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Ri.x,Ri.y).multiplyScalar(-e/Ri.z),Ri.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Ri.x,Ri.y).multiplyScalar(-e/Ri.z)}getViewSize(e,t){return this.getViewBounds(e,Ci,Li),t.subVectors(Li,Ci)}setViewOffset(e,t,n,i,r,a){this.aspect=e/t,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(.5*De*this.fov)/this.zoom,n=2*t,i=this.aspect*n,r=-.5*i;const a=this.view;if(null!==this.view&&this.view.enabled){const e=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/e,t-=a.offsetY*n/s,i*=a.width/e,n*=a.height/s}const s=this.filmOffset;0!==s&&(r+=e*s/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-n,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const Ii=-90;class Ni extends bn{constructor(e,t,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Pi(Ii,1,e,t);i.layers=this.layers,this.add(i);const r=new Pi(Ii,1,e,t);r.layers=this.layers,this.add(r);const a=new Pi(Ii,1,e,t);a.layers=this.layers,this.add(a);const s=new Pi(Ii,1,e,t);s.layers=this.layers,this.add(s);const o=new Pi(Ii,1,e,t);o.layers=this.layers,this.add(o);const l=new Pi(Ii,1,e,t);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[n,i,r,a,s,o]=t;for(const e of t)this.remove(e);if(e===Le)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),s.up.set(0,1,0),s.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else{if(e!==Pe)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),s.up.set(0,-1,0),s.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1)}for(const e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[r,a,s,o,l,c]=this.children,h=e.getRenderTarget(),u=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;const f=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,e.setRenderTarget(n,0,i),e.render(t,r),e.setRenderTarget(n,1,i),e.render(t,a),e.setRenderTarget(n,2,i),e.render(t,s),e.setRenderTarget(n,3,i),e.render(t,o),e.setRenderTarget(n,4,i),e.render(t,l),n.texture.generateMipmaps=f,e.setRenderTarget(n,5,i),e.render(t,c),e.setRenderTarget(h,u,d),e.xr.enabled=p,n.texture.needsPMREMUpdate=!0}}class Ui extends ht{constructor(e,t,n,i,r,a,s,o,l,h){super(e=void 0!==e?e:[],t=void 0!==t?t:c,n,i,r,a,s,o,l,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class Di extends pt{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const n={width:e,height:e,depth:1},i=[n,n,n,n,n,n];this.texture=new Ui(i,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:v}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new bi(5,5,5),r=new Ti({name:"CubemapFromEquirect",uniforms:Mi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=t;const a=new yi(i,r),s=t.minFilter;t.minFilter===y&&(t.minFilter=v);return new Ni(1,10,this).update(e,a),t.minFilter=s,a.geometry.dispose(),a.material.dispose(),this}clear(e,t,n,i){const r=e.getRenderTarget();for(let r=0;r<6;r++)e.setRenderTarget(this,r),e.clear(t,n,i);e.setRenderTarget(r)}}const Oi=new vt,Fi=new vt,ki=new je;class Bi{constructor(e=new vt(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,n,i){return this.normal.set(e,t,n),this.constant=i,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,n){const i=Oi.subVectors(n,t).cross(Fi.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(i,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){const e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t){const n=e.delta(Oi),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(e.start)?t.copy(e.start):null;const r=-(e.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:t.copy(e.start).addScaledVector(n,r)}intersectsLine(e){const t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const n=t||ki.getNormalMatrix(e),i=this.coplanarPoint(Oi).applyMatrix4(e),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const zi=new kt,Hi=new vt;class Vi{constructor(e=new Bi,t=new Bi,n=new Bi,i=new Bi,r=new Bi,a=new Bi){this.planes=[e,t,n,i,r,a]}set(e,t,n,i,r,a){const s=this.planes;return s[0].copy(e),s[1].copy(t),s[2].copy(n),s[3].copy(i),s[4].copy(r),s[5].copy(a),this}copy(e){const t=this.planes;for(let n=0;n<6;n++)t[n].copy(e.planes[n]);return this}setFromProjectionMatrix(e,t=2e3){const n=this.planes,i=e.elements,r=i[0],a=i[1],s=i[2],o=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],f=i[10],m=i[11],g=i[12],v=i[13],_=i[14],y=i[15];if(n[0].setComponents(o-r,u-l,m-d,y-g).normalize(),n[1].setComponents(o+r,u+l,m+d,y+g).normalize(),n[2].setComponents(o+a,u+c,m+p,y+v).normalize(),n[3].setComponents(o-a,u-c,m-p,y-v).normalize(),n[4].setComponents(o-s,u-h,m-f,y-_).normalize(),t===Le)n[5].setComponents(o+s,u+h,m+f,y+_).normalize();else{if(t!==Pe)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);n[5].setComponents(s,h,f,_).normalize()}return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),zi.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),zi.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(zi)}intersectsSprite(e){return zi.center.set(0,0,0),zi.radius=.7071067811865476,zi.applyMatrix4(e.matrixWorld),this.intersectsSphere(zi)}intersectsSphere(e){const t=this.planes,n=e.center,i=-e.radius;for(let e=0;e<6;e++){if(t[e].distanceToPoint(n)0?e.max.x:e.min.x,Hi.y=i.normal.y>0?e.max.y:e.min.y,Hi.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(Hi)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function Gi(){let e=null,t=!1,n=null,i=null;function r(t,a){n(t,a),i=e.requestAnimationFrame(r)}return{start:function(){!0!==t&&null!==n&&(i=e.requestAnimationFrame(r),t=!0)},stop:function(){e.cancelAnimationFrame(i),t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function Wi(e){const t=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),t.get(e)},remove:function(n){n.isInterleavedBufferAttribute&&(n=n.data);const i=t.get(n);i&&(e.deleteBuffer(i.buffer),t.delete(n))},update:function(n,i){if(n.isInterleavedBufferAttribute&&(n=n.data),n.isGLBufferAttribute){const e=t.get(n);return void((!e||e.version 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif",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\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn 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}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = 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\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn 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\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",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\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#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 \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},qi={common:{diffuse:{value:new Fn(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new je},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new je}},envmap:{envMap:{value:null},envMapRotation:{value:new je},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new je}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new je}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new je},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new je},normalScale:{value:new We(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new je},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new je}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new je}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new je}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Fn(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,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:new Fn(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0},uvTransform:{value:new je}},sprite:{diffuse:{value:new Fn(16777215)},opacity:{value:1},center:{value:new We(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new je},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0}}},Yi={basic:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.fog]),vertexShader:Xi.meshbasic_vert,fragmentShader:Xi.meshbasic_frag},lambert:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)}}]),vertexShader:Xi.meshlambert_vert,fragmentShader:Xi.meshlambert_frag},phong:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)},specular:{value:new Fn(1118481)},shininess:{value:30}}]),vertexShader:Xi.meshphong_vert,fragmentShader:Xi.meshphong_frag},standard:{uniforms:Si([qi.common,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.roughnessmap,qi.metalnessmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Xi.meshphysical_vert,fragmentShader:Xi.meshphysical_frag},toon:{uniforms:Si([qi.common,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.gradientmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)}}]),vertexShader:Xi.meshtoon_vert,fragmentShader:Xi.meshtoon_frag},matcap:{uniforms:Si([qi.common,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,{matcap:{value:null}}]),vertexShader:Xi.meshmatcap_vert,fragmentShader:Xi.meshmatcap_frag},points:{uniforms:Si([qi.points,qi.fog]),vertexShader:Xi.points_vert,fragmentShader:Xi.points_frag},dashed:{uniforms:Si([qi.common,qi.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Xi.linedashed_vert,fragmentShader:Xi.linedashed_frag},depth:{uniforms:Si([qi.common,qi.displacementmap]),vertexShader:Xi.depth_vert,fragmentShader:Xi.depth_frag},normal:{uniforms:Si([qi.common,qi.bumpmap,qi.normalmap,qi.displacementmap,{opacity:{value:1}}]),vertexShader:Xi.meshnormal_vert,fragmentShader:Xi.meshnormal_frag},sprite:{uniforms:Si([qi.sprite,qi.fog]),vertexShader:Xi.sprite_vert,fragmentShader:Xi.sprite_frag},background:{uniforms:{uvTransform:{value:new je},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Xi.background_vert,fragmentShader:Xi.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new je}},vertexShader:Xi.backgroundCube_vert,fragmentShader:Xi.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Xi.cube_vert,fragmentShader:Xi.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Xi.equirect_vert,fragmentShader:Xi.equirect_frag},distanceRGBA:{uniforms:Si([qi.common,qi.displacementmap,{referencePosition:{value:new vt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Xi.distanceRGBA_vert,fragmentShader:Xi.distanceRGBA_frag},shadow:{uniforms:Si([qi.lights,qi.fog,{color:{value:new Fn(0)},opacity:{value:1}}]),vertexShader:Xi.shadow_vert,fragmentShader:Xi.shadow_frag}};Yi.physical={uniforms:Si([Yi.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new je},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new je},clearcoatNormalScale:{value:new We(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new je},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new je},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new je},sheen:{value:0},sheenColor:{value:new Fn(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new je},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new je},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new je},transmissionSamplerSize:{value:new We},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new je},attenuationDistance:{value:0},attenuationColor:{value:new Fn(0)},specularColor:{value:new Fn(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new je},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new je},anisotropyVector:{value:new We},anisotropyMap:{value:null},anisotropyMapTransform:{value:new je}}]),vertexShader:Xi.meshphysical_vert,fragmentShader:Xi.meshphysical_frag};const Ki={r:0,b:0,g:0},Zi=new rn,Ji=new qt;function Qi(e,t,n,i,r,a,s){const o=new Fn(0);let l,c,h=!0===a?0:1,d=null,p=0,f=null;function m(e){let i=!0===e.isScene?e.background:null;if(i&&i.isTexture){i=(e.backgroundBlurriness>0?n:t).get(i)}return i}function g(t,n){t.getRGB(Ki,Ei(e)),i.buffers.color.setClear(Ki.r,Ki.g,Ki.b,n,s)}return{getClearColor:function(){return o},setClearColor:function(e,t=1){o.set(e),h=t,g(o,h)},getClearAlpha:function(){return h},setClearAlpha:function(e){h=e,g(o,h)},render:function(t){let n=!1;const r=m(t);null===r?g(o,h):r&&r.isColor&&(g(r,1),n=!0);const a=e.xr.getEnvironmentBlendMode();"additive"===a?i.buffers.color.setClear(0,0,0,1,s):"alpha-blend"===a&&i.buffers.color.setClear(0,0,0,0,s),(e.autoClear||n)&&(i.buffers.depth.setTest(!0),i.buffers.depth.setMask(!0),i.buffers.color.setMask(!0),e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil))},addToRenderList:function(t,n){const i=m(n);i&&(i.isCubeTexture||i.mapping===u)?(void 0===c&&(c=new yi(new bi(1,1,1),new Ti({name:"BackgroundCubeMaterial",uniforms:Mi(Yi.backgroundCube.uniforms),vertexShader:Yi.backgroundCube.vertexShader,fragmentShader:Yi.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(c)),Zi.copy(n.backgroundRotation),Zi.x*=-1,Zi.y*=-1,Zi.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(Zi.y*=-1,Zi.z*=-1),c.material.uniforms.envMap.value=i,c.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,c.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,c.material.uniforms.backgroundRotation.value.setFromMatrix4(Ji.makeRotationFromEuler(Zi)),c.material.toneMapped=nt.getTransfer(i.colorSpace)!==Ee,d===i&&p===i.version&&f===e.toneMapping||(c.material.needsUpdate=!0,d=i,p=i.version,f=e.toneMapping),c.layers.enableAll(),t.unshift(c,c.geometry,c.material,0,0,null)):i&&i.isTexture&&(void 0===l&&(l=new yi(new ji(2,2),new Ti({name:"BackgroundMaterial",uniforms:Mi(Yi.background.uniforms),vertexShader:Yi.background.vertexShader,fragmentShader:Yi.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(l)),l.material.uniforms.t2D.value=i,l.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,l.material.toneMapped=nt.getTransfer(i.colorSpace)!==Ee,!0===i.matrixAutoUpdate&&i.updateMatrix(),l.material.uniforms.uvTransform.value.copy(i.matrix),d===i&&p===i.version&&f===e.toneMapping||(l.material.needsUpdate=!0,d=i,p=i.version,f=e.toneMapping),l.layers.enableAll(),t.unshift(l,l.geometry,l.material,0,0,null))}}}function $i(e,t){const n=e.getParameter(e.MAX_VERTEX_ATTRIBS),i={},r=c(null);let a=r,s=!1;function o(t){return e.bindVertexArray(t)}function l(t){return e.deleteVertexArray(t)}function c(e){const t=[],i=[],r=[];for(let e=0;e=0){const n=r[t];let i=s[t];if(void 0===i&&("instanceMatrix"===t&&e.instanceMatrix&&(i=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(i=e.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;o++}}return a.attributesNum!==o||a.index!==i}(n,m,l,g),v&&function(e,t,n,i){const r={},s=t.attributes;let o=0;const l=n.getAttributes();for(const t in l){if(l[t].location>=0){let n=s[t];void 0===n&&("instanceMatrix"===t&&e.instanceMatrix&&(n=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(n=e.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[t]=i,o++}}a.attributes=r,a.attributesNum=o,a.index=i}(n,m,l,g),null!==g&&t.update(g,e.ELEMENT_ARRAY_BUFFER),(v||s)&&(s=!1,function(n,i,r,a){h();const s=a.attributes,o=r.getAttributes(),l=i.defaultAttributeValues;for(const i in o){const r=o[i];if(r.location>=0){let o=s[i];if(void 0===o&&("instanceMatrix"===i&&n.instanceMatrix&&(o=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(o=n.instanceColor)),void 0!==o){const i=o.normalized,s=o.itemSize,l=t.get(o);if(void 0===l)continue;const c=l.buffer,h=l.type,p=l.bytesPerElement,m=h===e.INT||h===e.UNSIGNED_INT||o.gpuType===E;if(o.isInterleavedBufferAttribute){const t=o.data,l=t.stride,g=o.offset;if(t.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let s=void 0!==n.precision?n.precision:"highp";const o=a(s);o!==s&&(console.warn("THREE.WebGLRenderer:",s,"not supported, using",o,"instead."),s=o);const l=!0===n.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===t.has("EXT_texture_filter_anisotropic")){const n=t.get("EXT_texture_filter_anisotropic");r=e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:a,textureFormatReadable:function(t){return t===I||i.convert(t)===e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===A&&(t.has("EXT_color_buffer_half_float")||t.has("EXT_color_buffer_float"));return!(n!==x&&i.convert(n)!==e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==T&&!r)},precision:s,logarithmicDepthBuffer:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:e.getParameter(e.MAX_TEXTURE_SIZE),maxCubemapSize:e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:e.getParameter(e.MAX_VERTEX_ATTRIBS),maxVertexUniforms:e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:e.getParameter(e.MAX_VARYING_VECTORS),maxFragmentUniforms:e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:h>0,maxSamples:e.getParameter(e.MAX_SAMPLES)}}function nr(e){const t=this;let n=null,i=0,r=!1,a=!1;const s=new Bi,o=new je,l={value:null,needsUpdate:!1};function c(e,n,i,r){const a=null!==e?e.length:0;let c=null;if(0!==a){if(c=l.value,!0!==r||null===c){const t=i+4*a,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);t.numPlanes=i,t.numIntersection=0}();else{const e=a?0:i,t=4*e;let r=f.clippingState||null;l.value=r,r=c(u,o,t,h);for(let e=0;e!==t;++e)r[e]=n[e];f.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=e}}}function ir(e){let t=new WeakMap;function n(e,t){return 303===t?e.mapping=c:304===t&&(e.mapping=h),e}function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping;if(303===a||304===a){if(t.has(r)){return n(t.get(r).texture,r.mapping)}{const a=r.image;if(a&&a.height>0){const s=new Di(a.height);return s.fromEquirectangularTexture(e,r),t.set(r,s),r.addEventListener("dispose",i),n(s.texture,r.mapping)}return null}}}return r},dispose:function(){t=new WeakMap}}}class rr extends Ai{constructor(e=-1,t=1,n=1,i=-1,r=.1,a=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=e,this.right=t,this.top=n,this.bottom=i,this.near=r,this.far=a,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.left=e.left,this.right=e.right,this.top=e.top,this.bottom=e.bottom,this.near=e.near,this.far=e.far,this.zoom=e.zoom,this.view=null===e.view?null:Object.assign({},e.view),this}setViewOffset(e,t,n,i,r,a){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=(this.right-this.left)/(2*this.zoom),t=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-e,a=n+e,s=i+t,o=i-t;if(null!==this.view&&this.view.enabled){const e=(this.right-this.left)/this.view.fullWidth/this.zoom,t=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=e*this.view.offsetX,a=r+e*this.view.width,s-=t*this.view.offsetY,o=s-t*this.view.height}this.projectionMatrix.makeOrthographic(r,a,s,o,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.zoom=this.zoom,t.object.left=this.left,t.object.right=this.right,t.object.top=this.top,t.object.bottom=this.bottom,t.object.near=this.near,t.object.far=this.far,null!==this.view&&(t.object.view=Object.assign({},this.view)),t}}const ar=[.125,.215,.35,.446,.526,.582],sr=20,or=new rr,lr=new Fn;let cr=null,hr=0,ur=0,dr=!1;const pr=(1+Math.sqrt(5))/2,fr=1/pr,mr=[new vt(-pr,fr,0),new vt(pr,fr,0),new vt(-fr,0,pr),new vt(fr,0,pr),new vt(0,pr,-fr),new vt(0,pr,fr),new vt(-1,1,-1),new vt(1,1,-1),new vt(-1,1,1),new vt(1,1,1)];class gr{constructor(e){this._renderer=e,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(e,t=0,n=.1,i=100){cr=this._renderer.getRenderTarget(),hr=this._renderer.getActiveCubeFace(),ur=this._renderer.getActiveMipmapLevel(),dr=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,n,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=xr(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=yr(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?o=ar[s-e+4-1]:0===s&&(o=0),i.push(o);const l=1/(a-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,f=3,m=2,g=1,v=new Float32Array(f*p*d),_=new Float32Array(m*p*d),y=new Float32Array(g*p*d);for(let e=0;e2?0:-1,i=[t,n,0,t+2/3,n,0,t+2/3,n+1,0,t,n,0,t+2/3,n+1,0,t,n+1,0];v.set(i,f*p*e),_.set(u,m*p*e);const r=[e,e,e,e,e,e];y.set(r,g*p*e)}const x=new ti;x.setAttribute("position",new Wn(v,f)),x.setAttribute("uv",new Wn(_,m)),x.setAttribute("faceIndex",new Wn(y,g)),t.push(x),r>4&&r--}return{lodPlanes:t,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(e,t,n){const i=new Float32Array(sr),r=new vt(0,1,0);return new Ti({name:"SphericalGaussianBlur",defines:{n:sr,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}(i,e,t)}return i}_compileMaterial(e){const t=new yi(this._lodPlanes[0],e);this._renderer.compile(t,or)}_sceneToCubeUV(e,t,n,i){const r=new Pi(90,1,t,n),a=[1,-1,1,1,1,1],s=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(lr),o.toneMapping=0,o.autoClear=!1;const h=new Hn({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new yi(new bi,h);let d=!1;const p=e.background;p?p.isColor&&(h.color.copy(p),e.background=null,d=!0):(h.color.copy(lr),d=!0);for(let t=0;t<6;t++){const n=t%3;0===n?(r.up.set(0,a[t],0),r.lookAt(s[t],0,0)):1===n?(r.up.set(0,0,a[t]),r.lookAt(0,s[t],0)):(r.up.set(0,a[t],0),r.lookAt(0,0,s[t]));const l=this._cubeSize;_r(i,n*l,t>2?l:0,l,l),o.setRenderTarget(i),d&&o.render(u,r),o.render(e,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,e.background=p}_textureToCubeUV(e,t){const n=this._renderer,i=e.mapping===c||e.mapping===h;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=xr()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===e.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=yr());const r=i?this._cubemapMaterial:this._equirectMaterial,a=new yi(this._lodPlanes[0],r);r.uniforms.envMap.value=e;const s=this._cubeSize;_r(t,0,0,3*s,2*s),n.setRenderTarget(t),n.render(a,or)}_applyPMREM(e){const t=this._renderer,n=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;tsr&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${f} samples when the maximum is set to 20`);const m=[];let g=0;for(let e=0;ev-4?i-v+4:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(t),o.render(c,or)}}function vr(e,t,n){const i=new pt(e,t,n);return i.texture.mapping=u,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function _r(e,t,n,i,r){e.viewport.set(t,n,i,r),e.scissor.set(t,n,i,r)}function yr(){return new Ti({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function xr(){return new Ti({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function br(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Mr(e){let t=new WeakMap,n=null;function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping,s=303===a||304===a,o=a===c||a===h;if(s||o){let a=t.get(r);const l=void 0!==a?a.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new gr(e)),a=s?n.fromEquirectangular(r,a):n.fromCubemap(r,a),a.texture.pmremVersion=r.pmremVersion,t.set(r,a),a.texture;if(void 0!==a)return a.texture;{const l=r.image;return s&&l&&l.height>0||o&&l&&function(e){let t=0;const n=6;for(let i=0;it.maxTextureSize&&(x=Math.ceil(y/t.maxTextureSize),y=t.maxTextureSize);const b=new Float32Array(y*x*4*h),M=new ft(b,y,x,h);M.type=T,M.needsUpdate=!0;const S=4*_;for(let w=0;w0)return e;const r=t*n;let a=Dr[r];if(void 0===a&&(a=new Float32Array(r),Dr[r]=a),0!==t){i.toArray(a,0);for(let i=1,r=0;i!==t;++i)r+=n,e[i].toArray(a,r)}return a}function Hr(e,t){if(e.length!==t.length)return!1;for(let n=0,i=e.length;n":" "} ${r}: ${n[e]}`)}return i.join("\n")}(e.getShaderSource(t),i)}return r}function ka(e,t){const n=function(e){const t=nt.getPrimaries(nt.workingColorSpace),n=nt.getPrimaries(e);let i;switch(t===n?i="":t===Te&&n===we?i="LinearDisplayP3ToLinearSRGB":t===we&&n===Te&&(i="LinearSRGBToLinearDisplayP3"),e){case xe:case Me:return[i,"LinearTransferOETF"];case ye:case be:return[i,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",e),[i,"LinearTransferOETF"]}}(t);return`vec4 ${e}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function Ba(e,t){let n;switch(t){case 1:n="Linear";break;case 2:n="Reinhard";break;case 3:n="OptimizedCineon";break;case 4:n="ACESFilmic";break;case 6:n="AgX";break;case 7:n="Neutral";break;case 5:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),n="Linear"}return"vec3 "+e+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const za=new vt;function Ha(){nt.getLuminanceCoefficients(za);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${za.x.toFixed(4)}, ${za.y.toFixed(4)}, ${za.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function Va(e){return""!==e}function Ga(e,t){const n=t.numSpotLightShadows+t.numSpotLightMaps-t.numSpotLightShadowsWithMaps;return e.replace(/NUM_DIR_LIGHTS/g,t.numDirLights).replace(/NUM_SPOT_LIGHTS/g,t.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,t.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,t.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,t.numPointLights).replace(/NUM_HEMI_LIGHTS/g,t.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,t.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,t.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,t.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,t.numPointLightShadows)}function Wa(e,t){return e.replace(/NUM_CLIPPING_PLANES/g,t.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,t.numClippingPlanes-t.numClipIntersection)}const ja=/^[ \t]*#include +<([\w\d./]+)>/gm;function Xa(e){return e.replace(ja,Ya)}const qa=new Map;function Ya(e,t){let n=Xi[t];if(void 0===n){const e=qa.get(t);if(void 0===e)throw new Error("Can not resolve #include <"+t+">");n=Xi[e],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,e)}return Xa(n)}const Ka=/#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 Za(e){return e.replace(Ka,Ja)}function Ja(e,t,n,i){let r="";for(let e=parseInt(t);e0&&(y+="\n"),x=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(Va).join("\n"),x.length>0&&(x+="\n")):(y=[Qa(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+l:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Va).join("\n"),x=[Qa(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.envMap?"#define "+f:"",m?"#define CUBEUV_TEXEL_WIDTH "+m.texelWidth:"",m?"#define CUBEUV_TEXEL_HEIGHT "+m.texelHeight:"",m?"#define CUBEUV_MAX_MIP "+m.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+l:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?Xi.tonemapping_pars_fragment:"",0!==n.toneMapping?Ba("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",Xi.colorspace_pars_fragment,ka("linearToOutputTexel",n.outputColorSpace),Ha(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Va).join("\n")),s=Xa(s),s=Ga(s,n),s=Wa(s,n),o=Xa(o),o=Ga(o,n),o=Wa(o,n),s=Za(s),o=Za(o),!0!==n.isRawShaderMaterial&&(b="#version 300 es\n",y=[g,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#define varying in",n.glslVersion===Ce?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Ce?"":"#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"+x);const M=b+y+s,S=b+x+o,E=Da(r,r.VERTEX_SHADER,M),w=Da(r,r.FRAGMENT_SHADER,S);function T(t){if(e.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(E).trim(),a=r.getShaderInfoLog(w).trim();let s=!0,o=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(s=!1,"function"==typeof e.debug.onShaderError)e.debug.onShaderError(r,_,E,w);else{const e=Fa(r,E,"vertex"),i=Fa(r,w,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+t.name+"\nMaterial Type: "+t.type+"\n\nProgram Info Log: "+n+"\n"+e+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==a||(o=!1);o&&(t.diagnostics={runnable:s,programLog:n,vertexShader:{log:i,prefix:y},fragmentShader:{log:a,prefix:x}})}r.deleteShader(E),r.deleteShader(w),A=new Ua(r,_),R=function(e,t){const n={},i=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES);for(let r=0;r0,q=a.clearcoat>0,Y=a.dispersion>0,K=a.iridescence>0,Z=a.sheen>0,J=a.transmission>0,Q=X&&!!a.anisotropyMap,$=q&&!!a.clearcoatMap,ee=q&&!!a.clearcoatNormalMap,te=q&&!!a.clearcoatRoughnessMap,ne=K&&!!a.iridescenceMap,ie=K&&!!a.iridescenceThicknessMap,re=Z&&!!a.sheenColorMap,ae=Z&&!!a.sheenRoughnessMap,se=!!a.specularMap,oe=!!a.specularColorMap,le=!!a.specularIntensityMap,ce=J&&!!a.transmissionMap,he=J&&!!a.thicknessMap,ue=!!a.gradientMap,de=!!a.alphaMap,pe=a.alphaTest>0,fe=!!a.alphaHash,me=!!a.extensions;let ge=0;a.toneMapped&&(null!==I&&!0!==I.isXRRenderTarget||(ge=e.toneMapping));const ve={shaderID:E,shaderType:a.type,shaderName:a.name,vertexShader:A,fragmentShader:R,defines:a.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===a.isRawShaderMaterial,glslVersion:a.glslVersion,precision:f,batching:U,batchingColor:U&&null!==_._colorsTexture,instancing:N,instancingColor:N&&null!==_.instanceColor,instancingMorph:N&&null!==_.morphTexture,supportsVertexTextures:p,outputColorSpace:null===I?e.outputColorSpace:!0===I.isXRRenderTarget?I.texture.colorSpace:xe,alphaToCoverage:!!a.alphaToCoverage,map:D,matcap:O,envMap:F,envMapMode:F&&M.mapping,envMapCubeUVHeight:S,aoMap:k,lightMap:B,bumpMap:z,normalMap:H,displacementMap:p&&V,emissiveMap:G,normalMapObjectSpace:H&&1===a.normalMapType,normalMapTangentSpace:H&&0===a.normalMapType,metalnessMap:W,roughnessMap:j,anisotropy:X,anisotropyMap:Q,clearcoat:q,clearcoatMap:$,clearcoatNormalMap:ee,clearcoatRoughnessMap:te,dispersion:Y,iridescence:K,iridescenceMap:ne,iridescenceThicknessMap:ie,sheen:Z,sheenColorMap:re,sheenRoughnessMap:ae,specularMap:se,specularColorMap:oe,specularIntensityMap:le,transmission:J,transmissionMap:ce,thicknessMap:he,gradientMap:ue,opaque:!1===a.transparent&&1===a.blending&&!1===a.alphaToCoverage,alphaMap:de,alphaTest:pe,alphaHash:fe,combine:a.combine,mapUv:D&&g(a.map.channel),aoMapUv:k&&g(a.aoMap.channel),lightMapUv:B&&g(a.lightMap.channel),bumpMapUv:z&&g(a.bumpMap.channel),normalMapUv:H&&g(a.normalMap.channel),displacementMapUv:V&&g(a.displacementMap.channel),emissiveMapUv:G&&g(a.emissiveMap.channel),metalnessMapUv:W&&g(a.metalnessMap.channel),roughnessMapUv:j&&g(a.roughnessMap.channel),anisotropyMapUv:Q&&g(a.anisotropyMap.channel),clearcoatMapUv:$&&g(a.clearcoatMap.channel),clearcoatNormalMapUv:ee&&g(a.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:te&&g(a.clearcoatRoughnessMap.channel),iridescenceMapUv:ne&&g(a.iridescenceMap.channel),iridescenceThicknessMapUv:ie&&g(a.iridescenceThicknessMap.channel),sheenColorMapUv:re&&g(a.sheenColorMap.channel),sheenRoughnessMapUv:ae&&g(a.sheenRoughnessMap.channel),specularMapUv:se&&g(a.specularMap.channel),specularColorMapUv:oe&&g(a.specularColorMap.channel),specularIntensityMapUv:le&&g(a.specularIntensityMap.channel),transmissionMapUv:ce&&g(a.transmissionMap.channel),thicknessMapUv:he&&g(a.thicknessMap.channel),alphaMapUv:de&&g(a.alphaMap.channel),vertexTangents:!!x.attributes.tangent&&(H||X),vertexColors:a.vertexColors,vertexAlphas:!0===a.vertexColors&&!!x.attributes.color&&4===x.attributes.color.itemSize,pointsUvs:!0===_.isPoints&&!!x.attributes.uv&&(D||de),fog:!!y,useFog:!0===a.fog,fogExp2:!!y&&y.isFogExp2,flatShading:!0===a.flatShading,sizeAttenuation:!0===a.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===_.isSkinnedMesh,morphTargets:void 0!==x.morphAttributes.position,morphNormals:void 0!==x.morphAttributes.normal,morphColors:void 0!==x.morphAttributes.color,morphTargetsCount:T,morphTextureStride:P,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numLightProbes:o.numLightProbes,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:a.dithering,shadowMapEnabled:e.shadowMap.enabled&&h.length>0,shadowMapType:e.shadowMap.type,toneMapping:ge,decodeVideoTexture:D&&!0===a.map.isVideoTexture&&nt.getTransfer(a.map.colorSpace)===Ee,premultipliedAlpha:a.premultipliedAlpha,doubleSided:2===a.side,flipSided:1===a.side,useDepthPacking:a.depthPacking>=0,depthPacking:a.depthPacking||0,index0AttributeName:a.index0AttributeName,extensionClipCullDistance:me&&!0===a.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(me&&!0===a.extensions.multiDraw||U)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:a.customProgramCacheKey()};return ve.vertexUv1s=c.has(1),ve.vertexUv2s=c.has(2),ve.vertexUv3s=c.has(3),c.clear(),ve},getProgramCacheKey:function(t){const n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.customVertexShaderID),n.push(t.customFragmentShaderID)),void 0!==t.defines)for(const e in t.defines)n.push(e),n.push(t.defines[e]);return!1===t.isRawShaderMaterial&&(!function(e,t){e.push(t.precision),e.push(t.outputColorSpace),e.push(t.envMapMode),e.push(t.envMapCubeUVHeight),e.push(t.mapUv),e.push(t.alphaMapUv),e.push(t.lightMapUv),e.push(t.aoMapUv),e.push(t.bumpMapUv),e.push(t.normalMapUv),e.push(t.displacementMapUv),e.push(t.emissiveMapUv),e.push(t.metalnessMapUv),e.push(t.roughnessMapUv),e.push(t.anisotropyMapUv),e.push(t.clearcoatMapUv),e.push(t.clearcoatNormalMapUv),e.push(t.clearcoatRoughnessMapUv),e.push(t.iridescenceMapUv),e.push(t.iridescenceThicknessMapUv),e.push(t.sheenColorMapUv),e.push(t.sheenRoughnessMapUv),e.push(t.specularMapUv),e.push(t.specularColorMapUv),e.push(t.specularIntensityMapUv),e.push(t.transmissionMapUv),e.push(t.thicknessMapUv),e.push(t.combine),e.push(t.fogExp2),e.push(t.sizeAttenuation),e.push(t.morphTargetsCount),e.push(t.morphAttributeCount),e.push(t.numDirLights),e.push(t.numPointLights),e.push(t.numSpotLights),e.push(t.numSpotLightMaps),e.push(t.numHemiLights),e.push(t.numRectAreaLights),e.push(t.numDirLightShadows),e.push(t.numPointLightShadows),e.push(t.numSpotLightShadows),e.push(t.numSpotLightShadowsWithMaps),e.push(t.numLightProbes),e.push(t.shadowMapType),e.push(t.toneMapping),e.push(t.numClippingPlanes),e.push(t.numClipIntersection),e.push(t.depthPacking)}(n,t),function(e,t){o.disableAll(),t.supportsVertexTextures&&o.enable(0);t.instancing&&o.enable(1);t.instancingColor&&o.enable(2);t.instancingMorph&&o.enable(3);t.matcap&&o.enable(4);t.envMap&&o.enable(5);t.normalMapObjectSpace&&o.enable(6);t.normalMapTangentSpace&&o.enable(7);t.clearcoat&&o.enable(8);t.iridescence&&o.enable(9);t.alphaTest&&o.enable(10);t.vertexColors&&o.enable(11);t.vertexAlphas&&o.enable(12);t.vertexUv1s&&o.enable(13);t.vertexUv2s&&o.enable(14);t.vertexUv3s&&o.enable(15);t.vertexTangents&&o.enable(16);t.anisotropy&&o.enable(17);t.alphaHash&&o.enable(18);t.batching&&o.enable(19);t.dispersion&&o.enable(20);t.batchingColor&&o.enable(21);e.push(o.mask),o.disableAll(),t.fog&&o.enable(0);t.useFog&&o.enable(1);t.flatShading&&o.enable(2);t.logarithmicDepthBuffer&&o.enable(3);t.skinning&&o.enable(4);t.morphTargets&&o.enable(5);t.morphNormals&&o.enable(6);t.morphColors&&o.enable(7);t.premultipliedAlpha&&o.enable(8);t.shadowMapEnabled&&o.enable(9);t.doubleSided&&o.enable(10);t.flipSided&&o.enable(11);t.useDepthPacking&&o.enable(12);t.dithering&&o.enable(13);t.transmission&&o.enable(14);t.sheen&&o.enable(15);t.opaque&&o.enable(16);t.pointsUvs&&o.enable(17);t.decodeVideoTexture&&o.enable(18);t.alphaToCoverage&&o.enable(19);e.push(o.mask)}(n,t),n.push(e.outputColorSpace)),n.push(t.customProgramCacheKey),n.join()},getUniforms:function(e){const t=m[e.type];let n;if(t){const e=Yi[t];n=wi.clone(e.uniforms)}else n=e.uniforms;return n},acquireProgram:function(t,n){let i;for(let e=0,t=h.length;e0?i.push(h):!0===s.transparent?r.push(h):n.push(h)},unshift:function(e,t,s,o,l,c){const h=a(e,t,s,o,l,c);s.transmission>0?i.unshift(h):!0===s.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=t,i=e.length;n1&&n.sort(e||as),i.length>1&&i.sort(t||ss),r.length>1&&r.sort(t||ss)}}}function ls(){let e=new WeakMap;return{get:function(t,n){const i=e.get(t);let r;return void 0===i?(r=new os,e.set(t,[r])):n>=i.length?(r=new os,i.push(r)):r=i[n],r},dispose:function(){e=new WeakMap}}}function cs(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let n;switch(t.type){case"DirectionalLight":n={direction:new vt,color:new Fn};break;case"SpotLight":n={position:new vt,direction:new vt,color:new Fn,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new vt,color:new Fn,distance:0,decay:0};break;case"HemisphereLight":n={direction:new vt,skyColor:new Fn,groundColor:new Fn};break;case"RectAreaLight":n={color:new Fn,position:new vt,halfWidth:new vt,halfHeight:new vt}}return e[t.id]=n,n}}}let hs=0;function us(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+(t.map?1:0)-(e.map?1:0)}function ds(e){const t=new cs,n=function(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let n;switch(t.type){case"DirectionalLight":case"SpotLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new We};break;case"PointLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new We,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=n,n}}}(),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let e=0;e<9;e++)i.probe.push(new vt);const r=new vt,a=new qt,s=new qt;return{setup:function(r){let a=0,s=0,o=0;for(let e=0;e<9;e++)i.probe[e].set(0,0,0);let l=0,c=0,h=0,u=0,d=0,p=0,f=0,m=0,g=0,v=0,_=0;r.sort(us);for(let e=0,y=r.length;e0&&(!0===e.has("OES_texture_float_linear")?(i.rectAreaLTC1=qi.LTC_FLOAT_1,i.rectAreaLTC2=qi.LTC_FLOAT_2):(i.rectAreaLTC1=qi.LTC_HALF_1,i.rectAreaLTC2=qi.LTC_HALF_2)),i.ambient[0]=a,i.ambient[1]=s,i.ambient[2]=o;const y=i.hash;y.directionalLength===l&&y.pointLength===c&&y.spotLength===h&&y.rectAreaLength===u&&y.hemiLength===d&&y.numDirectionalShadows===p&&y.numPointShadows===f&&y.numSpotShadows===m&&y.numSpotMaps===g&&y.numLightProbes===_||(i.directional.length=l,i.spot.length=h,i.rectArea.length=u,i.point.length=c,i.hemi.length=d,i.directionalShadow.length=p,i.directionalShadowMap.length=p,i.pointShadow.length=f,i.pointShadowMap.length=f,i.spotShadow.length=m,i.spotShadowMap.length=m,i.directionalShadowMatrix.length=p,i.pointShadowMatrix.length=f,i.spotLightMatrix.length=m+g-v,i.spotLightMap.length=g,i.numSpotLightShadowsWithMaps=v,i.numLightProbes=_,y.directionalLength=l,y.pointLength=c,y.spotLength=h,y.rectAreaLength=u,y.hemiLength=d,y.numDirectionalShadows=p,y.numPointShadows=f,y.numSpotShadows=m,y.numSpotMaps=g,y.numLightProbes=_,i.version=hs++)},setupView:function(e,t){let n=0,o=0,l=0,c=0,h=0;const u=t.matrixWorldInverse;for(let t=0,d=e.length;t=r.length?(a=new ps(e),r.push(a)):a=r[i],a},dispose:function(){t=new WeakMap}}}class ms extends zn{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class gs extends zn{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}function vs(e,t,n){let i=new Vi;const r=new We,a=new We,s=new ut,o=new ms({depthPacking:3201}),l=new gs,c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new Ti({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new We},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),p=d.clone();p.defines.HORIZONTAL_PASS=1;const f=new ti;f.setAttribute("position",new Wn(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new yi(f,d),v=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=1;let _=this.type;function y(n,i){const a=t.update(g);d.defines.VSM_SAMPLES!==n.blurSamples&&(d.defines.VSM_SAMPLES=n.blurSamples,p.defines.VSM_SAMPLES=n.blurSamples,d.needsUpdate=!0,p.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new pt(r.x,r.y)),d.uniforms.shadow_pass.value=n.map.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,a,d,g,null),p.uniforms.shadow_pass.value=n.mapPass.texture,p.uniforms.resolution.value=n.mapSize,p.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,a,p,g,null)}function x(t,n,i,r){let a=null;const s=!0===i.isPointLight?t.customDistanceMaterial:t.customDepthMaterial;if(void 0!==s)a=s;else if(a=!0===i.isPointLight?l:o,e.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const e=a.uuid,t=n.uuid;let i=c[e];void 0===i&&(i={},c[e]=i);let r=i[t];void 0===r&&(r=a.clone(),i[t]=r,n.addEventListener("dispose",M)),a=r}if(a.visible=n.visible,a.wireframe=n.wireframe,a.side=3===r?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:u[n.side],a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,!0===i.isPointLight&&!0===a.isMeshDistanceMaterial){e.properties.get(a).light=i}return a}function b(n,r,a,s,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);const i=t.update(n),l=n.material;if(Array.isArray(l)){const t=i.groups;for(let c=0,h=t.length;ch||r.y>h)&&(r.x>h&&(a.x=Math.floor(h/g.x),r.x=a.x*g.x,u.mapSize.x=a.x),r.y>h&&(a.y=Math.floor(h/g.y),r.y=a.y*g.y,u.mapSize.y=a.y)),null===u.map||!0===p||!0===f){const e=3!==this.type?{minFilter:m,magFilter:m}:{};null!==u.map&&u.map.dispose(),u.map=new pt(r.x,r.y,e),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}e.setRenderTarget(u.map),e.clear();const v=u.getViewportCount();for(let e=0;e=1):-1!==N.indexOf("OpenGL ES")&&(I=parseFloat(/^OpenGL ES (\d)/.exec(N)[1]),P=I>=2);let U=null,D={};const O=e.getParameter(e.SCISSOR_BOX),F=e.getParameter(e.VIEWPORT),k=(new ut).fromArray(O),B=(new ut).fromArray(F);function z(t,n,i,r){const a=new Uint8Array(4),s=e.createTexture();e.bindTexture(t,s),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(let s=0;sn||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&e instanceof VideoFrame){const n=Math.floor(i*r.width),a=Math.floor(i*r.height);void 0===u&&(u=E(n,a));const s=t?E(n,a):u;s.width=n,s.height=a;return s.getContext("2d").drawImage(e,0,0,n,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+a+")."),s}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),e}return e}function R(e){return e.generateMipmaps&&e.minFilter!==m&&e.minFilter!==v}function C(t){e.generateMipmap(t)}function P(n,i,r,a,s=!1){if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let o=i;if(i===e.RED&&(r===e.FLOAT&&(o=e.R32F),r===e.HALF_FLOAT&&(o=e.R16F),r===e.UNSIGNED_BYTE&&(o=e.R8)),i===e.RED_INTEGER&&(r===e.UNSIGNED_BYTE&&(o=e.R8UI),r===e.UNSIGNED_SHORT&&(o=e.R16UI),r===e.UNSIGNED_INT&&(o=e.R32UI),r===e.BYTE&&(o=e.R8I),r===e.SHORT&&(o=e.R16I),r===e.INT&&(o=e.R32I)),i===e.RG&&(r===e.FLOAT&&(o=e.RG32F),r===e.HALF_FLOAT&&(o=e.RG16F),r===e.UNSIGNED_BYTE&&(o=e.RG8)),i===e.RG_INTEGER&&(r===e.UNSIGNED_BYTE&&(o=e.RG8UI),r===e.UNSIGNED_SHORT&&(o=e.RG16UI),r===e.UNSIGNED_INT&&(o=e.RG32UI),r===e.BYTE&&(o=e.RG8I),r===e.SHORT&&(o=e.RG16I),r===e.INT&&(o=e.RG32I)),i===e.RGB&&r===e.UNSIGNED_INT_5_9_9_9_REV&&(o=e.RGB9_E5),i===e.RGBA){const t=s?Se:nt.getTransfer(a);r===e.FLOAT&&(o=e.RGBA32F),r===e.HALF_FLOAT&&(o=e.RGBA16F),r===e.UNSIGNED_BYTE&&(o=t===Ee?e.SRGB8_ALPHA8:e.RGBA8),r===e.UNSIGNED_SHORT_4_4_4_4&&(o=e.RGBA4),r===e.UNSIGNED_SHORT_5_5_5_1&&(o=e.RGB5_A1)}return o!==e.R16F&&o!==e.R32F&&o!==e.RG16F&&o!==e.RG32F&&o!==e.RGBA16F&&o!==e.RGBA32F||t.get("EXT_color_buffer_float"),o}function D(t,n){let i;return t?null===n||n===w||n===L?i=e.DEPTH24_STENCIL8:n===T?i=e.DEPTH32F_STENCIL8:n===S&&(i=e.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===w||n===L?i=e.DEPTH_COMPONENT24:n===T?i=e.DEPTH_COMPONENT32F:n===S&&(i=e.DEPTH_COMPONENT16),i}function O(e,t){return!0===R(e)||e.isFramebufferTexture&&e.minFilter!==m&&e.minFilter!==v?Math.log2(Math.max(t.width,t.height))+1:void 0!==e.mipmaps&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function F(e){const t=e.target;t.removeEventListener("dispose",F),function(e){const t=i.get(e);if(void 0===t.__webglInit)return;const n=e.source,r=b.get(n);if(r){const i=r[t.__cacheKey];i.usedTimes--,0===i.usedTimes&&B(e),0===Object.keys(r).length&&b.delete(n)}i.remove(e)}(t),t.isVideoTexture&&h.delete(t)}function k(t){const n=t.target;n.removeEventListener("dispose",k),function(t){const n=i.get(t);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(n.__webglFramebuffer[t]))for(let i=0;i0&&a.__version!==t.version){const e=t.image;if(null===e)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==e.complete)return void q(a,t,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(e.TEXTURE_2D,a.__webglTexture,e.TEXTURE0+r)}const V={[d]:e.REPEAT,[p]:e.CLAMP_TO_EDGE,[f]:e.MIRRORED_REPEAT},G={[m]:e.NEAREST,1004:e.NEAREST_MIPMAP_NEAREST,[g]:e.NEAREST_MIPMAP_LINEAR,[v]:e.LINEAR,[_]:e.LINEAR_MIPMAP_NEAREST,[y]:e.LINEAR_MIPMAP_LINEAR},W={512:e.NEVER,519:e.ALWAYS,513:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL};function j(n,a){if(a.type!==T||!1!==t.has("OES_texture_float_linear")||a.magFilter!==v&&a.magFilter!==_&&a.magFilter!==g&&a.magFilter!==y&&a.minFilter!==v&&a.minFilter!==_&&a.minFilter!==g&&a.minFilter!==y||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),e.texParameteri(n,e.TEXTURE_WRAP_S,V[a.wrapS]),e.texParameteri(n,e.TEXTURE_WRAP_T,V[a.wrapT]),n!==e.TEXTURE_3D&&n!==e.TEXTURE_2D_ARRAY||e.texParameteri(n,e.TEXTURE_WRAP_R,V[a.wrapR]),e.texParameteri(n,e.TEXTURE_MAG_FILTER,G[a.magFilter]),e.texParameteri(n,e.TEXTURE_MIN_FILTER,G[a.minFilter]),a.compareFunction&&(e.texParameteri(n,e.TEXTURE_COMPARE_MODE,e.COMPARE_REF_TO_TEXTURE),e.texParameteri(n,e.TEXTURE_COMPARE_FUNC,W[a.compareFunction])),!0===t.has("EXT_texture_filter_anisotropic")){if(a.magFilter===m)return;if(a.minFilter!==g&&a.minFilter!==y)return;if(a.type===T&&!1===t.has("OES_texture_float_linear"))return;if(a.anisotropy>1||i.get(a).__currentAnisotropy){const s=t.get("EXT_texture_filter_anisotropic");e.texParameterf(n,s.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,r.getMaxAnisotropy())),i.get(a).__currentAnisotropy=a.anisotropy}}}function X(t,n){let i=!1;void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",F));const r=n.source;let a=b.get(r);void 0===a&&(a={},b.set(r,a));const o=function(e){const t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}(n);if(o!==t.__cacheKey){void 0===a[o]&&(a[o]={texture:e.createTexture(),usedTimes:0},s.memory.textures++,i=!0),a[o].usedTimes++;const r=a[t.__cacheKey];void 0!==r&&(a[t.__cacheKey].usedTimes--,0===r.usedTimes&&B(n)),t.__cacheKey=o,t.__webglTexture=a[o].texture}return i}function q(t,s,o){let l=e.TEXTURE_2D;(s.isDataArrayTexture||s.isCompressedArrayTexture)&&(l=e.TEXTURE_2D_ARRAY),s.isData3DTexture&&(l=e.TEXTURE_3D);const c=X(t,s),h=s.source;n.bindTexture(l,t.__webglTexture,e.TEXTURE0+o);const u=i.get(h);if(h.version!==u.__version||!0===c){n.activeTexture(e.TEXTURE0+o);const t=nt.getPrimaries(nt.workingColorSpace),i=s.colorSpace===_e?null:nt.getPrimaries(s.colorSpace),d=s.colorSpace===_e||t===i?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,s.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,s.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,s.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,d);let p=A(s.image,!1,r.maxTextureSize);p=te(s,p);const f=a.convert(s.format,s.colorSpace),m=a.convert(s.type);let g,v=P(s.internalFormat,f,m,s.colorSpace,s.isVideoTexture);j(l,s);const _=s.mipmaps,y=!0!==s.isVideoTexture,x=void 0===u.__version||!0===c,b=h.dataReady,M=O(s,p);if(s.isDepthTexture)v=D(s.format===U,s.type),x&&(y?n.texStorage2D(e.TEXTURE_2D,1,v,p.width,p.height):n.texImage2D(e.TEXTURE_2D,0,v,p.width,p.height,0,f,m,null));else if(s.isDataTexture)if(_.length>0){y&&x&&n.texStorage2D(e.TEXTURE_2D,M,v,_[0].width,_[0].height);for(let t=0,i=_.length;t0){const i=ys(g.width,g.height,s.format,s.type);for(const r of s.layerUpdates){const a=g.data.subarray(r*i/g.data.BYTES_PER_ELEMENT,(r+1)*i/g.data.BYTES_PER_ELEMENT);n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,r,g.width,g.height,1,f,a,0,0)}s.clearLayerUpdates()}else n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,p.depth,f,g.data,0,0)}else n.compressedTexImage3D(e.TEXTURE_2D_ARRAY,t,v,g.width,g.height,p.depth,0,g.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else y?b&&n.texSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,p.depth,f,m,g.data):n.texImage3D(e.TEXTURE_2D_ARRAY,t,v,g.width,g.height,p.depth,0,f,m,g.data)}else{y&&x&&n.texStorage2D(e.TEXTURE_2D,M,v,_[0].width,_[0].height);for(let t=0,i=_.length;t0){const t=ys(p.width,p.height,s.format,s.type);for(const i of s.layerUpdates){const r=p.data.subarray(i*t/p.data.BYTES_PER_ELEMENT,(i+1)*t/p.data.BYTES_PER_ELEMENT);n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,i,p.width,p.height,1,f,m,r)}s.clearLayerUpdates()}else n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,0,p.width,p.height,p.depth,f,m,p.data)}else n.texImage3D(e.TEXTURE_2D_ARRAY,0,v,p.width,p.height,p.depth,0,f,m,p.data);else if(s.isData3DTexture)y?(x&&n.texStorage3D(e.TEXTURE_3D,M,v,p.width,p.height,p.depth),b&&n.texSubImage3D(e.TEXTURE_3D,0,0,0,0,p.width,p.height,p.depth,f,m,p.data)):n.texImage3D(e.TEXTURE_3D,0,v,p.width,p.height,p.depth,0,f,m,p.data);else if(s.isFramebufferTexture){if(x)if(y)n.texStorage2D(e.TEXTURE_2D,M,v,p.width,p.height);else{let t=p.width,i=p.height;for(let r=0;r>=1,i>>=1}}else if(_.length>0){if(y&&x){const t=ne(_[0]);n.texStorage2D(e.TEXTURE_2D,M,v,t.width,t.height)}for(let t=0,i=_.length;t>h),i=Math.max(1,r.height>>h);c===e.TEXTURE_3D||c===e.TEXTURE_2D_ARRAY?n.texImage3D(c,h,p,t,i,r.depth,0,u,d,null):n.texImage2D(c,h,p,t,i,0,u,d,null)}n.bindFramebuffer(e.FRAMEBUFFER,t),ee(r)?o.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,l,c,i.get(s).__webglTexture,0,$(r)):(c===e.TEXTURE_2D||c>=e.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=e.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&e.framebufferTexture2D(e.FRAMEBUFFER,l,c,i.get(s).__webglTexture,h),n.bindFramebuffer(e.FRAMEBUFFER,null)}function K(t,n,i){if(e.bindRenderbuffer(e.RENDERBUFFER,t),n.depthBuffer){const r=n.depthTexture,a=r&&r.isDepthTexture?r.type:null,s=D(n.stencilBuffer,a),l=n.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,c=$(n);ee(n)?o.renderbufferStorageMultisampleEXT(e.RENDERBUFFER,c,s,n.width,n.height):i?e.renderbufferStorageMultisample(e.RENDERBUFFER,c,s,n.width,n.height):e.renderbufferStorage(e.RENDERBUFFER,s,n.width,n.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,l,e.RENDERBUFFER,t)}else{const t=n.textures;for(let r=0;r0&&!0===t.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function te(e,t){const n=e.colorSpace,i=e.format,r=e.type;return!0===e.isCompressedTexture||!0===e.isVideoTexture||n!==xe&&n!==_e&&(nt.getTransfer(n)===Ee?i===I&&r===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),t}function ne(e){return"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement?(c.width=e.naturalWidth||e.width,c.height=e.naturalHeight||e.height):"undefined"!=typeof VideoFrame&&e instanceof VideoFrame?(c.width=e.displayWidth,c.height=e.displayHeight):(c.width=e.width,c.height=e.height),c}this.allocateTextureUnit=function(){const e=z;return e>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+r.maxTextures),z+=1,e},this.resetTextureUnits=function(){z=0},this.setTexture2D=H,this.setTexture2DArray=function(t,r){const a=i.get(t);t.version>0&&a.__version!==t.version?q(a,t,r):n.bindTexture(e.TEXTURE_2D_ARRAY,a.__webglTexture,e.TEXTURE0+r)},this.setTexture3D=function(t,r){const a=i.get(t);t.version>0&&a.__version!==t.version?q(a,t,r):n.bindTexture(e.TEXTURE_3D,a.__webglTexture,e.TEXTURE0+r)},this.setTextureCube=function(t,s){const o=i.get(t);t.version>0&&o.__version!==t.version?function(t,s,o){if(6!==s.image.length)return;const l=X(t,s),c=s.source;n.bindTexture(e.TEXTURE_CUBE_MAP,t.__webglTexture,e.TEXTURE0+o);const h=i.get(c);if(c.version!==h.__version||!0===l){n.activeTexture(e.TEXTURE0+o);const t=nt.getPrimaries(nt.workingColorSpace),i=s.colorSpace===_e?null:nt.getPrimaries(s.colorSpace),u=s.colorSpace===_e||t===i?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,s.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,s.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,s.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,u);const d=s.isCompressedTexture||s.image[0].isCompressedTexture,p=s.image[0]&&s.image[0].isDataTexture,f=[];for(let e=0;e<6;e++)f[e]=d||p?p?s.image[e].image:s.image[e]:A(s.image[e],!0,r.maxCubemapSize),f[e]=te(s,f[e]);const m=f[0],g=a.convert(s.format,s.colorSpace),v=a.convert(s.type),_=P(s.internalFormat,g,v,s.colorSpace),y=!0!==s.isVideoTexture,x=void 0===h.__version||!0===l,b=c.dataReady;let M,S=O(s,m);if(j(e.TEXTURE_CUBE_MAP,s),d){y&&x&&n.texStorage2D(e.TEXTURE_CUBE_MAP,S,_,m.width,m.height);for(let t=0;t<6;t++){M=f[t].mipmaps;for(let i=0;i0&&S++;const t=ne(f[0]);n.texStorage2D(e.TEXTURE_CUBE_MAP,S,_,t.width,t.height)}for(let t=0;t<6;t++)if(p){y?b&&n.texSubImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,0,0,f[t].width,f[t].height,g,v,f[t].data):n.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,_,f[t].width,f[t].height,0,g,v,f[t].data);for(let i=0;i1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=e.createTexture()),l.__version=r.version,s.memory.textures++),h){o.__webglFramebuffer=[];for(let t=0;t<6;t++)if(r.mipmaps&&r.mipmaps.length>0){o.__webglFramebuffer[t]=[];for(let n=0;n0){o.__webglFramebuffer=[];for(let t=0;t0&&!1===ee(t)){o.__webglMultisampledFramebuffer=e.createFramebuffer(),o.__webglColorRenderbuffer=[],n.bindFramebuffer(e.FRAMEBUFFER,o.__webglMultisampledFramebuffer);for(let n=0;n0)for(let i=0;i0)for(let n=0;n0)if(!1===ee(t)){const r=t.textures,a=t.width,s=t.height;let o=e.COLOR_BUFFER_BIT;const c=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,h=i.get(t),u=r.length>1;if(u)for(let t=0;to+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!l.inputState.pinching&&s<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else null!==o&&e.gripSpace&&(r=t.getPose(e.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==s&&(i=t.getPose(e.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(s.matrix.fromArray(i.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,i.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(i.linearVelocity)):s.hasLinearVelocity=!1,i.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(i.angularVelocity)):s.hasAngularVelocity=!1,this.dispatchEvent(Es)))}return null!==s&&(s.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==a),this}_getHandJoint(e,t){if(void 0===e.joints[t.jointName]){const n=new Ss;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}class Ts{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(null===this.texture){const i=new ht;e.properties.get(i).__webglTexture=t.texture,t.depthNear==n.depthNear&&t.depthFar==n.depthFar||(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=i}}getMesh(e){if(null!==this.texture&&null===this.mesh){const t=e.cameras[0].viewport,n=new Ti({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new yi(new ji(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class As extends Ie{constructor(e,t){super();const n=this;let i=null,r=1,a=null,s="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const f=new Ts,m=t.getContextAttributes();let g=null,v=null;const _=[],y=[],b=new We;let M=null;const S=new Pi;S.layers.enable(1),S.viewport=new ut;const E=new Pi;E.layers.enable(2),E.viewport=new ut;const T=[S,E],A=new Ms;A.layers.enable(1),A.layers.enable(2);let R=null,C=null;function P(e){const t=y.indexOf(e.inputSource);if(-1===t)return;const n=_[t];void 0!==n&&(n.update(e.inputSource,e.frame,l||a),n.dispatchEvent({type:e.type,data:e.inputSource}))}function D(){i.removeEventListener("select",P),i.removeEventListener("selectstart",P),i.removeEventListener("selectend",P),i.removeEventListener("squeeze",P),i.removeEventListener("squeezestart",P),i.removeEventListener("squeezeend",P),i.removeEventListener("end",D),i.removeEventListener("inputsourceschange",O);for(let e=0;e<_.length;e++){const t=y[e];null!==t&&(y[e]=null,_[e].disconnect(t))}R=null,C=null,f.reset(),e.setRenderTarget(g),d=null,u=null,h=null,i=null,v=null,H.stop(),n.isPresenting=!1,e.setPixelRatio(M),e.setSize(b.width,b.height,!1),n.dispatchEvent({type:"sessionend"})}function O(e){for(let t=0;t=0&&(y[i]=null,_[i].disconnect(n))}for(let t=0;t=y.length){y.push(n),i=e;break}if(null===y[e]){y[e]=n,i=e;break}}if(-1===i)break}const r=_[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=_[e];return void 0===t&&(t=new ws,_[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=_[e];return void 0===t&&(t=new ws,_[e]=t),t.getGripSpace()},this.getHand=function(e){let t=_[e];return void 0===t&&(t=new ws,_[e]=t),t.getHandSpace()},this.setFramebufferScaleFactor=function(e){r=e,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(e){s=e,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||a},this.setReferenceSpace=function(e){l=e},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(g=e.getRenderTarget(),i.addEventListener("select",P),i.addEventListener("selectstart",P),i.addEventListener("selectend",P),i.addEventListener("squeeze",P),i.addEventListener("squeezestart",P),i.addEventListener("squeezeend",P),i.addEventListener("end",D),i.addEventListener("inputsourceschange",O),!0!==m.xrCompatible&&await t.makeXRCompatible(),M=e.getPixelRatio(),e.getSize(b),void 0===i.renderState.layers){const n={antialias:m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,t,n),i.updateRenderState({baseLayer:d}),e.setPixelRatio(1),e.setSize(d.framebufferWidth,d.framebufferHeight,!1),v=new pt(d.framebufferWidth,d.framebufferHeight,{format:I,type:x,colorSpace:e.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,a=null,s=null;m.depth&&(s=m.stencil?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT24,n=m.stencil?U:N,a=m.stencil?L:w);const o={colorFormat:t.RGBA8,depthFormat:s,scaleFactor:r};h=new XRWebGLBinding(i,t),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),e.setPixelRatio(1),e.setSize(u.textureWidth,u.textureHeight,!1),v=new pt(u.textureWidth,u.textureHeight,{format:I,type:x,depthTexture:new Cr(u.textureWidth,u.textureHeight,a,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:e.outputColorSpace,samples:m.antialias?4:0,resolveDepthBuffer:!1===u.ignoreDepthValues})}v.isXRRenderTarget=!0,this.setFoveation(o),l=null,a=await i.requestReferenceSpace(s),H.setContext(i),H.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode},this.getDepthTexture=function(){return f.getDepthTexture()};const F=new vt,k=new vt;function B(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){if(null===i)return;null!==f.texture&&(e.near=f.depthNear,e.far=f.depthFar),A.near=E.near=S.near=e.near,A.far=E.far=S.far=e.far,R===A.near&&C===A.far||(i.updateRenderState({depthNear:A.near,depthFar:A.far}),R=A.near,C=A.far,S.near=R,S.far=C,E.near=R,E.far=C,S.updateProjectionMatrix(),E.updateProjectionMatrix(),e.updateProjectionMatrix());const t=e.parent,n=A.cameras;B(A,t);for(let e=0;e0&&(e.alphaTest.value=i.alphaTest);const r=t.get(i),a=r.envMap,s=r.envMapRotation;a&&(e.envMap.value=a,Rs.copy(s),Rs.x*=-1,Rs.y*=-1,Rs.z*=-1,a.isCubeTexture&&!1===a.isRenderTargetTexture&&(Rs.y*=-1,Rs.z*=-1),e.envMapRotation.value.setFromMatrix4(Cs.makeRotationFromEuler(Rs)),e.flipEnvMap.value=a.isCubeTexture&&!1===a.isRenderTargetTexture?-1:1,e.reflectivity.value=i.reflectivity,e.ior.value=i.ior,e.refractionRatio.value=i.refractionRatio),i.lightMap&&(e.lightMap.value=i.lightMap,e.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,e.lightMapTransform)),i.aoMap&&(e.aoMap.value=i.aoMap,e.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,e.aoMapTransform))}return{refreshFogUniforms:function(t,n){n.color.getRGB(t.fogColor.value,Ei(e)),n.isFog?(t.fogNear.value=n.near,t.fogFar.value=n.far):n.isFogExp2&&(t.fogDensity.value=n.density)},refreshMaterialUniforms:function(e,r,a,s,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(e,r):r.isMeshToonMaterial?(i(e,r),function(e,t){t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(e,r)):r.isMeshPhongMaterial?(i(e,r),function(e,t){e.specular.value.copy(t.specular),e.shininess.value=Math.max(t.shininess,1e-4)}(e,r)):r.isMeshStandardMaterial?(i(e,r),function(e,t){e.metalness.value=t.metalness,t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap,n(t.metalnessMap,e.metalnessMapTransform));e.roughness.value=t.roughness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap,n(t.roughnessMap,e.roughnessMapTransform));t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}(e,r),r.isMeshPhysicalMaterial&&function(e,t,i){e.ior.value=t.ior,t.sheen>0&&(e.sheenColor.value.copy(t.sheenColor).multiplyScalar(t.sheen),e.sheenRoughness.value=t.sheenRoughness,t.sheenColorMap&&(e.sheenColorMap.value=t.sheenColorMap,n(t.sheenColorMap,e.sheenColorMapTransform)),t.sheenRoughnessMap&&(e.sheenRoughnessMap.value=t.sheenRoughnessMap,n(t.sheenRoughnessMap,e.sheenRoughnessMapTransform)));t.clearcoat>0&&(e.clearcoat.value=t.clearcoat,e.clearcoatRoughness.value=t.clearcoatRoughness,t.clearcoatMap&&(e.clearcoatMap.value=t.clearcoatMap,n(t.clearcoatMap,e.clearcoatMapTransform)),t.clearcoatRoughnessMap&&(e.clearcoatRoughnessMap.value=t.clearcoatRoughnessMap,n(t.clearcoatRoughnessMap,e.clearcoatRoughnessMapTransform)),t.clearcoatNormalMap&&(e.clearcoatNormalMap.value=t.clearcoatNormalMap,n(t.clearcoatNormalMap,e.clearcoatNormalMapTransform),e.clearcoatNormalScale.value.copy(t.clearcoatNormalScale),1===t.side&&e.clearcoatNormalScale.value.negate()));t.dispersion>0&&(e.dispersion.value=t.dispersion);t.iridescence>0&&(e.iridescence.value=t.iridescence,e.iridescenceIOR.value=t.iridescenceIOR,e.iridescenceThicknessMinimum.value=t.iridescenceThicknessRange[0],e.iridescenceThicknessMaximum.value=t.iridescenceThicknessRange[1],t.iridescenceMap&&(e.iridescenceMap.value=t.iridescenceMap,n(t.iridescenceMap,e.iridescenceMapTransform)),t.iridescenceThicknessMap&&(e.iridescenceThicknessMap.value=t.iridescenceThicknessMap,n(t.iridescenceThicknessMap,e.iridescenceThicknessMapTransform)));t.transmission>0&&(e.transmission.value=t.transmission,e.transmissionSamplerMap.value=i.texture,e.transmissionSamplerSize.value.set(i.width,i.height),t.transmissionMap&&(e.transmissionMap.value=t.transmissionMap,n(t.transmissionMap,e.transmissionMapTransform)),e.thickness.value=t.thickness,t.thicknessMap&&(e.thicknessMap.value=t.thicknessMap,n(t.thicknessMap,e.thicknessMapTransform)),e.attenuationDistance.value=t.attenuationDistance,e.attenuationColor.value.copy(t.attenuationColor));t.anisotropy>0&&(e.anisotropyVector.value.set(t.anisotropy*Math.cos(t.anisotropyRotation),t.anisotropy*Math.sin(t.anisotropyRotation)),t.anisotropyMap&&(e.anisotropyMap.value=t.anisotropyMap,n(t.anisotropyMap,e.anisotropyMapTransform)));e.specularIntensity.value=t.specularIntensity,e.specularColor.value.copy(t.specularColor),t.specularColorMap&&(e.specularColorMap.value=t.specularColorMap,n(t.specularColorMap,e.specularColorMapTransform));t.specularIntensityMap&&(e.specularIntensityMap.value=t.specularIntensityMap,n(t.specularIntensityMap,e.specularIntensityMapTransform))}(e,r,o)):r.isMeshMatcapMaterial?(i(e,r),function(e,t){t.matcap&&(e.matcap.value=t.matcap)}(e,r)):r.isMeshDepthMaterial?i(e,r):r.isMeshDistanceMaterial?(i(e,r),function(e,n){const i=t.get(n).light;e.referencePosition.value.setFromMatrixPosition(i.matrixWorld),e.nearDistance.value=i.shadow.camera.near,e.farDistance.value=i.shadow.camera.far}(e,r)):r.isMeshNormalMaterial?i(e,r):r.isLineBasicMaterial?(function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform))}(e,r),r.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(e,r)):r.isPointsMaterial?function(e,t,i,r){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.size.value=t.size*i,e.scale.value=.5*r,t.map&&(e.map.value=t.map,n(t.map,e.uvTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r,a,s):r.isSpriteMaterial?function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.rotation.value=t.rotation,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r):r.isShadowMaterial?(e.color.value.copy(r.color),e.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function Ps(e,t,n,i){let r={},a={},s=[];const o=e.getParameter(e.MAX_UNIFORM_BUFFER_BINDINGS);function l(e,t,n,i){const r=e.value,a=t+"_"+n;if(void 0===i[a])return i[a]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const e=i[a];if("number"==typeof r||"boolean"==typeof r){if(e!==r)return i[a]=r,!0}else if(!1===e.equals(r))return e.copy(r),!0}return!1}function c(e){const t={boundary:0,storage:0};return"number"==typeof e||"boolean"==typeof e?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),t}function h(t){const n=t.target;n.removeEventListener("dispose",h);const i=s.indexOf(n.__bindingPointIndex);s.splice(i,1),e.deleteBuffer(r[n.id]),delete r[n.id],delete a[n.id]}return{bind:function(e,t){const n=t.program;i.uniformBlockBinding(e,n)},update:function(n,u){let d=r[n.id];void 0===d&&(!function(e){const t=e.uniforms;let n=0;const i=16;for(let e=0,r=t.length;e0&&(n+=i-r);e.__size=n,e.__cache={}}(n),d=function(t){const n=function(){for(let e=0;e0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let f=0;i.toneMapped&&(null!==T&&!0!==T.isXRRenderTarget||(f=_.toneMapping));const g=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,v=void 0!==g?g.length:0,y=le.get(i),x=m.state.lights;if(!0===Z&&(!0===J||e!==I)){const t=e===I&&i.id===P;be.setState(i,e,t)}let b=!1;i.version===y.__version?y.needsLights&&y.lightsStateVersion!==x.state.version||y.outputColorSpace!==o||r.isBatchedMesh&&!1===y.batching?b=!0:r.isBatchedMesh||!0!==y.batching?r.isBatchedMesh&&!0===y.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===y.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===y.instancing?b=!0:r.isInstancedMesh||!0!==y.instancing?r.isSkinnedMesh&&!1===y.skinning?b=!0:r.isSkinnedMesh||!0!==y.skinning?r.isInstancedMesh&&!0===y.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===y.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===y.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===y.instancingMorph&&null!==r.morphTexture||y.envMap!==l||!0===i.fog&&y.fog!==a?b=!0:void 0===y.numClippingPlanes||y.numClippingPlanes===be.numPlanes&&y.numIntersection===be.numIntersection?(y.vertexAlphas!==c||y.vertexTangents!==h||y.morphTargets!==u||y.morphNormals!==d||y.morphColors!==p||y.toneMapping!==f||y.morphTargetsCount!==v)&&(b=!0):b=!0:b=!0:b=!0:b=!0:(b=!0,y.__version=i.version);let M=y.currentProgram;!0===b&&(M=Ye(i,t,r));let S=!1,E=!1,w=!1;const A=M.getUniforms(),R=y.uniforms;se.useProgram(M.program)&&(S=!0,E=!0,w=!0);i.id!==P&&(P=i.id,E=!0);if(S||I!==e){A.setValue(Le,"projectionMatrix",e.projectionMatrix),A.setValue(Le,"viewMatrix",e.matrixWorldInverse);const t=A.map.cameraPosition;void 0!==t&&t.setValue(Le,$.setFromMatrixPosition(e.matrixWorld)),ae.logarithmicDepthBuffer&&A.setValue(Le,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&A.setValue(Le,"isOrthographic",!0===e.isOrthographicCamera),I!==e&&(I=e,E=!0,w=!0)}if(r.isSkinnedMesh){A.setOptional(Le,r,"bindMatrix"),A.setOptional(Le,r,"bindMatrixInverse");const e=r.skeleton;e&&(null===e.boneTexture&&e.computeBoneTexture(),A.setValue(Le,"boneTexture",e.boneTexture,ce))}r.isBatchedMesh&&(A.setOptional(Le,r,"batchingTexture"),A.setValue(Le,"batchingTexture",r._matricesTexture,ce),A.setOptional(Le,r,"batchingIdTexture"),A.setValue(Le,"batchingIdTexture",r._indirectTexture,ce),A.setOptional(Le,r,"batchingColorTexture"),null!==r._colorsTexture&&A.setValue(Le,"batchingColorTexture",r._colorsTexture,ce));const C=n.morphAttributes;void 0===C.position&&void 0===C.normal&&void 0===C.color||Ee.update(r,n,M);(E||y.receiveShadow!==r.receiveShadow)&&(y.receiveShadow=r.receiveShadow,A.setValue(Le,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(R.envMap.value=l,R.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==t.environment&&(R.envMapIntensity.value=t.environmentIntensity);E&&(A.setValue(Le,"toneMappingExposure",_.toneMappingExposure),y.needsLights&&function(e,t){e.ambientLightColor.needsUpdate=t,e.lightProbe.needsUpdate=t,e.directionalLights.needsUpdate=t,e.directionalLightShadows.needsUpdate=t,e.pointLights.needsUpdate=t,e.pointLightShadows.needsUpdate=t,e.spotLights.needsUpdate=t,e.spotLightShadows.needsUpdate=t,e.rectAreaLights.needsUpdate=t,e.hemisphereLights.needsUpdate=t}(R,w),a&&!0===i.fog&&ge.refreshFogUniforms(R,a),ge.refreshMaterialUniforms(R,i,G,V,m.state.transmissionRenderTarget[e.id]),Ua.upload(Le,Ze(y),R,ce));i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(Ua.upload(Le,Ze(y),R,ce),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&A.setValue(Le,"center",r.center);if(A.setValue(Le,"modelViewMatrix",r.modelViewMatrix),A.setValue(Le,"normalMatrix",r.normalMatrix),A.setValue(Le,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const e=i.uniformsGroups;for(let t=0,n=e.length;t{function n(){i.forEach((function(e){le.get(e).currentProgram.isReady()&&i.delete(e)})),0!==i.size?setTimeout(n,10):t(e)}null!==re.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let Be=null;function ze(){Ve.stop()}function He(){Ve.start()}const Ve=new Gi;function Ge(e,t,n,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)n=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)m.pushLight(e),e.castShadow&&m.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||K.intersectsSprite(e)){i&&ee.setFromMatrixPosition(e.matrixWorld).applyMatrix4(Q);const t=fe.update(e),r=e.material;r.visible&&f.push(e,t,r,n,ee.z,null)}}else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||K.intersectsObject(e))){const t=fe.update(e),r=e.material;if(i&&(void 0!==e.boundingSphere?(null===e.boundingSphere&&e.computeBoundingSphere(),ee.copy(e.boundingSphere.center)):(null===t.boundingSphere&&t.computeBoundingSphere(),ee.copy(t.boundingSphere.center)),ee.applyMatrix4(e.matrixWorld).applyMatrix4(Q)),Array.isArray(r)){const i=t.groups;for(let a=0,s=i.length;a0&&Xe(r,t,n),a.length>0&&Xe(a,t,n),s.length>0&&Xe(s,t,n),se.buffers.depth.setTest(!0),se.buffers.depth.setMask(!0),se.buffers.color.setMask(!0),se.setPolygonOffset(!1)}function je(e,t,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===m.state.transmissionRenderTarget[i.id]&&(m.state.transmissionRenderTarget[i.id]=new pt(1,1,{generateMipmaps:!0,type:re.has("EXT_color_buffer_half_float")||re.has("EXT_color_buffer_float")?A:x,minFilter:y,samples:4,stencilBuffer:r,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:nt.workingColorSpace}));const a=m.state.transmissionRenderTarget[i.id],s=i.viewport||N;a.setSize(s.z,s.w);const o=_.getRenderTarget();_.setRenderTarget(a),_.getClearColor(B),z=_.getClearAlpha(),z<1&&_.setClearColor(16777215,.5),_.clear(),ne&&Se.render(n);const l=_.toneMapping;_.toneMapping=0;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),m.setupLightsView(i),!0===Z&&be.setGlobalState(_.clippingPlanes,i),Xe(e,n,i),ce.updateMultisampleRenderTarget(a),ce.updateRenderTargetMipmap(a),!1===re.has("WEBGL_multisampled_render_to_texture")){let e=!1;for(let r=0,a=t.length;r0)for(let t=0,a=n.length;t0&&je(i,r,e,t),ne&&Se.render(e),We(f,e,t);null!==T&&(ce.updateMultisampleRenderTarget(T),ce.updateRenderTargetMipmap(T)),!0===e.isScene&&e.onAfterRender(_,e,t),Re.resetDefaultState(),P=-1,I=null,v.pop(),v.length>0?(m=v[v.length-1],!0===Z&&be.setGlobalState(_.clippingPlanes,m.state.camera)):m=null,g.pop(),f=g.length>0?g[g.length-1]:null},this.getActiveCubeFace=function(){return M},this.getActiveMipmapLevel=function(){return E},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(e,t,n){le.get(e.texture).__webglTexture=t,le.get(e.depthTexture).__webglTexture=n;const i=le.get(e);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===re.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(e,t){const n=le.get(e);n.__webglFramebuffer=t,n.__useDefaultFramebuffer=void 0===t},this.setRenderTarget=function(e,t=0,n=0){T=e,M=t,E=n;let i=!0,r=null,a=!1,s=!1;if(e){const o=le.get(e);void 0!==o.__useDefaultFramebuffer?(se.bindFramebuffer(Le.FRAMEBUFFER,null),i=!1):void 0===o.__webglFramebuffer?ce.setupRenderTarget(e):o.__hasExternalTextures&&ce.rebindTextures(e,le.get(e.texture).__webglTexture,le.get(e.depthTexture).__webglTexture);const l=e.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(s=!0);const c=le.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(r=Array.isArray(c[t])?c[t][n]:c[t],a=!0):r=e.samples>0&&!1===ce.useMultisampledRTT(e)?le.get(e).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,N.copy(e.viewport),U.copy(e.scissor),k=e.scissorTest}else N.copy(X).multiplyScalar(G).floor(),U.copy(q).multiplyScalar(G).floor(),k=Y;if(se.bindFramebuffer(Le.FRAMEBUFFER,r)&&i&&se.drawBuffers(e,r),se.viewport(N),se.scissor(U),se.setScissorTest(k),a){const i=le.get(e.texture);Le.framebufferTexture2D(Le.FRAMEBUFFER,Le.COLOR_ATTACHMENT0,Le.TEXTURE_CUBE_MAP_POSITIVE_X+t,i.__webglTexture,n)}else if(s){const i=le.get(e.texture),r=t||0;Le.framebufferTextureLayer(Le.FRAMEBUFFER,Le.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}P=-1},this.readRenderTargetPixels=function(e,t,n,i,r,a,s){if(!e||!e.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=le.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==s&&(o=o[s]),o){se.bindFramebuffer(Le.FRAMEBUFFER,o);try{const s=e.texture,o=s.format,l=s.type;if(!ae.textureFormatReadable(o))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!ae.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&Le.readPixels(t,n,i,r,Ae.convert(o),Ae.convert(l),a)}finally{const e=null!==T?le.get(T).__webglFramebuffer:null;se.bindFramebuffer(Le.FRAMEBUFFER,e)}}},this.readRenderTargetPixelsAsync=async function(e,t,n,i,r,a,s){if(!e||!e.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=le.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==s&&(o=o[s]),o){se.bindFramebuffer(Le.FRAMEBUFFER,o);try{const s=e.texture,o=s.format,l=s.type;if(!ae.textureFormatReadable(o))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ae.textureTypeReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r){const e=Le.createBuffer();Le.bindBuffer(Le.PIXEL_PACK_BUFFER,e),Le.bufferData(Le.PIXEL_PACK_BUFFER,a.byteLength,Le.STREAM_READ),Le.readPixels(t,n,i,r,Ae.convert(o),Ae.convert(l),0),Le.flush();const s=Le.fenceSync(Le.SYNC_GPU_COMMANDS_COMPLETE,0);await function(e,t,n){return new Promise((function(i,r){setTimeout((function a(){switch(e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0)){case e.WAIT_FAILED:r();break;case e.TIMEOUT_EXPIRED:setTimeout(a,n);break;default:i()}}),n)}))}(Le,s,4);try{Le.bindBuffer(Le.PIXEL_PACK_BUFFER,e),Le.getBufferSubData(Le.PIXEL_PACK_BUFFER,0,a)}finally{Le.deleteBuffer(e),Le.deleteSync(s)}return a}}finally{const e=null!==T?le.get(T).__webglFramebuffer:null;se.bindFramebuffer(Le.FRAMEBUFFER,e)}}},this.copyFramebufferToTexture=function(e,t=null,n=0){!0!==e.isTexture&&(Je("WebGLRenderer: copyFramebufferToTexture function signature has changed."),t=arguments[0]||null,e=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),a=Math.floor(e.image.height*i),s=null!==t?t.x:0,o=null!==t?t.y:0;ce.setTexture2D(e,0),Le.copyTexSubImage2D(Le.TEXTURE_2D,n,0,0,s,o,r,a),se.unbindTexture()},this.copyTextureToTexture=function(e,t,n=null,i=null,r=0){let a,s,o,l,c,h;!0!==e.isTexture&&(Je("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,e=arguments[1],t=arguments[2],r=arguments[3]||0,n=null),null!==n?(a=n.max.x-n.min.x,s=n.max.y-n.min.y,o=n.min.x,l=n.min.y):(a=e.image.width,s=e.image.height,o=0,l=0),null!==i?(c=i.x,h=i.y):(c=0,h=0);const u=Ae.convert(t.format),d=Ae.convert(t.type);ce.setTexture2D(t,0),Le.pixelStorei(Le.UNPACK_FLIP_Y_WEBGL,t.flipY),Le.pixelStorei(Le.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Le.pixelStorei(Le.UNPACK_ALIGNMENT,t.unpackAlignment);const p=Le.getParameter(Le.UNPACK_ROW_LENGTH),f=Le.getParameter(Le.UNPACK_IMAGE_HEIGHT),m=Le.getParameter(Le.UNPACK_SKIP_PIXELS),g=Le.getParameter(Le.UNPACK_SKIP_ROWS),v=Le.getParameter(Le.UNPACK_SKIP_IMAGES),_=e.isCompressedTexture?e.mipmaps[r]:e.image;Le.pixelStorei(Le.UNPACK_ROW_LENGTH,_.width),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,_.height),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,o),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,l),e.isDataTexture?Le.texSubImage2D(Le.TEXTURE_2D,r,c,h,a,s,u,d,_.data):e.isCompressedTexture?Le.compressedTexSubImage2D(Le.TEXTURE_2D,r,c,h,_.width,_.height,u,_.data):Le.texSubImage2D(Le.TEXTURE_2D,r,c,h,a,s,u,d,_),Le.pixelStorei(Le.UNPACK_ROW_LENGTH,p),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,f),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,m),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,g),Le.pixelStorei(Le.UNPACK_SKIP_IMAGES,v),0===r&&t.generateMipmaps&&Le.generateMipmap(Le.TEXTURE_2D),se.unbindTexture()},this.copyTextureToTexture3D=function(e,t,n=null,i=null,r=0){let a,s,o,l,c,h,u,d,p;!0!==e.isTexture&&(Je("WebGLRenderer: copyTextureToTexture3D function signature has changed."),n=arguments[0]||null,i=arguments[1]||null,e=arguments[2],t=arguments[3],r=arguments[4]||0);const f=e.isCompressedTexture?e.mipmaps[r]:e.image;null!==n?(a=n.max.x-n.min.x,s=n.max.y-n.min.y,o=n.max.z-n.min.z,l=n.min.x,c=n.min.y,h=n.min.z):(a=f.width,s=f.height,o=f.depth,l=0,c=0,h=0),null!==i?(u=i.x,d=i.y,p=i.z):(u=0,d=0,p=0);const m=Ae.convert(t.format),g=Ae.convert(t.type);let v;if(t.isData3DTexture)ce.setTexture3D(t,0),v=Le.TEXTURE_3D;else{if(!t.isDataArrayTexture&&!t.isCompressedArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");ce.setTexture2DArray(t,0),v=Le.TEXTURE_2D_ARRAY}Le.pixelStorei(Le.UNPACK_FLIP_Y_WEBGL,t.flipY),Le.pixelStorei(Le.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Le.pixelStorei(Le.UNPACK_ALIGNMENT,t.unpackAlignment);const _=Le.getParameter(Le.UNPACK_ROW_LENGTH),y=Le.getParameter(Le.UNPACK_IMAGE_HEIGHT),x=Le.getParameter(Le.UNPACK_SKIP_PIXELS),b=Le.getParameter(Le.UNPACK_SKIP_ROWS),M=Le.getParameter(Le.UNPACK_SKIP_IMAGES);Le.pixelStorei(Le.UNPACK_ROW_LENGTH,f.width),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,f.height),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,l),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,c),Le.pixelStorei(Le.UNPACK_SKIP_IMAGES,h),e.isDataTexture||e.isData3DTexture?Le.texSubImage3D(v,r,u,d,p,a,s,o,m,g,f.data):t.isCompressedArrayTexture?Le.compressedTexSubImage3D(v,r,u,d,p,a,s,o,m,f.data):Le.texSubImage3D(v,r,u,d,p,a,s,o,m,g,f),Le.pixelStorei(Le.UNPACK_ROW_LENGTH,_),Le.pixelStorei(Le.UNPACK_IMAGE_HEIGHT,y),Le.pixelStorei(Le.UNPACK_SKIP_PIXELS,x),Le.pixelStorei(Le.UNPACK_SKIP_ROWS,b),Le.pixelStorei(Le.UNPACK_SKIP_IMAGES,M),0===r&&t.generateMipmaps&&Le.generateMipmap(v),se.unbindTexture()},this.initRenderTarget=function(e){void 0===le.get(e).__webglFramebuffer&&ce.setupRenderTarget(e)},this.initTexture=function(e){e.isCubeTexture?ce.setTextureCube(e,0):e.isData3DTexture?ce.setTexture3D(e,0):e.isDataArrayTexture||e.isCompressedArrayTexture?ce.setTexture2DArray(e,0):ce.setTexture2D(e,0),se.unbindTexture()},this.resetState=function(){M=0,E=0,T=null,se.reset(),Re.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return Le}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(e){this._outputColorSpace=e;const t=this.getContext();t.drawingBufferColorSpace=e===be?"display-p3":"srgb",t.unpackColorSpace=nt.workingColorSpace===Me?"display-p3":"srgb"}}class Ns extends bn{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new rn,this.environmentIntensity=1,this.environmentRotation=new rn,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class Us{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=Re,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.version=0,this.uuid=Fe()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return Je("THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,n){e*=this.stride,n*=t.stride;for(let i=0,r=this.stride;ie.far||t.push({distance:o,point:Bs.clone(),uv:In.getInterpolation(Bs,js,Xs,qs,Ys,Ks,Zs,new We),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function Qs(e,t,n,i,r,a){Vs.subVectors(e,n).addScalar(.5).multiply(i),void 0!==r?(Gs.x=a*Vs.x-r*Vs.y,Gs.y=r*Vs.x+a*Vs.y):Gs.copy(Vs),e.copy(t),e.x+=Gs.x,e.y+=Gs.y,e.applyMatrix4(Ws)}const $s=new vt,eo=new ut,to=new ut,no=new vt,io=new qt,ro=new vt,ao=new kt,so=new qt,oo=new Xt;class lo extends yi{constructor(e,t){super(e,t),this.isSkinnedMesh=!0,this.type="SkinnedMesh",this.bindMode=l,this.bindMatrix=new qt,this.bindMatrixInverse=new qt,this.boundingBox=null,this.boundingSphere=null}computeBoundingBox(){const e=this.geometry;null===this.boundingBox&&(this.boundingBox=new xt),this.boundingBox.makeEmpty();const t=e.getAttribute("position");for(let e=0;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;ei)return;bo.applyMatrix4(e.matrixWorld);const o=t.ray.origin.distanceTo(bo);return ot.far?void 0:{distance:o,point:Mo.clone().applyMatrix4(e.matrixWorld),index:r,face:null,faceIndex:null,object:e}}const wo=new vt,To=new vt;class Ao extends So{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const e=this.geometry;if(null===e.index){const t=e.attributes.position,n=[];for(let e=0,i=t.count;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;er.far)return;a.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:t,face:null,object:s})}}class Do extends ti{constructor(e=1,t=1,n=1,i=32,r=1,a=!1,s=0,o=2*Math.PI){super(),this.type="CylinderGeometry",this.parameters={radiusTop:e,radiusBottom:t,height:n,radialSegments:i,heightSegments:r,openEnded:a,thetaStart:s,thetaLength:o};const l=this;i=Math.floor(i),r=Math.floor(r);const c=[],h=[],u=[],d=[];let p=0;const f=[],m=n/2;let g=0;function v(n){const r=p,a=new We,f=new vt;let v=0;const _=!0===n?e:t,y=!0===n?1:-1;for(let e=1;e<=i;e++)h.push(0,m*y,0),u.push(0,y,0),d.push(.5,.5),p++;const x=p;for(let e=0;e<=i;e++){const t=e/i*o+s,n=Math.cos(t),r=Math.sin(t);f.x=_*r,f.y=m*y,f.z=_*n,h.push(f.x,f.y,f.z),u.push(0,y,0),a.x=.5*n+.5,a.y=.5*r*y+.5,d.push(a.x,a.y),p++}for(let e=0;e0&&v(!0),t>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new qn(h,3)),this.setAttribute("normal",new qn(u,3)),this.setAttribute("uv",new qn(d,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Do(e.radiusTop,e.radiusBottom,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class Oo extends ti{constructor(e=1,t=32,n=16,i=0,r=2*Math.PI,a=0,s=Math.PI){super(),this.type="SphereGeometry",this.parameters={radius:e,widthSegments:t,heightSegments:n,phiStart:i,phiLength:r,thetaStart:a,thetaLength:s},t=Math.max(3,Math.floor(t)),n=Math.max(2,Math.floor(n));const o=Math.min(a+s,Math.PI);let l=0;const c=[],h=new vt,u=new vt,d=[],p=[],f=[],m=[];for(let d=0;d<=n;d++){const g=[],v=d/n;let _=0;0===d&&0===a?_=.5/t:d===n&&o===Math.PI&&(_=-.5/t);for(let n=0;n<=t;n++){const o=n/t;h.x=-e*Math.cos(i+o*r)*Math.sin(a+v*s),h.y=e*Math.cos(a+v*s),h.z=e*Math.sin(i+o*r)*Math.sin(a+v*s),p.push(h.x,h.y,h.z),u.copy(h).normalize(),f.push(u.x,u.y,u.z),m.push(o+_,1-v),g.push(l++)}c.push(g)}for(let e=0;e0)&&d.push(t,r,l),(e!==n-1||o=r)break e;{const s=t[1];e=r)break t}a=n,n=0}}for(;n>>1;et;)--a;if(++a,0!==r||a!==i){r>=a&&(a=Math.max(a,1),r=a-1);const e=this.getValueSize();this.times=n.slice(r,a),this.values=this.values.slice(r*e,a*e)}return this}validate(){let e=!0;const t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);let a=null;for(let t=0;t!==r;t++){const i=n[t];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,t,i),e=!1;break}if(null!==a&&a>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,t,i,a),e=!1;break}a=i}if(void 0!==i&&(s=i,ArrayBuffer.isView(s)&&!(s instanceof DataView)))for(let t=0,n=i.length;t!==n;++t){const n=i[t];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,t,n),e=!1;break}}var s;return e}optimize(){const e=this.times.slice(),t=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===ve,r=e.length-1;let a=1;for(let s=1;s0){e[a]=e[r];for(let e=r*n,i=a*n,s=0;s!==n;++s)t[i+s]=t[e+s];++a}return a!==e.length?(this.times=e.slice(0,a),this.values=t.slice(0,a*n)):(this.times=e,this.values=t),this}clone(){const e=this.times.slice(),t=this.values.slice(),n=new(0,this.constructor)(this.name,e,t);return n.createInterpolant=this.createInterpolant,n}}qo.prototype.TimeBufferType=Float32Array,qo.prototype.ValueBufferType=Float32Array,qo.prototype.DefaultInterpolation=ge;class Yo extends qo{constructor(e,t,n){super(e,t,n)}}Yo.prototype.ValueTypeName="bool",Yo.prototype.ValueBufferType=Array,Yo.prototype.DefaultInterpolation=me,Yo.prototype.InterpolantFactoryMethodLinear=void 0,Yo.prototype.InterpolantFactoryMethodSmooth=void 0;class Ko extends qo{}Ko.prototype.ValueTypeName="color";class Zo extends qo{}Zo.prototype.ValueTypeName="number";class Jo extends Go{constructor(e,t,n,i){super(e,t,n,i)}interpolate_(e,t,n,i){const r=this.resultBuffer,a=this.sampleValues,s=this.valueSize,o=(n-t)/(i-t);let l=e*s;for(let e=l+s;l!==e;l+=4)gt.slerpFlat(r,0,a,l-s,a,l,o);return r}}class Qo extends qo{InterpolantFactoryMethodLinear(e){return new Jo(this.times,this.values,this.getValueSize(),e)}}Qo.prototype.ValueTypeName="quaternion",Qo.prototype.InterpolantFactoryMethodSmooth=void 0;class $o extends qo{constructor(e,t,n){super(e,t,n)}}$o.prototype.ValueTypeName="string",$o.prototype.ValueBufferType=Array,$o.prototype.DefaultInterpolation=me,$o.prototype.InterpolantFactoryMethodLinear=void 0,$o.prototype.InterpolantFactoryMethodSmooth=void 0;class el extends qo{}el.prototype.ValueTypeName="vector";class tl{constructor(e="",t=-1,n=[],i=2500){this.name=e,this.tracks=n,this.duration=t,this.blendMode=i,this.uuid=Fe(),this.duration<0&&this.resetDuration()}static parse(e){const t=[],n=e.tracks,i=1/(e.fps||1);for(let e=0,r=n.length;e!==r;++e)t.push(nl(n[e]).scale(i));const r=new this(e.name,e.duration,t,e.blendMode);return r.uuid=e.uuid,r}static toJSON(e){const t=[],n=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,i=n.length;e!==i;++e)t.push(qo.toJSON(n[e]));return i}static CreateFromMorphTargetSequence(e,t,n,i){const r=t.length,a=[];for(let e=0;e1){const e=a[1];let t=i[e];t||(i[e]=t=[]),t.push(n)}}const a=[];for(const e in i)a.push(this.CreateFromMorphTargetSequence(e,i[e],t,n));return a}static parseAnimation(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(e,t,n,i,r){if(0!==n.length){const a=[],s=[];Vo(n,a,s,i),0!==a.length&&r.push(new e(t,a,s))}},i=[],r=e.name||"default",a=e.fps||30,s=e.blendMode;let o=e.length||-1;const l=e.hierarchy||[];for(let e=0;e{t&&t(r),this.manager.itemEnd(e)}),0),r;if(void 0!==ol[e])return void ol[e].push({onLoad:t,onProgress:n,onError:i});ol[e]=[],ol[e].push({onLoad:t,onProgress:n,onError:i});const a=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),s=this.mimeType,o=this.responseType;fetch(a).then((t=>{if(200===t.status||0===t.status){if(0===t.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===t.body||void 0===t.body.getReader)return t;const n=ol[e],i=t.body.getReader(),r=t.headers.get("X-File-Size")||t.headers.get("Content-Length"),a=r?parseInt(r):0,s=0!==a;let o=0;const l=new ReadableStream({start(e){!function t(){i.read().then((({done:i,value:r})=>{if(i)e.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:s,loaded:o,total:a});for(let e=0,t=n.length;e{e.error(t)}))}()}});return new Response(l)}throw new ll(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)})).then((e=>{switch(o){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((e=>(new DOMParser).parseFromString(e,s)));case"json":return e.json();default:if(void 0===s)return e.text();{const t=/charset="?([^;"\s]*)"?/i.exec(s),n=t&&t[1]?t[1].toLowerCase():void 0,i=new TextDecoder(n);return e.arrayBuffer().then((e=>i.decode(e)))}}})).then((t=>{il.add(e,t);const n=ol[e];delete ol[e];for(let e=0,i=n.length;e{const n=ol[e];if(void 0===n)throw this.manager.itemError(e),t;delete ol[e];for(let e=0,i=n.length;e{this.manager.itemEnd(e)})),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}}class hl extends sl{constructor(e){super(e)}load(e,t,n,i){void 0!==this.path&&(e=this.path+e),e=this.manager.resolveURL(e);const r=this,a=il.get(e);if(void 0!==a)return r.manager.itemStart(e),setTimeout((function(){t&&t(a),r.manager.itemEnd(e)}),0),a;const s=Ye("img");function o(){c(),il.add(e,this),t&&t(this),r.manager.itemEnd(e)}function l(t){c(),i&&i(t),r.manager.itemError(e),r.manager.itemEnd(e)}function c(){s.removeEventListener("load",o,!1),s.removeEventListener("error",l,!1)}return s.addEventListener("load",o,!1),s.addEventListener("error",l,!1),"data:"!==e.slice(0,5)&&void 0!==this.crossOrigin&&(s.crossOrigin=this.crossOrigin),r.manager.itemStart(e),s.src=e,s}}class ul extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=new ho,s=new cl(this.manager);return s.setResponseType("arraybuffer"),s.setRequestHeader(this.requestHeader),s.setPath(this.path),s.setWithCredentials(r.withCredentials),s.load(e,(function(e){let n;try{n=r.parse(e)}catch(e){if(void 0===i)return void console.error(e);i(e)}void 0!==n.image?a.image=n.image:void 0!==n.data&&(a.image.width=n.width,a.image.height=n.height,a.image.data=n.data),a.wrapS=void 0!==n.wrapS?n.wrapS:p,a.wrapT=void 0!==n.wrapT?n.wrapT:p,a.magFilter=void 0!==n.magFilter?n.magFilter:v,a.minFilter=void 0!==n.minFilter?n.minFilter:v,a.anisotropy=void 0!==n.anisotropy?n.anisotropy:1,void 0!==n.colorSpace&&(a.colorSpace=n.colorSpace),void 0!==n.flipY&&(a.flipY=n.flipY),void 0!==n.format&&(a.format=n.format),void 0!==n.type&&(a.type=n.type),void 0!==n.mipmaps&&(a.mipmaps=n.mipmaps,a.minFilter=y),1===n.mipmapCount&&(a.minFilter=v),void 0!==n.generateMipmaps&&(a.generateMipmaps=n.generateMipmaps),a.needsUpdate=!0,t&&t(a,n)}),n,i),a}}class dl extends sl{constructor(e){super(e)}load(e,t,n,i){const r=new ht,a=new hl(this.manager);return a.setCrossOrigin(this.crossOrigin),a.setPath(this.path),a.load(e,(function(e){r.image=e,r.needsUpdate=!0,void 0!==t&&t(r)}),n,i),r}}class pl extends bn{constructor(e,t=1){super(),this.isLight=!0,this.type="Light",this.color=new Fn(e),this.intensity=t}dispose(){}copy(e,t){return super.copy(e,t),this.color.copy(e.color),this.intensity=e.intensity,this}toJSON(e){const t=super.toJSON(e);return t.object.color=this.color.getHex(),t.object.intensity=this.intensity,void 0!==this.groundColor&&(t.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(t.object.distance=this.distance),void 0!==this.angle&&(t.object.angle=this.angle),void 0!==this.decay&&(t.object.decay=this.decay),void 0!==this.penumbra&&(t.object.penumbra=this.penumbra),void 0!==this.shadow&&(t.object.shadow=this.shadow.toJSON()),void 0!==this.target&&(t.object.target=this.target.uuid),t}}const fl=new qt,ml=new vt,gl=new vt;class vl{constructor(e){this.camera=e,this.intensity=1,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new We(512,512),this.map=null,this.mapPass=null,this.matrix=new qt,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Vi,this._frameExtents=new We(1,1),this._viewportCount=1,this._viewports=[new ut(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(e){const t=this.camera,n=this.matrix;ml.setFromMatrixPosition(e.matrixWorld),t.position.copy(ml),gl.setFromMatrixPosition(e.target.matrixWorld),t.lookAt(gl),t.updateMatrixWorld(),fl.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this._frustum.setFromProjectionMatrix(fl),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(fl)}getViewport(e){return this._viewports[e]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(e){return this.camera=e.camera.clone(),this.intensity=e.intensity,this.bias=e.bias,this.radius=e.radius,this.mapSize.copy(e.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const e={};return 1!==this.intensity&&(e.intensity=this.intensity),0!==this.bias&&(e.bias=this.bias),0!==this.normalBias&&(e.normalBias=this.normalBias),1!==this.radius&&(e.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(e.mapSize=this.mapSize.toArray()),e.camera=this.camera.toJSON(!1).object,delete e.camera.matrix,e}}class _l extends vl{constructor(){super(new Pi(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(e){const t=this.camera,n=2*Oe*e.angle*this.focus,i=this.mapSize.width/this.mapSize.height,r=e.distance||t.far;n===t.fov&&i===t.aspect&&r===t.far||(t.fov=n,t.aspect=i,t.far=r,t.updateProjectionMatrix()),super.updateMatrices(e)}copy(e){return super.copy(e),this.focus=e.focus,this}}class yl extends pl{constructor(e,t,n=0,i=Math.PI/3,r=0,a=2){super(e,t),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(bn.DEFAULT_UP),this.updateMatrix(),this.target=new bn,this.distance=n,this.angle=i,this.penumbra=r,this.decay=a,this.map=null,this.shadow=new _l}get power(){return this.intensity*Math.PI}set power(e){this.intensity=e/Math.PI}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.angle=e.angle,this.penumbra=e.penumbra,this.decay=e.decay,this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}}const xl=new qt,bl=new vt,Ml=new vt;class Sl extends vl{constructor(){super(new Pi(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new We(4,2),this._viewportCount=6,this._viewports=[new ut(2,1,1,1),new ut(0,1,1,1),new ut(3,1,1,1),new ut(1,1,1,1),new ut(3,0,1,1),new ut(1,0,1,1)],this._cubeDirections=[new vt(1,0,0),new vt(-1,0,0),new vt(0,0,1),new vt(0,0,-1),new vt(0,1,0),new vt(0,-1,0)],this._cubeUps=[new vt(0,1,0),new vt(0,1,0),new vt(0,1,0),new vt(0,1,0),new vt(0,0,1),new vt(0,0,-1)]}updateMatrices(e,t=0){const n=this.camera,i=this.matrix,r=e.distance||n.far;r!==n.far&&(n.far=r,n.updateProjectionMatrix()),bl.setFromMatrixPosition(e.matrixWorld),n.position.copy(bl),Ml.copy(n.position),Ml.add(this._cubeDirections[t]),n.up.copy(this._cubeUps[t]),n.lookAt(Ml),n.updateMatrixWorld(),i.makeTranslation(-bl.x,-bl.y,-bl.z),xl.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(xl)}}class El extends pl{constructor(e,t,n=0,i=2){super(e,t),this.isPointLight=!0,this.type="PointLight",this.distance=n,this.decay=i,this.shadow=new Sl}get power(){return 4*this.intensity*Math.PI}set power(e){this.intensity=e/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.decay=e.decay,this.shadow=e.shadow.clone(),this}}class wl extends vl{constructor(){super(new rr(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Tl extends pl{constructor(e,t){super(e,t),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(bn.DEFAULT_UP),this.updateMatrix(),this.target=new bn,this.shadow=new wl}dispose(){this.shadow.dispose()}copy(e){return super.copy(e),this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}}class Al extends pl{constructor(e,t){super(e,t),this.isAmbientLight=!0,this.type="AmbientLight"}}class Rl{static decodeText(e){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(e);let t="";for(let n=0,i=e.length;n.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{Nl.set(e.z,0,-e.x).normalize();const t=Math.acos(e.y);this.quaternion.setFromAxisAngle(Nl,t)}}setLength(e,t=.2*e,n=.2*t){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(n,t,n),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:r}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=r);var Fl=function(e,t,n,i){var r=new Fn;return r.setRGB(e,t,n),i<=.99?new Hn({color:r.getHex(),opacity:i+.1,transparent:!0,depthWrite:!0,blendSrc:s,blendDst:o,blendEquation:102,blending:1}):new Fo({color:r.getHex(),opacity:i,blending:1})},kl=function(e,t,n){var i=new vt,r=new vt;i.subVectors(t,e.origin);var a=e.direction.dot(n);if(!(Math.abs(a)0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),"," (- z + zOffset / 1000.0) * maxDepthPerTile,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),n.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n"),n}return Kl(t,e),jl(t,[{key:"metaLoaded",value:function(){this.metaLoaded=!0,this.initStreamer()}},{key:"initStreamer",value:function(){var e=this;if(this.metaLoaded){this.texture=new ht(this.video),this.geometry=new ti;for(var t=0,n=this.width*this.height;t256||24!==e.colormap_size||1!==e.colormap_type)throw new Error("THREE.TGALoader: Invalid type colormap data for indexed type.");break;case i:case r:case s:case o:if(e.colormap_type)throw new Error("THREE.TGALoader: Invalid type colormap data for colormap type.");break;case t:throw new Error("THREE.TGALoader: No data.");default:throw new Error("THREE.TGALoader: Invalid type "+e.image_type)}if(e.width<=0||e.height<=0)throw new Error("THREE.TGALoader: Invalid image size.");if(8!==e.pixel_size&&16!==e.pixel_size&&24!==e.pixel_size&&32!==e.pixel_size)throw new Error("THREE.TGALoader: Invalid pixel size "+e.pixel_size)}(g),g.id_length+f>e.length)throw new Error("THREE.TGALoader: No data.");f+=g.id_length;let v=!1,_=!1,x=!1;switch(g.image_type){case a:v=!0,_=!0;break;case n:_=!0;break;case s:v=!0;break;case i:break;case o:v=!0,x=!0;break;case r:x=!0}const b=new Uint8Array(g.width*g.height*4),M=function(e,t,n,i,r){let a,s;const o=n.pixel_size>>3,l=n.width*n.height*o;if(t&&(s=r.subarray(i,i+=n.colormap_length*(n.colormap_size>>3))),e){let e,t,n;a=new Uint8Array(l);let s=0;const c=new Uint8Array(o);for(;s>c){default:case d:a=0,o=1,m=t,s=0,f=1,v=n;break;case h:a=0,o=1,m=t,s=n-1,f=-1,v=-1;break;case p:a=t-1,o=-1,m=-1,s=0,f=1,v=n;break;case u:a=t-1,o=-1,m=-1,s=n-1,f=-1,v=-1}if(x)switch(g.pixel_size){case 8:!function(e,t,n,i,r,a,s,o){let l,c,h,u=0;const d=g.width;for(h=t;h!==i;h+=n)for(c=r;c!==s;c+=a,u++)l=o[u],e[4*(c+d*h)+0]=l,e[4*(c+d*h)+1]=l,e[4*(c+d*h)+2]=l,e[4*(c+d*h)+3]=255}(e,s,f,v,a,o,m,i);break;case 16:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=2)e[4*(l+u*c)+0]=o[h+0],e[4*(l+u*c)+1]=o[h+0],e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+3]=o[h+1]}(e,s,f,v,a,o,m,i);break;default:throw new Error("THREE.TGALoader: Format not supported.")}else switch(g.pixel_size){case 8:!function(e,t,n,i,r,a,s,o,l){const c=l;let h,u,d,p=0;const f=g.width;for(d=t;d!==i;d+=n)for(u=r;u!==s;u+=a,p++)h=o[p],e[4*(u+f*d)+3]=255,e[4*(u+f*d)+2]=c[3*h+0],e[4*(u+f*d)+1]=c[3*h+1],e[4*(u+f*d)+0]=c[3*h+2]}(e,s,f,v,a,o,m,i,r);break;case 16:!function(e,t,n,i,r,a,s,o){let l,c,h,u=0;const d=g.width;for(h=t;h!==i;h+=n)for(c=r;c!==s;c+=a,u+=2)l=o[u+0]+(o[u+1]<<8),e[4*(c+d*h)+0]=(31744&l)>>7,e[4*(c+d*h)+1]=(992&l)>>2,e[4*(c+d*h)+2]=(31&l)<<3,e[4*(c+d*h)+3]=32768&l?0:255}(e,s,f,v,a,o,m,i);break;case 24:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=3)e[4*(l+u*c)+3]=255,e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+1]=o[h+1],e[4*(l+u*c)+0]=o[h+2]}(e,s,f,v,a,o,m,i);break;case 32:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=4)e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+1]=o[h+1],e[4*(l+u*c)+0]=o[h+2],e[4*(l+u*c)+3]=o[h+3]}(e,s,f,v,a,o,m,i);break;default:throw new Error("THREE.TGALoader: Format not supported.")}}(b,g.width,g.height,M.pixel_data,M.palettes),{data:b,width:g.width,height:g.height,flipY:!0,generateMipmaps:!0,minFilter:y}}}function ac(e,t,n){return t=ql(t),Xl(e,sc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function sc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(sc=function(){return!!e})()}var oc=function(e){function t(){return Hl(this,t),ac(this,t,arguments)}return Kl(t,e),jl(t,[{key:"load",value:function(e,t,n,i){var r=this,a=""===r.path?Rl.extractUrlBase(e):r.path,s=new cl(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(e,(function(n){try{t(r.parse(n,a))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}},{key:"parse",value:function(e,t){function n(e,t){for(var n=[],i=e.childNodes,r=0,a=i.length;r0&&t.push(new el(i+".position",r,a)),s.length>0&&t.push(new Qo(i+".quaternion",r,s)),o.length>0&&t.push(new el(i+".scale",r,o)),t}function E(e,t,n){var i,r,a,s=!0;for(r=0,a=e.length;r=0;){var i=e[t];if(null!==i.value[n])return i;t--}return null}function T(e,t,n){for(;t>>0));if("tga"===(n=n.toLowerCase()))t=Je;else t=$e;return t}function J(e){var t,n,i=(t=e.url,f(rt.effects[t],K)),r=i.profile.technique;switch(r.type){case"phong":case"blinn":n=new Fo;break;case"lambert":n=new ko;break;default:n=new Hn}function a(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=i.profile.samplers[e.id],r=null;if(void 0!==n){var a=i.profile.surfaces[n.source];r=D(a.init_from)}else console.warn("THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530)."),r=D(e.id);if(null!==r){var s=Z(r);if(void 0!==s){var l=s.load(r),c=e.extra;if(void 0!==c&&void 0!==c.technique&&!1===o(c.technique)){var h=c.technique;l.wrapS=h.wrapU?d:p,l.wrapT=h.wrapV?d:p,l.offset.set(h.offsetU||0,h.offsetV||0),l.repeat.set(h.repeatU||1,h.repeatV||1)}else l.wrapS=d,l.wrapT=d;return null!==t&&(l.colorSpace=t),l}return console.warn("THREE.ColladaLoader: Loader for texture %s not found.",r),null}return console.warn("THREE.ColladaLoader: Couldn't create texture with ID:",e.id),null}n.name=e.name||"";var s=r.parameters;for(var l in s){var c=s[l];switch(l){case"diffuse":c.color&&n.color.fromArray(c.color),c.texture&&(n.map=a(c.texture,ye));break;case"specular":c.color&&n.specular&&n.specular.fromArray(c.color),c.texture&&(n.specularMap=a(c.texture));break;case"bump":c.texture&&(n.normalMap=a(c.texture));break;case"ambient":c.texture&&(n.lightMap=a(c.texture,ye));break;case"shininess":c.float&&n.shininess&&(n.shininess=c.float);break;case"emission":c.color&&n.emissive&&n.emissive.fromArray(c.color),c.texture&&(n.emissiveMap=a(c.texture,ye))}}n.color.convertSRGBToLinear(),n.specular&&n.specular.convertSRGBToLinear(),n.emissive&&n.emissive.convertSRGBToLinear();var h=s.transparent,u=s.transparency;if(void 0===u&&h&&(u={float:1}),void 0===h&&u&&(h={opaque:"A_ONE",data:{color:[1,1,1,1]}}),h&&u)if(h.data.texture)n.transparent=!0;else{var m=h.data.color;switch(h.opaque){case"A_ONE":n.opacity=m[3]*u.float;break;case"RGB_ZERO":n.opacity=1-m[0]*u.float;break;case"A_ZERO":n.opacity=1-m[3]*u.float;break;case"RGB_ONE":n.opacity=m[0]*u.float;break;default:console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.',h.opaque)}n.opacity<1&&(n.transparent=!0)}if(void 0!==r.extra&&void 0!==r.extra.technique){var g=r.extra.technique;for(var v in g){var _=g[v];switch(v){case"double_sided":n.side=1===_?2:0;break;case"bump":n.normalMap=a(_.texture),n.normalScale=new We(1,1)}}}return n}function Q(e){return f(rt.materials[e],J)}function $(e){for(var t=0;t0?l+h:l;t.inputs[u]={id:o,offset:c},t.stride=Math.max(t.stride,c+1),"TEXCOORD"===l&&(t.hasUV=!0);break;case"vcount":t.vcount=a(r.textContent);break;case"p":t.p=a(r.textContent)}}return t}function ue(e){for(var t=0,n=0,i=e.length;n0&&t0&&p.setAttribute("position",new qn(r.array,r.stride)),a.array.length>0&&p.setAttribute("normal",new qn(a.array,a.stride)),l.array.length>0&&p.setAttribute("color",new qn(l.array,l.stride)),s.array.length>0&&p.setAttribute("uv",new qn(s.array,s.stride)),o.array.length>0&&p.setAttribute("uv1",new qn(o.array,o.stride)),c.length>0&&p.setAttribute("skinIndex",new qn(c,h)),u.length>0&&p.setAttribute("skinWeight",new qn(u,d)),i.data=p,i.type=e[0].type,i.materialKeys=f,i}function fe(e,t,n,i){var r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],a=e.p,s=e.stride,o=e.vcount;function l(e){for(var t=a[e+n]*h,s=t+h;t4)for(var M=1,S=f-2;M<=S;M++){var E=u+0*s,w=u+s*M,T=u+s*(M+1);l(E),l(w),l(T)}u+=s*f}else for(var A=0,R=a.length;A=t.limits.max&&(t.static=!0),t.middlePosition=(t.limits.min+t.limits.max)/2,t}function be(e){for(var t={sid:e.getAttribute("sid"),name:e.getAttribute("name")||"",attachments:[],transforms:[]},n=0;ni.limits.max||t0?t[t.length-1]:"",smooth:void 0!==n?n.smooth:this.smooth,groupStart:void 0!==n?n.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(e){const t={index:"number"==typeof e?e:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return t.clone=this.clone.bind(t),t}};return this.materials.push(i),i},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(e){const t=this.currentMaterial();if(t&&-1===t.groupEnd&&(t.groupEnd=this.geometry.vertices.length/3,t.groupCount=t.groupEnd-t.groupStart,t.inherited=!1),e&&this.materials.length>1)for(let e=this.materials.length-1;e>=0;e--)this.materials[e].groupCount<=0&&this.materials.splice(e,1);return e&&0===this.materials.length&&this.materials.push({name:"",smooth:this.smooth}),t}},n&&n.name&&"function"==typeof n.clone){const e=n.clone(0);e.inherited=!0,this.object.materials.push(e)}this.objects.push(this.object)},finalize:function(){this.object&&"function"==typeof this.object._finalize&&this.object._finalize(!0)},parseVertexIndex:function(e,t){const n=parseInt(e,10);return 3*(n>=0?n-1:n+t/3)},parseNormalIndex:function(e,t){const n=parseInt(e,10);return 3*(n>=0?n-1:n+t/3)},parseUVIndex:function(e,t){const n=parseInt(e,10);return 2*(n>=0?n-1:n+t/2)},addVertex:function(e,t,n){const i=this.vertices,r=this.object.geometry.vertices;r.push(i[e+0],i[e+1],i[e+2]),r.push(i[t+0],i[t+1],i[t+2]),r.push(i[n+0],i[n+1],i[n+2])},addVertexPoint:function(e){const t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){const t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,n){const i=this.normals,r=this.object.geometry.normals;r.push(i[e+0],i[e+1],i[e+2]),r.push(i[t+0],i[t+1],i[t+2]),r.push(i[n+0],i[n+1],i[n+2])},addFaceNormal:function(e,t,n){const i=this.vertices,r=this.object.geometry.normals;pc.fromArray(i,e),fc.fromArray(i,t),mc.fromArray(i,n),vc.subVectors(mc,fc),gc.subVectors(pc,fc),vc.cross(gc),vc.normalize(),r.push(vc.x,vc.y,vc.z),r.push(vc.x,vc.y,vc.z),r.push(vc.x,vc.y,vc.z)},addColor:function(e,t,n){const i=this.colors,r=this.object.geometry.colors;void 0!==i[e]&&r.push(i[e+0],i[e+1],i[e+2]),void 0!==i[t]&&r.push(i[t+0],i[t+1],i[t+2]),void 0!==i[n]&&r.push(i[n+0],i[n+1],i[n+2])},addUV:function(e,t,n){const i=this.uvs,r=this.object.geometry.uvs;r.push(i[e+0],i[e+1]),r.push(i[t+0],i[t+1]),r.push(i[n+0],i[n+1])},addDefaultUV:function(){const e=this.object.geometry.uvs;e.push(0,0),e.push(0,0),e.push(0,0)},addUVLine:function(e){const t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,n,i,r,a,s,o,l){const c=this.vertices.length;let h=this.parseVertexIndex(e,c),u=this.parseVertexIndex(t,c),d=this.parseVertexIndex(n,c);if(this.addVertex(h,u,d),this.addColor(h,u,d),void 0!==s&&""!==s){const e=this.normals.length;h=this.parseNormalIndex(s,e),u=this.parseNormalIndex(o,e),d=this.parseNormalIndex(l,e),this.addNormal(h,u,d)}else this.addFaceNormal(h,u,d);if(void 0!==i&&""!==i){const e=this.uvs.length;h=this.parseUVIndex(i,e),u=this.parseUVIndex(r,e),d=this.parseUVIndex(a,e),this.addUV(h,u,d),this.object.geometry.hasUVIndices=!0}else this.addDefaultUV()},addPointGeometry:function(e){this.object.geometry.type="Points";const t=this.vertices.length;for(let n=0,i=e.length;n=7?(_c.setRGB(parseFloat(e[4]),parseFloat(e[5]),parseFloat(e[6])).convertSRGBToLinear(),t.colors.push(_c.r,_c.g,_c.b)):t.colors.push(void 0,void 0,void 0);break;case"vn":t.normals.push(parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3]));break;case"vt":t.uvs.push(parseFloat(e[1]),parseFloat(e[2]))}}else if("f"===a){const e=r.slice(1).trim().split(dc),n=[];for(let t=0,i=e.length;t0){const e=i.split("/");n.push(e)}}const i=n[0];for(let e=1,r=n.length-1;e1){const e=i[1].trim().toLowerCase();t.object.smooth="0"!==e&&"off"!==e}else t.object.smooth=!0;const e=t.object.currentMaterial();e&&(e.smooth=t.object.smooth)}else{if("\0"===r)continue;console.warn('THREE.OBJLoader: Unexpected line: "'+r+'"')}}t.finalize();const r=new Ss;r.materialLibraries=[].concat(t.materialLibraries);if(!0===!(1===t.objects.length&&0===t.objects[0].geometry.vertices.length))for(let e=0,n=t.objects.length;e0&&c.setAttribute("normal",new qn(i.normals,3)),i.colors.length>0&&(l=!0,c.setAttribute("color",new qn(i.colors,3))),!0===i.hasUVIndices&&c.setAttribute("uv",new qn(i.uvs,2));const h=[];for(let e=0,n=a.length;e1){for(let e=0,t=a.length;e0){const e=new Ro({size:1,sizeAttenuation:!1}),n=new ti;n.setAttribute("position",new qn(t.vertices,3)),t.colors.length>0&&void 0!==t.colors[0]&&(n.setAttribute("color",new qn(t.colors,3)),e.vertexColors=!0);const i=new No(n,e);r.add(i)}return r}}class bc extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=new cl(this.manager);a.setPath(this.path),a.setResponseType("arraybuffer"),a.setRequestHeader(this.requestHeader),a.setWithCredentials(this.withCredentials),a.load(e,(function(n){try{t(r.parse(n))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}parse(e){function t(e,t,n){for(let i=0,r=e.length;i>5&31)/31,a=(e>>10&31)/31):(i=o,r=l,a=c)}for(let o=1;o<=3;o++){const l=n+12*o,c=3*e*3+3*(o-1);p[c]=t.getFloat32(l,!0),p[c+1]=t.getFloat32(l+4,!0),p[c+2]=t.getFloat32(l+8,!0),f[c]=h,f[c+1]=d,f[c+2]=g,u&&(m.set(i,r,a).convertSRGBToLinear(),s[c]=m.r,s[c+1]=m.g,s[c+2]=m.b)}}return d.setAttribute("position",new Wn(p,3)),d.setAttribute("normal",new Wn(f,3)),u&&(d.setAttribute("color",new Wn(s,3)),d.hasColors=!0,d.alpha=h),d}(n):function(e){const t=new ti,n=/solid([\s\S]*?)endsolid/g,i=/facet([\s\S]*?)endfacet/g,r=/solid\s(.+)/;let a=0;const s=/[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source,o=new RegExp("vertex"+s+s+s,"g"),l=new RegExp("normal"+s+s+s,"g"),c=[],h=[],u=[],d=new vt;let p,f=0,m=0,g=0;for(;null!==(p=n.exec(e));){m=g;const e=p[0],n=null!==(p=r.exec(e))?p[1]:"";for(u.push(n);null!==(p=i.exec(e));){let e=0,t=0;const n=p[0];for(;null!==(p=l.exec(n));)d.x=parseFloat(p[1]),d.y=parseFloat(p[2]),d.z=parseFloat(p[3]),t++;for(;null!==(p=o.exec(n));)c.push(parseFloat(p[1]),parseFloat(p[2]),parseFloat(p[3])),h.push(d.x,d.y,d.z),e++,g++;1!==t&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+a),3!==e&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+a),a++}const s=m,v=g-m;t.userData.groupNames=u,t.addGroup(s,v,f),f++}return t.setAttribute("position",new qn(c,3)),t.setAttribute("normal",new qn(h,3)),t}("string"!=typeof(i=e)?(new TextDecoder).decode(i):i);var i}}class Mc extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=""===this.path?Rl.extractUrlBase(e):this.path,s=new cl(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(e,(function(n){try{t(r.parse(n,a))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}setMaterialOptions(e){return this.materialOptions=e,this}parse(e,t){const n=e.split("\n");let i={};const r=/\s+/,a={};for(let e=0;e=0?t.substring(0,s):t;o=o.toLowerCase();let l=s>=0?t.substring(s+1):"";if(l=l.trim(),"newmtl"===o)i={name:l},a[l]=i;else if("ka"===o||"kd"===o||"ks"===o||"ke"===o){const e=l.split(r,3);i[o]=[parseFloat(e[0]),parseFloat(e[1]),parseFloat(e[2])]}else i[o]=l}const s=new Sc(this.resourcePath||t,this.materialOptions);return s.setCrossOrigin(this.crossOrigin),s.setManager(this.manager),s.setMaterials(a),s}}class Sc{constructor(e="",t={}){this.baseUrl=e,this.options=t,this.materialsInfo={},this.materials={},this.materialsArray=[],this.nameLookup={},this.crossOrigin="anonymous",this.side=void 0!==this.options.side?this.options.side:0,this.wrap=void 0!==this.options.wrap?this.options.wrap:d}setCrossOrigin(e){return this.crossOrigin=e,this}setManager(e){this.manager=e}setMaterials(e){this.materialsInfo=this.convert(e),this.materials={},this.materialsArray=[],this.nameLookup={}}convert(e){if(!this.options)return e;const t={};for(const n in e){const i=e[n],r={};t[n]=r;for(const e in i){let t=!0,n=i[e];const a=e.toLowerCase();switch(a){case"kd":case"ka":case"ks":this.options&&this.options.normalizeRGB&&(n=[n[0]/255,n[1]/255,n[2]/255]),this.options&&this.options.ignoreZeroRGBs&&0===n[0]&&0===n[1]&&0===n[2]&&(t=!1)}t&&(r[a]=n)}}return t}preload(){for(const e in this.materialsInfo)this.create(e)}getIndex(e){return this.nameLookup[e]}getAsArray(){let e=0;for(const t in this.materialsInfo)this.materialsArray[e]=this.create(t),this.nameLookup[t]=e,e++;return this.materialsArray}create(e){return void 0===this.materials[e]&&this.createMaterial_(e),this.materials[e]}createMaterial_(e){const t=this,n=this.materialsInfo[e],i={name:e,side:this.side};function r(e,n){if(i[e])return;const r=t.getTextureParams(n,i),a=t.loadTexture((s=t.baseUrl,"string"!=typeof(o=r.url)||""===o?"":/^https?:\/\//i.test(o)?o:s+o));var s,o;a.repeat.copy(r.scale),a.offset.copy(r.offset),a.wrapS=t.wrap,a.wrapT=t.wrap,"map"!==e&&"emissiveMap"!==e||(a.colorSpace=ye),i[e]=a}for(const e in n){const t=n[e];let a;if(""!==t)switch(e.toLowerCase()){case"kd":i.color=(new Fn).fromArray(t).convertSRGBToLinear();break;case"ks":i.specular=(new Fn).fromArray(t).convertSRGBToLinear();break;case"ke":i.emissive=(new Fn).fromArray(t).convertSRGBToLinear();break;case"map_kd":r("map",t);break;case"map_ks":r("specularMap",t);break;case"map_ke":r("emissiveMap",t);break;case"norm":r("normalMap",t);break;case"map_bump":case"bump":r("bumpMap",t);break;case"map_d":r("alphaMap",t),i.transparent=!0;break;case"ns":i.shininess=parseFloat(t);break;case"d":a=parseFloat(t),a<1&&(i.opacity=a,i.transparent=!0);break;case"tr":a=parseFloat(t),this.options&&this.options.invertTrProperty&&(a=1-a),a>0&&(i.opacity=1-a,i.transparent=!0)}}return this.materials[e]=new Fo(i),this.materials[e]}getTextureParams(e,t){const n={scale:new We(1,1),offset:new We(0,0)},i=e.split(/\s+/);let r;return r=i.indexOf("-bm"),r>=0&&(t.bumpScale=parseFloat(i[r+1]),i.splice(r,2)),r=i.indexOf("-s"),r>=0&&(n.scale.set(parseFloat(i[r+1]),parseFloat(i[r+2])),i.splice(r,4)),r=i.indexOf("-o"),r>=0&&(n.offset.set(parseFloat(i[r+1]),parseFloat(i[r+2])),i.splice(r,4)),n.url=i.join(" ").trim(),n}loadTexture(e,t,n,i,r){const a=void 0!==this.manager?this.manager:al;let s=a.getHandler(e);null===s&&(s=new dl(a)),s.setCrossOrigin&&s.setCrossOrigin(this.crossOrigin);const o=s.load(e,n,i,r);return void 0!==t&&(o.mapping=t),o}}var Ec={onError:function(e){console.error(e)},loaders:{dae:function(e,t,n){var i=new oc(n.loader);return console.log("Loading collada: "+t),i.load(t,(function(t){var n=t.scene;e.add(n),console.log("Done loading collada")})),i.log=function(t){e.warnings&&console.warn(t)},i},obj:function(e,t,n){n.material;var i=new xc(n.loader);return i.log=function(t){e.warnings&&console.warn(t)},i.load(t,(function(r){var a=Rl.extractUrlBase(t);if(r.materialLibraries.length){var s=r.materialLibraries[0];new Mc(n.loader).setPath(a).load(s,(function(n){n.preload(),function(n,i){n.setMaterials(i).load(t,(function(t){e.add(t)}),null,Ec.onError)}(i,n)}),null,Ec.onError)}else e.add(r)}),null,Ec.onError),i},stl:function(e,t,n){var i=n.material,r=new bc(n.loader);return r.load(t,(function(t){var n;t.computeVertexNormals(),n=new yi(t,null!==i?i:new Hn({color:10066329})),e.add(n)}),null,Ec.onError),r}}};function wc(e,t,n){return t=ql(t),Xl(e,Tc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Tc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Tc=function(){return!!e})()}var Ac=function(e){function t(e){var n;Hl(this,t),n=wc(this,t);var i=(e=e||{}).path||"/",r=e.resource;e.material,n.warnings=e.warnings,"/"!==i.substr(i.length-1)&&(i+="/");var a=i+r,s=a.substr(-3).toLowerCase(),o=Ec.loaders[s];return o?o(n,a,e):console.warn("Unsupported loader for file type: '"+s+"'"),n}return Kl(t,e),jl(t)}(bn);function Rc(e,t,n){return t=ql(t),Xl(e,Cc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Cc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Cc=function(){return!!e})()}var Lc=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).material||new Hn,r=e.vertices,a=e.colors;n=Rc(this,t),i.side=2;for(var s,o,l=new ti,c=new Float32Array(3*r.length),h=0;h0){var K=n.msgColor,Z=document.createElement("canvas"),J=Z.getContext("2d"),Q="normal 100px sans-serif";J.font=Q;var $=J.measureText(r.text).width;Z.width=$,Z.height=150,J.font=Q,J.fillStyle="rgba("+Math.round(255*K.r)+", "+Math.round(255*K.g)+", "+Math.round(255*K.b)+", "+K.a+")",J.textAlign="left",J.textBaseline="middle",J.fillText(r.text,0,Z.height/2);var ee=new ht(Z);ee.needsUpdate=!0;var te=new Fs({map:ee,useScreenCoordinates:!1}),ne=new Js(te),ie=r.scale.x;ne.scale.set($/Z.height*ie,ie,1),n.add(ne)}break;case 10:var re=null;0===r.color.r&&0===r.color.g&&0===r.color.b&&0===r.color.a||(re=a),n.msgMesh=r.mesh_resource.substr(10);var ae=new Ac({path:i,resource:n.msgMesh,material:re});n.add(ae);break;case 11:var se=new Lc({material:a,vertices:r.points,colors:r.colors});se.scale.set(r.scale.x,r.scale.y,r.scale.z),n.add(se);break;default:console.error("Currently unsupported marker type: "+r.type)}return n}return Kl(t,e),jl(t,[{key:"setPose",value:function(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()}},{key:"update",value:function(e){if(this.setPose(e.pose),e.color.r!==this.msgColor.r||e.color.g!==this.msgColor.g||e.color.b!==this.msgColor.b||e.color.a!==this.msgColor.a){var t=Fl(e.color.r,e.color.g,e.color.b,e.color.a);switch(e.type){case 4:case 5:case 8:break;case 0:case 1:case 2:case 3:case 11:case 9:this.traverse((function(e){e instanceof yi&&(e.material=t)}));break;case 10:var n=null;0===e.color.r&&0===e.color.g&&0===e.color.b&&0===e.color.a||(n=this.colorMaterial),this.traverse((function(e){e instanceof yi&&(e.material=n)}));break;default:return!1}this.msgColor=e.color}var i=Math.abs(this.msgScale[0]-e.scale.x)>1e-6||Math.abs(this.msgScale[1]-e.scale.y)>1e-6||Math.abs(this.msgScale[2]-e.scale.z)>1e-6;switch(this.msgScale=[e.scale.x,e.scale.y,e.scale.z],e.type){case 1:case 2:case 3:if(i)return!1;break;case 9:if(i||this.text!==e.text)return!1;break;case 10:if(e.mesh_resource.substr(10)!==this.msgMesh)return!1;if(i)return!1;break;case 0:case 4:case 5:case 6:case 7:case 8:case 11:return!1}return!0}},{key:"dispose",value:function(){this.children.forEach((function(e){e instanceof Ac?e.children.forEach((function(t){void 0!==t.material&&t.material.dispose(),t.children.forEach((function(e){void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose(),t.remove(e)})),e.remove(t)})):(void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose()),e.parent.remove(e)}))}}])}(bn);function Uc(e,t,n){return t=ql(t),Xl(e,Dc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Dc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Dc=function(){return!!e})()}function Oc(e,t,n,i){var r=ec(ql(1&i?e.prototype:e),t,n);return 2&i?function(e){return r.apply(n,e)}:r}var Fc=function(e){function t(e){var n;Hl(this,t);var r=n=Uc(this,t);e=e||{},n.parent=e.parent;var a=e.handle,s=e.message;n.message=s,n.name=s.name,n.camera=e.camera,n.path=e.path||"/",n.loader=e.loader,n.dragging=!1,n.startMousePos=new We,n.isShift=!1;var o=new gt(s.orientation.x,s.orientation.y,s.orientation.z,s.orientation.w);o.normalize();var l=new vt(1,0,0);switch(l.applyQuaternion(o),n.currentControlOri=new gt,s.interaction_mode){case 9:case 7:n.addEventListener("mousemove",n.parent.move3d.bind(n.parent,n,l));break;case 3:n.addEventListener("mousemove",n.parent.moveAxis.bind(n.parent,n,l)),n.addEventListener("touchmove",n.parent.moveAxis.bind(n.parent,n,l));break;case 5:n.addEventListener("mousemove",n.parent.rotateAxis.bind(n.parent,n,o));break;case 4:n.addEventListener("mousemove",n.parent.movePlane.bind(n.parent,n,l));break;case 2:n.addEventListener("click",n.parent.buttonClick.bind(n.parent,n))}function c(e){e.stopPropagation()}0!==s.interaction_mode&&(n.addEventListener("mousedown",n.parent.startDrag.bind(n.parent,n)),n.addEventListener("mouseup",n.parent.stopDrag.bind(n.parent,n)),n.addEventListener("contextmenu",n.parent.showMenu.bind(n.parent,n)),n.addEventListener("mouseup",(function(e){0===r.startMousePos.distanceToSquared(e.mousePos)&&(e.type="contextmenu",r.dispatchEvent(e))})),n.addEventListener("mouseover",c),n.addEventListener("mouseout",c),n.addEventListener("click",c),n.addEventListener("mousedown",(function(e){r.startMousePos=e.mousePos})),n.addEventListener("touchstart",(function(e){1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,r.dispatchEvent(e))})),n.addEventListener("touchmove",(function(e){1===e.domEvent.touches.length&&(e.type="mousemove",e.domEvent.button=0,r.dispatchEvent(e))})),n.addEventListener("touchend",(function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",r.dispatchEvent(e),e.type="click",r.dispatchEvent(e))})),window.addEventListener("keydown",(function(e){16===e.keyCode&&(r.isShift=!0)})),window.addEventListener("keyup",(function(e){16===e.keyCode&&(r.isShift=!1)})));var h=new gt,u=n.parent.position.clone().multiplyScalar(-1);switch(s.orientation_mode){case 0:h=n.parent.quaternion.clone().inverse();break;case 1:case 2:break;default:console.error("Unkown orientation mode: "+s.orientation_mode)}var d=new i.TFClient({ros:a.tfClient.ros,fixedFrame:a.message.header.frame_id,serverName:a.tfClient.serverName});return s.markers.forEach((function(e){var t=function(t){var n=new Nc({message:e,path:r.path,loader:r.loader});if(null!==t){var a=new i.Pose({position:n.position,orientation:n.quaternion});a.applyTransform(new i.Transform(t));var s=new Nc({message:e,path:r.path,loader:r.loader});s.position.add(u),s.position.applyQuaternion(h),s.quaternion.multiplyQuaternions(h,s.quaternion);var o=new vt(s.position.x,s.position.y,s.position.z),l=new i.Transform({translation:o,orientation:s.quaternion});a.applyTransform(l),n.setPose(a),n.updateMatrixWorld(),d.unsubscribe(e.header.frame_id)}r.add(n)};""!==e.header.frame_id?d.subscribe(e.header.frame_id,t):t(null)})),n}return Kl(t,e),jl(t,[{key:"updateMatrixWorld",value:function(e){var n=this,i=this.message;switch(i.orientation_mode){case 0:Oc(t,"updateMatrixWorld",this,3)([e]),n.currentControlOri.copy(n.quaternion),n.currentControlOri.normalize();break;case 1:n.quaternion.copy(n.parent.quaternion.clone().inverse()),n.updateMatrix(),n.matrixWorldNeedsUpdate=!0,Oc(t,"updateMatrixWorld",this,3)([e]),n.currentControlOri.copy(n.quaternion);break;case 2:n.camera.updateMatrixWorld();var r=(new qt).extractRotation(n.camera.matrixWorld),a=new qt,s=.5*Math.PI,o=new rn(-s,0,s);a.makeRotationFromEuler(o);var l=new qt;l.getInverse(n.parent.matrixWorld),r.multiplyMatrices(r,a),r.multiplyMatrices(l,r),n.currentControlOri.setFromRotationMatrix(r),i.independent_marker_orientation||(n.quaternion.copy(n.currentControlOri),n.updateMatrix(),n.matrixWorldNeedsUpdate=!0),Oc(t,"updateMatrixWorld",this,3)([e]);break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}}}])}(bn);function kc(e,t,n){return t=ql(t),Xl(e,Bc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Bc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Bc=function(){return!!e})()}var zc=function(e){function t(e){var n;Hl(this,t);var i=n=kc(this,t),r=(e=e||{}).menuEntries,a=e.className||"default-interactive-marker-menu";e.entryClassName;var s,o,l,c=e.overlayClassName||"default-interactive-marker-overlay",h=e.menuFontSize||"0.8em",u=[];if(u[0]={children:[]},null===document.getElementById("default-interactive-marker-menu-css")){var d=document.createElement("style");d.id="default-interactive-marker-menu-css",d.type="text/css",d.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: "+h+";z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(d)}for(n.menuDomElem=document.createElement("div"),n.menuDomElem.style.position="absolute",n.menuDomElem.className=a,n.menuDomElem.addEventListener("contextmenu",(function(e){e.preventDefault()})),n.overlayDomElem=document.createElement("div"),n.overlayDomElem.className=c,n.hideListener=n.hide.bind(n),n.overlayDomElem.addEventListener("contextmenu",n.hideListener),n.overlayDomElem.addEventListener("click",n.hideListener),n.overlayDomElem.addEventListener("touchstart",n.hideListener),s=0;s0?(e(o,a[s]),l.addEventListener("click",i.hide.bind(i)),l.addEventListener("touchstart",i.hide.bind(i))):(l.addEventListener("click",f.bind(i,a[s])),l.addEventListener("touchstart",f.bind(i,a[s])),l.className="default-interactive-marker-menu-entry")}}(n.menuDomElem,u[0]),n}return Kl(t,e),jl(t,[{key:"show",value:function(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,void 0!==t.domEvent.changedTouches?(this.menuDomElem.style.left=t.domEvent.changedTouches[0].pageX+"px",this.menuDomElem.style.top=t.domEvent.changedTouches[0].pageY+"px"):(this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px"),document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)}},{key:"hide",value:function(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)}}])}(Ie);function Hc(e,t,n){return t=ql(t),Xl(e,Vc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Vc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Vc=function(){return!!e})()}var Gc=function(e){function t(e){var n;Hl(this,t),n=Hc(this,t);var i=(e=e||{}).handle;n.name=i.name;var r=e.camera,a=e.path||"/",s=e.loader;return n.dragging=!1,n.onServerSetPose({pose:i.pose}),n.dragStart={position:new vt,orientation:new gt,positionWorld:new vt,orientationWorld:new gt,event3d:{}},i.controls.forEach(function(e){this.add(new Fc({parent:this,handle:i,message:e,camera:r,path:a,loader:s}))}.bind(n)),i.menuEntries.length>0&&(n.menu=new zc({menuEntries:i.menuEntries,menuFontSize:i.menuFontSize}),n.menu.addEventListener("menu-select",function(e){this.dispatchEvent(e)}.bind(n))),n}return Kl(t,e),jl(t,[{key:"showMenu",value:function(e,t){this.menu&&this.menu.show(e,t)}},{key:"moveAxis",value:function(e,t,n){if(this.dragging){var i=e.currentControlOri,r=t.clone().applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),o=new Xt(a,s),l=zl(o,n.camera,n.mousePos),c=new vt;c.addVectors(this.dragStart.position,r.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(l)),this.setPosition(e,c),n.stopPropagation()}}},{key:"move3d",value:function(e,t,n){if(this.dragging)if(e.isShift);else{var i=e.camera.getWorldDirection(),r=Math.abs(i.x),a=Math.abs(i.y),s=Math.abs(i.z),o=new gt(1,0,0,1);a>r&&a>s?o=new gt(0,0,1,1):s>r&&s>a&&(o=new gt(0,1,0,1)),o.normalize(),(t=new vt(1,0,0)).applyQuaternion(o),this.movePlane(e,t,n)}}},{key:"movePlane",value:function(e,t,n){if(this.dragging){var i=e.currentControlOri,r=t.clone().applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.clone().applyQuaternion(this.dragStart.orientationWorld),o=kl(n.mouseRay,a,s),l=new vt;l.subVectors(o,a),l.add(this.dragStart.positionWorld),this.setPosition(e,l),n.stopPropagation()}}},{key:"rotateAxis",value:function(e,t,n){if(this.dragging){e.updateMatrixWorld();var i=e.currentControlOri.clone().multiply(t.clone()),r=new vt(1,0,0).applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.applyQuaternion(this.dragStart.orientationWorld),o=kl(n.mouseRay,a,s),l=new Xt(this.dragStart.positionWorld,s),c=kl(l,a,s),h=this.dragStart.orientationWorld.clone().multiply(i).clone().inverse();o.sub(c),o.applyQuaternion(h);var u=this.dragStart.event3d.intersection.point.clone();u.sub(c),u.applyQuaternion(h);var d=Math.atan2(o.y,o.z),p=Math.atan2(u.y,u.z)-d,f=new gt;f.setFromAxisAngle(r,p),this.setOrientation(e,f.multiply(this.dragStart.orientationWorld)),n.stopPropagation()}}},{key:"feedbackEvent",value:function(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})}},{key:"startDrag",value:function(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var n=new vt;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,n),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}}},{key:"stopDrag",value:function(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))}},{key:"buttonClick",value:function(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)}},{key:"setPosition",value:function(e,t){this.position.copy(t),this.feedbackEvent("user-pose-change",e)}},{key:"setOrientation",value:function(e,t){t.normalize(),this.quaternion.copy(t),this.feedbackEvent("user-pose-change",e)}},{key:"onServerSetPose",value:function(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.copy(t.position),this.quaternion.copy(t.orientation),this.updateMatrixWorld(!0)}}},{key:"dispose",value:function(){this.children.forEach(function(e){e.children.forEach((function(t){t.dispose(),e.remove(t)})),this.remove(e)}.bind(this))}}])}(bn);function Wc(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var jc,Xc={exports:{}}; -/*! - * EventEmitter2 - * https://github.com/hij1nx/EventEmitter2 - * - * Copyright (c) 2013 hij1nx - * Licensed under the MIT license. - */jc=Xc,function(e){var t=Object.hasOwnProperty,n=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},i="object"==typeof process&&"function"==typeof process.nextTick,r="function"==typeof Symbol,a="object"==typeof Reflect,s="function"==typeof setImmediate?setImmediate:setTimeout,o=r?a&&"function"==typeof Reflect.ownKeys?Reflect.ownKeys:function(e){var t=Object.getOwnPropertyNames(e);return t.push.apply(t,Object.getOwnPropertySymbols(e)),t}:Object.keys;function l(){this._events={},this._conf&&c.call(this,this._conf)}function c(t){t&&(this._conf=t,t.delimiter&&(this.delimiter=t.delimiter),t.maxListeners!==e&&(this._maxListeners=t.maxListeners),t.wildcard&&(this.wildcard=t.wildcard),t.newListener&&(this._newListener=t.newListener),t.removeListener&&(this._removeListener=t.removeListener),t.verboseMemoryLeak&&(this.verboseMemoryLeak=t.verboseMemoryLeak),t.ignoreErrors&&(this.ignoreErrors=t.ignoreErrors),this.wildcard&&(this.listenerTree={}))}function h(e,t){var n="(node) warning: possible EventEmitter memory leak detected. "+e+" listeners added. Use emitter.setMaxListeners() to increase limit.";if(this.verboseMemoryLeak&&(n+=" Event name: "+t+"."),"undefined"!=typeof process&&process.emitWarning){var i=new Error(n);i.name="MaxListenersExceededWarning",i.emitter=this,i.count=e,process.emitWarning(i)}else console.error(n),console.trace&&console.trace()}var u=function(e,t,n){var i=arguments.length;switch(i){case 0:return[];case 1:return[e];case 2:return[e,t];case 3:return[e,t,n];default:for(var r=new Array(i);i--;)r[i]=arguments[i];return r}};function d(t,n){for(var i={},r=t.length,a=n?value.length:0,s=0;s0;)if(a===e[s])return i;r(t)}}Object.assign(p.prototype,{subscribe:function(e,t,n){var i=this,r=this._target,a=this._emitter,s=this._listeners,o=function(){var i=u.apply(null,arguments),s={data:i,name:t,original:e};if(n){var o=n.call(r,s);!1!==o&&a.emit.apply(a,[s.name].concat(i))}else a.emit.apply(a,[t].concat(i))};if(s[e])throw Error("Event '"+e+"' is already listening");this._listenersCount++,a._newListener&&a._removeListener&&!i._onNewListener?(this._onNewListener=function(n){n===t&&null===s[e]&&(s[e]=o,i._on.call(r,e,o))},a.on("newListener",this._onNewListener),this._onRemoveListener=function(n){n===t&&!a.hasListeners(n)&&s[e]&&(s[e]=null,i._off.call(r,e,o))},s[e]=null,a.on("removeListener",this._onRemoveListener)):(s[e]=o,i._on.call(r,e,o))},unsubscribe:function(e){var t,n,i,r=this,a=this._listeners,s=this._emitter,l=this._off,c=this._target;if(e&&"string"!=typeof e)throw TypeError("event must be a string");function h(){r._onNewListener&&(s.off("newListener",r._onNewListener),s.off("removeListener",r._onRemoveListener),r._onNewListener=null,r._onRemoveListener=null);var e=x.call(s,r);s._observers.splice(e,1)}if(e){if(!(t=a[e]))return;l.call(c,e,t),delete a[e],--this._listenersCount||h()}else{for(i=(n=o(a)).length;i-- >0;)e=n[i],l.call(c,e,a[e]);this._listeners={},this._listenersCount=0,h()}}});var v=g(["function"]),_=g(["object","function"]);function y(e,t,n){var i,r,a,s=0,o=new e((function(l,c,h){function u(){r&&(r=null),s&&(clearTimeout(s),s=0)}n=f(n,{timeout:0,overload:!1},{timeout:function(e,t){return("number"!=typeof(e*=1)||e<0||!Number.isFinite(e))&&t("timeout must be a positive number"),e}}),i=!n.overload&&"function"==typeof e.prototype.cancel&&"function"==typeof h;var d=function(e){u(),l(e)},p=function(e){u(),c(e)};i?t(d,p,h):(r=[function(e){p(e||Error("canceled"))}],t(d,p,(function(e){if(a)throw Error("Unable to subscribe on cancel event asynchronously");if("function"!=typeof e)throw TypeError("onCancel callback must be a function");r.push(e)})),a=!0),n.timeout>0&&(s=setTimeout((function(){var e=Error("timeout");e.code="ETIMEDOUT",s=0,o.cancel(e),c(e)}),n.timeout))}));return i||(o.cancel=function(e){if(r){for(var t=r.length,n=1;n0;)"_listeners"!==(p=_[l])&&(y=b(e,t,n[p],i+1,r))&&(x?x.push.apply(x,y):x=y);return x}if("**"===M){for((v=i+1===r||i+2===r&&"*"===S)&&n._listeners&&(x=b(e,t,n,r,r)),l=(_=o(n)).length;l-- >0;)"_listeners"!==(p=_[l])&&("*"===p||"**"===p?(n[p]._listeners&&!v&&(y=b(e,t,n[p],r,r))&&(x?x.push.apply(x,y):x=y),y=b(e,t,n[p],i,r)):y=b(e,t,n[p],p===S?i+2:i,r),y&&(x?x.push.apply(x,y):x=y));return x}n[M]&&(x=b(e,t,n[M],i+1,r))}if((f=n["*"])&&b(e,t,f,i+1,r),m=n["**"])if(i0;)"_listeners"!==(p=_[l])&&(p===S?b(e,t,m[p],i+2,r):p===M?b(e,t,m[p],i+1,r):((g={})[p]=m[p],b(e,t,{"**":g},i+1,r)));else m._listeners?b(e,t,m,r,r):m["*"]&&m["*"]._listeners&&b(e,t,m["*"],r,r);return x}function M(e,t,n){var i,r,a=0,s=0,o=this.delimiter,l=o.length;if("string"==typeof e)if(-1!==(i=e.indexOf(o))){r=new Array(5);do{r[a++]=e.slice(s,i),s=i+l}while(-1!==(i=e.indexOf(o,s)));r[a++]=e.slice(s)}else r=[e],a=1;else r=e,a=e.length;if(a>1)for(i=0;i+10&&u._listeners.length>this._maxListeners&&(u._listeners.warned=!0,h.call(this,u._listeners.length,c))):u._listeners=t,!0;return!0}function S(e,t,n,i){for(var r,a,s,l,c=o(e),h=c.length,u=e._listeners;h-- >0;)r=e[a=c[h]],s="_listeners"===a?n:n?n.concat(a):[a],l=i||"symbol"==typeof a,u&&t.push(l?s:s.join(this.delimiter)),"object"==typeof r&&S.call(this,r,t,s,l);return t}function E(e){for(var t,n,i,r=o(e),a=r.length;a-- >0;)(t=e[n=r[a]])&&(i=!0,"_listeners"===n||E(t)||delete e[n]);return i}function w(e,t,n){this.emitter=e,this.event=t,this.listener=n}function T(t,n,r){if(!0===r)o=!0;else if(!1===r)a=!0;else{if(!r||"object"!=typeof r)throw TypeError("options should be an object or true");var a=r.async,o=r.promisify,l=r.nextTick,c=r.objectify}if(a||l||o){var h=n,u=n._origin||n;if(l&&!i)throw Error("process.nextTick is not supported");o===e&&(o="AsyncFunction"===n.constructor.name),n=function(){var e=arguments,t=this,n=this.event;return o?l?Promise.resolve():new Promise((function(e){s(e)})).then((function(){return t.event=n,h.apply(t,e)})):(l?process.nextTick:s)((function(){t.event=n,h.apply(t,e)}))},n._async=!0,n._origin=u}return[n,c?new w(this,t,n):this]}function A(e){this._events={},this._newListener=!1,this._removeListener=!1,this.verboseMemoryLeak=!1,c.call(this,e)}w.prototype.off=function(){return this.emitter.off(this.event,this.listener),this},A.EventEmitter2=A,A.prototype.listenTo=function(t,i,r){if("object"!=typeof t)throw TypeError("target musts be an object");var a=this;function s(e){if("object"!=typeof e)throw TypeError("events must be an object");var n,i=r.reducers,s=x.call(a,t);n=-1===s?new p(a,t,r):a._observers[s];for(var l,c=o(e),h=c.length,u="function"==typeof i,d=0;d0;)i=n[r],e&&i._target!==e||(i.unsubscribe(t),a=!0);return a},A.prototype.delimiter=".",A.prototype.setMaxListeners=function(t){t!==e&&(this._maxListeners=t,this._conf||(this._conf={}),this._conf.maxListeners=t)},A.prototype.getMaxListeners=function(){return this._maxListeners},A.prototype.event="",A.prototype.once=function(e,t,n){return this._once(e,t,!1,n)},A.prototype.prependOnceListener=function(e,t,n){return this._once(e,t,!0,n)},A.prototype._once=function(e,t,n,i){return this._many(e,1,t,n,i)},A.prototype.many=function(e,t,n,i){return this._many(e,t,n,!1,i)},A.prototype.prependMany=function(e,t,n,i){return this._many(e,t,n,!0,i)},A.prototype._many=function(e,t,n,i,r){var a=this;if("function"!=typeof n)throw new Error("many only accepts instances of Function");function s(){return 0==--t&&a.off(e,s),n.apply(this,arguments)}return s._origin=n,this._on(e,s,i,r)},A.prototype.emit=function(){if(!this._events&&!this._all)return!1;this._events||l.call(this);var e,t,n,i,a,s,o=arguments[0],c=this.wildcard;if("newListener"===o&&!this._newListener&&!this._events.newListener)return!1;if(c&&(e=o,"newListener"!==o&&"removeListener"!==o&&"object"==typeof o)){if(n=o.length,r)for(i=0;i3)for(t=new Array(u-1),a=1;a3)for(n=new Array(d-1),s=1;s0&&this._events[t].length>this._maxListeners&&(this._events[t].warned=!0,h.call(this,this._events[t].length,t))):this._events[t]=n,s)},A.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var i,r=[];if(this.wildcard){var a="string"==typeof e?e.split(this.delimiter):e.slice();if(!(r=b.call(this,null,a,this.listenerTree,0)))return this}else{if(!this._events[e])return this;i=this._events[e],r.push({_listeners:i})}for(var s=0;s0){for(n=0,i=(t=this._all).length;n0;)"function"==typeof(i=l[n[a]])?r.push(i):r.push.apply(r,i);return r}if(this.wildcard){if(!(s=this.listenerTree))return[];var c=[],h="string"==typeof t?t.split(this.delimiter):t.slice();return b.call(this,c,h,s,0),c}return l&&(i=l[t])?"function"==typeof i?[i]:i:[]},A.prototype.eventNames=function(e){var t=this._events;return this.wildcard?S.call(this,this.listenerTree,[],null,e):t?o(t):[]},A.prototype.listenerCount=function(e){return this.listeners(e).length},A.prototype.hasListeners=function(t){if(this.wildcard){var n=[],i="string"==typeof t?t.split(this.delimiter):t.slice();return b.call(this,n,i,this.listenerTree,0),n.length>0}var r=this._events,a=this._all;return!!(a&&a.length||r&&(t===e?o(r).length:r[t]))},A.prototype.listenersAny=function(){return this._all?this._all:[]},A.prototype.waitFor=function(t,n){var i=this,r=typeof n;return"number"===r?n={timeout:n}:"function"===r&&(n={filter:n}),y((n=f(n,{timeout:0,filter:e,handleError:!1,Promise:Promise,overload:!1},{filter:v,Promise:m})).Promise,(function(e,r,a){function s(){var a=n.filter;if(!a||a.apply(i,arguments))if(i.off(t,s),n.handleError){var o=arguments[0];o?r(o):e(u.apply(null,arguments).slice(1))}else e(u.apply(null,arguments))}a((function(){i.off(t,s)})),i._on(t,s,!1)}),{timeout:n.timeout,overload:n.overload})};var R=A.prototype;Object.defineProperties(A,{defaultMaxListeners:{get:function(){return R._maxListeners},set:function(e){if("number"!=typeof e||e<0||Number.isNaN(e))throw TypeError("n must be a non-negative number");R._maxListeners=e},enumerable:!0},once:{value:function(e,t,n){return y((n=f(n,{Promise:Promise,timeout:0,overload:!1},{Promise:m})).Promise,(function(n,i,r){var a;if("function"==typeof e.addEventListener)return a=function(){n(u.apply(null,arguments))},r((function(){e.removeEventListener(t,a)})),void e.addEventListener(t,a,{once:!0});var s,o=function(){s&&e.removeListener("error",s),n(u.apply(null,arguments))};"error"!==t&&(s=function(n){e.removeListener(t,o),i(n)},e.once("error",s)),r((function(){s&&e.removeListener("error",s),e.removeListener(t,o)})),e.once(t,o)}),{timeout:n.timeout,overload:n.overload})},writable:!0,configurable:!0}}),Object.defineProperties(R,{_maxListeners:{value:10,writable:!0,configurable:!0},_observers:{value:null,writable:!0,configurable:!0}}),jc.exports=A}();var qc=Wc(Xc.exports);function Yc(e,t,n){return t=ql(t),Xl(e,Kc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Kc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Kc=function(){return!!e})()}var Zc=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Yc(this,t)).message=e.message,n.feedbackTopic=e.feedbackTopic,n.tfClient=e.tfClient,n.menuFontSize=e.menuFontSize||"0.8em",n.name=n.message.name,n.header=n.message.header,n.controls=n.message.controls,n.menuEntries=n.message.menu_entries,n.dragging=!1,n.timeoutHandle=null,n.tfTransform=new i.Transform,n.pose=new i.Pose,n.setPoseFromClientBound=n.setPoseFromClient.bind(n),n.onMouseDownBound=n.onMouseDown.bind(n),n.onMouseUpBound=n.onMouseUp.bind(n),n.onButtonClickBound=n.onButtonClick.bind(n),n.onMenuSelectBound=n.onMenuSelect.bind(n),n.setPoseFromServer(n.message.pose),n.tfUpdateBound=n.tfUpdate.bind(n),n}return Kl(t,e),jl(t,[{key:"subscribeTf",value:function(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}},{key:"unsubscribeTf",value:function(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}},{key:"emitServerPoseUpdate",value:function(){var e=new i.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}},{key:"setPoseFromServer",value:function(e){this.pose=new i.Pose(e),this.emitServerPoseUpdate()}},{key:"tfUpdate",value:function(e){this.tfTransform=new i.Transform(e),this.emitServerPoseUpdate()}},{key:"setPoseFromClient",value:function(e){this.pose=new i.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}},{key:"onButtonClick",value:function(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}},{key:"onMouseDown",value:function(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}},{key:"onMouseUp",value:function(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}},{key:"onMenuSelect",value:function(e){this.sendFeedback(2,void 0,e.id,e.controlName)}},{key:"sendFeedback",value:function(e,t,n,i){var r=void 0!==t;t=t||{x:0,y:0,z:0};var a={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:i,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:r,menu_entry_id:n};this.feedbackTopic.publish(a)}}])}(qc),Jc=function(){return jl((function e(t){Hl(this,e),t=t||{},this.ros=t.ros,this.tfClient=t.tfClient,this.topicName=t.topic,this.path=t.path||"/",this.camera=t.camera,this.rootObject=t.rootObject||new bn,this.loader=t.loader,this.menuFontSize=t.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.processUpdateBound=this.processUpdate.bind(this),this.topicName&&this.subscribe(this.topicName)}),[{key:"subscribe",value:function(e){this.unsubscribe(),this.updateTopic=new i.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdateBound),this.feedbackTopic=new i.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new i.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new i.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}},{key:"unsubscribe",value:function(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdateBound),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}},{key:"processInit",value:function(e){var t=e.msg;for(var n in t.erases=[],this.interactiveMarkers)t.erases.push(n);t.poses=[],this.processUpdate(t)}},{key:"processUpdate",value:function(e){e.erases.forEach((function(e){this.eraseIntMarker(e)})),e.poses.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&t.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&this.eraseIntMarker(t.name);var n=new Zc({message:e,feedbackTopic:this.feedbackTopic,tfClient:this.tfClient,menuFontSize:this.menuFontSize});this.interactiveMarkers[e.name]=n;var i=new Gc({handle:n,camera:this.camera,path:this.path,loader:this.loader});i.name=e.name,this.rootObject.add(i),n.on("pose",(function(e){i.onServerSetPose({pose:e})})),i.addEventListener("user-pose-change",n.setPoseFromClientBound),i.addEventListener("user-mousedown",n.onMouseDownBound),i.addEventListener("user-mouseup",n.onMouseUpBound),i.addEventListener("user-button-click",n.onButtonClickBound),i.addEventListener("menu-select",n.onMenuSelectBound),n.subscribeTf()}))}},{key:"eraseIntMarker",value:function(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var n=this.interactiveMarkers[e];n.unsubscribeTf(),t.removeEventListener("user-pose-change",n.setPoseFromClientBound),t.removeEventListener("user-mousedown",n.onMouseDownBound),t.removeEventListener("user-mouseup",n.onMouseUpBound),t.removeEventListener("user-button-click",n.onButtonClickBound),t.removeEventListener("menu-select",n.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}}])}();function Qc(e,t,n){return t=ql(t),Xl(e,$c()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function $c(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return($c=function(){return!!e})()}var eh=function(e){function t(e){var n;Hl(this,t),e=e||{},(n=Qc(this,t)).tfClient=e.tfClient,n.frameID=e.frameID;var r=e.object;return n.pose=e.pose||new i.Pose,n.visible=!1,n.add(r),n.updatePose(n.pose),n.tfUpdate=function(e){var t=new i.Transform(e),n=new i.Pose(this.pose);n.applyTransform(t),this.updatePose(n),this.visible=!0},n.tfUpdateBound=n.tfUpdate.bind(n),n.tfClient.subscribe(n.frameID,n.tfUpdateBound),n}return Kl(t,e),jl(t,[{key:"updatePose",value:function(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}},{key:"unsubscribeTf",value:function(){this.tfClient.unsubscribe(this.frameID,this.tfUpdateBound)}}])}(bn);function th(e,t,n){return t=ql(t),Xl(e,nh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function nh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(nh=function(){return!!e})()}var ih=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=th(this,t)).ros=e.ros,n.topicName=e.topic,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.path=e.path||"/",n.markers={},n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var n=!1;if(t in this.markers&&((n=this.markers[t].children[0].update(e))||this.removeMarker(t)),!n){var i=new Nc({message:e,path:this.path});this.markers[t]=new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:i}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var r in this.markers)this.removeMarker(r);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}},{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"removeMarker",value:function(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((function(e){e.dispose()})),delete this.markers[e])}}])}(qc);function rh(e,t,n){return t=ql(t),Xl(e,ah()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function ah(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(ah=function(){return!!e})()}var sh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=rh(this,t)).ros=e.ros,n.topicName=e.topic,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.path=e.path||"/",n.lifetime=e.lifetime||0,n.markers={},n.rosTopic=void 0,n.updatedTime={},n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"checkTime",value:function(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){var t=e.ns+e.id,n=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),n?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var i=new Nc({message:e,path:this.path});this.markers[t]=new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:i}),this.rootObject.add(this.markers[t])}this.emit("change")}},{key:"removeMarker",value:function(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((function(e){e.dispose()})),delete this.markers[e])}}])}(qc);function oh(e,t,n){return t=ql(t),Xl(e,lh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function lh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(lh=function(){return!!e})()}var ch=function(e){function t(e){Hl(this,t);var n=(e=e||{}).origin||new vt(0,0,0),i=e.direction||new vt(1,0,0),r=e.length||1;return e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Hn,oh(this,t,[i,n,r,16711680])}return Kl(t,e),jl(t,[{key:"dispose",value:function(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}])}(Ol);function hh(e,t,n){return t=ql(t),Xl(e,uh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function uh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(uh=function(){return!!e})()}var dh=function(e){function t(e){var n;Hl(this,t);var i=n=hh(this,t),r=(e=e||{}).shaftRadius||.008,a=e.headRadius||.023,s=e.headLength||.1,o=e.scale||1,l=e.lineType||"full",c=e.lineDashLength||.1;function h(e){var t=new Fn;t.setRGB(e.x,e.y,e.z);var n=new Hn({color:t.getHex()}),a=new vt;a.crossVectors(e,new vt(0,-1,0));var s=new gt;s.setFromAxisAngle(a,.5*Math.PI);var o,h=new yi(i.headGeom,n);if(h.position.copy(e),h.position.multiplyScalar(.95),h.quaternion.copy(s),h.updateMatrix(),i.add(h),"dashed"===l)for(var u=c,d=0;u/2+3*u*d+u/2<=1;++d){var p=new Do(r,r,u);(o=new yi(p,n)).position.copy(e),o.position.multiplyScalar(u/2+3*u*d),o.quaternion.copy(s),o.updateMatrix(),i.add(o)}else"full"===l?((o=new yi(i.lineGeom,n)).position.copy(e),o.position.multiplyScalar(.45),o.quaternion.copy(s),o.updateMatrix(),i.add(o)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}return n.scale.set(o,o,o),n.lineGeom=new Do(r,r,1-s),n.headGeom=new Do(0,a,s),h(new vt(1,0,0)),h(new vt(0,1,0)),h(new vt(0,0,1)),n}return Kl(t,e),jl(t)}(bn);function ph(e,t,n){return t=ql(t),Xl(e,fh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function fh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(fh=function(){return!!e})()}var mh=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).num_cells||10,r=e.color||"#cccccc",a=e.lineWidth||1,s=e.cellSize||1;n=ph(this,t);for(var o=new mo({color:r,linewidth:a}),l=[],c=0;c<=i;++c){var h=s*i/2,u=h-c*s;l.push(new vt(-h,u,0),new vt(h,u,0)),l.push(new vt(u,-h,0),new vt(u,h,0))}var d=(new ti).setFromPoints(l),p=new Ao(d,o);return n.add(p),n}return Kl(t,e),jl(t)}(bn);function gh(e,t,n){return t=ql(t),Xl(e,vh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function vh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(vh=function(){return!!e})()}var _h=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).message,r=e.opacity||1,a=e.color||{r:255,g:255,b:255,a:255},s=i.info,o=s.origin,l=s.width,c=s.height,h=new ji(l,c),u=new Uint8Array(l*c*4),d=new ho(u,l,c,I);d.flipY=!0,d.minFilter=m,d.magFilter=m,d.needsUpdate=!0;var p=new Hn({map:d,transparent:r<1,opacity:r});p.side=2,n=gh(this,t,[h,p]),Object.assign(n,e),n.quaternion.copy(new gt(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),n.position.x=l*s.resolution/2+o.position.x,n.position.y=c*s.resolution/2+o.position.y,n.position.z=o.position.z,n.scale.x=s.resolution,n.scale.y=s.resolution;var f=i.data;n.color=a,n.material=p,n.texture=d;for(var g=0;ge.length)&&(t=e.length);for(var n=0,i=Array(t);nn.length)throw new Error("Cannot read data stream. Overflow. Len="+n.length+" crsr="+n._cursor);var t=n._dataView[i](n._cursor,n.isLittleEndian);return n._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:function(){return n.cursor>=n.data.length}}),this}var Lh=function(){return jl((function e(t){Hl(this,e),this.resolution=void 0!==t.resolution?t.resolution:1,this.color=new Fn(void 0!==t.color?t.color:"green"),this.opacity=void 0!==t.opacity?t.opacity:1,this.voxelRenderMode=void 0!==t.voxelRenderMode?t.voxelRenderMode:wh,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);for(var n=this.resolution,i=this._treeDepth-1;i>=0;--i)this.nodeSizeTable[i]=n,n*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}),[{key:"searchAtDepth",value:function(e,t){t=void 0!==t&&t>0?t:this._treeDepth;for(var n=this._adjustKeyAtDepth(e,t),i=this._treeDepth-t,r=this._rootNode,a=this._treeDepth-1;a>=i;--a){var s=this._computeChildIdx(n,a);if(!r.hasChildAt(s))return r.hasChildren()?null:r;r=r.getChildAt(s)}return r}},{key:"_computeCoordFromKey",value:function(e){var t=this;return e.map((function(e){return t.resolution*(e-t._treeMaxKeyVal)}))}},{key:"_computeChildIdx",value:function(e,t){var n=0;return e[0]&1<>i<0;)for(var i=n.pop(),r=t.readUint16(),a=8;0!==a;){var s=(r&3<<2*--a)>>2*a;if(s!==this._BINARY_UNALLOCATED){var o=this._newNode();this._BINARY_CHILD_BUILD_TABLE[s].bind(this)(o),i.createChildNodeAt(o,a),s===this._BINARY_HAS_CHILDREN&&n.push(o)}}}},{key:"read",value:function(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();var t=new Ch(e,!0),n=new Array;for(n.push(this._rootNode);n.length>0;){var i=n.pop();this._readNodeData(t,i);for(var r=t.readUint8(),a=8;0!==a;){if(r&1<<--a){var s=this._newNode();s.value=null,i.createChildNodeAt(s,a),n.push(s)}}}}},{key:"_readNodeData",value:function(e,t){console.error("Not implemented")}},{key:"buildGeometry",value:function(){console.assert(null!==this._rootNode,"No tree data");var e=this._buildFaces(),t=e.vertices,n=e.normals,i=e.colors,r=e.indices,a=new ti,s=new Hn({color:"white",flatShading:!0,vertexColors:!0,transparent:this.opacity<1,opacity:this.opacity});a.addAttribute("position",new Wn(new Float32Array(t),3)),a.addAttribute("normal",new Wn(new Float32Array(n),3)),a.addAttribute("color",new Wn(new Float32Array(i),3)),a.setIndex(r);var o=new yi(a,s);this.object=new bn,this.object.add(o)}},{key:"_traverseLeaves",value:function(e){var t=new Array;for(t.push({node:this._rootNode,depth:0,key:[0,0,0]});t.length>0;){var n=t.pop();if(n.node.isLeafNode())e(n.node,n.key,n.depth-1);else for(var i=0;i<8;++i)if(n.node.hasChildAt(i)){var r=this._computeKeyFromChildIdx(i,n.key,n.depth);t.push({node:n.node.getChildAt(i),depth:n.depth+1,key:r})}}}},{key:"_obtainColor",value:function(e){return this.color}},{key:"_checkOccupied",value:function(e){return!1!==e.value}},{key:"_buildFaces",value:function(){var e=this,t={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,n,i){var r,a,s=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*n,t[1]+e[1]*n,t[2]+e[2]*n)}));var o=[i.r,i.g,i.b];(r=this.colors).push.apply(r,o.concat(o,o,o)),(a=this.normals).push.apply(a,Sh(e.normal).concat(Sh(e.normal),Sh(e.normal),Sh(e.normal))),this.indices.push(s,s+1,s+2,s+2,s+1,s+3)},_checkNeighborsTouchingFace:function(e,t,n){var i=new Array;i.push(t);for(var r=function(){var t=i.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;var r=t.getChildAt(e),a=this._checkOccupied(t);(a&&n===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!a&&n===Th)&&i.push(r)}))};0!==i.length;)r();return!1}};return this._traverseLeaves((function(n,i,r){var a=e._computeCoordFromKey(i),s=e.nodeSizeTable[r],o=e._treeDepth-r,l=e._checkOccupied(n);(l||e.voxelRenderMode!==wh)&&(l&&e.voxelRenderMode===Th||e._FACES.forEach((function(e){var l=[i[0]+e.normal[0]*o*o,i[1]+e.normal[1]*o*o,i[2]+e.normal[2]*o*o],c=this.searchAtDepth(l);null===c?t._insertFace(e,a,s,this._obtainColor(n)):r=this.palette.length-1?this.palette[this.palette.length-1]:{r:i*this.palette[n].r+(1-i)*this.palette[n+1].r,g:i*this.palette[n].g+(1-i)*this.palette[n+1].g,b:i*this.palette[n].b+(1-i)*this.palette[n+1].b}}},{key:"_checkOccupied",value:function(e){return e.value>=this.occupancyThreshold}}])}(Lh);function Uh(e,t,n){return t=ql(t),Xl(e,Dh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Dh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Dh=function(){return!!e})()}var Oh=function(e){function t(e){var n;return Hl(this,t),(n=Uh(this,t,[e])).useOwnColor=void 0!==e.palette&&e.colorMode===Rh,n}return Kl(t,e),jl(t,[{key:"_readNodeData",value:function(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}},{key:"_obtainColor",value:function(e){return this.useOwnColor?e.color:Nh.prototype._obtainColor.call(this,e)}}])}(Nh);function Fh(e,t,n){return t=ql(t),Xl(e,kh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function kh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(kh=function(){return!!e})()}var Bh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Fh(this,t)).ros=e.ros,n.topicName=e.topic||"/octomap",n.compression=e.compression||"cbor",n.continuous=e.continuous,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.offsetPose=e.offsetPose||new i.Pose,n.options={},void 0!==e.color&&(n.options.color=e.color),void 0!==e.opacity&&(n.options.opacity=e.opacity),void 0!==e.colorMode&&(n.options.colorMode=e.colorMode),void 0!==e.palette&&(n.options.palette=e.palette),void 0!==e.paletteScale&&(n.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(n.options.voxelRenderMode=e.voxelRenderMode),n.currentMap=null,n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"_loadOcTree",value:function(e){return new Promise(function(t,n){var i=Object.assign({resolution:e.resolution},this.options),r=null;if(e.binary)(r=new Lh(i)).readBinary(e.data);else{var a={OcTree:Nh,ColorOcTree:Oh};e.id in a&&(console.log(e.id,a),(r=new a[e.id](i)).read(e.data))}r.buildGeometry(),t(r)}.bind(this))}},{key:"_processMessagePrivate",value:function(e){this._loadOcTree(e).then(function(t){var n=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(n),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}}])}(qc);function zh(e,t,n){return t=ql(t),Xl(e,Hh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Hh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Hh=function(){return!!e})()}var Vh=function(e){function t(e){var n;return Hl(this,t),(n=zh(this,t)).options=e||{},n.ros=e.ros,n.topicName=e.topic||"/particlecloud",n.tfClient=e.tfClient,n.color=e.color||13369599,n.length=e.length||1,n.rootObject=e.rootObject||new bn,n.keep=e.keep||1,n.sns=[],n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new vt(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new gt(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new vt(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Hn({color:this.color});var n=new ic(this.options);this.sns.push(new eh({frameID:e.header.frame_id,tfClient:this.tfClient,object:n})),this.rootObject.add(this.sns[this.sns.length-1])}}])}(bn);function Gh(e,t,n){return t=ql(t),Xl(e,Wh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Wh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Wh=function(){return!!e})()}var jh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Gh(this,t)).ros=e.ros,n.topicName=e.topic||"/path",n.tfClient=e.tfClient,n.color=e.color||13369599,n.rootObject=e.rootObject||new bn,n.sn=null,n.line=null,n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new ti,n=0;n=e.range_min&&r<=e.range_max){var a=e.angle_min+i*e.angle_increment;this.points.positions.array[n++]=r*Math.cos(a),this.points.positions.array[n++]=r*Math.sin(a),this.points.positions.array[n++]=0}}this.points.update(n/3)}}}])}(bn);function pu(e,t,n){return t=ql(t),Xl(e,fu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function fu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(fu=function(){return!!e})()}var mu=function(e){function t(e){var n;Hl(this,t),e=e||{},(n=pu(this,t)).ros=e.ros,n.topicName=e.topic||"/gps/fix",n.rootObject=e.rootObject||new bn,n.object3d=e.object3d||new bn;var i=e.material||{};return n.altitudeNaN=e.altitudeNaN||0,n.keep=e.keep||100,n.convert=e.convert||function(e,t,n){return new vt(e,t,n)},n.count=0,n.next1=0,n.next2=n.keep,n.geom=new ti,n.vertices=new Wn(new Float32Array(6*n.keep),3),n.geom.addAttribute("position",n.vertices),n.material=i.isMaterial?i:new mo(i),n.line=new So(n.geom,n.material),n.rootObject.add(n.object3d),n.rootObject.add(n.line),n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,n=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(n),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=n.x,this.vertices.array[3*this.next1+1]=n.y,this.vertices.array[3*this.next1+2]=n.z,this.vertices.array[3*this.next2]=n.x,this.vertices.array[3*this.next2+1]=n.y,this.vertices.array[3*this.next2+2]=n.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}])}(bn);function gu(e,t,n){return t=ql(t),Xl(e,vu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function vu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(vu=function(){return!!e})()}function _u(e,t,n,i){var r,a=0,s=0,o=0,l=e.length,c=t.length,h=((i=i||1)-1)*(n=n||c)*8;for(r=0;r=8&&(s-=8,t[o++]=a>>>s&255,o%n==0&&(r+=Math.ceil((h-s)/6),(s%=8)>0&&(a=_u.e[e.charAt(r)])));return Math.floor(o/n)}_u.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",_u.e={};for(var yu=0;yu<64;yu++)_u.e[_u.S.charAt(yu)]=yu;var xu=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=gu(this,t)).ros=e.ros,n.topicName=e.topic||"/points",n.throttle_rate=e.throttle_rate||null,n.compression=e.compression||"cbor",n.max_pts=e.max_pts||1e4,n.points=new cu(e),n.rosTopic=void 0,n.buffer=null,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,n=this.points.pointRatio,i=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,i)),t=Math.min(e.height*e.width/n,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(i=p[0].object,d.intersection=this.lastIntersection=p[0]):i=this.fallbackTarget,i!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(i,"mouseover",d);0===f?this.notify(this.lastTarget,"mouseout",d):1===f&&(i=this.fallbackTarget)!==this.lastTarget&&(this.notify(i,"mouseover",d),this.notify(this.lastTarget,"mouseout",d))}i!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(i,e.type,d)?(this.notify(this.lastTarget,"touchleave",d),this.notify(this.lastTarget,"touchend",d)):(i=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",d),this.notify(this.lastTarget,"touchend",d)));this.notify(i,e.type,d),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=i}},{key:"notify",value:function(e,t,n){for(n.type=t,n.cancelBubble=!1,n.continueBubble=!1,n.stopPropagation=function(){n.cancelBubble=!0},n.continuePropagation=function(){n.continueBubble=!0},n.currentTarget=e;n.currentTarget;){if(n.currentTarget.dispatchEvent&&n.currentTarget.dispatchEvent instanceof Function){if(n.currentTarget.dispatchEvent(n),n.cancelBubble)return this.dispatchEvent(n),0;if(n.continueBubble)return 2}n.currentTarget=n.currentTarget.parent}return 1}}])}(Ie);function Iu(e,t,n){return t=ql(t),Xl(e,Nu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Nu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Nu=function(){return!!e})()}var Uu=function(e){function t(e){var n;Hl(this,t);var i=n=Iu(this,t),r=(e=e||{}).scene;n.camera=e.camera,n.center=new vt,n.userZoom=!0,n.userZoomSpeed=e.userZoomSpeed||1,n.userRotate=!0,n.userRotateSpeed=e.userRotateSpeed||1,n.autoRotate=e.autoRotate,n.autoRotateSpeed=e.autoRotateSpeed||2,n.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,n.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",n.camera.up=new vt(0,0,1);var a=1800,s=new We,o=new We,l=new We,c=new We,h=new We,u=new We,d=new vt,p=new vt,f=new vt,m=new vt,g=new Array(2),v=new Array(2);n.phiDelta=0,n.thetaDelta=0,n.scale=1,n.lastPosition=new vt;var _=-1,y=0,x=1,b=2,M=_;function S(e,t,n){var i=new vt;new vt;i.subVectors(t,e.origin);var r=e.direction.dot(n);if(Math.abs(r)0?i.zoomIn():i.zoomOut(),this.showAxes()}}return n.axes=new dh({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:n.lineTypePanAndZoomFrame}),n.displayPanAndZoomFrame&&(r.add(n.axes),n.axes.traverse((function(e){e.visible=!1}))),n.addEventListener("mousedown",(function(e){var t=e.domEvent;switch(t.preventDefault(),t.button){case 0:M=y,s.set(t.clientX,t.clientY);break;case 1:M=b,p=new vt(0,0,1);var n=(new qt).extractRotation(this.camera.matrix);p.applyMatrix4(n),d=i.center.clone(),f=i.camera.position.clone(),m=S(e.mouseRay,d,p);break;case 2:M=x,c.set(t.clientX,t.clientY)}this.showAxes()})),n.addEventListener("mouseup",(function(e){i.userRotate&&(M=_)})),n.addEventListener("mousemove",(function(e){var t=e.domEvent;if(M===y)o.set(t.clientX,t.clientY),l.subVectors(o,s),i.rotateLeft(2*Math.PI*l.x/a*i.userRotateSpeed),i.rotateUp(2*Math.PI*l.y/a*i.userRotateSpeed),s.copy(o),this.showAxes();else if(M===x)h.set(t.clientX,t.clientY),u.subVectors(h,c),u.y>0?i.zoomIn():i.zoomOut(),c.copy(h),this.showAxes();else if(M===b){var n=S(e.mouseRay,i.center,p);if(!n)return;var r=(new vt).subVectors(m.clone(),n.clone());i.center.addVectors(d.clone(),r.clone()),i.camera.position.addVectors(f.clone(),r.clone()),i.update(),i.camera.updateMatrixWorld(),this.showAxes()}})),n.addEventListener("touchstart",(function(e){var t=e.domEvent;switch(t.touches.length){case 1:M=y,s.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY);break;case 2:M=_,p=new vt(0,0,1);var n=(new qt).extractRotation(this.camera.matrix);p.applyMatrix4(n),d=i.center.clone(),f=i.camera.position.clone(),m=S(e.mouseRay,d,p),g[0]=new We(t.touches[0].pageX,t.touches[0].pageY),g[1]=new We(t.touches[1].pageX,t.touches[1].pageY),v[0]=new We(0,0),v[1]=new We(0,0)}this.showAxes(),t.preventDefault()})),n.addEventListener("touchmove",(function(e){var t=e.domEvent;if(M===y)o.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY),l.subVectors(o,s),i.rotateLeft(2*Math.PI*l.x/a*i.userRotateSpeed),i.rotateUp(2*Math.PI*l.y/a*i.userRotateSpeed),s.copy(o),this.showAxes();else{if(v[0].set(g[0].x-t.touches[0].pageX,g[0].y-t.touches[0].pageY),v[1].set(g[1].x-t.touches[1].pageX,g[1].y-t.touches[1].pageY),v[0].lengthSq()>10&&v[1].lengthSq()>10&&(g[0].set(t.touches[0].pageX,t.touches[0].pageY),g[1].set(t.touches[1].pageX,t.touches[1].pageY),v[0].dot(v[1])>0&&M!==x?M=b:v[0].dot(v[1])<0&&M!==b&&(M=x),M===x)){var n=new We;n.subVectors(g[0],g[1]),v[0].dot(n)<0&&v[1].dot(n)>0?i.zoomOut():v[0].dot(n)>0&&v[1].dot(n)<0&&i.zoomIn()}if(M===b){var r=S(e.mouseRay,i.center,p);if(!r)return;var c=(new vt).subVectors(m.clone(),r.clone());i.center.addVectors(d.clone(),c.clone()),i.camera.position.addVectors(f.clone(),c.clone()),i.update(),i.camera.updateMatrixWorld()}this.showAxes(),t.preventDefault()}})),n.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&M!==y?(M=y,s.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):M=_})),n.addEventListener("mousewheel",E),n.addEventListener("DOMMouseScroll",E),n}return Kl(t,e),jl(t,[{key:"showAxes",value:function(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}},{key:"rotateLeft",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}},{key:"rotateRight",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}},{key:"rotateUp",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}},{key:"rotateDown",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}},{key:"zoomIn",value:function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}},{key:"zoomOut",value:function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}},{key:"update",value:function(){var e=this.camera.position,t=e.clone().sub(this.center),n=Math.atan2(t.y,t.x),i=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),n+=this.thetaDelta,i+=this.phiDelta;var r=1e-6;i=Math.max(r,Math.min(Math.PI-r,i));var a=t.length();t.set(a*Math.sin(i)*Math.cos(n),a*Math.sin(i)*Math.sin(n),a*Math.cos(i)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),a=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*a,.05*a,.05*a),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}])}(Ie),Du=function(){return jl((function e(t){Hl(this,e),console.log("Here 1");var n=(t=t||{}).divID,i=t.elem,r=t.width,a=t.height,s=t.background||"#111111",o=t.antialias,l=t.intensity||.66,c=t.near||.01,h=t.far||1e3,u=t.alpha||1,d=t.cameraPose||{x:3,y:3,z:3},p=t.cameraZoomSpeed||.5,f=void 0===t.displayPanAndZoomFrame||!!t.displayPanAndZoomFrame,m=t.lineTypePanAndZoomFrame||"full";this.renderer=new Is({antialias:o,alpha:!0}),this.renderer.setClearColor(parseInt(s.replace("#","0x"),16),u),this.renderer.sortObjects=!1,this.renderer.setSize(r,a),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ns,this.camera=new Pi(40,r/a,c,h),this.camera.position.x=d.x,this.camera.position.y=d.y,this.camera.position.z=d.z,this.cameraControls=new Uu({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:f,lineTypePanAndZoomFrame:m}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Al(5592405)),this.directionalLight=new Tl(16777215,l),this.scene.add(this.directionalLight),console.log("Here 2"),this.selectableObjects=new Ss,this.scene.add(this.selectableObjects);var g=new Pu({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ru({mouseHandler:g}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(n)).appendChild(this.renderer.domElement),this.start(),console.log("Here 3")}),[{key:"start",value:function(){this.stopped=!1,this.draw()}},{key:"draw",value:function(){this.stopped||(this.cameraControls.update(),console.log("Here 5"),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}},{key:"stop",value:function(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}},{key:"addObject",value:function(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}},{key:"resize",value:function(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}}])}();return e.Arrow=ic,e.Arrow2=ch,e.Axes=dh,e.ColorOcTree=Oh,e.DepthCloud=Ql,e.Grid=mh,e.Highlighter=Ru,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=Gc,e.InteractiveMarkerClient=Jc,e.InteractiveMarkerControl=Fc,e.InteractiveMarkerHandle=Zc,e.InteractiveMarkerMenu=zc,e.LaserScan=du,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=Nc,e.MarkerArrayClient=ih,e.MarkerClient=sh,e.MeshLoader=Ec,e.MeshResource=Ac,e.MouseHandler=Pu,e.NavSatFix=mu,e.OcTree=Nh,e.OcTreeClient=Bh,e.OccupancyGrid=_h,e.OccupancyGridClient=bh,e.Odometry=Vh,e.OrbitControls=Uu,e.Path=jh,e.Point=Yh,e.PointCloud2=xu,e.Points=cu,e.Polygon=Jh,e.Pose=eu,e.PoseArray=iu,e.PoseWithCovariance=su,e.SceneNode=eh,e.TFAxes=Su,e.TriangleList=Lc,e.Urdf=Tu,e.UrdfClient=Au,e.Viewer=Du,e.closestAxisPoint=zl,e.findClosestPoint=Bl,e.intersectPlane=kl,e.makeColorMaterial=Fl,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); + */const r="167",a=100,s=204,o=205,l="attached",c=301,h=302,u=306,d=1e3,p=1001,f=1002,m=1003,g=1005,v=1006,_=1007,y=1008,x=1009,b=1010,M=1011,S=1012,E=1013,T=1014,w=1015,A=1016,R=1017,C=1018,P=1020,L=35902,I=1023,N=1026,U=1027,D=1029,O=1031,F=1033,k=33776,B=33777,z=33778,H=33779,V=35840,G=35841,W=35842,j=35843,X=36196,q=37492,Y=37496,K=37808,Z=37809,J=37810,Q=37811,$=37812,ee=37813,te=37814,ne=37815,ie=37816,re=37817,ae=37818,se=37819,oe=37820,le=37821,ce=36492,he=36494,ue=36495,de=36284,pe=36285,fe=36286,me=2300,ge=2301,ve=2302,_e="",ye="srgb",xe="srgb-linear",be="display-p3",Me="display-p3-linear",Se="linear",Ee="srgb",Te="rec709",we="p3",Ae=7680,Re=35044,Ce="300 es",Pe=2e3,Le=2001;class Ie{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[e]&&(n[e]=[]),-1===n[e].indexOf(t)&&n[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[e]&&-1!==n[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;const n=this._listeners[e];if(void 0!==n){const e=n.indexOf(t);-1!==e&&n.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;const t=this._listeners[e.type];if(void 0!==t){e.target=this;const n=t.slice(0);for(let t=0,i=n.length;t>8&255]+Ne[e>>16&255]+Ne[e>>24&255]+"-"+Ne[255&t]+Ne[t>>8&255]+"-"+Ne[t>>16&15|64]+Ne[t>>24&255]+"-"+Ne[63&n|128]+Ne[n>>8&255]+"-"+Ne[n>>16&255]+Ne[n>>24&255]+Ne[255&i]+Ne[i>>8&255]+Ne[i>>16&255]+Ne[i>>24&255]).toLowerCase()}function ke(e,t,n){return Math.max(t,Math.min(n,e))}function Be(e,t){return(e%t+t)%t}function ze(e,t,n){return(1-n)*e+n*t}function He(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw new Error("Invalid component type.")}}function Ve(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw new Error("Invalid component type.")}}const Ge={DEG2RAD:De,RAD2DEG:Oe,generateUUID:Fe,clamp:ke,euclideanModulo:Be,mapLinear:function(e,t,n,i,r){return i+(e-t)*(r-i)/(n-t)},inverseLerp:function(e,t,n){return e!==t?(n-e)/(t-e):0},lerp:ze,damp:function(e,t,n,i){return ze(e,t,1-Math.exp(-n*i))},pingpong:function(e,t=1){return t-Math.abs(Be(e,2*t)-t)},smoothstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*(3-2*e)},smootherstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},seededRandom:function(e){void 0!==e&&(Ue=e);let t=Ue+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296},degToRad:function(e){return e*De},radToDeg:function(e){return e*Oe},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,n,i,r){const a=Math.cos,s=Math.sin,o=a(n/2),l=s(n/2),c=a((t+i)/2),h=s((t+i)/2),u=a((t-i)/2),d=s((t-i)/2),p=a((i-t)/2),f=s((i-t)/2);switch(r){case"XYX":e.set(o*h,l*u,l*d,o*c);break;case"YZY":e.set(l*d,o*h,l*u,o*c);break;case"ZXZ":e.set(l*u,l*d,o*h,o*c);break;case"XZX":e.set(o*h,l*f,l*p,o*c);break;case"YXY":e.set(l*p,o*h,l*f,o*c);break;case"ZYZ":e.set(l*f,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Ve,denormalize:He};class We{constructor(e=0,t=0){We.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,n=this.y,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6],this.y=i[1]*t+i[4]*n+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.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(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(ke(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const n=Math.cos(t),i=Math.sin(t),r=this.x-e.x,a=this.y-e.y;return this.x=r*n-a*i+e.x,this.y=r*i+a*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class je{constructor(e,t,n,i,r,a,s,o,l){je.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,n,i,r,a,s,o,l)}set(e,t,n,i,r,a,s,o,l){const c=this.elements;return c[0]=e,c[1]=i,c[2]=s,c[3]=t,c[4]=r,c[5]=o,c[6]=n,c[7]=a,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,i=t.elements,r=this.elements,a=n[0],s=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],f=i[0],m=i[3],g=i[6],v=i[1],_=i[4],y=i[7],x=i[2],b=i[5],M=i[8];return r[0]=a*f+s*v+o*x,r[3]=a*m+s*_+o*b,r[6]=a*g+s*y+o*M,r[1]=l*f+c*v+h*x,r[4]=l*m+c*_+h*b,r[7]=l*g+c*y+h*M,r[2]=u*f+d*v+p*x,r[5]=u*m+d*_+p*b,r[8]=u*g+d*y+p*M,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8];return t*a*c-t*s*l-n*r*c+n*s*o+i*r*l-i*a*o}invert(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8],h=c*a-s*l,u=s*o-c*r,d=l*r-a*o,p=t*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const f=1/p;return e[0]=h*f,e[1]=(i*l-c*n)*f,e[2]=(s*n-i*a)*f,e[3]=u*f,e[4]=(c*t-i*o)*f,e[5]=(i*r-s*t)*f,e[6]=d*f,e[7]=(n*o-l*t)*f,e[8]=(a*t-n*r)*f,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,i,r,a,s){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*a+l*s)+a+e,-i*l,i*o,-i*(-l*a+o*s)+s+t,0,0,1),this}scale(e,t){return this.premultiply(Xe.makeScale(e,t)),this}rotate(e){return this.premultiply(Xe.makeRotation(-e)),this}translate(e,t){return this.premultiply(Xe.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,n=e.elements;for(let e=0;e<9;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return(new this.constructor).fromArray(this.elements)}}const Xe=new je;function qe(e){for(let t=e.length-1;t>=0;--t)if(e[t]>=65535)return!0;return!1}function Ye(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}function Ke(){const e=Ye("canvas");return e.style.display="block",e}const Ze={};function Je(e){e in Ze||(Ze[e]=!0,console.warn(e))}const Qe=(new je).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),$e=(new je).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),et={[xe]:{transfer:Se,primaries:Te,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[ye]:{transfer:Ee,primaries:Te,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[Me]:{transfer:Se,primaries:we,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3($e),fromReference:e=>e.applyMatrix3(Qe)},[be]:{transfer:Ee,primaries:we,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3($e),fromReference:e=>e.applyMatrix3(Qe).convertLinearToSRGB()}},tt=new Set([xe,Me]),nt={enabled:!0,_workingColorSpace:xe,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!tt.has(e))throw new Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,n){if(!1===this.enabled||t===n||!t||!n)return e;const i=et[t].toReference;return(0,et[n].fromReference)(i(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return et[e].primaries},getTransfer:function(e){return e===_e?Se:et[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(et[t].luminanceCoefficients)}};function it(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function rt(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let at;let st=0;class ot{constructor(e=null){this.isSource=!0,Object.defineProperty(this,"id",{value:st++}),this.uuid=Fe(),this.data=e,this.dataReady=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}toJSON(e){const t=void 0===e||"string"==typeof e;if(!t&&void 0!==e.images[this.uuid])return e.images[this.uuid];const n={uuid:this.uuid,url:""},i=this.data;if(null!==i){let e;if(Array.isArray(i)){e=[];for(let t=0,n=i.length;t2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){const t=Ye("canvas");t.width=e.width,t.height=e.height;const n=t.getContext("2d");n.drawImage(e,0,0,e.width,e.height);const i=n.getImageData(0,0,e.width,e.height),r=i.data;for(let e=0;e0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(300!==this.mapping)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case d:e.x=e.x-Math.floor(e.x);break;case p:e.x=e.x<0?0:1;break;case f:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case d:e.y=e.y-Math.floor(e.y);break;case p:e.y=e.y<0?0:1;break;case f:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){!0===e&&this.pmremVersion++}}ht.DEFAULT_IMAGE=null,ht.DEFAULT_MAPPING=300,ht.DEFAULT_ANISOTROPY=1;class ut{constructor(e=0,t=0,n=0,i=1){ut.prototype.isVector4=!0,this.x=e,this.y=t,this.z=n,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,i){return this.x=e,this.y=t,this.z=n,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){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: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,n=this.y,i=this.z,r=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*t+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*t+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*t+a[7]*n+a[11]*i+a[15]*r,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,n,i,r;const a=.01,s=.1,o=e.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],f=o[2],m=o[6],g=o[10];if(Math.abs(c-u)o&&e>v?ev?o=0?1:-1,i=1-t*t;if(i>Number.EPSILON){const r=Math.sqrt(i),a=Math.atan2(r,t*n);e=Math.sin(e*a)/r,s=Math.sin(s*a)/r}const r=s*n;if(o=o*e+u*r,l=l*e+d*r,c=c*e+p*r,h=h*e+f*r,e===1-s){const e=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=e,l*=e,c*=e,h*=e}}e[t]=o,e[t+1]=l,e[t+2]=c,e[t+3]=h}static multiplyQuaternionsFlat(e,t,n,i,r,a){const s=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[a],u=r[a+1],d=r[a+2],p=r[a+3];return e[t]=s*p+c*h+o*d-l*u,e[t+1]=o*p+c*u+l*h-s*d,e[t+2]=l*p+c*d+s*u-o*h,e[t+3]=c*p-s*h-o*u-l*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const n=e._x,i=e._y,r=e._z,a=e._order,s=Math.cos,o=Math.sin,l=s(n/2),c=s(i/2),h=s(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(a){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return!0===t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const n=t/2,i=Math.sin(n);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,n=t[0],i=t[4],r=t[8],a=t[1],s=t[5],o=t[9],l=t[2],c=t[6],h=t[10],u=n+s+h;if(u>0){const e=.5/Math.sqrt(u+1);this._w=.25/e,this._x=(c-o)*e,this._y=(r-l)*e,this._z=(a-i)*e}else if(n>s&&n>h){const e=2*Math.sqrt(1+n-s-h);this._w=(c-o)/e,this._x=.25*e,this._y=(i+a)/e,this._z=(r+l)/e}else if(s>h){const e=2*Math.sqrt(1+s-n-h);this._w=(r-l)/e,this._x=(i+a)/e,this._y=.25*e,this._z=(o+c)/e}else{const e=2*Math.sqrt(1+h-n-s);this._w=(a-i)/e,this._x=(r+l)/e,this._y=(o+c)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return nMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(ke(this.dot(e),-1,1)))}rotateTowards(e,t){const n=this.angleTo(e);if(0===n)return this;const i=Math.min(1,t/n);return this.slerp(e,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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 e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const n=e._x,i=e._y,r=e._z,a=e._w,s=t._x,o=t._y,l=t._z,c=t._w;return this._x=n*c+a*s+i*l-r*o,this._y=i*c+a*o+r*s-n*l,this._z=r*c+a*l+n*o-i*s,this._w=a*c-n*s-i*o-r*l,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);const n=this._x,i=this._y,r=this._z,a=this._w;let s=a*e._w+n*e._x+i*e._y+r*e._z;if(s<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,s=-s):this.copy(e),s>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;const o=1-s*s;if(o<=Number.EPSILON){const e=1-t;return this._w=e*a+t*this._w,this._x=e*n+t*this._x,this._y=e*i+t*this._y,this._z=e*r+t*this._z,this.normalize(),this}const l=Math.sqrt(o),c=Math.atan2(l,s),h=Math.sin((1-t)*c)/l,u=Math.sin(t*c)/l;return this._w=a*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),i=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(i*Math.sin(e),i*Math.cos(e),r*Math.sin(t),r*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class vt{constructor(e=0,t=0,n=0){vt.prototype.isVector3=!0,this.x=e,this.y=t,this.z=n}set(e,t,n){return void 0===n&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(yt.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(yt.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6]*i,this.y=r[1]*t+r[4]*n+r[7]*i,this.z=r[2]*t+r[5]*n+r[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,n=this.y,i=this.z,r=e.elements,a=1/(r[3]*t+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*t+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*t+r[6]*n+r[10]*i+r[14])*a,this}applyQuaternion(e){const t=this.x,n=this.y,i=this.z,r=e.x,a=e.y,s=e.z,o=e.w,l=2*(a*i-s*n),c=2*(s*t-r*i),h=2*(r*n-a*t);return this.x=t+o*l+a*h-s*c,this.y=n+o*c+s*l-r*h,this.z=i+o*h+r*c-a*l,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*n+r[8]*i,this.y=r[1]*t+r[5]*n+r[9]*i,this.z=r[2]*t+r[6]*n+r[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.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(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const n=e.x,i=e.y,r=e.z,a=t.x,s=t.y,o=t.z;return this.x=i*o-r*s,this.y=r*a-n*o,this.z=n*s-i*a,this}projectOnVector(e){const t=e.lengthSq();if(0===t)return this.set(0,0,0);const n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return _t.copy(this).projectOnVector(e),this.sub(_t)}reflect(e){return this.sub(_t.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(ke(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y,i=this.z-e.z;return t*t+n*n+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){const i=Math.sin(t)*e;return this.x=i*Math.sin(n),this.y=Math.cos(t)*e,this.z=i*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=2*Math.random()-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const _t=new vt,yt=new gt;class xt{constructor(e=new vt(1/0,1/0,1/0),t=new vt(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Mt),Mt.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Pt),Lt.subVectors(this.max,Pt),Et.subVectors(e.a,Pt),Tt.subVectors(e.b,Pt),wt.subVectors(e.c,Pt),At.subVectors(Tt,Et),Rt.subVectors(wt,Tt),Ct.subVectors(Et,wt);let t=[0,-At.z,At.y,0,-Rt.z,Rt.y,0,-Ct.z,Ct.y,At.z,0,-At.x,Rt.z,0,-Rt.x,Ct.z,0,-Ct.x,-At.y,At.x,0,-Rt.y,Rt.x,0,-Ct.y,Ct.x,0];return!!Ut(t,Et,Tt,wt,Lt)&&(t=[1,0,0,0,1,0,0,0,1],!!Ut(t,Et,Tt,wt,Lt)&&(It.crossVectors(At,Rt),t=[It.x,It.y,It.z],Ut(t,Et,Tt,wt,Lt)))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Mt).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Mt).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(bt[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),bt[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),bt[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),bt[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),bt[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),bt[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),bt[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),bt[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(bt)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const bt=[new vt,new vt,new vt,new vt,new vt,new vt,new vt,new vt],Mt=new vt,St=new xt,Et=new vt,Tt=new vt,wt=new vt,At=new vt,Rt=new vt,Ct=new vt,Pt=new vt,Lt=new vt,It=new vt,Nt=new vt;function Ut(e,t,n,i,r){for(let a=0,s=e.length-3;a<=s;a+=3){Nt.fromArray(e,a);const s=r.x*Math.abs(Nt.x)+r.y*Math.abs(Nt.y)+r.z*Math.abs(Nt.z),o=t.dot(Nt),l=n.dot(Nt),c=i.dot(Nt);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>s)return!1}return!0}const Dt=new xt,Ot=new vt,Ft=new vt;class kt{constructor(e=new vt,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const n=this.center;void 0!==t?n.copy(t):Dt.setFromPoints(e).getCenter(n);let i=0;for(let t=0,r=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Ot.subVectors(e,this.center);const t=Ot.lengthSq();if(t>this.radius*this.radius){const e=Math.sqrt(t),n=.5*(e-this.radius);this.center.addScaledVector(Ot,n/e),this.radius+=n}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(Ft.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Ot.copy(e.center).add(Ft)),this.expandByPoint(Ot.copy(e.center).sub(Ft))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Bt=new vt,zt=new vt,Ht=new vt,Vt=new vt,Gt=new vt,Wt=new vt,jt=new vt;class Xt{constructor(e=new vt,t=new vt(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Bt)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=Bt.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Bt.copy(this.origin).addScaledVector(this.direction,t),Bt.distanceToSquared(e))}distanceSqToSegment(e,t,n,i){zt.copy(e).add(t).multiplyScalar(.5),Ht.copy(t).sub(e).normalize(),Vt.copy(this.origin).sub(zt);const r=.5*e.distanceTo(t),a=-this.direction.dot(Ht),s=Vt.dot(this.direction),o=-Vt.dot(Ht),l=Vt.lengthSq(),c=Math.abs(1-a*a);let h,u,d,p;if(c>0)if(h=a*o-s,u=a*s-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const e=1/c;h*=e,u*=e,d=h*(h+a*u+2*s)+u*(a*h+u+2*o)+l}else u=r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-a*r+s)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(a*r+s)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=a>0?-r:r,h=Math.max(0,-(a*u+s)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(zt).addScaledVector(Ht,u),d}intersectSphere(e,t){Bt.subVectors(e.center,this.origin);const n=Bt.dot(this.direction),i=Bt.dot(Bt)-n*n,r=e.radius*e.radius;if(i>r)return null;const a=Math.sqrt(r-i),s=n-a,o=n+a;return o<0?null:s<0?this.at(o,t):this.at(s,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){const n=this.distanceToPlane(e);return null===n?null:this.at(n,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);if(0===t)return!0;return e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,i,r,a,s,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(e.min.x-u.x)*l,i=(e.max.x-u.x)*l):(n=(e.max.x-u.x)*l,i=(e.min.x-u.x)*l),c>=0?(r=(e.min.y-u.y)*c,a=(e.max.y-u.y)*c):(r=(e.max.y-u.y)*c,a=(e.min.y-u.y)*c),n>a||r>i?null:((r>n||isNaN(n))&&(n=r),(a=0?(s=(e.min.z-u.z)*h,o=(e.max.z-u.z)*h):(s=(e.max.z-u.z)*h,o=(e.min.z-u.z)*h),n>o||s>i?null:((s>n||n!=n)&&(n=s),(o=0?n:i,t)))}intersectsBox(e){return null!==this.intersectBox(e,Bt)}intersectTriangle(e,t,n,i,r){Gt.subVectors(t,e),Wt.subVectors(n,e),jt.crossVectors(Gt,Wt);let a,s=this.direction.dot(jt);if(s>0){if(i)return null;a=1}else{if(!(s<0))return null;a=-1,s=-s}Vt.subVectors(this.origin,e);const o=a*this.direction.dot(Wt.crossVectors(Vt,Wt));if(o<0)return null;const l=a*this.direction.dot(Gt.cross(Vt));if(l<0)return null;if(o+l>s)return null;const c=-a*Vt.dot(jt);return c<0?null:this.at(c/s,r)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class qt{constructor(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m){qt.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m)}set(e,t,n,i,r,a,s,o,l,c,h,u,d,p,f,m){const g=this.elements;return g[0]=e,g[4]=t,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=s,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=f,g[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new qt).fromArray(this.elements)}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this}copyPosition(e){const t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,n=e.elements,i=1/Yt.setFromMatrixColumn(e,0).length(),r=1/Yt.setFromMatrixColumn(e,1).length(),a=1/Yt.setFromMatrixColumn(e,2).length();return t[0]=n[0]*i,t[1]=n[1]*i,t[2]=n[2]*i,t[3]=0,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,n=e.x,i=e.y,r=e.z,a=Math.cos(n),s=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===e.order){const e=a*c,n=a*h,i=s*c,r=s*h;t[0]=o*c,t[4]=-o*h,t[8]=l,t[1]=n+i*l,t[5]=e-r*l,t[9]=-s*o,t[2]=r-e*l,t[6]=i+n*l,t[10]=a*o}else if("YXZ"===e.order){const e=o*c,n=o*h,i=l*c,r=l*h;t[0]=e+r*s,t[4]=i*s-n,t[8]=a*l,t[1]=a*h,t[5]=a*c,t[9]=-s,t[2]=n*s-i,t[6]=r+e*s,t[10]=a*o}else if("ZXY"===e.order){const e=o*c,n=o*h,i=l*c,r=l*h;t[0]=e-r*s,t[4]=-a*h,t[8]=i+n*s,t[1]=n+i*s,t[5]=a*c,t[9]=r-e*s,t[2]=-a*l,t[6]=s,t[10]=a*o}else if("ZYX"===e.order){const e=a*c,n=a*h,i=s*c,r=s*h;t[0]=o*c,t[4]=i*l-n,t[8]=e*l+r,t[1]=o*h,t[5]=r*l+e,t[9]=n*l-i,t[2]=-l,t[6]=s*o,t[10]=a*o}else if("YZX"===e.order){const e=a*o,n=a*l,i=s*o,r=s*l;t[0]=o*c,t[4]=r-e*h,t[8]=i*h+n,t[1]=h,t[5]=a*c,t[9]=-s*c,t[2]=-l*c,t[6]=n*h+i,t[10]=e-r*h}else if("XZY"===e.order){const e=a*o,n=a*l,i=s*o,r=s*l;t[0]=o*c,t[4]=-h,t[8]=l*c,t[1]=e*h+r,t[5]=a*c,t[9]=n*h-i,t[2]=i*h-n,t[6]=s*c,t[10]=r*h+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(Zt,e,Jt)}lookAt(e,t,n){const i=this.elements;return en.subVectors(e,t),0===en.lengthSq()&&(en.z=1),en.normalize(),Qt.crossVectors(n,en),0===Qt.lengthSq()&&(1===Math.abs(n.z)?en.x+=1e-4:en.z+=1e-4,en.normalize(),Qt.crossVectors(n,en)),Qt.normalize(),$t.crossVectors(en,Qt),i[0]=Qt.x,i[4]=$t.x,i[8]=en.x,i[1]=Qt.y,i[5]=$t.y,i[9]=en.y,i[2]=Qt.z,i[6]=$t.z,i[10]=en.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,i=t.elements,r=this.elements,a=n[0],s=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],f=n[6],m=n[10],g=n[14],v=n[3],_=n[7],y=n[11],x=n[15],b=i[0],M=i[4],S=i[8],E=i[12],T=i[1],w=i[5],A=i[9],R=i[13],C=i[2],P=i[6],L=i[10],I=i[14],N=i[3],U=i[7],D=i[11],O=i[15];return r[0]=a*b+s*T+o*C+l*N,r[4]=a*M+s*w+o*P+l*U,r[8]=a*S+s*A+o*L+l*D,r[12]=a*E+s*R+o*I+l*O,r[1]=c*b+h*T+u*C+d*N,r[5]=c*M+h*w+u*P+d*U,r[9]=c*S+h*A+u*L+d*D,r[13]=c*E+h*R+u*I+d*O,r[2]=p*b+f*T+m*C+g*N,r[6]=p*M+f*w+m*P+g*U,r[10]=p*S+f*A+m*L+g*D,r[14]=p*E+f*R+m*I+g*O,r[3]=v*b+_*T+y*C+x*N,r[7]=v*M+_*w+y*P+x*U,r[11]=v*S+_*A+y*L+x*D,r[15]=v*E+_*R+y*I+x*O,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[4],i=e[8],r=e[12],a=e[1],s=e[5],o=e[9],l=e[13],c=e[2],h=e[6],u=e[10],d=e[14];return e[3]*(+r*o*h-i*l*h-r*s*u+n*l*u+i*s*d-n*o*d)+e[7]*(+t*o*d-t*l*u+r*a*u-i*a*d+i*l*c-r*o*c)+e[11]*(+t*l*h-t*s*d-r*a*h+n*a*d+r*s*c-n*l*c)+e[15]*(-i*s*c-t*o*h+t*s*u+i*a*h-n*a*u+n*o*c)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,n){const i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=n),this}invert(){const e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],s=e[5],o=e[6],l=e[7],c=e[8],h=e[9],u=e[10],d=e[11],p=e[12],f=e[13],m=e[14],g=e[15],v=h*m*l-f*u*l+f*o*d-s*m*d-h*o*g+s*u*g,_=p*u*l-c*m*l-p*o*d+a*m*d+c*o*g-a*u*g,y=c*f*l-p*h*l+p*s*d-a*f*d-c*s*g+a*h*g,x=p*h*o-c*f*o-p*s*u+a*f*u+c*s*m-a*h*m,b=t*v+n*_+i*y+r*x;if(0===b)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const M=1/b;return e[0]=v*M,e[1]=(f*u*r-h*m*r-f*i*d+n*m*d+h*i*g-n*u*g)*M,e[2]=(s*m*r-f*o*r+f*i*l-n*m*l-s*i*g+n*o*g)*M,e[3]=(h*o*r-s*u*r-h*i*l+n*u*l+s*i*d-n*o*d)*M,e[4]=_*M,e[5]=(c*m*r-p*u*r+p*i*d-t*m*d-c*i*g+t*u*g)*M,e[6]=(p*o*r-a*m*r-p*i*l+t*m*l+a*i*g-t*o*g)*M,e[7]=(a*u*r-c*o*r+c*i*l-t*u*l-a*i*d+t*o*d)*M,e[8]=y*M,e[9]=(p*h*r-c*f*r-p*n*d+t*f*d+c*n*g-t*h*g)*M,e[10]=(a*f*r-p*s*r+p*n*l-t*f*l-a*n*g+t*s*g)*M,e[11]=(c*s*r-a*h*r-c*n*l+t*h*l+a*n*d-t*s*d)*M,e[12]=x*M,e[13]=(c*f*i-p*h*i+p*n*u-t*f*u-c*n*m+t*h*m)*M,e[14]=(p*s*i-a*f*i-p*n*o+t*f*o+a*n*m-t*s*m)*M,e[15]=(a*h*i-c*s*i+c*n*o-t*h*o-a*n*u+t*s*u)*M,this}scale(e){const t=this.elements,n=e.x,i=e.y,r=e.z;return t[0]*=n,t[4]*=i,t[8]*=r,t[1]*=n,t[5]*=i,t[9]*=r,t[2]*=n,t[6]*=i,t[10]*=r,t[3]*=n,t[7]*=i,t[11]*=r,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,i))}makeTranslation(e,t,n){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const n=Math.cos(t),i=Math.sin(t),r=1-n,a=e.x,s=e.y,o=e.z,l=r*a,c=r*s;return this.set(l*a+n,l*s-i*o,l*o+i*s,0,l*s+i*o,c*s+n,c*o-i*a,0,l*o-i*s,c*o+i*a,r*o*o+n,0,0,0,0,1),this}makeScale(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this}makeShear(e,t,n,i,r,a){return this.set(1,n,r,0,e,1,a,0,t,i,1,0,0,0,0,1),this}compose(e,t,n){const i=this.elements,r=t._x,a=t._y,s=t._z,o=t._w,l=r+r,c=a+a,h=s+s,u=r*l,d=r*c,p=r*h,f=a*c,m=a*h,g=s*h,v=o*l,_=o*c,y=o*h,x=n.x,b=n.y,M=n.z;return i[0]=(1-(f+g))*x,i[1]=(d+y)*x,i[2]=(p-_)*x,i[3]=0,i[4]=(d-y)*b,i[5]=(1-(u+g))*b,i[6]=(m+v)*b,i[7]=0,i[8]=(p+_)*M,i[9]=(m-v)*M,i[10]=(1-(u+f))*M,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this}decompose(e,t,n){const i=this.elements;let r=Yt.set(i[0],i[1],i[2]).length();const a=Yt.set(i[4],i[5],i[6]).length(),s=Yt.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],Kt.copy(this);const o=1/r,l=1/a,c=1/s;return Kt.elements[0]*=o,Kt.elements[1]*=o,Kt.elements[2]*=o,Kt.elements[4]*=l,Kt.elements[5]*=l,Kt.elements[6]*=l,Kt.elements[8]*=c,Kt.elements[9]*=c,Kt.elements[10]*=c,t.setFromRotationMatrix(Kt),n.x=r,n.y=a,n.z=s,this}makePerspective(e,t,n,i,r,a,s=2e3){const o=this.elements,l=2*r/(t-e),c=2*r/(n-i),h=(t+e)/(t-e),u=(n+i)/(n-i);let d,p;if(s===Pe)d=-(a+r)/(a-r),p=-2*a*r/(a-r);else{if(s!==Le)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+s);d=-a/(a-r),p=-a*r/(a-r)}return o[0]=l,o[4]=0,o[8]=h,o[12]=0,o[1]=0,o[5]=c,o[9]=u,o[13]=0,o[2]=0,o[6]=0,o[10]=d,o[14]=p,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this}makeOrthographic(e,t,n,i,r,a,s=2e3){const o=this.elements,l=1/(t-e),c=1/(n-i),h=1/(a-r),u=(t+e)*l,d=(n+i)*c;let p,f;if(s===Pe)p=(a+r)*h,f=-2*h;else{if(s!==Le)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+s);p=r*h,f=-1*h}return o[0]=2*l,o[4]=0,o[8]=0,o[12]=-u,o[1]=0,o[5]=2*c,o[9]=0,o[13]=-d,o[2]=0,o[6]=0,o[10]=f,o[14]=-p,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this}equals(e){const t=this.elements,n=e.elements;for(let e=0;e<16;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<16;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}}const Yt=new vt,Kt=new qt,Zt=new vt(0,0,0),Jt=new vt(1,1,1),Qt=new vt,$t=new vt,en=new vt,tn=new qt,nn=new gt;class rn{constructor(e=0,t=0,n=0,i=rn.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=n,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,n,i=this._order){return this._x=e,this._y=t,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,n=!0){const i=e.elements,r=i[0],a=i[4],s=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(t){case"XYZ":this._y=Math.asin(ke(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-a,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-ke(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(s,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(ke(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-a,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-ke(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-a,l));break;case"YZX":this._z=Math.asin(ke(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(s,d));break;case"XZY":this._z=Math.asin(-ke(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(s,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===n&&this._onChangeCallback(),this}setFromQuaternion(e,t,n){return tn.makeRotationFromQuaternion(e),this.setFromRotationMatrix(tn,t,n)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return nn.setFromEuler(this),this.setFromQuaternion(nn,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}rn.DEFAULT_ORDER="XYZ";class an{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(e),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(e)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(e.geometries,this.geometry);const t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){const n=t.shapes;if(Array.isArray(n))for(let t=0,i=n.length;t0){i.children=[];for(let t=0;t0){i.animations=[];for(let t=0;t0&&(n.geometries=t),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),s.length>0&&(n.images=s),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function a(e){const t=[];for(const n in e){const i=e[n];delete i.metadata,t.push(i)}return t}}clone(e){return(new this.constructor).copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(e,t,n,i,r){Mn.subVectors(i,t),Sn.subVectors(n,t),En.subVectors(e,t);const a=Mn.dot(Mn),s=Mn.dot(Sn),o=Mn.dot(En),l=Sn.dot(Sn),c=Sn.dot(En),h=a*l-s*s;if(0===h)return r.set(0,0,0),null;const u=1/h,d=(l*o-s*c)*u,p=(a*c-s*o)*u;return r.set(1-d-p,p,d)}static containsPoint(e,t,n,i){return null!==this.getBarycoord(e,t,n,i,Tn)&&(Tn.x>=0&&Tn.y>=0&&Tn.x+Tn.y<=1)}static getInterpolation(e,t,n,i,r,a,s,o){return null===this.getBarycoord(e,t,n,i,Tn)?(o.x=0,o.y=0,"z"in o&&(o.z=0),"w"in o&&(o.w=0),null):(o.setScalar(0),o.addScaledVector(r,Tn.x),o.addScaledVector(a,Tn.y),o.addScaledVector(s,Tn.z),o)}static isFrontFacing(e,t,n,i){return Mn.subVectors(n,t),Sn.subVectors(e,t),Mn.cross(Sn).dot(i)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,i){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,n,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,i),this}clone(){return(new this.constructor).copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Mn.subVectors(this.c,this.b),Sn.subVectors(this.a,this.b),.5*Mn.cross(Sn).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return In.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return In.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,n,i,r){return In.getInterpolation(e,this.a,this.b,this.c,t,n,i,r)}containsPoint(e){return In.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return In.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const n=this.a,i=this.b,r=this.c;let a,s;wn.subVectors(i,n),An.subVectors(r,n),Cn.subVectors(e,n);const o=wn.dot(Cn),l=An.dot(Cn);if(o<=0&&l<=0)return t.copy(n);Pn.subVectors(e,i);const c=wn.dot(Pn),h=An.dot(Pn);if(c>=0&&h<=c)return t.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return a=o/(o-c),t.copy(n).addScaledVector(wn,a);Ln.subVectors(e,r);const d=wn.dot(Ln),p=An.dot(Ln);if(p>=0&&d<=p)return t.copy(r);const f=d*l-o*p;if(f<=0&&l>=0&&p<=0)return s=l/(l-p),t.copy(n).addScaledVector(An,s);const m=c*p-d*h;if(m<=0&&h-c>=0&&d-p>=0)return Rn.subVectors(r,i),s=(h-c)/(h-c+(d-p)),t.copy(i).addScaledVector(Rn,s);const g=1/(m+f+u);return a=f*g,s=u*g,t.copy(n).addScaledVector(wn,a).addScaledVector(An,s)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const Nn={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},Un={h:0,s:0,l:0},Dn={h:0,s:0,l:0};function On(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+6*(t-e)*(2/3-n):e}class Fn{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(void 0===t&&void 0===n){const t=e;t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t="srgb"){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,nt.toWorkingColorSpace(this,t),this}setRGB(e,t,n,i=nt.workingColorSpace){return this.r=e,this.g=t,this.b=n,nt.toWorkingColorSpace(this,i),this}setHSL(e,t,n,i=nt.workingColorSpace){if(e=Be(e,1),t=ke(t,0,1),n=ke(n,0,1),0===t)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+t):n+t-n*t,r=2*n-i;this.r=On(r,i,e+1/3),this.g=On(r,i,e),this.b=On(r,i,e-1/3)}return nt.toWorkingColorSpace(this,i),this}setStyle(e,t="srgb"){function n(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let r;const a=i[1],s=i[2];switch(a){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,t);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,t);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,t);if(6===r)return this.setHex(parseInt(n,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t="srgb"){const n=Nn[e.toLowerCase()];return void 0!==n?this.setHex(n,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=it(e.r),this.g=it(e.g),this.b=it(e.b),this}copyLinearToSRGB(e){return this.r=rt(e.r),this.g=rt(e.g),this.b=rt(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e="srgb"){return nt.fromWorkingColorSpace(kn.copy(this),e),65536*Math.round(ke(255*kn.r,0,255))+256*Math.round(ke(255*kn.g,0,255))+Math.round(ke(255*kn.b,0,255))}getHexString(e="srgb"){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=nt.workingColorSpace){nt.fromWorkingColorSpace(kn.copy(this),t);const n=kn.r,i=kn.g,r=kn.b,a=Math.max(n,i,r),s=Math.min(n,i,r);let o,l;const c=(s+a)/2;if(s===a)o=0,l=0;else{const e=a-s;switch(l=c<=.5?e/(a+s):e/(2-a-s),a){case n:o=(i-r)/e+(i0!=e>0&&this.version++,this._alphaTest=e}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(const t in e){const n=e[t];if(void 0===n){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const i=this[t];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[t]=n:console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`)}}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(e){const t=[];for(const n in e){const i=e[n];delete i.metadata,t.push(i)}return t}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(n.dispersion=this.dispersion),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapRotation&&(n.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),0!==this.side&&(n.side=this.side),!0===this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=!0),this.blendSrc!==s&&(n.blendSrc=this.blendSrc),this.blendDst!==o&&(n.blendDst=this.blendDst),this.blendEquation!==a&&(n.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(n.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(n.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(n.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(n.depthFunc=this.depthFunc),!1===this.depthTest&&(n.depthTest=this.depthTest),!1===this.depthWrite&&(n.depthWrite=this.depthWrite),!1===this.colorWrite&&(n.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(n.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(n.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(n.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==Ae&&(n.stencilFail=this.stencilFail),this.stencilZFail!==Ae&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==Ae&&(n.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(n.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaHash&&(n.alphaHash=!0),!0===this.alphaToCoverage&&(n.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=!0),!0===this.forceSinglePass&&(n.forceSinglePass=!0),!0===this.wireframe&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),t){const t=i(e.textures),r=i(e.images);t.length>0&&(n.textures=t),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let n=null;if(null!==t){const e=t.length;n=new Array(e);for(let i=0;i!==e;++i)n[i]=t[i].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}onBeforeRender(){console.warn("Material: onBeforeRender() has been removed.")}}class Hn extends zn{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Fn(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.envMapRotation=new rn,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const Vn=new vt,Gn=new We;class Wn{constructor(e,t,n=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=n,this.usage=Re,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.gpuType=w,this.version=0}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return Je("THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let i=0,r=this.itemSize;i0&&(e.userData=this.userData),void 0!==this.parameters){const t=this.parameters;for(const n in t)void 0!==t[n]&&(e[n]=t[n]);return e}e.data={attributes:{}};const t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const n=this.attributes;for(const t in n){const i=n[t];e.data.attributes[t]=i.toJSON(e.data)}const i={};let r=!1;for(const t in this.morphAttributes){const n=this.morphAttributes[t],a=[];for(let t=0,i=n.length;t0&&(i[t]=a,r=!0)}r&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(e.data.groups=JSON.parse(JSON.stringify(a)));const s=this.boundingSphere;return null!==s&&(e.data.boundingSphere={center:s.center.toArray(),radius:s.radius}),e}clone(){return(new this.constructor).copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const n=e.index;null!==n&&this.setIndex(n.clone(t));const i=e.attributes;for(const e in i){const n=i[e];this.setAttribute(e,n.clone(t))}const r=e.morphAttributes;for(const e in r){const n=[],i=r[e];for(let e=0,r=i.length;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;e(e.far-e.near)**2)return}ni.copy(r).invert(),ii.copy(e.ray).applyMatrix4(ni),null!==n.boundingBox&&!1===ii.intersectsBox(n.boundingBox)||this._computeIntersections(e,t,ii)}}_computeIntersections(e,t,n){let i;const r=this.geometry,a=this.material,s=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==s)if(Array.isArray(a))for(let r=0,o=u.length;rn.far?null:{distance:c,point:_i.clone(),object:e}}(e,t,n,i,si,oi,li,vi);if(h){r&&(ui.fromBufferAttribute(r,o),di.fromBufferAttribute(r,l),pi.fromBufferAttribute(r,c),h.uv=In.getInterpolation(vi,si,oi,li,ui,di,pi,new We)),a&&(ui.fromBufferAttribute(a,o),di.fromBufferAttribute(a,l),pi.fromBufferAttribute(a,c),h.uv1=In.getInterpolation(vi,si,oi,li,ui,di,pi,new We)),s&&(fi.fromBufferAttribute(s,o),mi.fromBufferAttribute(s,l),gi.fromBufferAttribute(s,c),h.normal=In.getInterpolation(vi,si,oi,li,fi,mi,gi,new vt),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const e={a:o,b:l,c:c,normal:new vt,materialIndex:0};In.getNormal(si,oi,li,e.normal),h.face=e}return h}class bi extends ti{constructor(e=1,t=1,n=1,i=1,r=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:n,widthSegments:i,heightSegments:r,depthSegments:a};const s=this;i=Math.floor(i),r=Math.floor(r),a=Math.floor(a);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(e,t,n,i,r,a,p,f,m,g,v){const _=a/m,y=p/g,x=a/2,b=p/2,M=f/2,S=m+1,E=g+1;let T=0,w=0;const A=new vt;for(let a=0;a0?1:-1,c.push(A.x,A.y,A.z),h.push(o/m),h.push(1-a/g),T+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const n={};for(const e in this.extensions)!0===this.extensions[e]&&(n[e]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}}class Ai extends bn{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new qt,this.projectionMatrix=new qt,this.projectionMatrixInverse=new qt,this.coordinateSystem=Pe}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Ri=new vt,Ci=new We,Pi=new We;class Li extends Ai{constructor(e=50,t=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=2*Oe*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(.5*De*this.fov);return.5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*Oe*Math.atan(Math.tan(.5*De*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,n){Ri.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Ri.x,Ri.y).multiplyScalar(-e/Ri.z),Ri.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Ri.x,Ri.y).multiplyScalar(-e/Ri.z)}getViewSize(e,t){return this.getViewBounds(e,Ci,Pi),t.subVectors(Pi,Ci)}setViewOffset(e,t,n,i,r,a){this.aspect=e/t,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(.5*De*this.fov)/this.zoom,n=2*t,i=this.aspect*n,r=-.5*i;const a=this.view;if(null!==this.view&&this.view.enabled){const e=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/e,t-=a.offsetY*n/s,i*=a.width/e,n*=a.height/s}const s=this.filmOffset;0!==s&&(r+=e*s/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-n,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const Ii=-90;class Ni extends bn{constructor(e,t,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Li(Ii,1,e,t);i.layers=this.layers,this.add(i);const r=new Li(Ii,1,e,t);r.layers=this.layers,this.add(r);const a=new Li(Ii,1,e,t);a.layers=this.layers,this.add(a);const s=new Li(Ii,1,e,t);s.layers=this.layers,this.add(s);const o=new Li(Ii,1,e,t);o.layers=this.layers,this.add(o);const l=new Li(Ii,1,e,t);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[n,i,r,a,s,o]=t;for(const e of t)this.remove(e);if(e===Pe)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),s.up.set(0,1,0),s.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else{if(e!==Le)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),s.up.set(0,-1,0),s.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1)}for(const e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[r,a,s,o,l,c]=this.children,h=e.getRenderTarget(),u=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;const f=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,e.setRenderTarget(n,0,i),e.render(t,r),e.setRenderTarget(n,1,i),e.render(t,a),e.setRenderTarget(n,2,i),e.render(t,s),e.setRenderTarget(n,3,i),e.render(t,o),e.setRenderTarget(n,4,i),e.render(t,l),n.texture.generateMipmaps=f,e.setRenderTarget(n,5,i),e.render(t,c),e.setRenderTarget(h,u,d),e.xr.enabled=p,n.texture.needsPMREMUpdate=!0}}class Ui extends ht{constructor(e,t,n,i,r,a,s,o,l,h){super(e=void 0!==e?e:[],t=void 0!==t?t:c,n,i,r,a,s,o,l,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class Di extends pt{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const n={width:e,height:e,depth:1},i=[n,n,n,n,n,n];this.texture=new Ui(i,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:v}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new bi(5,5,5),r=new wi({name:"CubemapFromEquirect",uniforms:Mi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=t;const a=new yi(i,r),s=t.minFilter;t.minFilter===y&&(t.minFilter=v);return new Ni(1,10,this).update(e,a),t.minFilter=s,a.geometry.dispose(),a.material.dispose(),this}clear(e,t,n,i){const r=e.getRenderTarget();for(let r=0;r<6;r++)e.setRenderTarget(this,r),e.clear(t,n,i);e.setRenderTarget(r)}}const Oi=new vt,Fi=new vt,ki=new je;class Bi{constructor(e=new vt(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,n,i){return this.normal.set(e,t,n),this.constant=i,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,n){const i=Oi.subVectors(n,t).cross(Fi.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(i,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){const e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t){const n=e.delta(Oi),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(e.start)?t.copy(e.start):null;const r=-(e.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:t.copy(e.start).addScaledVector(n,r)}intersectsLine(e){const t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const n=t||ki.getNormalMatrix(e),i=this.coplanarPoint(Oi).applyMatrix4(e),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const zi=new kt,Hi=new vt;class Vi{constructor(e=new Bi,t=new Bi,n=new Bi,i=new Bi,r=new Bi,a=new Bi){this.planes=[e,t,n,i,r,a]}set(e,t,n,i,r,a){const s=this.planes;return s[0].copy(e),s[1].copy(t),s[2].copy(n),s[3].copy(i),s[4].copy(r),s[5].copy(a),this}copy(e){const t=this.planes;for(let n=0;n<6;n++)t[n].copy(e.planes[n]);return this}setFromProjectionMatrix(e,t=2e3){const n=this.planes,i=e.elements,r=i[0],a=i[1],s=i[2],o=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],f=i[10],m=i[11],g=i[12],v=i[13],_=i[14],y=i[15];if(n[0].setComponents(o-r,u-l,m-d,y-g).normalize(),n[1].setComponents(o+r,u+l,m+d,y+g).normalize(),n[2].setComponents(o+a,u+c,m+p,y+v).normalize(),n[3].setComponents(o-a,u-c,m-p,y-v).normalize(),n[4].setComponents(o-s,u-h,m-f,y-_).normalize(),t===Pe)n[5].setComponents(o+s,u+h,m+f,y+_).normalize();else{if(t!==Le)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);n[5].setComponents(s,h,f,_).normalize()}return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),zi.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),zi.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(zi)}intersectsSprite(e){return zi.center.set(0,0,0),zi.radius=.7071067811865476,zi.applyMatrix4(e.matrixWorld),this.intersectsSphere(zi)}intersectsSphere(e){const t=this.planes,n=e.center,i=-e.radius;for(let e=0;e<6;e++){if(t[e].distanceToPoint(n)0?e.max.x:e.min.x,Hi.y=i.normal.y>0?e.max.y:e.min.y,Hi.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(Hi)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function Gi(){let e=null,t=!1,n=null,i=null;function r(t,a){n(t,a),i=e.requestAnimationFrame(r)}return{start:function(){!0!==t&&null!==n&&(i=e.requestAnimationFrame(r),t=!0)},stop:function(){e.cancelAnimationFrame(i),t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function Wi(e){const t=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),t.get(e)},remove:function(n){n.isInterleavedBufferAttribute&&(n=n.data);const i=t.get(n);i&&(e.deleteBuffer(i.buffer),t.delete(n))},update:function(n,i){if(n.isInterleavedBufferAttribute&&(n=n.data),n.isGLBufferAttribute){const e=t.get(n);return void((!e||e.version 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif",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\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn 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}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn 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\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn 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\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn 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\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = 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\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn 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\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",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\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying 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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#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 \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying 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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#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\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},qi={common:{diffuse:{value:new Fn(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new je},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new je}},envmap:{envMap:{value:null},envMapRotation:{value:new je},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new je}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new je}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new je},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new je},normalScale:{value:new We(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new je},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new je}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new je}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new je}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Fn(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,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:new Fn(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0},uvTransform:{value:new je}},sprite:{diffuse:{value:new Fn(16777215)},opacity:{value:1},center:{value:new We(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new je},alphaMap:{value:null},alphaMapTransform:{value:new je},alphaTest:{value:0}}},Yi={basic:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.fog]),vertexShader:Xi.meshbasic_vert,fragmentShader:Xi.meshbasic_frag},lambert:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)}}]),vertexShader:Xi.meshlambert_vert,fragmentShader:Xi.meshlambert_frag},phong:{uniforms:Si([qi.common,qi.specularmap,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)},specular:{value:new Fn(1118481)},shininess:{value:30}}]),vertexShader:Xi.meshphong_vert,fragmentShader:Xi.meshphong_frag},standard:{uniforms:Si([qi.common,qi.envmap,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.roughnessmap,qi.metalnessmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Xi.meshphysical_vert,fragmentShader:Xi.meshphysical_frag},toon:{uniforms:Si([qi.common,qi.aomap,qi.lightmap,qi.emissivemap,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.gradientmap,qi.fog,qi.lights,{emissive:{value:new Fn(0)}}]),vertexShader:Xi.meshtoon_vert,fragmentShader:Xi.meshtoon_frag},matcap:{uniforms:Si([qi.common,qi.bumpmap,qi.normalmap,qi.displacementmap,qi.fog,{matcap:{value:null}}]),vertexShader:Xi.meshmatcap_vert,fragmentShader:Xi.meshmatcap_frag},points:{uniforms:Si([qi.points,qi.fog]),vertexShader:Xi.points_vert,fragmentShader:Xi.points_frag},dashed:{uniforms:Si([qi.common,qi.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Xi.linedashed_vert,fragmentShader:Xi.linedashed_frag},depth:{uniforms:Si([qi.common,qi.displacementmap]),vertexShader:Xi.depth_vert,fragmentShader:Xi.depth_frag},normal:{uniforms:Si([qi.common,qi.bumpmap,qi.normalmap,qi.displacementmap,{opacity:{value:1}}]),vertexShader:Xi.meshnormal_vert,fragmentShader:Xi.meshnormal_frag},sprite:{uniforms:Si([qi.sprite,qi.fog]),vertexShader:Xi.sprite_vert,fragmentShader:Xi.sprite_frag},background:{uniforms:{uvTransform:{value:new je},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Xi.background_vert,fragmentShader:Xi.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new je}},vertexShader:Xi.backgroundCube_vert,fragmentShader:Xi.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Xi.cube_vert,fragmentShader:Xi.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Xi.equirect_vert,fragmentShader:Xi.equirect_frag},distanceRGBA:{uniforms:Si([qi.common,qi.displacementmap,{referencePosition:{value:new vt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Xi.distanceRGBA_vert,fragmentShader:Xi.distanceRGBA_frag},shadow:{uniforms:Si([qi.lights,qi.fog,{color:{value:new Fn(0)},opacity:{value:1}}]),vertexShader:Xi.shadow_vert,fragmentShader:Xi.shadow_frag}};Yi.physical={uniforms:Si([Yi.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new je},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new je},clearcoatNormalScale:{value:new We(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new je},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new je},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new je},sheen:{value:0},sheenColor:{value:new Fn(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new je},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new je},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new je},transmissionSamplerSize:{value:new We},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new je},attenuationDistance:{value:0},attenuationColor:{value:new Fn(0)},specularColor:{value:new Fn(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new je},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new je},anisotropyVector:{value:new We},anisotropyMap:{value:null},anisotropyMapTransform:{value:new je}}]),vertexShader:Xi.meshphysical_vert,fragmentShader:Xi.meshphysical_frag};const Ki={r:0,b:0,g:0},Zi=new rn,Ji=new qt;function Qi(e,t,n,i,r,a,s){const o=new Fn(0);let l,c,h=!0===a?0:1,d=null,p=0,f=null;function m(e){let i=!0===e.isScene?e.background:null;if(i&&i.isTexture){i=(e.backgroundBlurriness>0?n:t).get(i)}return i}function g(t,n){t.getRGB(Ki,Ei(e)),i.buffers.color.setClear(Ki.r,Ki.g,Ki.b,n,s)}return{getClearColor:function(){return o},setClearColor:function(e,t=1){o.set(e),h=t,g(o,h)},getClearAlpha:function(){return h},setClearAlpha:function(e){h=e,g(o,h)},render:function(t){let n=!1;const r=m(t);null===r?g(o,h):r&&r.isColor&&(g(r,1),n=!0);const a=e.xr.getEnvironmentBlendMode();"additive"===a?i.buffers.color.setClear(0,0,0,1,s):"alpha-blend"===a&&i.buffers.color.setClear(0,0,0,0,s),(e.autoClear||n)&&(i.buffers.depth.setTest(!0),i.buffers.depth.setMask(!0),i.buffers.color.setMask(!0),e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil))},addToRenderList:function(t,n){const i=m(n);i&&(i.isCubeTexture||i.mapping===u)?(void 0===c&&(c=new yi(new bi(1,1,1),new wi({name:"BackgroundCubeMaterial",uniforms:Mi(Yi.backgroundCube.uniforms),vertexShader:Yi.backgroundCube.vertexShader,fragmentShader:Yi.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(c)),Zi.copy(n.backgroundRotation),Zi.x*=-1,Zi.y*=-1,Zi.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(Zi.y*=-1,Zi.z*=-1),c.material.uniforms.envMap.value=i,c.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,c.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,c.material.uniforms.backgroundRotation.value.setFromMatrix4(Ji.makeRotationFromEuler(Zi)),c.material.toneMapped=nt.getTransfer(i.colorSpace)!==Ee,d===i&&p===i.version&&f===e.toneMapping||(c.material.needsUpdate=!0,d=i,p=i.version,f=e.toneMapping),c.layers.enableAll(),t.unshift(c,c.geometry,c.material,0,0,null)):i&&i.isTexture&&(void 0===l&&(l=new yi(new ji(2,2),new wi({name:"BackgroundMaterial",uniforms:Mi(Yi.background.uniforms),vertexShader:Yi.background.vertexShader,fragmentShader:Yi.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(l)),l.material.uniforms.t2D.value=i,l.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,l.material.toneMapped=nt.getTransfer(i.colorSpace)!==Ee,!0===i.matrixAutoUpdate&&i.updateMatrix(),l.material.uniforms.uvTransform.value.copy(i.matrix),d===i&&p===i.version&&f===e.toneMapping||(l.material.needsUpdate=!0,d=i,p=i.version,f=e.toneMapping),l.layers.enableAll(),t.unshift(l,l.geometry,l.material,0,0,null))}}}function $i(e,t){const n=e.getParameter(e.MAX_VERTEX_ATTRIBS),i={},r=c(null);let a=r,s=!1;function o(t){return e.bindVertexArray(t)}function l(t){return e.deleteVertexArray(t)}function c(e){const t=[],i=[],r=[];for(let e=0;e=0){const n=r[t];let i=s[t];if(void 0===i&&("instanceMatrix"===t&&e.instanceMatrix&&(i=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(i=e.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;o++}}return a.attributesNum!==o||a.index!==i}(n,m,l,g),v&&function(e,t,n,i){const r={},s=t.attributes;let o=0;const l=n.getAttributes();for(const t in l){if(l[t].location>=0){let n=s[t];void 0===n&&("instanceMatrix"===t&&e.instanceMatrix&&(n=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(n=e.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[t]=i,o++}}a.attributes=r,a.attributesNum=o,a.index=i}(n,m,l,g),null!==g&&t.update(g,e.ELEMENT_ARRAY_BUFFER),(v||s)&&(s=!1,function(n,i,r,a){h();const s=a.attributes,o=r.getAttributes(),l=i.defaultAttributeValues;for(const i in o){const r=o[i];if(r.location>=0){let o=s[i];if(void 0===o&&("instanceMatrix"===i&&n.instanceMatrix&&(o=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(o=n.instanceColor)),void 0!==o){const i=o.normalized,s=o.itemSize,l=t.get(o);if(void 0===l)continue;const c=l.buffer,h=l.type,p=l.bytesPerElement,m=h===e.INT||h===e.UNSIGNED_INT||o.gpuType===E;if(o.isInterleavedBufferAttribute){const t=o.data,l=t.stride,g=o.offset;if(t.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let s=void 0!==n.precision?n.precision:"highp";const o=a(s);o!==s&&(console.warn("THREE.WebGLRenderer:",s,"not supported, using",o,"instead."),s=o);const l=!0===n.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===t.has("EXT_texture_filter_anisotropic")){const n=t.get("EXT_texture_filter_anisotropic");r=e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:a,textureFormatReadable:function(t){return t===I||i.convert(t)===e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===A&&(t.has("EXT_color_buffer_half_float")||t.has("EXT_color_buffer_float"));return!(n!==x&&i.convert(n)!==e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==w&&!r)},precision:s,logarithmicDepthBuffer:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:e.getParameter(e.MAX_TEXTURE_SIZE),maxCubemapSize:e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:e.getParameter(e.MAX_VERTEX_ATTRIBS),maxVertexUniforms:e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:e.getParameter(e.MAX_VARYING_VECTORS),maxFragmentUniforms:e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:h>0,maxSamples:e.getParameter(e.MAX_SAMPLES)}}function nr(e){const t=this;let n=null,i=0,r=!1,a=!1;const s=new Bi,o=new je,l={value:null,needsUpdate:!1};function c(e,n,i,r){const a=null!==e?e.length:0;let c=null;if(0!==a){if(c=l.value,!0!==r||null===c){const t=i+4*a,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);t.numPlanes=i,t.numIntersection=0}();else{const e=a?0:i,t=4*e;let r=f.clippingState||null;l.value=r,r=c(u,o,t,h);for(let e=0;e!==t;++e)r[e]=n[e];f.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=e}}}function ir(e){let t=new WeakMap;function n(e,t){return 303===t?e.mapping=c:304===t&&(e.mapping=h),e}function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping;if(303===a||304===a){if(t.has(r)){return n(t.get(r).texture,r.mapping)}{const a=r.image;if(a&&a.height>0){const s=new Di(a.height);return s.fromEquirectangularTexture(e,r),t.set(r,s),r.addEventListener("dispose",i),n(s.texture,r.mapping)}return null}}}return r},dispose:function(){t=new WeakMap}}}class rr extends Ai{constructor(e=-1,t=1,n=1,i=-1,r=.1,a=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=e,this.right=t,this.top=n,this.bottom=i,this.near=r,this.far=a,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.left=e.left,this.right=e.right,this.top=e.top,this.bottom=e.bottom,this.near=e.near,this.far=e.far,this.zoom=e.zoom,this.view=null===e.view?null:Object.assign({},e.view),this}setViewOffset(e,t,n,i,r,a){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=(this.right-this.left)/(2*this.zoom),t=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-e,a=n+e,s=i+t,o=i-t;if(null!==this.view&&this.view.enabled){const e=(this.right-this.left)/this.view.fullWidth/this.zoom,t=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=e*this.view.offsetX,a=r+e*this.view.width,s-=t*this.view.offsetY,o=s-t*this.view.height}this.projectionMatrix.makeOrthographic(r,a,s,o,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.zoom=this.zoom,t.object.left=this.left,t.object.right=this.right,t.object.top=this.top,t.object.bottom=this.bottom,t.object.near=this.near,t.object.far=this.far,null!==this.view&&(t.object.view=Object.assign({},this.view)),t}}const ar=[.125,.215,.35,.446,.526,.582],sr=20,or=new rr,lr=new Fn;let cr=null,hr=0,ur=0,dr=!1;const pr=(1+Math.sqrt(5))/2,fr=1/pr,mr=[new vt(-pr,fr,0),new vt(pr,fr,0),new vt(-fr,0,pr),new vt(fr,0,pr),new vt(0,pr,-fr),new vt(0,pr,fr),new vt(-1,1,-1),new vt(1,1,-1),new vt(-1,1,1),new vt(1,1,1)];class gr{constructor(e){this._renderer=e,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(e,t=0,n=.1,i=100){cr=this._renderer.getRenderTarget(),hr=this._renderer.getActiveCubeFace(),ur=this._renderer.getActiveMipmapLevel(),dr=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,n,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=xr(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=yr(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?o=ar[s-e+4-1]:0===s&&(o=0),i.push(o);const l=1/(a-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,f=3,m=2,g=1,v=new Float32Array(f*p*d),_=new Float32Array(m*p*d),y=new Float32Array(g*p*d);for(let e=0;e2?0:-1,i=[t,n,0,t+2/3,n,0,t+2/3,n+1,0,t,n,0,t+2/3,n+1,0,t,n+1,0];v.set(i,f*p*e),_.set(u,m*p*e);const r=[e,e,e,e,e,e];y.set(r,g*p*e)}const x=new ti;x.setAttribute("position",new Wn(v,f)),x.setAttribute("uv",new Wn(_,m)),x.setAttribute("faceIndex",new Wn(y,g)),t.push(x),r>4&&r--}return{lodPlanes:t,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(e,t,n){const i=new Float32Array(sr),r=new vt(0,1,0);return new wi({name:"SphericalGaussianBlur",defines:{n:sr,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}(i,e,t)}return i}_compileMaterial(e){const t=new yi(this._lodPlanes[0],e);this._renderer.compile(t,or)}_sceneToCubeUV(e,t,n,i){const r=new Li(90,1,t,n),a=[1,-1,1,1,1,1],s=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(lr),o.toneMapping=0,o.autoClear=!1;const h=new Hn({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new yi(new bi,h);let d=!1;const p=e.background;p?p.isColor&&(h.color.copy(p),e.background=null,d=!0):(h.color.copy(lr),d=!0);for(let t=0;t<6;t++){const n=t%3;0===n?(r.up.set(0,a[t],0),r.lookAt(s[t],0,0)):1===n?(r.up.set(0,0,a[t]),r.lookAt(0,s[t],0)):(r.up.set(0,a[t],0),r.lookAt(0,0,s[t]));const l=this._cubeSize;_r(i,n*l,t>2?l:0,l,l),o.setRenderTarget(i),d&&o.render(u,r),o.render(e,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,e.background=p}_textureToCubeUV(e,t){const n=this._renderer,i=e.mapping===c||e.mapping===h;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=xr()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===e.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=yr());const r=i?this._cubemapMaterial:this._equirectMaterial,a=new yi(this._lodPlanes[0],r);r.uniforms.envMap.value=e;const s=this._cubeSize;_r(t,0,0,3*s,2*s),n.setRenderTarget(t),n.render(a,or)}_applyPMREM(e){const t=this._renderer,n=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;tsr&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${f} samples when the maximum is set to 20`);const m=[];let g=0;for(let e=0;ev-4?i-v+4:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(t),o.render(c,or)}}function vr(e,t,n){const i=new pt(e,t,n);return i.texture.mapping=u,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function _r(e,t,n,i,r){e.viewport.set(t,n,i,r),e.scissor.set(t,n,i,r)}function yr(){return new wi({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function xr(){return new wi({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:br(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function br(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Mr(e){let t=new WeakMap,n=null;function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping,s=303===a||304===a,o=a===c||a===h;if(s||o){let a=t.get(r);const l=void 0!==a?a.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new gr(e)),a=s?n.fromEquirectangular(r,a):n.fromCubemap(r,a),a.texture.pmremVersion=r.pmremVersion,t.set(r,a),a.texture;if(void 0!==a)return a.texture;{const l=r.image;return s&&l&&l.height>0||o&&l&&function(e){let t=0;const n=6;for(let i=0;it.maxTextureSize&&(x=Math.ceil(y/t.maxTextureSize),y=t.maxTextureSize);const b=new Float32Array(y*x*4*h),M=new ft(b,y,x,h);M.type=w,M.needsUpdate=!0;const S=4*_;for(let T=0;T0)return e;const r=t*n;let a=Dr[r];if(void 0===a&&(a=new Float32Array(r),Dr[r]=a),0!==t){i.toArray(a,0);for(let i=1,r=0;i!==t;++i)r+=n,e[i].toArray(a,r)}return a}function Hr(e,t){if(e.length!==t.length)return!1;for(let n=0,i=e.length;n":" "} ${r}: ${n[e]}`)}return i.join("\n")}(e.getShaderSource(t),i)}return r}function ka(e,t){const n=function(e){const t=nt.getPrimaries(nt.workingColorSpace),n=nt.getPrimaries(e);let i;switch(t===n?i="":t===we&&n===Te?i="LinearDisplayP3ToLinearSRGB":t===Te&&n===we&&(i="LinearSRGBToLinearDisplayP3"),e){case xe:case Me:return[i,"LinearTransferOETF"];case ye:case be:return[i,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",e),[i,"LinearTransferOETF"]}}(t);return`vec4 ${e}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function Ba(e,t){let n;switch(t){case 1:n="Linear";break;case 2:n="Reinhard";break;case 3:n="OptimizedCineon";break;case 4:n="ACESFilmic";break;case 6:n="AgX";break;case 7:n="Neutral";break;case 5:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),n="Linear"}return"vec3 "+e+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const za=new vt;function Ha(){nt.getLuminanceCoefficients(za);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${za.x.toFixed(4)}, ${za.y.toFixed(4)}, ${za.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function Va(e){return""!==e}function Ga(e,t){const n=t.numSpotLightShadows+t.numSpotLightMaps-t.numSpotLightShadowsWithMaps;return e.replace(/NUM_DIR_LIGHTS/g,t.numDirLights).replace(/NUM_SPOT_LIGHTS/g,t.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,t.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,t.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,t.numPointLights).replace(/NUM_HEMI_LIGHTS/g,t.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,t.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,t.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,t.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,t.numPointLightShadows)}function Wa(e,t){return e.replace(/NUM_CLIPPING_PLANES/g,t.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,t.numClippingPlanes-t.numClipIntersection)}const ja=/^[ \t]*#include +<([\w\d./]+)>/gm;function Xa(e){return e.replace(ja,Ya)}const qa=new Map;function Ya(e,t){let n=Xi[t];if(void 0===n){const e=qa.get(t);if(void 0===e)throw new Error("Can not resolve #include <"+t+">");n=Xi[e],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,e)}return Xa(n)}const Ka=/#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 Za(e){return e.replace(Ka,Ja)}function Ja(e,t,n,i){let r="";for(let e=parseInt(t);e0&&(y+="\n"),x=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(Va).join("\n"),x.length>0&&(x+="\n")):(y=[Qa(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+l:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Va).join("\n"),x=[Qa(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.envMap?"#define "+f:"",m?"#define CUBEUV_TEXEL_WIDTH "+m.texelWidth:"",m?"#define CUBEUV_TEXEL_HEIGHT "+m.texelHeight:"",m?"#define CUBEUV_MAX_MIP "+m.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+l:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?Xi.tonemapping_pars_fragment:"",0!==n.toneMapping?Ba("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",Xi.colorspace_pars_fragment,ka("linearToOutputTexel",n.outputColorSpace),Ha(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Va).join("\n")),s=Xa(s),s=Ga(s,n),s=Wa(s,n),o=Xa(o),o=Ga(o,n),o=Wa(o,n),s=Za(s),o=Za(o),!0!==n.isRawShaderMaterial&&(b="#version 300 es\n",y=[g,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#define varying in",n.glslVersion===Ce?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Ce?"":"#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"+x);const M=b+y+s,S=b+x+o,E=Da(r,r.VERTEX_SHADER,M),T=Da(r,r.FRAGMENT_SHADER,S);function w(t){if(e.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(E).trim(),a=r.getShaderInfoLog(T).trim();let s=!0,o=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(s=!1,"function"==typeof e.debug.onShaderError)e.debug.onShaderError(r,_,E,T);else{const e=Fa(r,E,"vertex"),i=Fa(r,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+t.name+"\nMaterial Type: "+t.type+"\n\nProgram Info Log: "+n+"\n"+e+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==a||(o=!1);o&&(t.diagnostics={runnable:s,programLog:n,vertexShader:{log:i,prefix:y},fragmentShader:{log:a,prefix:x}})}r.deleteShader(E),r.deleteShader(T),A=new Ua(r,_),R=function(e,t){const n={},i=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES);for(let r=0;r0,q=a.clearcoat>0,Y=a.dispersion>0,K=a.iridescence>0,Z=a.sheen>0,J=a.transmission>0,Q=X&&!!a.anisotropyMap,$=q&&!!a.clearcoatMap,ee=q&&!!a.clearcoatNormalMap,te=q&&!!a.clearcoatRoughnessMap,ne=K&&!!a.iridescenceMap,ie=K&&!!a.iridescenceThicknessMap,re=Z&&!!a.sheenColorMap,ae=Z&&!!a.sheenRoughnessMap,se=!!a.specularMap,oe=!!a.specularColorMap,le=!!a.specularIntensityMap,ce=J&&!!a.transmissionMap,he=J&&!!a.thicknessMap,ue=!!a.gradientMap,de=!!a.alphaMap,pe=a.alphaTest>0,fe=!!a.alphaHash,me=!!a.extensions;let ge=0;a.toneMapped&&(null!==I&&!0!==I.isXRRenderTarget||(ge=e.toneMapping));const ve={shaderID:E,shaderType:a.type,shaderName:a.name,vertexShader:A,fragmentShader:R,defines:a.defines,customVertexShaderID:C,customFragmentShaderID:P,isRawShaderMaterial:!0===a.isRawShaderMaterial,glslVersion:a.glslVersion,precision:f,batching:U,batchingColor:U&&null!==_._colorsTexture,instancing:N,instancingColor:N&&null!==_.instanceColor,instancingMorph:N&&null!==_.morphTexture,supportsVertexTextures:p,outputColorSpace:null===I?e.outputColorSpace:!0===I.isXRRenderTarget?I.texture.colorSpace:xe,alphaToCoverage:!!a.alphaToCoverage,map:D,matcap:O,envMap:F,envMapMode:F&&M.mapping,envMapCubeUVHeight:S,aoMap:k,lightMap:B,bumpMap:z,normalMap:H,displacementMap:p&&V,emissiveMap:G,normalMapObjectSpace:H&&1===a.normalMapType,normalMapTangentSpace:H&&0===a.normalMapType,metalnessMap:W,roughnessMap:j,anisotropy:X,anisotropyMap:Q,clearcoat:q,clearcoatMap:$,clearcoatNormalMap:ee,clearcoatRoughnessMap:te,dispersion:Y,iridescence:K,iridescenceMap:ne,iridescenceThicknessMap:ie,sheen:Z,sheenColorMap:re,sheenRoughnessMap:ae,specularMap:se,specularColorMap:oe,specularIntensityMap:le,transmission:J,transmissionMap:ce,thicknessMap:he,gradientMap:ue,opaque:!1===a.transparent&&1===a.blending&&!1===a.alphaToCoverage,alphaMap:de,alphaTest:pe,alphaHash:fe,combine:a.combine,mapUv:D&&g(a.map.channel),aoMapUv:k&&g(a.aoMap.channel),lightMapUv:B&&g(a.lightMap.channel),bumpMapUv:z&&g(a.bumpMap.channel),normalMapUv:H&&g(a.normalMap.channel),displacementMapUv:V&&g(a.displacementMap.channel),emissiveMapUv:G&&g(a.emissiveMap.channel),metalnessMapUv:W&&g(a.metalnessMap.channel),roughnessMapUv:j&&g(a.roughnessMap.channel),anisotropyMapUv:Q&&g(a.anisotropyMap.channel),clearcoatMapUv:$&&g(a.clearcoatMap.channel),clearcoatNormalMapUv:ee&&g(a.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:te&&g(a.clearcoatRoughnessMap.channel),iridescenceMapUv:ne&&g(a.iridescenceMap.channel),iridescenceThicknessMapUv:ie&&g(a.iridescenceThicknessMap.channel),sheenColorMapUv:re&&g(a.sheenColorMap.channel),sheenRoughnessMapUv:ae&&g(a.sheenRoughnessMap.channel),specularMapUv:se&&g(a.specularMap.channel),specularColorMapUv:oe&&g(a.specularColorMap.channel),specularIntensityMapUv:le&&g(a.specularIntensityMap.channel),transmissionMapUv:ce&&g(a.transmissionMap.channel),thicknessMapUv:he&&g(a.thicknessMap.channel),alphaMapUv:de&&g(a.alphaMap.channel),vertexTangents:!!x.attributes.tangent&&(H||X),vertexColors:a.vertexColors,vertexAlphas:!0===a.vertexColors&&!!x.attributes.color&&4===x.attributes.color.itemSize,pointsUvs:!0===_.isPoints&&!!x.attributes.uv&&(D||de),fog:!!y,useFog:!0===a.fog,fogExp2:!!y&&y.isFogExp2,flatShading:!0===a.flatShading,sizeAttenuation:!0===a.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===_.isSkinnedMesh,morphTargets:void 0!==x.morphAttributes.position,morphNormals:void 0!==x.morphAttributes.normal,morphColors:void 0!==x.morphAttributes.color,morphTargetsCount:w,morphTextureStride:L,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numLightProbes:o.numLightProbes,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:a.dithering,shadowMapEnabled:e.shadowMap.enabled&&h.length>0,shadowMapType:e.shadowMap.type,toneMapping:ge,decodeVideoTexture:D&&!0===a.map.isVideoTexture&&nt.getTransfer(a.map.colorSpace)===Ee,premultipliedAlpha:a.premultipliedAlpha,doubleSided:2===a.side,flipSided:1===a.side,useDepthPacking:a.depthPacking>=0,depthPacking:a.depthPacking||0,index0AttributeName:a.index0AttributeName,extensionClipCullDistance:me&&!0===a.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(me&&!0===a.extensions.multiDraw||U)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:a.customProgramCacheKey()};return ve.vertexUv1s=c.has(1),ve.vertexUv2s=c.has(2),ve.vertexUv3s=c.has(3),c.clear(),ve},getProgramCacheKey:function(t){const n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.customVertexShaderID),n.push(t.customFragmentShaderID)),void 0!==t.defines)for(const e in t.defines)n.push(e),n.push(t.defines[e]);return!1===t.isRawShaderMaterial&&(!function(e,t){e.push(t.precision),e.push(t.outputColorSpace),e.push(t.envMapMode),e.push(t.envMapCubeUVHeight),e.push(t.mapUv),e.push(t.alphaMapUv),e.push(t.lightMapUv),e.push(t.aoMapUv),e.push(t.bumpMapUv),e.push(t.normalMapUv),e.push(t.displacementMapUv),e.push(t.emissiveMapUv),e.push(t.metalnessMapUv),e.push(t.roughnessMapUv),e.push(t.anisotropyMapUv),e.push(t.clearcoatMapUv),e.push(t.clearcoatNormalMapUv),e.push(t.clearcoatRoughnessMapUv),e.push(t.iridescenceMapUv),e.push(t.iridescenceThicknessMapUv),e.push(t.sheenColorMapUv),e.push(t.sheenRoughnessMapUv),e.push(t.specularMapUv),e.push(t.specularColorMapUv),e.push(t.specularIntensityMapUv),e.push(t.transmissionMapUv),e.push(t.thicknessMapUv),e.push(t.combine),e.push(t.fogExp2),e.push(t.sizeAttenuation),e.push(t.morphTargetsCount),e.push(t.morphAttributeCount),e.push(t.numDirLights),e.push(t.numPointLights),e.push(t.numSpotLights),e.push(t.numSpotLightMaps),e.push(t.numHemiLights),e.push(t.numRectAreaLights),e.push(t.numDirLightShadows),e.push(t.numPointLightShadows),e.push(t.numSpotLightShadows),e.push(t.numSpotLightShadowsWithMaps),e.push(t.numLightProbes),e.push(t.shadowMapType),e.push(t.toneMapping),e.push(t.numClippingPlanes),e.push(t.numClipIntersection),e.push(t.depthPacking)}(n,t),function(e,t){o.disableAll(),t.supportsVertexTextures&&o.enable(0);t.instancing&&o.enable(1);t.instancingColor&&o.enable(2);t.instancingMorph&&o.enable(3);t.matcap&&o.enable(4);t.envMap&&o.enable(5);t.normalMapObjectSpace&&o.enable(6);t.normalMapTangentSpace&&o.enable(7);t.clearcoat&&o.enable(8);t.iridescence&&o.enable(9);t.alphaTest&&o.enable(10);t.vertexColors&&o.enable(11);t.vertexAlphas&&o.enable(12);t.vertexUv1s&&o.enable(13);t.vertexUv2s&&o.enable(14);t.vertexUv3s&&o.enable(15);t.vertexTangents&&o.enable(16);t.anisotropy&&o.enable(17);t.alphaHash&&o.enable(18);t.batching&&o.enable(19);t.dispersion&&o.enable(20);t.batchingColor&&o.enable(21);e.push(o.mask),o.disableAll(),t.fog&&o.enable(0);t.useFog&&o.enable(1);t.flatShading&&o.enable(2);t.logarithmicDepthBuffer&&o.enable(3);t.skinning&&o.enable(4);t.morphTargets&&o.enable(5);t.morphNormals&&o.enable(6);t.morphColors&&o.enable(7);t.premultipliedAlpha&&o.enable(8);t.shadowMapEnabled&&o.enable(9);t.doubleSided&&o.enable(10);t.flipSided&&o.enable(11);t.useDepthPacking&&o.enable(12);t.dithering&&o.enable(13);t.transmission&&o.enable(14);t.sheen&&o.enable(15);t.opaque&&o.enable(16);t.pointsUvs&&o.enable(17);t.decodeVideoTexture&&o.enable(18);t.alphaToCoverage&&o.enable(19);e.push(o.mask)}(n,t),n.push(e.outputColorSpace)),n.push(t.customProgramCacheKey),n.join()},getUniforms:function(e){const t=m[e.type];let n;if(t){const e=Yi[t];n=Ti.clone(e.uniforms)}else n=e.uniforms;return n},acquireProgram:function(t,n){let i;for(let e=0,t=h.length;e0?i.push(h):!0===s.transparent?r.push(h):n.push(h)},unshift:function(e,t,s,o,l,c){const h=a(e,t,s,o,l,c);s.transmission>0?i.unshift(h):!0===s.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=t,i=e.length;n1&&n.sort(e||as),i.length>1&&i.sort(t||ss),r.length>1&&r.sort(t||ss)}}}function ls(){let e=new WeakMap;return{get:function(t,n){const i=e.get(t);let r;return void 0===i?(r=new os,e.set(t,[r])):n>=i.length?(r=new os,i.push(r)):r=i[n],r},dispose:function(){e=new WeakMap}}}function cs(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let n;switch(t.type){case"DirectionalLight":n={direction:new vt,color:new Fn};break;case"SpotLight":n={position:new vt,direction:new vt,color:new Fn,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new vt,color:new Fn,distance:0,decay:0};break;case"HemisphereLight":n={direction:new vt,skyColor:new Fn,groundColor:new Fn};break;case"RectAreaLight":n={color:new Fn,position:new vt,halfWidth:new vt,halfHeight:new vt}}return e[t.id]=n,n}}}let hs=0;function us(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+(t.map?1:0)-(e.map?1:0)}function ds(e){const t=new cs,n=function(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let n;switch(t.type){case"DirectionalLight":case"SpotLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new We};break;case"PointLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new We,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=n,n}}}(),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let e=0;e<9;e++)i.probe.push(new vt);const r=new vt,a=new qt,s=new qt;return{setup:function(r){let a=0,s=0,o=0;for(let e=0;e<9;e++)i.probe[e].set(0,0,0);let l=0,c=0,h=0,u=0,d=0,p=0,f=0,m=0,g=0,v=0,_=0;r.sort(us);for(let e=0,y=r.length;e0&&(!0===e.has("OES_texture_float_linear")?(i.rectAreaLTC1=qi.LTC_FLOAT_1,i.rectAreaLTC2=qi.LTC_FLOAT_2):(i.rectAreaLTC1=qi.LTC_HALF_1,i.rectAreaLTC2=qi.LTC_HALF_2)),i.ambient[0]=a,i.ambient[1]=s,i.ambient[2]=o;const y=i.hash;y.directionalLength===l&&y.pointLength===c&&y.spotLength===h&&y.rectAreaLength===u&&y.hemiLength===d&&y.numDirectionalShadows===p&&y.numPointShadows===f&&y.numSpotShadows===m&&y.numSpotMaps===g&&y.numLightProbes===_||(i.directional.length=l,i.spot.length=h,i.rectArea.length=u,i.point.length=c,i.hemi.length=d,i.directionalShadow.length=p,i.directionalShadowMap.length=p,i.pointShadow.length=f,i.pointShadowMap.length=f,i.spotShadow.length=m,i.spotShadowMap.length=m,i.directionalShadowMatrix.length=p,i.pointShadowMatrix.length=f,i.spotLightMatrix.length=m+g-v,i.spotLightMap.length=g,i.numSpotLightShadowsWithMaps=v,i.numLightProbes=_,y.directionalLength=l,y.pointLength=c,y.spotLength=h,y.rectAreaLength=u,y.hemiLength=d,y.numDirectionalShadows=p,y.numPointShadows=f,y.numSpotShadows=m,y.numSpotMaps=g,y.numLightProbes=_,i.version=hs++)},setupView:function(e,t){let n=0,o=0,l=0,c=0,h=0;const u=t.matrixWorldInverse;for(let t=0,d=e.length;t=r.length?(a=new ps(e),r.push(a)):a=r[i],a},dispose:function(){t=new WeakMap}}}class ms extends zn{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class gs extends zn{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}function vs(e,t,n){let i=new Vi;const r=new We,a=new We,s=new ut,o=new ms({depthPacking:3201}),l=new gs,c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new wi({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new We},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),p=d.clone();p.defines.HORIZONTAL_PASS=1;const f=new ti;f.setAttribute("position",new Wn(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new yi(f,d),v=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=1;let _=this.type;function y(n,i){const a=t.update(g);d.defines.VSM_SAMPLES!==n.blurSamples&&(d.defines.VSM_SAMPLES=n.blurSamples,p.defines.VSM_SAMPLES=n.blurSamples,d.needsUpdate=!0,p.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new pt(r.x,r.y)),d.uniforms.shadow_pass.value=n.map.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,a,d,g,null),p.uniforms.shadow_pass.value=n.mapPass.texture,p.uniforms.resolution.value=n.mapSize,p.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,a,p,g,null)}function x(t,n,i,r){let a=null;const s=!0===i.isPointLight?t.customDistanceMaterial:t.customDepthMaterial;if(void 0!==s)a=s;else if(a=!0===i.isPointLight?l:o,e.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const e=a.uuid,t=n.uuid;let i=c[e];void 0===i&&(i={},c[e]=i);let r=i[t];void 0===r&&(r=a.clone(),i[t]=r,n.addEventListener("dispose",M)),a=r}if(a.visible=n.visible,a.wireframe=n.wireframe,a.side=3===r?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:u[n.side],a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,!0===i.isPointLight&&!0===a.isMeshDistanceMaterial){e.properties.get(a).light=i}return a}function b(n,r,a,s,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);const i=t.update(n),l=n.material;if(Array.isArray(l)){const t=i.groups;for(let c=0,h=t.length;ch||r.y>h)&&(r.x>h&&(a.x=Math.floor(h/g.x),r.x=a.x*g.x,u.mapSize.x=a.x),r.y>h&&(a.y=Math.floor(h/g.y),r.y=a.y*g.y,u.mapSize.y=a.y)),null===u.map||!0===p||!0===f){const e=3!==this.type?{minFilter:m,magFilter:m}:{};null!==u.map&&u.map.dispose(),u.map=new pt(r.x,r.y,e),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}e.setRenderTarget(u.map),e.clear();const v=u.getViewportCount();for(let e=0;e=1):-1!==N.indexOf("OpenGL ES")&&(I=parseFloat(/^OpenGL ES (\d)/.exec(N)[1]),L=I>=2);let U=null,D={};const O=e.getParameter(e.SCISSOR_BOX),F=e.getParameter(e.VIEWPORT),k=(new ut).fromArray(O),B=(new ut).fromArray(F);function z(t,n,i,r){const a=new Uint8Array(4),s=e.createTexture();e.bindTexture(t,s),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(let s=0;sn||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&e instanceof VideoFrame){const n=Math.floor(i*r.width),a=Math.floor(i*r.height);void 0===u&&(u=E(n,a));const s=t?E(n,a):u;s.width=n,s.height=a;return s.getContext("2d").drawImage(e,0,0,n,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+a+")."),s}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),e}return e}function R(e){return e.generateMipmaps&&e.minFilter!==m&&e.minFilter!==v}function C(t){e.generateMipmap(t)}function L(n,i,r,a,s=!1){if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let o=i;if(i===e.RED&&(r===e.FLOAT&&(o=e.R32F),r===e.HALF_FLOAT&&(o=e.R16F),r===e.UNSIGNED_BYTE&&(o=e.R8)),i===e.RED_INTEGER&&(r===e.UNSIGNED_BYTE&&(o=e.R8UI),r===e.UNSIGNED_SHORT&&(o=e.R16UI),r===e.UNSIGNED_INT&&(o=e.R32UI),r===e.BYTE&&(o=e.R8I),r===e.SHORT&&(o=e.R16I),r===e.INT&&(o=e.R32I)),i===e.RG&&(r===e.FLOAT&&(o=e.RG32F),r===e.HALF_FLOAT&&(o=e.RG16F),r===e.UNSIGNED_BYTE&&(o=e.RG8)),i===e.RG_INTEGER&&(r===e.UNSIGNED_BYTE&&(o=e.RG8UI),r===e.UNSIGNED_SHORT&&(o=e.RG16UI),r===e.UNSIGNED_INT&&(o=e.RG32UI),r===e.BYTE&&(o=e.RG8I),r===e.SHORT&&(o=e.RG16I),r===e.INT&&(o=e.RG32I)),i===e.RGB&&r===e.UNSIGNED_INT_5_9_9_9_REV&&(o=e.RGB9_E5),i===e.RGBA){const t=s?Se:nt.getTransfer(a);r===e.FLOAT&&(o=e.RGBA32F),r===e.HALF_FLOAT&&(o=e.RGBA16F),r===e.UNSIGNED_BYTE&&(o=t===Ee?e.SRGB8_ALPHA8:e.RGBA8),r===e.UNSIGNED_SHORT_4_4_4_4&&(o=e.RGBA4),r===e.UNSIGNED_SHORT_5_5_5_1&&(o=e.RGB5_A1)}return o!==e.R16F&&o!==e.R32F&&o!==e.RG16F&&o!==e.RG32F&&o!==e.RGBA16F&&o!==e.RGBA32F||t.get("EXT_color_buffer_float"),o}function D(t,n){let i;return t?null===n||n===T||n===P?i=e.DEPTH24_STENCIL8:n===w?i=e.DEPTH32F_STENCIL8:n===S&&(i=e.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===T||n===P?i=e.DEPTH_COMPONENT24:n===w?i=e.DEPTH_COMPONENT32F:n===S&&(i=e.DEPTH_COMPONENT16),i}function O(e,t){return!0===R(e)||e.isFramebufferTexture&&e.minFilter!==m&&e.minFilter!==v?Math.log2(Math.max(t.width,t.height))+1:void 0!==e.mipmaps&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function F(e){const t=e.target;t.removeEventListener("dispose",F),function(e){const t=i.get(e);if(void 0===t.__webglInit)return;const n=e.source,r=b.get(n);if(r){const i=r[t.__cacheKey];i.usedTimes--,0===i.usedTimes&&B(e),0===Object.keys(r).length&&b.delete(n)}i.remove(e)}(t),t.isVideoTexture&&h.delete(t)}function k(t){const n=t.target;n.removeEventListener("dispose",k),function(t){const n=i.get(t);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(n.__webglFramebuffer[t]))for(let i=0;i0&&a.__version!==t.version){const e=t.image;if(null===e)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==e.complete)return void q(a,t,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(e.TEXTURE_2D,a.__webglTexture,e.TEXTURE0+r)}const V={[d]:e.REPEAT,[p]:e.CLAMP_TO_EDGE,[f]:e.MIRRORED_REPEAT},G={[m]:e.NEAREST,1004:e.NEAREST_MIPMAP_NEAREST,[g]:e.NEAREST_MIPMAP_LINEAR,[v]:e.LINEAR,[_]:e.LINEAR_MIPMAP_NEAREST,[y]:e.LINEAR_MIPMAP_LINEAR},W={512:e.NEVER,519:e.ALWAYS,513:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL};function j(n,a){if(a.type!==w||!1!==t.has("OES_texture_float_linear")||a.magFilter!==v&&a.magFilter!==_&&a.magFilter!==g&&a.magFilter!==y&&a.minFilter!==v&&a.minFilter!==_&&a.minFilter!==g&&a.minFilter!==y||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),e.texParameteri(n,e.TEXTURE_WRAP_S,V[a.wrapS]),e.texParameteri(n,e.TEXTURE_WRAP_T,V[a.wrapT]),n!==e.TEXTURE_3D&&n!==e.TEXTURE_2D_ARRAY||e.texParameteri(n,e.TEXTURE_WRAP_R,V[a.wrapR]),e.texParameteri(n,e.TEXTURE_MAG_FILTER,G[a.magFilter]),e.texParameteri(n,e.TEXTURE_MIN_FILTER,G[a.minFilter]),a.compareFunction&&(e.texParameteri(n,e.TEXTURE_COMPARE_MODE,e.COMPARE_REF_TO_TEXTURE),e.texParameteri(n,e.TEXTURE_COMPARE_FUNC,W[a.compareFunction])),!0===t.has("EXT_texture_filter_anisotropic")){if(a.magFilter===m)return;if(a.minFilter!==g&&a.minFilter!==y)return;if(a.type===w&&!1===t.has("OES_texture_float_linear"))return;if(a.anisotropy>1||i.get(a).__currentAnisotropy){const s=t.get("EXT_texture_filter_anisotropic");e.texParameterf(n,s.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,r.getMaxAnisotropy())),i.get(a).__currentAnisotropy=a.anisotropy}}}function X(t,n){let i=!1;void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",F));const r=n.source;let a=b.get(r);void 0===a&&(a={},b.set(r,a));const o=function(e){const t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}(n);if(o!==t.__cacheKey){void 0===a[o]&&(a[o]={texture:e.createTexture(),usedTimes:0},s.memory.textures++,i=!0),a[o].usedTimes++;const r=a[t.__cacheKey];void 0!==r&&(a[t.__cacheKey].usedTimes--,0===r.usedTimes&&B(n)),t.__cacheKey=o,t.__webglTexture=a[o].texture}return i}function q(t,s,o){let l=e.TEXTURE_2D;(s.isDataArrayTexture||s.isCompressedArrayTexture)&&(l=e.TEXTURE_2D_ARRAY),s.isData3DTexture&&(l=e.TEXTURE_3D);const c=X(t,s),h=s.source;n.bindTexture(l,t.__webglTexture,e.TEXTURE0+o);const u=i.get(h);if(h.version!==u.__version||!0===c){n.activeTexture(e.TEXTURE0+o);const t=nt.getPrimaries(nt.workingColorSpace),i=s.colorSpace===_e?null:nt.getPrimaries(s.colorSpace),d=s.colorSpace===_e||t===i?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,s.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,s.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,s.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,d);let p=A(s.image,!1,r.maxTextureSize);p=te(s,p);const f=a.convert(s.format,s.colorSpace),m=a.convert(s.type);let g,v=L(s.internalFormat,f,m,s.colorSpace,s.isVideoTexture);j(l,s);const _=s.mipmaps,y=!0!==s.isVideoTexture,x=void 0===u.__version||!0===c,b=h.dataReady,M=O(s,p);if(s.isDepthTexture)v=D(s.format===U,s.type),x&&(y?n.texStorage2D(e.TEXTURE_2D,1,v,p.width,p.height):n.texImage2D(e.TEXTURE_2D,0,v,p.width,p.height,0,f,m,null));else if(s.isDataTexture)if(_.length>0){y&&x&&n.texStorage2D(e.TEXTURE_2D,M,v,_[0].width,_[0].height);for(let t=0,i=_.length;t0){const i=ys(g.width,g.height,s.format,s.type);for(const r of s.layerUpdates){const a=g.data.subarray(r*i/g.data.BYTES_PER_ELEMENT,(r+1)*i/g.data.BYTES_PER_ELEMENT);n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,r,g.width,g.height,1,f,a,0,0)}s.clearLayerUpdates()}else n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,p.depth,f,g.data,0,0)}else n.compressedTexImage3D(e.TEXTURE_2D_ARRAY,t,v,g.width,g.height,p.depth,0,g.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else y?b&&n.texSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,p.depth,f,m,g.data):n.texImage3D(e.TEXTURE_2D_ARRAY,t,v,g.width,g.height,p.depth,0,f,m,g.data)}else{y&&x&&n.texStorage2D(e.TEXTURE_2D,M,v,_[0].width,_[0].height);for(let t=0,i=_.length;t0){const t=ys(p.width,p.height,s.format,s.type);for(const i of s.layerUpdates){const r=p.data.subarray(i*t/p.data.BYTES_PER_ELEMENT,(i+1)*t/p.data.BYTES_PER_ELEMENT);n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,i,p.width,p.height,1,f,m,r)}s.clearLayerUpdates()}else n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,0,p.width,p.height,p.depth,f,m,p.data)}else n.texImage3D(e.TEXTURE_2D_ARRAY,0,v,p.width,p.height,p.depth,0,f,m,p.data);else if(s.isData3DTexture)y?(x&&n.texStorage3D(e.TEXTURE_3D,M,v,p.width,p.height,p.depth),b&&n.texSubImage3D(e.TEXTURE_3D,0,0,0,0,p.width,p.height,p.depth,f,m,p.data)):n.texImage3D(e.TEXTURE_3D,0,v,p.width,p.height,p.depth,0,f,m,p.data);else if(s.isFramebufferTexture){if(x)if(y)n.texStorage2D(e.TEXTURE_2D,M,v,p.width,p.height);else{let t=p.width,i=p.height;for(let r=0;r>=1,i>>=1}}else if(_.length>0){if(y&&x){const t=ne(_[0]);n.texStorage2D(e.TEXTURE_2D,M,v,t.width,t.height)}for(let t=0,i=_.length;t>h),i=Math.max(1,r.height>>h);c===e.TEXTURE_3D||c===e.TEXTURE_2D_ARRAY?n.texImage3D(c,h,p,t,i,r.depth,0,u,d,null):n.texImage2D(c,h,p,t,i,0,u,d,null)}n.bindFramebuffer(e.FRAMEBUFFER,t),ee(r)?o.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,l,c,i.get(s).__webglTexture,0,$(r)):(c===e.TEXTURE_2D||c>=e.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=e.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&e.framebufferTexture2D(e.FRAMEBUFFER,l,c,i.get(s).__webglTexture,h),n.bindFramebuffer(e.FRAMEBUFFER,null)}function K(t,n,i){if(e.bindRenderbuffer(e.RENDERBUFFER,t),n.depthBuffer){const r=n.depthTexture,a=r&&r.isDepthTexture?r.type:null,s=D(n.stencilBuffer,a),l=n.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,c=$(n);ee(n)?o.renderbufferStorageMultisampleEXT(e.RENDERBUFFER,c,s,n.width,n.height):i?e.renderbufferStorageMultisample(e.RENDERBUFFER,c,s,n.width,n.height):e.renderbufferStorage(e.RENDERBUFFER,s,n.width,n.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,l,e.RENDERBUFFER,t)}else{const t=n.textures;for(let r=0;r0&&!0===t.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function te(e,t){const n=e.colorSpace,i=e.format,r=e.type;return!0===e.isCompressedTexture||!0===e.isVideoTexture||n!==xe&&n!==_e&&(nt.getTransfer(n)===Ee?i===I&&r===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),t}function ne(e){return"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement?(c.width=e.naturalWidth||e.width,c.height=e.naturalHeight||e.height):"undefined"!=typeof VideoFrame&&e instanceof VideoFrame?(c.width=e.displayWidth,c.height=e.displayHeight):(c.width=e.width,c.height=e.height),c}this.allocateTextureUnit=function(){const e=z;return e>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+r.maxTextures),z+=1,e},this.resetTextureUnits=function(){z=0},this.setTexture2D=H,this.setTexture2DArray=function(t,r){const a=i.get(t);t.version>0&&a.__version!==t.version?q(a,t,r):n.bindTexture(e.TEXTURE_2D_ARRAY,a.__webglTexture,e.TEXTURE0+r)},this.setTexture3D=function(t,r){const a=i.get(t);t.version>0&&a.__version!==t.version?q(a,t,r):n.bindTexture(e.TEXTURE_3D,a.__webglTexture,e.TEXTURE0+r)},this.setTextureCube=function(t,s){const o=i.get(t);t.version>0&&o.__version!==t.version?function(t,s,o){if(6!==s.image.length)return;const l=X(t,s),c=s.source;n.bindTexture(e.TEXTURE_CUBE_MAP,t.__webglTexture,e.TEXTURE0+o);const h=i.get(c);if(c.version!==h.__version||!0===l){n.activeTexture(e.TEXTURE0+o);const t=nt.getPrimaries(nt.workingColorSpace),i=s.colorSpace===_e?null:nt.getPrimaries(s.colorSpace),u=s.colorSpace===_e||t===i?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,s.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,s.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,s.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,u);const d=s.isCompressedTexture||s.image[0].isCompressedTexture,p=s.image[0]&&s.image[0].isDataTexture,f=[];for(let e=0;e<6;e++)f[e]=d||p?p?s.image[e].image:s.image[e]:A(s.image[e],!0,r.maxCubemapSize),f[e]=te(s,f[e]);const m=f[0],g=a.convert(s.format,s.colorSpace),v=a.convert(s.type),_=L(s.internalFormat,g,v,s.colorSpace),y=!0!==s.isVideoTexture,x=void 0===h.__version||!0===l,b=c.dataReady;let M,S=O(s,m);if(j(e.TEXTURE_CUBE_MAP,s),d){y&&x&&n.texStorage2D(e.TEXTURE_CUBE_MAP,S,_,m.width,m.height);for(let t=0;t<6;t++){M=f[t].mipmaps;for(let i=0;i0&&S++;const t=ne(f[0]);n.texStorage2D(e.TEXTURE_CUBE_MAP,S,_,t.width,t.height)}for(let t=0;t<6;t++)if(p){y?b&&n.texSubImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,0,0,f[t].width,f[t].height,g,v,f[t].data):n.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,_,f[t].width,f[t].height,0,g,v,f[t].data);for(let i=0;i1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=e.createTexture()),l.__version=r.version,s.memory.textures++),h){o.__webglFramebuffer=[];for(let t=0;t<6;t++)if(r.mipmaps&&r.mipmaps.length>0){o.__webglFramebuffer[t]=[];for(let n=0;n0){o.__webglFramebuffer=[];for(let t=0;t0&&!1===ee(t)){o.__webglMultisampledFramebuffer=e.createFramebuffer(),o.__webglColorRenderbuffer=[],n.bindFramebuffer(e.FRAMEBUFFER,o.__webglMultisampledFramebuffer);for(let n=0;n0)for(let i=0;i0)for(let n=0;n0)if(!1===ee(t)){const r=t.textures,a=t.width,s=t.height;let o=e.COLOR_BUFFER_BIT;const c=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,h=i.get(t),u=r.length>1;if(u)for(let t=0;to+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!l.inputState.pinching&&s<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else null!==o&&e.gripSpace&&(r=t.getPose(e.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==s&&(i=t.getPose(e.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(s.matrix.fromArray(i.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,i.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(i.linearVelocity)):s.hasLinearVelocity=!1,i.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(i.angularVelocity)):s.hasAngularVelocity=!1,this.dispatchEvent(Es)))}return null!==s&&(s.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==a),this}_getHandJoint(e,t){if(void 0===e.joints[t.jointName]){const n=new Ss;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}class ws{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(null===this.texture){const i=new ht;e.properties.get(i).__webglTexture=t.texture,t.depthNear==n.depthNear&&t.depthFar==n.depthFar||(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=i}}getMesh(e){if(null!==this.texture&&null===this.mesh){const t=e.cameras[0].viewport,n=new wi({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new yi(new ji(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class As extends Ie{constructor(e,t){super();const n=this;let i=null,r=1,a=null,s="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const f=new ws,m=t.getContextAttributes();let g=null,v=null;const _=[],y=[],b=new We;let M=null;const S=new Li;S.layers.enable(1),S.viewport=new ut;const E=new Li;E.layers.enable(2),E.viewport=new ut;const w=[S,E],A=new Ms;A.layers.enable(1),A.layers.enable(2);let R=null,C=null;function L(e){const t=y.indexOf(e.inputSource);if(-1===t)return;const n=_[t];void 0!==n&&(n.update(e.inputSource,e.frame,l||a),n.dispatchEvent({type:e.type,data:e.inputSource}))}function D(){i.removeEventListener("select",L),i.removeEventListener("selectstart",L),i.removeEventListener("selectend",L),i.removeEventListener("squeeze",L),i.removeEventListener("squeezestart",L),i.removeEventListener("squeezeend",L),i.removeEventListener("end",D),i.removeEventListener("inputsourceschange",O);for(let e=0;e<_.length;e++){const t=y[e];null!==t&&(y[e]=null,_[e].disconnect(t))}R=null,C=null,f.reset(),e.setRenderTarget(g),d=null,u=null,h=null,i=null,v=null,H.stop(),n.isPresenting=!1,e.setPixelRatio(M),e.setSize(b.width,b.height,!1),n.dispatchEvent({type:"sessionend"})}function O(e){for(let t=0;t=0&&(y[i]=null,_[i].disconnect(n))}for(let t=0;t=y.length){y.push(n),i=e;break}if(null===y[e]){y[e]=n,i=e;break}}if(-1===i)break}const r=_[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=_[e];return void 0===t&&(t=new Ts,_[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=_[e];return void 0===t&&(t=new Ts,_[e]=t),t.getGripSpace()},this.getHand=function(e){let t=_[e];return void 0===t&&(t=new Ts,_[e]=t),t.getHandSpace()},this.setFramebufferScaleFactor=function(e){r=e,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(e){s=e,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||a},this.setReferenceSpace=function(e){l=e},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(g=e.getRenderTarget(),i.addEventListener("select",L),i.addEventListener("selectstart",L),i.addEventListener("selectend",L),i.addEventListener("squeeze",L),i.addEventListener("squeezestart",L),i.addEventListener("squeezeend",L),i.addEventListener("end",D),i.addEventListener("inputsourceschange",O),!0!==m.xrCompatible&&await t.makeXRCompatible(),M=e.getPixelRatio(),e.getSize(b),void 0===i.renderState.layers){const n={antialias:m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,t,n),i.updateRenderState({baseLayer:d}),e.setPixelRatio(1),e.setSize(d.framebufferWidth,d.framebufferHeight,!1),v=new pt(d.framebufferWidth,d.framebufferHeight,{format:I,type:x,colorSpace:e.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,a=null,s=null;m.depth&&(s=m.stencil?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT24,n=m.stencil?U:N,a=m.stencil?P:T);const o={colorFormat:t.RGBA8,depthFormat:s,scaleFactor:r};h=new XRWebGLBinding(i,t),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),e.setPixelRatio(1),e.setSize(u.textureWidth,u.textureHeight,!1),v=new pt(u.textureWidth,u.textureHeight,{format:I,type:x,depthTexture:new Cr(u.textureWidth,u.textureHeight,a,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:e.outputColorSpace,samples:m.antialias?4:0,resolveDepthBuffer:!1===u.ignoreDepthValues})}v.isXRRenderTarget=!0,this.setFoveation(o),l=null,a=await i.requestReferenceSpace(s),H.setContext(i),H.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode},this.getDepthTexture=function(){return f.getDepthTexture()};const F=new vt,k=new vt;function B(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){if(null===i)return;null!==f.texture&&(e.near=f.depthNear,e.far=f.depthFar),A.near=E.near=S.near=e.near,A.far=E.far=S.far=e.far,R===A.near&&C===A.far||(i.updateRenderState({depthNear:A.near,depthFar:A.far}),R=A.near,C=A.far,S.near=R,S.far=C,E.near=R,E.far=C,S.updateProjectionMatrix(),E.updateProjectionMatrix(),e.updateProjectionMatrix());const t=e.parent,n=A.cameras;B(A,t);for(let e=0;e0&&(e.alphaTest.value=i.alphaTest);const r=t.get(i),a=r.envMap,s=r.envMapRotation;a&&(e.envMap.value=a,Rs.copy(s),Rs.x*=-1,Rs.y*=-1,Rs.z*=-1,a.isCubeTexture&&!1===a.isRenderTargetTexture&&(Rs.y*=-1,Rs.z*=-1),e.envMapRotation.value.setFromMatrix4(Cs.makeRotationFromEuler(Rs)),e.flipEnvMap.value=a.isCubeTexture&&!1===a.isRenderTargetTexture?-1:1,e.reflectivity.value=i.reflectivity,e.ior.value=i.ior,e.refractionRatio.value=i.refractionRatio),i.lightMap&&(e.lightMap.value=i.lightMap,e.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,e.lightMapTransform)),i.aoMap&&(e.aoMap.value=i.aoMap,e.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,e.aoMapTransform))}return{refreshFogUniforms:function(t,n){n.color.getRGB(t.fogColor.value,Ei(e)),n.isFog?(t.fogNear.value=n.near,t.fogFar.value=n.far):n.isFogExp2&&(t.fogDensity.value=n.density)},refreshMaterialUniforms:function(e,r,a,s,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(e,r):r.isMeshToonMaterial?(i(e,r),function(e,t){t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(e,r)):r.isMeshPhongMaterial?(i(e,r),function(e,t){e.specular.value.copy(t.specular),e.shininess.value=Math.max(t.shininess,1e-4)}(e,r)):r.isMeshStandardMaterial?(i(e,r),function(e,t){e.metalness.value=t.metalness,t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap,n(t.metalnessMap,e.metalnessMapTransform));e.roughness.value=t.roughness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap,n(t.roughnessMap,e.roughnessMapTransform));t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}(e,r),r.isMeshPhysicalMaterial&&function(e,t,i){e.ior.value=t.ior,t.sheen>0&&(e.sheenColor.value.copy(t.sheenColor).multiplyScalar(t.sheen),e.sheenRoughness.value=t.sheenRoughness,t.sheenColorMap&&(e.sheenColorMap.value=t.sheenColorMap,n(t.sheenColorMap,e.sheenColorMapTransform)),t.sheenRoughnessMap&&(e.sheenRoughnessMap.value=t.sheenRoughnessMap,n(t.sheenRoughnessMap,e.sheenRoughnessMapTransform)));t.clearcoat>0&&(e.clearcoat.value=t.clearcoat,e.clearcoatRoughness.value=t.clearcoatRoughness,t.clearcoatMap&&(e.clearcoatMap.value=t.clearcoatMap,n(t.clearcoatMap,e.clearcoatMapTransform)),t.clearcoatRoughnessMap&&(e.clearcoatRoughnessMap.value=t.clearcoatRoughnessMap,n(t.clearcoatRoughnessMap,e.clearcoatRoughnessMapTransform)),t.clearcoatNormalMap&&(e.clearcoatNormalMap.value=t.clearcoatNormalMap,n(t.clearcoatNormalMap,e.clearcoatNormalMapTransform),e.clearcoatNormalScale.value.copy(t.clearcoatNormalScale),1===t.side&&e.clearcoatNormalScale.value.negate()));t.dispersion>0&&(e.dispersion.value=t.dispersion);t.iridescence>0&&(e.iridescence.value=t.iridescence,e.iridescenceIOR.value=t.iridescenceIOR,e.iridescenceThicknessMinimum.value=t.iridescenceThicknessRange[0],e.iridescenceThicknessMaximum.value=t.iridescenceThicknessRange[1],t.iridescenceMap&&(e.iridescenceMap.value=t.iridescenceMap,n(t.iridescenceMap,e.iridescenceMapTransform)),t.iridescenceThicknessMap&&(e.iridescenceThicknessMap.value=t.iridescenceThicknessMap,n(t.iridescenceThicknessMap,e.iridescenceThicknessMapTransform)));t.transmission>0&&(e.transmission.value=t.transmission,e.transmissionSamplerMap.value=i.texture,e.transmissionSamplerSize.value.set(i.width,i.height),t.transmissionMap&&(e.transmissionMap.value=t.transmissionMap,n(t.transmissionMap,e.transmissionMapTransform)),e.thickness.value=t.thickness,t.thicknessMap&&(e.thicknessMap.value=t.thicknessMap,n(t.thicknessMap,e.thicknessMapTransform)),e.attenuationDistance.value=t.attenuationDistance,e.attenuationColor.value.copy(t.attenuationColor));t.anisotropy>0&&(e.anisotropyVector.value.set(t.anisotropy*Math.cos(t.anisotropyRotation),t.anisotropy*Math.sin(t.anisotropyRotation)),t.anisotropyMap&&(e.anisotropyMap.value=t.anisotropyMap,n(t.anisotropyMap,e.anisotropyMapTransform)));e.specularIntensity.value=t.specularIntensity,e.specularColor.value.copy(t.specularColor),t.specularColorMap&&(e.specularColorMap.value=t.specularColorMap,n(t.specularColorMap,e.specularColorMapTransform));t.specularIntensityMap&&(e.specularIntensityMap.value=t.specularIntensityMap,n(t.specularIntensityMap,e.specularIntensityMapTransform))}(e,r,o)):r.isMeshMatcapMaterial?(i(e,r),function(e,t){t.matcap&&(e.matcap.value=t.matcap)}(e,r)):r.isMeshDepthMaterial?i(e,r):r.isMeshDistanceMaterial?(i(e,r),function(e,n){const i=t.get(n).light;e.referencePosition.value.setFromMatrixPosition(i.matrixWorld),e.nearDistance.value=i.shadow.camera.near,e.farDistance.value=i.shadow.camera.far}(e,r)):r.isMeshNormalMaterial?i(e,r):r.isLineBasicMaterial?(function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform))}(e,r),r.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(e,r)):r.isPointsMaterial?function(e,t,i,r){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.size.value=t.size*i,e.scale.value=.5*r,t.map&&(e.map.value=t.map,n(t.map,e.uvTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r,a,s):r.isSpriteMaterial?function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.rotation.value=t.rotation,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r):r.isShadowMaterial?(e.color.value.copy(r.color),e.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function Ls(e,t,n,i){let r={},a={},s=[];const o=e.getParameter(e.MAX_UNIFORM_BUFFER_BINDINGS);function l(e,t,n,i){const r=e.value,a=t+"_"+n;if(void 0===i[a])return i[a]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const e=i[a];if("number"==typeof r||"boolean"==typeof r){if(e!==r)return i[a]=r,!0}else if(!1===e.equals(r))return e.copy(r),!0}return!1}function c(e){const t={boundary:0,storage:0};return"number"==typeof e||"boolean"==typeof e?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),t}function h(t){const n=t.target;n.removeEventListener("dispose",h);const i=s.indexOf(n.__bindingPointIndex);s.splice(i,1),e.deleteBuffer(r[n.id]),delete r[n.id],delete a[n.id]}return{bind:function(e,t){const n=t.program;i.uniformBlockBinding(e,n)},update:function(n,u){let d=r[n.id];void 0===d&&(!function(e){const t=e.uniforms;let n=0;const i=16;for(let e=0,r=t.length;e0&&(n+=i-r);e.__size=n,e.__cache={}}(n),d=function(t){const n=function(){for(let e=0;e0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let f=0;i.toneMapped&&(null!==w&&!0!==w.isXRRenderTarget||(f=_.toneMapping));const g=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,v=void 0!==g?g.length:0,y=le.get(i),x=m.state.lights;if(!0===Z&&(!0===J||e!==I)){const t=e===I&&i.id===L;be.setState(i,e,t)}let b=!1;i.version===y.__version?y.needsLights&&y.lightsStateVersion!==x.state.version||y.outputColorSpace!==o||r.isBatchedMesh&&!1===y.batching?b=!0:r.isBatchedMesh||!0!==y.batching?r.isBatchedMesh&&!0===y.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===y.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===y.instancing?b=!0:r.isInstancedMesh||!0!==y.instancing?r.isSkinnedMesh&&!1===y.skinning?b=!0:r.isSkinnedMesh||!0!==y.skinning?r.isInstancedMesh&&!0===y.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===y.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===y.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===y.instancingMorph&&null!==r.morphTexture||y.envMap!==l||!0===i.fog&&y.fog!==a?b=!0:void 0===y.numClippingPlanes||y.numClippingPlanes===be.numPlanes&&y.numIntersection===be.numIntersection?(y.vertexAlphas!==c||y.vertexTangents!==h||y.morphTargets!==u||y.morphNormals!==d||y.morphColors!==p||y.toneMapping!==f||y.morphTargetsCount!==v)&&(b=!0):b=!0:b=!0:b=!0:b=!0:(b=!0,y.__version=i.version);let M=y.currentProgram;!0===b&&(M=Ye(i,t,r));let S=!1,E=!1,T=!1;const A=M.getUniforms(),R=y.uniforms;se.useProgram(M.program)&&(S=!0,E=!0,T=!0);i.id!==L&&(L=i.id,E=!0);if(S||I!==e){A.setValue(Pe,"projectionMatrix",e.projectionMatrix),A.setValue(Pe,"viewMatrix",e.matrixWorldInverse);const t=A.map.cameraPosition;void 0!==t&&t.setValue(Pe,$.setFromMatrixPosition(e.matrixWorld)),ae.logarithmicDepthBuffer&&A.setValue(Pe,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&A.setValue(Pe,"isOrthographic",!0===e.isOrthographicCamera),I!==e&&(I=e,E=!0,T=!0)}if(r.isSkinnedMesh){A.setOptional(Pe,r,"bindMatrix"),A.setOptional(Pe,r,"bindMatrixInverse");const e=r.skeleton;e&&(null===e.boneTexture&&e.computeBoneTexture(),A.setValue(Pe,"boneTexture",e.boneTexture,ce))}r.isBatchedMesh&&(A.setOptional(Pe,r,"batchingTexture"),A.setValue(Pe,"batchingTexture",r._matricesTexture,ce),A.setOptional(Pe,r,"batchingIdTexture"),A.setValue(Pe,"batchingIdTexture",r._indirectTexture,ce),A.setOptional(Pe,r,"batchingColorTexture"),null!==r._colorsTexture&&A.setValue(Pe,"batchingColorTexture",r._colorsTexture,ce));const C=n.morphAttributes;void 0===C.position&&void 0===C.normal&&void 0===C.color||Ee.update(r,n,M);(E||y.receiveShadow!==r.receiveShadow)&&(y.receiveShadow=r.receiveShadow,A.setValue(Pe,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(R.envMap.value=l,R.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==t.environment&&(R.envMapIntensity.value=t.environmentIntensity);E&&(A.setValue(Pe,"toneMappingExposure",_.toneMappingExposure),y.needsLights&&(N=T,(P=R).ambientLightColor.needsUpdate=N,P.lightProbe.needsUpdate=N,P.directionalLights.needsUpdate=N,P.directionalLightShadows.needsUpdate=N,P.pointLights.needsUpdate=N,P.pointLightShadows.needsUpdate=N,P.spotLights.needsUpdate=N,P.spotLightShadows.needsUpdate=N,P.rectAreaLights.needsUpdate=N,P.hemisphereLights.needsUpdate=N),a&&!0===i.fog&&ge.refreshFogUniforms(R,a),ge.refreshMaterialUniforms(R,i,G,V,m.state.transmissionRenderTarget[e.id]),Ua.upload(Pe,Ze(y),R,ce));var P,N;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(Ua.upload(Pe,Ze(y),R,ce),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&A.setValue(Pe,"center",r.center);if(A.setValue(Pe,"modelViewMatrix",r.modelViewMatrix),A.setValue(Pe,"normalMatrix",r.normalMatrix),A.setValue(Pe,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const e=i.uniformsGroups;for(let t=0,n=e.length;t{function n(){i.forEach((function(e){le.get(e).currentProgram.isReady()&&i.delete(e)})),0!==i.size?setTimeout(n,10):t(e)}null!==re.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let Be=null;function ze(){Ve.stop()}function He(){Ve.start()}const Ve=new Gi;function Ge(e,t,n,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)n=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)m.pushLight(e),e.castShadow&&m.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||K.intersectsSprite(e)){i&&ee.setFromMatrixPosition(e.matrixWorld).applyMatrix4(Q);const t=fe.update(e),r=e.material;r.visible&&f.push(e,t,r,n,ee.z,null)}}else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||K.intersectsObject(e))){const t=fe.update(e),r=e.material;if(i&&(void 0!==e.boundingSphere?(null===e.boundingSphere&&e.computeBoundingSphere(),ee.copy(e.boundingSphere.center)):(null===t.boundingSphere&&t.computeBoundingSphere(),ee.copy(t.boundingSphere.center)),ee.applyMatrix4(e.matrixWorld).applyMatrix4(Q)),Array.isArray(r)){const i=t.groups;for(let a=0,s=i.length;a0&&Xe(r,t,n),a.length>0&&Xe(a,t,n),s.length>0&&Xe(s,t,n),se.buffers.depth.setTest(!0),se.buffers.depth.setMask(!0),se.buffers.color.setMask(!0),se.setPolygonOffset(!1)}function je(e,t,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===m.state.transmissionRenderTarget[i.id]&&(m.state.transmissionRenderTarget[i.id]=new pt(1,1,{generateMipmaps:!0,type:re.has("EXT_color_buffer_half_float")||re.has("EXT_color_buffer_float")?A:x,minFilter:y,samples:4,stencilBuffer:r,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:nt.workingColorSpace}));const a=m.state.transmissionRenderTarget[i.id],s=i.viewport||N;a.setSize(s.z,s.w);const o=_.getRenderTarget();_.setRenderTarget(a),_.getClearColor(B),z=_.getClearAlpha(),z<1&&_.setClearColor(16777215,.5),_.clear(),ne&&Se.render(n);const l=_.toneMapping;_.toneMapping=0;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),m.setupLightsView(i),!0===Z&&be.setGlobalState(_.clippingPlanes,i),Xe(e,n,i),ce.updateMultisampleRenderTarget(a),ce.updateRenderTargetMipmap(a),!1===re.has("WEBGL_multisampled_render_to_texture")){let e=!1;for(let r=0,a=t.length;r0)for(let t=0,a=n.length;t0&&je(i,r,e,t),ne&&Se.render(e),We(f,e,t);null!==w&&(ce.updateMultisampleRenderTarget(w),ce.updateRenderTargetMipmap(w)),!0===e.isScene&&e.onAfterRender(_,e,t),Re.resetDefaultState(),L=-1,I=null,v.pop(),v.length>0?(m=v[v.length-1],!0===Z&&be.setGlobalState(_.clippingPlanes,m.state.camera)):m=null,g.pop(),f=g.length>0?g[g.length-1]:null},this.getActiveCubeFace=function(){return M},this.getActiveMipmapLevel=function(){return E},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(e,t,n){le.get(e.texture).__webglTexture=t,le.get(e.depthTexture).__webglTexture=n;const i=le.get(e);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===re.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(e,t){const n=le.get(e);n.__webglFramebuffer=t,n.__useDefaultFramebuffer=void 0===t},this.setRenderTarget=function(e,t=0,n=0){w=e,M=t,E=n;let i=!0,r=null,a=!1,s=!1;if(e){const o=le.get(e);void 0!==o.__useDefaultFramebuffer?(se.bindFramebuffer(Pe.FRAMEBUFFER,null),i=!1):void 0===o.__webglFramebuffer?ce.setupRenderTarget(e):o.__hasExternalTextures&&ce.rebindTextures(e,le.get(e.texture).__webglTexture,le.get(e.depthTexture).__webglTexture);const l=e.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(s=!0);const c=le.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(r=Array.isArray(c[t])?c[t][n]:c[t],a=!0):r=e.samples>0&&!1===ce.useMultisampledRTT(e)?le.get(e).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,N.copy(e.viewport),U.copy(e.scissor),k=e.scissorTest}else N.copy(X).multiplyScalar(G).floor(),U.copy(q).multiplyScalar(G).floor(),k=Y;if(se.bindFramebuffer(Pe.FRAMEBUFFER,r)&&i&&se.drawBuffers(e,r),se.viewport(N),se.scissor(U),se.setScissorTest(k),a){const i=le.get(e.texture);Pe.framebufferTexture2D(Pe.FRAMEBUFFER,Pe.COLOR_ATTACHMENT0,Pe.TEXTURE_CUBE_MAP_POSITIVE_X+t,i.__webglTexture,n)}else if(s){const i=le.get(e.texture),r=t||0;Pe.framebufferTextureLayer(Pe.FRAMEBUFFER,Pe.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}L=-1},this.readRenderTargetPixels=function(e,t,n,i,r,a,s){if(!e||!e.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=le.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==s&&(o=o[s]),o){se.bindFramebuffer(Pe.FRAMEBUFFER,o);try{const s=e.texture,o=s.format,l=s.type;if(!ae.textureFormatReadable(o))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!ae.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&Pe.readPixels(t,n,i,r,Ae.convert(o),Ae.convert(l),a)}finally{const e=null!==w?le.get(w).__webglFramebuffer:null;se.bindFramebuffer(Pe.FRAMEBUFFER,e)}}},this.readRenderTargetPixelsAsync=async function(e,t,n,i,r,a,s){if(!e||!e.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=le.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==s&&(o=o[s]),o){se.bindFramebuffer(Pe.FRAMEBUFFER,o);try{const s=e.texture,o=s.format,l=s.type;if(!ae.textureFormatReadable(o))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ae.textureTypeReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r){const e=Pe.createBuffer();Pe.bindBuffer(Pe.PIXEL_PACK_BUFFER,e),Pe.bufferData(Pe.PIXEL_PACK_BUFFER,a.byteLength,Pe.STREAM_READ),Pe.readPixels(t,n,i,r,Ae.convert(o),Ae.convert(l),0),Pe.flush();const s=Pe.fenceSync(Pe.SYNC_GPU_COMMANDS_COMPLETE,0);await function(e,t,n){return new Promise((function(i,r){setTimeout((function a(){switch(e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0)){case e.WAIT_FAILED:r();break;case e.TIMEOUT_EXPIRED:setTimeout(a,n);break;default:i()}}),n)}))}(Pe,s,4);try{Pe.bindBuffer(Pe.PIXEL_PACK_BUFFER,e),Pe.getBufferSubData(Pe.PIXEL_PACK_BUFFER,0,a)}finally{Pe.deleteBuffer(e),Pe.deleteSync(s)}return a}}finally{const e=null!==w?le.get(w).__webglFramebuffer:null;se.bindFramebuffer(Pe.FRAMEBUFFER,e)}}},this.copyFramebufferToTexture=function(e,t=null,n=0){!0!==e.isTexture&&(Je("WebGLRenderer: copyFramebufferToTexture function signature has changed."),t=arguments[0]||null,e=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),a=Math.floor(e.image.height*i),s=null!==t?t.x:0,o=null!==t?t.y:0;ce.setTexture2D(e,0),Pe.copyTexSubImage2D(Pe.TEXTURE_2D,n,0,0,s,o,r,a),se.unbindTexture()},this.copyTextureToTexture=function(e,t,n=null,i=null,r=0){let a,s,o,l,c,h;!0!==e.isTexture&&(Je("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,e=arguments[1],t=arguments[2],r=arguments[3]||0,n=null),null!==n?(a=n.max.x-n.min.x,s=n.max.y-n.min.y,o=n.min.x,l=n.min.y):(a=e.image.width,s=e.image.height,o=0,l=0),null!==i?(c=i.x,h=i.y):(c=0,h=0);const u=Ae.convert(t.format),d=Ae.convert(t.type);ce.setTexture2D(t,0),Pe.pixelStorei(Pe.UNPACK_FLIP_Y_WEBGL,t.flipY),Pe.pixelStorei(Pe.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Pe.pixelStorei(Pe.UNPACK_ALIGNMENT,t.unpackAlignment);const p=Pe.getParameter(Pe.UNPACK_ROW_LENGTH),f=Pe.getParameter(Pe.UNPACK_IMAGE_HEIGHT),m=Pe.getParameter(Pe.UNPACK_SKIP_PIXELS),g=Pe.getParameter(Pe.UNPACK_SKIP_ROWS),v=Pe.getParameter(Pe.UNPACK_SKIP_IMAGES),_=e.isCompressedTexture?e.mipmaps[r]:e.image;Pe.pixelStorei(Pe.UNPACK_ROW_LENGTH,_.width),Pe.pixelStorei(Pe.UNPACK_IMAGE_HEIGHT,_.height),Pe.pixelStorei(Pe.UNPACK_SKIP_PIXELS,o),Pe.pixelStorei(Pe.UNPACK_SKIP_ROWS,l),e.isDataTexture?Pe.texSubImage2D(Pe.TEXTURE_2D,r,c,h,a,s,u,d,_.data):e.isCompressedTexture?Pe.compressedTexSubImage2D(Pe.TEXTURE_2D,r,c,h,_.width,_.height,u,_.data):Pe.texSubImage2D(Pe.TEXTURE_2D,r,c,h,a,s,u,d,_),Pe.pixelStorei(Pe.UNPACK_ROW_LENGTH,p),Pe.pixelStorei(Pe.UNPACK_IMAGE_HEIGHT,f),Pe.pixelStorei(Pe.UNPACK_SKIP_PIXELS,m),Pe.pixelStorei(Pe.UNPACK_SKIP_ROWS,g),Pe.pixelStorei(Pe.UNPACK_SKIP_IMAGES,v),0===r&&t.generateMipmaps&&Pe.generateMipmap(Pe.TEXTURE_2D),se.unbindTexture()},this.copyTextureToTexture3D=function(e,t,n=null,i=null,r=0){let a,s,o,l,c,h,u,d,p;!0!==e.isTexture&&(Je("WebGLRenderer: copyTextureToTexture3D function signature has changed."),n=arguments[0]||null,i=arguments[1]||null,e=arguments[2],t=arguments[3],r=arguments[4]||0);const f=e.isCompressedTexture?e.mipmaps[r]:e.image;null!==n?(a=n.max.x-n.min.x,s=n.max.y-n.min.y,o=n.max.z-n.min.z,l=n.min.x,c=n.min.y,h=n.min.z):(a=f.width,s=f.height,o=f.depth,l=0,c=0,h=0),null!==i?(u=i.x,d=i.y,p=i.z):(u=0,d=0,p=0);const m=Ae.convert(t.format),g=Ae.convert(t.type);let v;if(t.isData3DTexture)ce.setTexture3D(t,0),v=Pe.TEXTURE_3D;else{if(!t.isDataArrayTexture&&!t.isCompressedArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");ce.setTexture2DArray(t,0),v=Pe.TEXTURE_2D_ARRAY}Pe.pixelStorei(Pe.UNPACK_FLIP_Y_WEBGL,t.flipY),Pe.pixelStorei(Pe.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Pe.pixelStorei(Pe.UNPACK_ALIGNMENT,t.unpackAlignment);const _=Pe.getParameter(Pe.UNPACK_ROW_LENGTH),y=Pe.getParameter(Pe.UNPACK_IMAGE_HEIGHT),x=Pe.getParameter(Pe.UNPACK_SKIP_PIXELS),b=Pe.getParameter(Pe.UNPACK_SKIP_ROWS),M=Pe.getParameter(Pe.UNPACK_SKIP_IMAGES);Pe.pixelStorei(Pe.UNPACK_ROW_LENGTH,f.width),Pe.pixelStorei(Pe.UNPACK_IMAGE_HEIGHT,f.height),Pe.pixelStorei(Pe.UNPACK_SKIP_PIXELS,l),Pe.pixelStorei(Pe.UNPACK_SKIP_ROWS,c),Pe.pixelStorei(Pe.UNPACK_SKIP_IMAGES,h),e.isDataTexture||e.isData3DTexture?Pe.texSubImage3D(v,r,u,d,p,a,s,o,m,g,f.data):t.isCompressedArrayTexture?Pe.compressedTexSubImage3D(v,r,u,d,p,a,s,o,m,f.data):Pe.texSubImage3D(v,r,u,d,p,a,s,o,m,g,f),Pe.pixelStorei(Pe.UNPACK_ROW_LENGTH,_),Pe.pixelStorei(Pe.UNPACK_IMAGE_HEIGHT,y),Pe.pixelStorei(Pe.UNPACK_SKIP_PIXELS,x),Pe.pixelStorei(Pe.UNPACK_SKIP_ROWS,b),Pe.pixelStorei(Pe.UNPACK_SKIP_IMAGES,M),0===r&&t.generateMipmaps&&Pe.generateMipmap(v),se.unbindTexture()},this.initRenderTarget=function(e){void 0===le.get(e).__webglFramebuffer&&ce.setupRenderTarget(e)},this.initTexture=function(e){e.isCubeTexture?ce.setTextureCube(e,0):e.isData3DTexture?ce.setTexture3D(e,0):e.isDataArrayTexture||e.isCompressedArrayTexture?ce.setTexture2DArray(e,0):ce.setTexture2D(e,0),se.unbindTexture()},this.resetState=function(){M=0,E=0,w=null,se.reset(),Re.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return Pe}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(e){this._outputColorSpace=e;const t=this.getContext();t.drawingBufferColorSpace=e===be?"display-p3":"srgb",t.unpackColorSpace=nt.workingColorSpace===Me?"display-p3":"srgb"}}class Ns extends bn{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new rn,this.environmentIntensity=1,this.environmentRotation=new rn,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class Us{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=Re,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.version=0,this.uuid=Fe()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return Je("THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,n){e*=this.stride,n*=t.stride;for(let i=0,r=this.stride;ie.far||t.push({distance:o,point:Bs.clone(),uv:In.getInterpolation(Bs,js,Xs,qs,Ys,Ks,Zs,new We),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function Qs(e,t,n,i,r,a){Vs.subVectors(e,n).addScalar(.5).multiply(i),void 0!==r?(Gs.x=a*Vs.x-r*Vs.y,Gs.y=r*Vs.x+a*Vs.y):Gs.copy(Vs),e.copy(t),e.x+=Gs.x,e.y+=Gs.y,e.applyMatrix4(Ws)}const $s=new vt,eo=new ut,to=new ut,no=new vt,io=new qt,ro=new vt,ao=new kt,so=new qt,oo=new Xt;class lo extends yi{constructor(e,t){super(e,t),this.isSkinnedMesh=!0,this.type="SkinnedMesh",this.bindMode=l,this.bindMatrix=new qt,this.bindMatrixInverse=new qt,this.boundingBox=null,this.boundingSphere=null}computeBoundingBox(){const e=this.geometry;null===this.boundingBox&&(this.boundingBox=new xt),this.boundingBox.makeEmpty();const t=e.getAttribute("position");for(let e=0;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;ei)return;bo.applyMatrix4(e.matrixWorld);const o=t.ray.origin.distanceTo(bo);return ot.far?void 0:{distance:o,point:Mo.clone().applyMatrix4(e.matrixWorld),index:r,face:null,faceIndex:null,object:e}}const To=new vt,wo=new vt;class Ao extends So{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const e=this.geometry;if(null===e.index){const t=e.attributes.position,n=[];for(let e=0,i=t.count;e0){const n=e[t[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;er.far)return;a.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:t,face:null,object:s})}}class Do extends ti{constructor(e=1,t=1,n=1,i=32,r=1,a=!1,s=0,o=2*Math.PI){super(),this.type="CylinderGeometry",this.parameters={radiusTop:e,radiusBottom:t,height:n,radialSegments:i,heightSegments:r,openEnded:a,thetaStart:s,thetaLength:o};const l=this;i=Math.floor(i),r=Math.floor(r);const c=[],h=[],u=[],d=[];let p=0;const f=[],m=n/2;let g=0;function v(n){const r=p,a=new We,f=new vt;let v=0;const _=!0===n?e:t,y=!0===n?1:-1;for(let e=1;e<=i;e++)h.push(0,m*y,0),u.push(0,y,0),d.push(.5,.5),p++;const x=p;for(let e=0;e<=i;e++){const t=e/i*o+s,n=Math.cos(t),r=Math.sin(t);f.x=_*r,f.y=m*y,f.z=_*n,h.push(f.x,f.y,f.z),u.push(0,y,0),a.x=.5*n+.5,a.y=.5*r*y+.5,d.push(a.x,a.y),p++}for(let e=0;e0&&v(!0),t>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new qn(h,3)),this.setAttribute("normal",new qn(u,3)),this.setAttribute("uv",new qn(d,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Do(e.radiusTop,e.radiusBottom,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class Oo extends ti{constructor(e=1,t=32,n=16,i=0,r=2*Math.PI,a=0,s=Math.PI){super(),this.type="SphereGeometry",this.parameters={radius:e,widthSegments:t,heightSegments:n,phiStart:i,phiLength:r,thetaStart:a,thetaLength:s},t=Math.max(3,Math.floor(t)),n=Math.max(2,Math.floor(n));const o=Math.min(a+s,Math.PI);let l=0;const c=[],h=new vt,u=new vt,d=[],p=[],f=[],m=[];for(let d=0;d<=n;d++){const g=[],v=d/n;let _=0;0===d&&0===a?_=.5/t:d===n&&o===Math.PI&&(_=-.5/t);for(let n=0;n<=t;n++){const o=n/t;h.x=-e*Math.cos(i+o*r)*Math.sin(a+v*s),h.y=e*Math.cos(a+v*s),h.z=e*Math.sin(i+o*r)*Math.sin(a+v*s),p.push(h.x,h.y,h.z),u.copy(h).normalize(),f.push(u.x,u.y,u.z),m.push(o+_,1-v),g.push(l++)}c.push(g)}for(let e=0;e0)&&d.push(t,r,l),(e!==n-1||o=r)break e;{const s=t[1];e=r)break t}a=n,n=0}}for(;n>>1;et;)--a;if(++a,0!==r||a!==i){r>=a&&(a=Math.max(a,1),r=a-1);const e=this.getValueSize();this.times=n.slice(r,a),this.values=this.values.slice(r*e,a*e)}return this}validate(){let e=!0;const t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);let a=null;for(let t=0;t!==r;t++){const i=n[t];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,t,i),e=!1;break}if(null!==a&&a>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,t,i,a),e=!1;break}a=i}if(void 0!==i&&(s=i,ArrayBuffer.isView(s)&&!(s instanceof DataView)))for(let t=0,n=i.length;t!==n;++t){const n=i[t];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,t,n),e=!1;break}}var s;return e}optimize(){const e=this.times.slice(),t=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===ve,r=e.length-1;let a=1;for(let s=1;s0){e[a]=e[r];for(let e=r*n,i=a*n,s=0;s!==n;++s)t[i+s]=t[e+s];++a}return a!==e.length?(this.times=e.slice(0,a),this.values=t.slice(0,a*n)):(this.times=e,this.values=t),this}clone(){const e=this.times.slice(),t=this.values.slice(),n=new(0,this.constructor)(this.name,e,t);return n.createInterpolant=this.createInterpolant,n}}qo.prototype.TimeBufferType=Float32Array,qo.prototype.ValueBufferType=Float32Array,qo.prototype.DefaultInterpolation=ge;class Yo extends qo{constructor(e,t,n){super(e,t,n)}}Yo.prototype.ValueTypeName="bool",Yo.prototype.ValueBufferType=Array,Yo.prototype.DefaultInterpolation=me,Yo.prototype.InterpolantFactoryMethodLinear=void 0,Yo.prototype.InterpolantFactoryMethodSmooth=void 0;class Ko extends qo{}Ko.prototype.ValueTypeName="color";class Zo extends qo{}Zo.prototype.ValueTypeName="number";class Jo extends Go{constructor(e,t,n,i){super(e,t,n,i)}interpolate_(e,t,n,i){const r=this.resultBuffer,a=this.sampleValues,s=this.valueSize,o=(n-t)/(i-t);let l=e*s;for(let e=l+s;l!==e;l+=4)gt.slerpFlat(r,0,a,l-s,a,l,o);return r}}class Qo extends qo{InterpolantFactoryMethodLinear(e){return new Jo(this.times,this.values,this.getValueSize(),e)}}Qo.prototype.ValueTypeName="quaternion",Qo.prototype.InterpolantFactoryMethodSmooth=void 0;class $o extends qo{constructor(e,t,n){super(e,t,n)}}$o.prototype.ValueTypeName="string",$o.prototype.ValueBufferType=Array,$o.prototype.DefaultInterpolation=me,$o.prototype.InterpolantFactoryMethodLinear=void 0,$o.prototype.InterpolantFactoryMethodSmooth=void 0;class el extends qo{}el.prototype.ValueTypeName="vector";class tl{constructor(e="",t=-1,n=[],i=2500){this.name=e,this.tracks=n,this.duration=t,this.blendMode=i,this.uuid=Fe(),this.duration<0&&this.resetDuration()}static parse(e){const t=[],n=e.tracks,i=1/(e.fps||1);for(let e=0,r=n.length;e!==r;++e)t.push(nl(n[e]).scale(i));const r=new this(e.name,e.duration,t,e.blendMode);return r.uuid=e.uuid,r}static toJSON(e){const t=[],n=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,i=n.length;e!==i;++e)t.push(qo.toJSON(n[e]));return i}static CreateFromMorphTargetSequence(e,t,n,i){const r=t.length,a=[];for(let e=0;e1){const e=a[1];let t=i[e];t||(i[e]=t=[]),t.push(n)}}const a=[];for(const e in i)a.push(this.CreateFromMorphTargetSequence(e,i[e],t,n));return a}static parseAnimation(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(e,t,n,i,r){if(0!==n.length){const a=[],s=[];Vo(n,a,s,i),0!==a.length&&r.push(new e(t,a,s))}},i=[],r=e.name||"default",a=e.fps||30,s=e.blendMode;let o=e.length||-1;const l=e.hierarchy||[];for(let e=0;e{t&&t(r),this.manager.itemEnd(e)}),0),r;if(void 0!==ol[e])return void ol[e].push({onLoad:t,onProgress:n,onError:i});ol[e]=[],ol[e].push({onLoad:t,onProgress:n,onError:i});const a=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),s=this.mimeType,o=this.responseType;fetch(a).then((t=>{if(200===t.status||0===t.status){if(0===t.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===t.body||void 0===t.body.getReader)return t;const n=ol[e],i=t.body.getReader(),r=t.headers.get("X-File-Size")||t.headers.get("Content-Length"),a=r?parseInt(r):0,s=0!==a;let o=0;const l=new ReadableStream({start(e){!function t(){i.read().then((({done:i,value:r})=>{if(i)e.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:s,loaded:o,total:a});for(let e=0,t=n.length;e{e.error(t)}))}()}});return new Response(l)}throw new ll(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)})).then((e=>{switch(o){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((e=>(new DOMParser).parseFromString(e,s)));case"json":return e.json();default:if(void 0===s)return e.text();{const t=/charset="?([^;"\s]*)"?/i.exec(s),n=t&&t[1]?t[1].toLowerCase():void 0,i=new TextDecoder(n);return e.arrayBuffer().then((e=>i.decode(e)))}}})).then((t=>{il.add(e,t);const n=ol[e];delete ol[e];for(let e=0,i=n.length;e{const n=ol[e];if(void 0===n)throw this.manager.itemError(e),t;delete ol[e];for(let e=0,i=n.length;e{this.manager.itemEnd(e)})),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}}class hl extends sl{constructor(e){super(e)}load(e,t,n,i){void 0!==this.path&&(e=this.path+e),e=this.manager.resolveURL(e);const r=this,a=il.get(e);if(void 0!==a)return r.manager.itemStart(e),setTimeout((function(){t&&t(a),r.manager.itemEnd(e)}),0),a;const s=Ye("img");function o(){c(),il.add(e,this),t&&t(this),r.manager.itemEnd(e)}function l(t){c(),i&&i(t),r.manager.itemError(e),r.manager.itemEnd(e)}function c(){s.removeEventListener("load",o,!1),s.removeEventListener("error",l,!1)}return s.addEventListener("load",o,!1),s.addEventListener("error",l,!1),"data:"!==e.slice(0,5)&&void 0!==this.crossOrigin&&(s.crossOrigin=this.crossOrigin),r.manager.itemStart(e),s.src=e,s}}class ul extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=new ho,s=new cl(this.manager);return s.setResponseType("arraybuffer"),s.setRequestHeader(this.requestHeader),s.setPath(this.path),s.setWithCredentials(r.withCredentials),s.load(e,(function(e){let n;try{n=r.parse(e)}catch(e){if(void 0===i)return void console.error(e);i(e)}void 0!==n.image?a.image=n.image:void 0!==n.data&&(a.image.width=n.width,a.image.height=n.height,a.image.data=n.data),a.wrapS=void 0!==n.wrapS?n.wrapS:p,a.wrapT=void 0!==n.wrapT?n.wrapT:p,a.magFilter=void 0!==n.magFilter?n.magFilter:v,a.minFilter=void 0!==n.minFilter?n.minFilter:v,a.anisotropy=void 0!==n.anisotropy?n.anisotropy:1,void 0!==n.colorSpace&&(a.colorSpace=n.colorSpace),void 0!==n.flipY&&(a.flipY=n.flipY),void 0!==n.format&&(a.format=n.format),void 0!==n.type&&(a.type=n.type),void 0!==n.mipmaps&&(a.mipmaps=n.mipmaps,a.minFilter=y),1===n.mipmapCount&&(a.minFilter=v),void 0!==n.generateMipmaps&&(a.generateMipmaps=n.generateMipmaps),a.needsUpdate=!0,t&&t(a,n)}),n,i),a}}class dl extends sl{constructor(e){super(e)}load(e,t,n,i){const r=new ht,a=new hl(this.manager);return a.setCrossOrigin(this.crossOrigin),a.setPath(this.path),a.load(e,(function(e){r.image=e,r.needsUpdate=!0,void 0!==t&&t(r)}),n,i),r}}class pl extends bn{constructor(e,t=1){super(),this.isLight=!0,this.type="Light",this.color=new Fn(e),this.intensity=t}dispose(){}copy(e,t){return super.copy(e,t),this.color.copy(e.color),this.intensity=e.intensity,this}toJSON(e){const t=super.toJSON(e);return t.object.color=this.color.getHex(),t.object.intensity=this.intensity,void 0!==this.groundColor&&(t.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(t.object.distance=this.distance),void 0!==this.angle&&(t.object.angle=this.angle),void 0!==this.decay&&(t.object.decay=this.decay),void 0!==this.penumbra&&(t.object.penumbra=this.penumbra),void 0!==this.shadow&&(t.object.shadow=this.shadow.toJSON()),void 0!==this.target&&(t.object.target=this.target.uuid),t}}const fl=new qt,ml=new vt,gl=new vt;class vl{constructor(e){this.camera=e,this.intensity=1,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new We(512,512),this.map=null,this.mapPass=null,this.matrix=new qt,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Vi,this._frameExtents=new We(1,1),this._viewportCount=1,this._viewports=[new ut(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(e){const t=this.camera,n=this.matrix;ml.setFromMatrixPosition(e.matrixWorld),t.position.copy(ml),gl.setFromMatrixPosition(e.target.matrixWorld),t.lookAt(gl),t.updateMatrixWorld(),fl.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this._frustum.setFromProjectionMatrix(fl),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(fl)}getViewport(e){return this._viewports[e]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(e){return this.camera=e.camera.clone(),this.intensity=e.intensity,this.bias=e.bias,this.radius=e.radius,this.mapSize.copy(e.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const e={};return 1!==this.intensity&&(e.intensity=this.intensity),0!==this.bias&&(e.bias=this.bias),0!==this.normalBias&&(e.normalBias=this.normalBias),1!==this.radius&&(e.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(e.mapSize=this.mapSize.toArray()),e.camera=this.camera.toJSON(!1).object,delete e.camera.matrix,e}}class _l extends vl{constructor(){super(new Li(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(e){const t=this.camera,n=2*Oe*e.angle*this.focus,i=this.mapSize.width/this.mapSize.height,r=e.distance||t.far;n===t.fov&&i===t.aspect&&r===t.far||(t.fov=n,t.aspect=i,t.far=r,t.updateProjectionMatrix()),super.updateMatrices(e)}copy(e){return super.copy(e),this.focus=e.focus,this}}class yl extends pl{constructor(e,t,n=0,i=Math.PI/3,r=0,a=2){super(e,t),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(bn.DEFAULT_UP),this.updateMatrix(),this.target=new bn,this.distance=n,this.angle=i,this.penumbra=r,this.decay=a,this.map=null,this.shadow=new _l}get power(){return this.intensity*Math.PI}set power(e){this.intensity=e/Math.PI}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.angle=e.angle,this.penumbra=e.penumbra,this.decay=e.decay,this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}}const xl=new qt,bl=new vt,Ml=new vt;class Sl extends vl{constructor(){super(new Li(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new We(4,2),this._viewportCount=6,this._viewports=[new ut(2,1,1,1),new ut(0,1,1,1),new ut(3,1,1,1),new ut(1,1,1,1),new ut(3,0,1,1),new ut(1,0,1,1)],this._cubeDirections=[new vt(1,0,0),new vt(-1,0,0),new vt(0,0,1),new vt(0,0,-1),new vt(0,1,0),new vt(0,-1,0)],this._cubeUps=[new vt(0,1,0),new vt(0,1,0),new vt(0,1,0),new vt(0,1,0),new vt(0,0,1),new vt(0,0,-1)]}updateMatrices(e,t=0){const n=this.camera,i=this.matrix,r=e.distance||n.far;r!==n.far&&(n.far=r,n.updateProjectionMatrix()),bl.setFromMatrixPosition(e.matrixWorld),n.position.copy(bl),Ml.copy(n.position),Ml.add(this._cubeDirections[t]),n.up.copy(this._cubeUps[t]),n.lookAt(Ml),n.updateMatrixWorld(),i.makeTranslation(-bl.x,-bl.y,-bl.z),xl.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(xl)}}class El extends pl{constructor(e,t,n=0,i=2){super(e,t),this.isPointLight=!0,this.type="PointLight",this.distance=n,this.decay=i,this.shadow=new Sl}get power(){return 4*this.intensity*Math.PI}set power(e){this.intensity=e/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.decay=e.decay,this.shadow=e.shadow.clone(),this}}class Tl extends vl{constructor(){super(new rr(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class wl extends pl{constructor(e,t){super(e,t),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(bn.DEFAULT_UP),this.updateMatrix(),this.target=new bn,this.shadow=new Tl}dispose(){this.shadow.dispose()}copy(e){return super.copy(e),this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}}class Al extends pl{constructor(e,t){super(e,t),this.isAmbientLight=!0,this.type="AmbientLight"}}class Rl{static decodeText(e){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(e);let t="";for(let n=0,i=e.length;n.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{Nl.set(e.z,0,-e.x).normalize();const t=Math.acos(e.y);this.quaternion.setFromAxisAngle(Nl,t)}}setLength(e,t=.2*e,n=.2*t){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(n,t,n),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:r}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=r);var Fl=function(e,t,n,i){var r=new Fn;return r.setRGB(e,t,n),i<=.99?new Hn({color:r.getHex(),opacity:i+.1,transparent:!0,depthWrite:!0,blendSrc:s,blendDst:o,blendEquation:102,blending:1}):new Fo({color:r.getHex(),opacity:i,blending:1})},kl=function(e,t,n){var i=new vt,r=new vt;i.subVectors(t,e.origin);var a=e.direction.dot(n);if(!(Math.abs(a)0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),"," (- z + zOffset / 1000.0) * maxDepthPerTile,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),n.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n"),n}return Kl(t,e),jl(t,[{key:"metaLoaded",value:function(){this.metaLoaded=!0,this.initStreamer()}},{key:"initStreamer",value:function(){var e=this;if(this.metaLoaded){this.texture=new ht(this.video),this.geometry=new ti;for(var t=0,n=this.width*this.height;t256||24!==e.colormap_size||1!==e.colormap_type)throw new Error("THREE.TGALoader: Invalid type colormap data for indexed type.");break;case i:case r:case s:case o:if(e.colormap_type)throw new Error("THREE.TGALoader: Invalid type colormap data for colormap type.");break;case t:throw new Error("THREE.TGALoader: No data.");default:throw new Error("THREE.TGALoader: Invalid type "+e.image_type)}if(e.width<=0||e.height<=0)throw new Error("THREE.TGALoader: Invalid image size.");if(8!==e.pixel_size&&16!==e.pixel_size&&24!==e.pixel_size&&32!==e.pixel_size)throw new Error("THREE.TGALoader: Invalid pixel size "+e.pixel_size)}(g),g.id_length+f>e.length)throw new Error("THREE.TGALoader: No data.");f+=g.id_length;let v=!1,_=!1,x=!1;switch(g.image_type){case a:v=!0,_=!0;break;case n:_=!0;break;case s:v=!0;break;case i:break;case o:v=!0,x=!0;break;case r:x=!0}const b=new Uint8Array(g.width*g.height*4),M=function(e,t,n,i,r){let a,s;const o=n.pixel_size>>3,l=n.width*n.height*o;if(t&&(s=r.subarray(i,i+=n.colormap_length*(n.colormap_size>>3))),e){let e,t,n;a=new Uint8Array(l);let s=0;const c=new Uint8Array(o);for(;s>c){default:case d:a=0,o=1,m=t,s=0,f=1,v=n;break;case h:a=0,o=1,m=t,s=n-1,f=-1,v=-1;break;case p:a=t-1,o=-1,m=-1,s=0,f=1,v=n;break;case u:a=t-1,o=-1,m=-1,s=n-1,f=-1,v=-1}if(x)switch(g.pixel_size){case 8:!function(e,t,n,i,r,a,s,o){let l,c,h,u=0;const d=g.width;for(h=t;h!==i;h+=n)for(c=r;c!==s;c+=a,u++)l=o[u],e[4*(c+d*h)+0]=l,e[4*(c+d*h)+1]=l,e[4*(c+d*h)+2]=l,e[4*(c+d*h)+3]=255}(e,s,f,v,a,o,m,i);break;case 16:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=2)e[4*(l+u*c)+0]=o[h+0],e[4*(l+u*c)+1]=o[h+0],e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+3]=o[h+1]}(e,s,f,v,a,o,m,i);break;default:throw new Error("THREE.TGALoader: Format not supported.")}else switch(g.pixel_size){case 8:!function(e,t,n,i,r,a,s,o,l){const c=l;let h,u,d,p=0;const f=g.width;for(d=t;d!==i;d+=n)for(u=r;u!==s;u+=a,p++)h=o[p],e[4*(u+f*d)+3]=255,e[4*(u+f*d)+2]=c[3*h+0],e[4*(u+f*d)+1]=c[3*h+1],e[4*(u+f*d)+0]=c[3*h+2]}(e,s,f,v,a,o,m,i,r);break;case 16:!function(e,t,n,i,r,a,s,o){let l,c,h,u=0;const d=g.width;for(h=t;h!==i;h+=n)for(c=r;c!==s;c+=a,u+=2)l=o[u+0]+(o[u+1]<<8),e[4*(c+d*h)+0]=(31744&l)>>7,e[4*(c+d*h)+1]=(992&l)>>2,e[4*(c+d*h)+2]=(31&l)<<3,e[4*(c+d*h)+3]=32768&l?0:255}(e,s,f,v,a,o,m,i);break;case 24:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=3)e[4*(l+u*c)+3]=255,e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+1]=o[h+1],e[4*(l+u*c)+0]=o[h+2]}(e,s,f,v,a,o,m,i);break;case 32:!function(e,t,n,i,r,a,s,o){let l,c,h=0;const u=g.width;for(c=t;c!==i;c+=n)for(l=r;l!==s;l+=a,h+=4)e[4*(l+u*c)+2]=o[h+0],e[4*(l+u*c)+1]=o[h+1],e[4*(l+u*c)+0]=o[h+2],e[4*(l+u*c)+3]=o[h+3]}(e,s,f,v,a,o,m,i);break;default:throw new Error("THREE.TGALoader: Format not supported.")}}(b,g.width,g.height,M.pixel_data,M.palettes),{data:b,width:g.width,height:g.height,flipY:!0,generateMipmaps:!0,minFilter:y}}}function ac(e,t,n){return t=ql(t),Xl(e,sc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function sc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(sc=function(){return!!e})()}var oc=function(e){function t(){return Hl(this,t),ac(this,t,arguments)}return Kl(t,e),jl(t,[{key:"load",value:function(e,t,n,i){var r=this,a=""===r.path?Rl.extractUrlBase(e):r.path,s=new cl(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(e,(function(n){try{t(r.parse(n,a))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}},{key:"parse",value:function(e,t){function n(e,t){for(var n=[],i=e.childNodes,r=0,a=i.length;r0&&t.push(new el(i+".position",r,a)),s.length>0&&t.push(new Qo(i+".quaternion",r,s)),o.length>0&&t.push(new el(i+".scale",r,o)),t}function E(e,t,n){var i,r,a,s=!0;for(r=0,a=e.length;r=0;){var i=e[t];if(null!==i.value[n])return i;t--}return null}function w(e,t,n){for(;t>>0));if("tga"===(n=n.toLowerCase()))t=Je;else t=$e;return t}function J(e){var t,n,i=(t=e.url,f(rt.effects[t],K)),r=i.profile.technique;switch(r.type){case"phong":case"blinn":n=new Fo;break;case"lambert":n=new ko;break;default:n=new Hn}function a(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=i.profile.samplers[e.id],r=null;if(void 0!==n){var a=i.profile.surfaces[n.source];r=D(a.init_from)}else console.warn("THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530)."),r=D(e.id);if(null!==r){var s=Z(r);if(void 0!==s){var l=s.load(r),c=e.extra;if(void 0!==c&&void 0!==c.technique&&!1===o(c.technique)){var h=c.technique;l.wrapS=h.wrapU?d:p,l.wrapT=h.wrapV?d:p,l.offset.set(h.offsetU||0,h.offsetV||0),l.repeat.set(h.repeatU||1,h.repeatV||1)}else l.wrapS=d,l.wrapT=d;return null!==t&&(l.colorSpace=t),l}return console.warn("THREE.ColladaLoader: Loader for texture %s not found.",r),null}return console.warn("THREE.ColladaLoader: Couldn't create texture with ID:",e.id),null}n.name=e.name||"";var s=r.parameters;for(var l in s){var c=s[l];switch(l){case"diffuse":c.color&&n.color.fromArray(c.color),c.texture&&(n.map=a(c.texture,ye));break;case"specular":c.color&&n.specular&&n.specular.fromArray(c.color),c.texture&&(n.specularMap=a(c.texture));break;case"bump":c.texture&&(n.normalMap=a(c.texture));break;case"ambient":c.texture&&(n.lightMap=a(c.texture,ye));break;case"shininess":c.float&&n.shininess&&(n.shininess=c.float);break;case"emission":c.color&&n.emissive&&n.emissive.fromArray(c.color),c.texture&&(n.emissiveMap=a(c.texture,ye))}}n.color.convertSRGBToLinear(),n.specular&&n.specular.convertSRGBToLinear(),n.emissive&&n.emissive.convertSRGBToLinear();var h=s.transparent,u=s.transparency;if(void 0===u&&h&&(u={float:1}),void 0===h&&u&&(h={opaque:"A_ONE",data:{color:[1,1,1,1]}}),h&&u)if(h.data.texture)n.transparent=!0;else{var m=h.data.color;switch(h.opaque){case"A_ONE":n.opacity=m[3]*u.float;break;case"RGB_ZERO":n.opacity=1-m[0]*u.float;break;case"A_ZERO":n.opacity=1-m[3]*u.float;break;case"RGB_ONE":n.opacity=m[0]*u.float;break;default:console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.',h.opaque)}n.opacity<1&&(n.transparent=!0)}if(void 0!==r.extra&&void 0!==r.extra.technique){var g=r.extra.technique;for(var v in g){var _=g[v];switch(v){case"double_sided":n.side=1===_?2:0;break;case"bump":n.normalMap=a(_.texture),n.normalScale=new We(1,1)}}}return n}function Q(e){return f(rt.materials[e],J)}function $(e){for(var t=0;t0?l+h:l;t.inputs[u]={id:o,offset:c},t.stride=Math.max(t.stride,c+1),"TEXCOORD"===l&&(t.hasUV=!0);break;case"vcount":t.vcount=a(r.textContent);break;case"p":t.p=a(r.textContent)}}return t}function ue(e){for(var t=0,n=0,i=e.length;n0&&t0&&p.setAttribute("position",new qn(r.array,r.stride)),a.array.length>0&&p.setAttribute("normal",new qn(a.array,a.stride)),l.array.length>0&&p.setAttribute("color",new qn(l.array,l.stride)),s.array.length>0&&p.setAttribute("uv",new qn(s.array,s.stride)),o.array.length>0&&p.setAttribute("uv1",new qn(o.array,o.stride)),c.length>0&&p.setAttribute("skinIndex",new qn(c,h)),u.length>0&&p.setAttribute("skinWeight",new qn(u,d)),i.data=p,i.type=e[0].type,i.materialKeys=f,i}function fe(e,t,n,i){var r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],a=e.p,s=e.stride,o=e.vcount;function l(e){for(var t=a[e+n]*h,s=t+h;t4)for(var M=1,S=f-2;M<=S;M++){var E=u+0*s,T=u+s*M,w=u+s*(M+1);l(E),l(T),l(w)}u+=s*f}else for(var A=0,R=a.length;A=t.limits.max&&(t.static=!0),t.middlePosition=(t.limits.min+t.limits.max)/2,t}function be(e){for(var t={sid:e.getAttribute("sid"),name:e.getAttribute("name")||"",attachments:[],transforms:[]},n=0;ni.limits.max||t0?t[t.length-1]:"",smooth:void 0!==n?n.smooth:this.smooth,groupStart:void 0!==n?n.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(e){const t={index:"number"==typeof e?e:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return t.clone=this.clone.bind(t),t}};return this.materials.push(i),i},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(e){const t=this.currentMaterial();if(t&&-1===t.groupEnd&&(t.groupEnd=this.geometry.vertices.length/3,t.groupCount=t.groupEnd-t.groupStart,t.inherited=!1),e&&this.materials.length>1)for(let e=this.materials.length-1;e>=0;e--)this.materials[e].groupCount<=0&&this.materials.splice(e,1);return e&&0===this.materials.length&&this.materials.push({name:"",smooth:this.smooth}),t}},n&&n.name&&"function"==typeof n.clone){const e=n.clone(0);e.inherited=!0,this.object.materials.push(e)}this.objects.push(this.object)},finalize:function(){this.object&&"function"==typeof this.object._finalize&&this.object._finalize(!0)},parseVertexIndex:function(e,t){const n=parseInt(e,10);return 3*(n>=0?n-1:n+t/3)},parseNormalIndex:function(e,t){const n=parseInt(e,10);return 3*(n>=0?n-1:n+t/3)},parseUVIndex:function(e,t){const n=parseInt(e,10);return 2*(n>=0?n-1:n+t/2)},addVertex:function(e,t,n){const i=this.vertices,r=this.object.geometry.vertices;r.push(i[e+0],i[e+1],i[e+2]),r.push(i[t+0],i[t+1],i[t+2]),r.push(i[n+0],i[n+1],i[n+2])},addVertexPoint:function(e){const t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){const t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,n){const i=this.normals,r=this.object.geometry.normals;r.push(i[e+0],i[e+1],i[e+2]),r.push(i[t+0],i[t+1],i[t+2]),r.push(i[n+0],i[n+1],i[n+2])},addFaceNormal:function(e,t,n){const i=this.vertices,r=this.object.geometry.normals;pc.fromArray(i,e),fc.fromArray(i,t),mc.fromArray(i,n),vc.subVectors(mc,fc),gc.subVectors(pc,fc),vc.cross(gc),vc.normalize(),r.push(vc.x,vc.y,vc.z),r.push(vc.x,vc.y,vc.z),r.push(vc.x,vc.y,vc.z)},addColor:function(e,t,n){const i=this.colors,r=this.object.geometry.colors;void 0!==i[e]&&r.push(i[e+0],i[e+1],i[e+2]),void 0!==i[t]&&r.push(i[t+0],i[t+1],i[t+2]),void 0!==i[n]&&r.push(i[n+0],i[n+1],i[n+2])},addUV:function(e,t,n){const i=this.uvs,r=this.object.geometry.uvs;r.push(i[e+0],i[e+1]),r.push(i[t+0],i[t+1]),r.push(i[n+0],i[n+1])},addDefaultUV:function(){const e=this.object.geometry.uvs;e.push(0,0),e.push(0,0),e.push(0,0)},addUVLine:function(e){const t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,n,i,r,a,s,o,l){const c=this.vertices.length;let h=this.parseVertexIndex(e,c),u=this.parseVertexIndex(t,c),d=this.parseVertexIndex(n,c);if(this.addVertex(h,u,d),this.addColor(h,u,d),void 0!==s&&""!==s){const e=this.normals.length;h=this.parseNormalIndex(s,e),u=this.parseNormalIndex(o,e),d=this.parseNormalIndex(l,e),this.addNormal(h,u,d)}else this.addFaceNormal(h,u,d);if(void 0!==i&&""!==i){const e=this.uvs.length;h=this.parseUVIndex(i,e),u=this.parseUVIndex(r,e),d=this.parseUVIndex(a,e),this.addUV(h,u,d),this.object.geometry.hasUVIndices=!0}else this.addDefaultUV()},addPointGeometry:function(e){this.object.geometry.type="Points";const t=this.vertices.length;for(let n=0,i=e.length;n=7?(_c.setRGB(parseFloat(e[4]),parseFloat(e[5]),parseFloat(e[6])).convertSRGBToLinear(),t.colors.push(_c.r,_c.g,_c.b)):t.colors.push(void 0,void 0,void 0);break;case"vn":t.normals.push(parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3]));break;case"vt":t.uvs.push(parseFloat(e[1]),parseFloat(e[2]))}}else if("f"===a){const e=r.slice(1).trim().split(dc),n=[];for(let t=0,i=e.length;t0){const e=i.split("/");n.push(e)}}const i=n[0];for(let e=1,r=n.length-1;e1){const e=i[1].trim().toLowerCase();t.object.smooth="0"!==e&&"off"!==e}else t.object.smooth=!0;const e=t.object.currentMaterial();e&&(e.smooth=t.object.smooth)}else{if("\0"===r)continue;console.warn('THREE.OBJLoader: Unexpected line: "'+r+'"')}}t.finalize();const r=new Ss;r.materialLibraries=[].concat(t.materialLibraries);if(!0===!(1===t.objects.length&&0===t.objects[0].geometry.vertices.length))for(let e=0,n=t.objects.length;e0&&c.setAttribute("normal",new qn(i.normals,3)),i.colors.length>0&&(l=!0,c.setAttribute("color",new qn(i.colors,3))),!0===i.hasUVIndices&&c.setAttribute("uv",new qn(i.uvs,2));const h=[];for(let e=0,n=a.length;e1){for(let e=0,t=a.length;e0){const e=new Ro({size:1,sizeAttenuation:!1}),n=new ti;n.setAttribute("position",new qn(t.vertices,3)),t.colors.length>0&&void 0!==t.colors[0]&&(n.setAttribute("color",new qn(t.colors,3)),e.vertexColors=!0);const i=new No(n,e);r.add(i)}return r}}class bc extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=new cl(this.manager);a.setPath(this.path),a.setResponseType("arraybuffer"),a.setRequestHeader(this.requestHeader),a.setWithCredentials(this.withCredentials),a.load(e,(function(n){try{t(r.parse(n))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}parse(e){function t(e,t,n){for(let i=0,r=e.length;i>5&31)/31,a=(e>>10&31)/31):(i=o,r=l,a=c)}for(let o=1;o<=3;o++){const l=n+12*o,c=3*e*3+3*(o-1);p[c]=t.getFloat32(l,!0),p[c+1]=t.getFloat32(l+4,!0),p[c+2]=t.getFloat32(l+8,!0),f[c]=h,f[c+1]=d,f[c+2]=g,u&&(m.set(i,r,a).convertSRGBToLinear(),s[c]=m.r,s[c+1]=m.g,s[c+2]=m.b)}}return d.setAttribute("position",new Wn(p,3)),d.setAttribute("normal",new Wn(f,3)),u&&(d.setAttribute("color",new Wn(s,3)),d.hasColors=!0,d.alpha=h),d}(n):function(e){const t=new ti,n=/solid([\s\S]*?)endsolid/g,i=/facet([\s\S]*?)endfacet/g,r=/solid\s(.+)/;let a=0;const s=/[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source,o=new RegExp("vertex"+s+s+s,"g"),l=new RegExp("normal"+s+s+s,"g"),c=[],h=[],u=[],d=new vt;let p,f=0,m=0,g=0;for(;null!==(p=n.exec(e));){m=g;const e=p[0],n=null!==(p=r.exec(e))?p[1]:"";for(u.push(n);null!==(p=i.exec(e));){let e=0,t=0;const n=p[0];for(;null!==(p=l.exec(n));)d.x=parseFloat(p[1]),d.y=parseFloat(p[2]),d.z=parseFloat(p[3]),t++;for(;null!==(p=o.exec(n));)c.push(parseFloat(p[1]),parseFloat(p[2]),parseFloat(p[3])),h.push(d.x,d.y,d.z),e++,g++;1!==t&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+a),3!==e&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+a),a++}const s=m,v=g-m;t.userData.groupNames=u,t.addGroup(s,v,f),f++}return t.setAttribute("position",new qn(c,3)),t.setAttribute("normal",new qn(h,3)),t}("string"!=typeof(i=e)?(new TextDecoder).decode(i):i);var i}}class Mc extends sl{constructor(e){super(e)}load(e,t,n,i){const r=this,a=""===this.path?Rl.extractUrlBase(e):this.path,s=new cl(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(e,(function(n){try{t(r.parse(n,a))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),n,i)}setMaterialOptions(e){return this.materialOptions=e,this}parse(e,t){const n=e.split("\n");let i={};const r=/\s+/,a={};for(let e=0;e=0?t.substring(0,s):t;o=o.toLowerCase();let l=s>=0?t.substring(s+1):"";if(l=l.trim(),"newmtl"===o)i={name:l},a[l]=i;else if("ka"===o||"kd"===o||"ks"===o||"ke"===o){const e=l.split(r,3);i[o]=[parseFloat(e[0]),parseFloat(e[1]),parseFloat(e[2])]}else i[o]=l}const s=new Sc(this.resourcePath||t,this.materialOptions);return s.setCrossOrigin(this.crossOrigin),s.setManager(this.manager),s.setMaterials(a),s}}class Sc{constructor(e="",t={}){this.baseUrl=e,this.options=t,this.materialsInfo={},this.materials={},this.materialsArray=[],this.nameLookup={},this.crossOrigin="anonymous",this.side=void 0!==this.options.side?this.options.side:0,this.wrap=void 0!==this.options.wrap?this.options.wrap:d}setCrossOrigin(e){return this.crossOrigin=e,this}setManager(e){this.manager=e}setMaterials(e){this.materialsInfo=this.convert(e),this.materials={},this.materialsArray=[],this.nameLookup={}}convert(e){if(!this.options)return e;const t={};for(const n in e){const i=e[n],r={};t[n]=r;for(const e in i){let t=!0,n=i[e];const a=e.toLowerCase();switch(a){case"kd":case"ka":case"ks":this.options&&this.options.normalizeRGB&&(n=[n[0]/255,n[1]/255,n[2]/255]),this.options&&this.options.ignoreZeroRGBs&&0===n[0]&&0===n[1]&&0===n[2]&&(t=!1)}t&&(r[a]=n)}}return t}preload(){for(const e in this.materialsInfo)this.create(e)}getIndex(e){return this.nameLookup[e]}getAsArray(){let e=0;for(const t in this.materialsInfo)this.materialsArray[e]=this.create(t),this.nameLookup[t]=e,e++;return this.materialsArray}create(e){return void 0===this.materials[e]&&this.createMaterial_(e),this.materials[e]}createMaterial_(e){const t=this,n=this.materialsInfo[e],i={name:e,side:this.side};function r(e,n){if(i[e])return;const r=t.getTextureParams(n,i),a=t.loadTexture((s=t.baseUrl,"string"!=typeof(o=r.url)||""===o?"":/^https?:\/\//i.test(o)?o:s+o));var s,o;a.repeat.copy(r.scale),a.offset.copy(r.offset),a.wrapS=t.wrap,a.wrapT=t.wrap,"map"!==e&&"emissiveMap"!==e||(a.colorSpace=ye),i[e]=a}for(const e in n){const t=n[e];let a;if(""!==t)switch(e.toLowerCase()){case"kd":i.color=(new Fn).fromArray(t).convertSRGBToLinear();break;case"ks":i.specular=(new Fn).fromArray(t).convertSRGBToLinear();break;case"ke":i.emissive=(new Fn).fromArray(t).convertSRGBToLinear();break;case"map_kd":r("map",t);break;case"map_ks":r("specularMap",t);break;case"map_ke":r("emissiveMap",t);break;case"norm":r("normalMap",t);break;case"map_bump":case"bump":r("bumpMap",t);break;case"map_d":r("alphaMap",t),i.transparent=!0;break;case"ns":i.shininess=parseFloat(t);break;case"d":a=parseFloat(t),a<1&&(i.opacity=a,i.transparent=!0);break;case"tr":a=parseFloat(t),this.options&&this.options.invertTrProperty&&(a=1-a),a>0&&(i.opacity=1-a,i.transparent=!0)}}return this.materials[e]=new Fo(i),this.materials[e]}getTextureParams(e,t){const n={scale:new We(1,1),offset:new We(0,0)},i=e.split(/\s+/);let r;return r=i.indexOf("-bm"),r>=0&&(t.bumpScale=parseFloat(i[r+1]),i.splice(r,2)),r=i.indexOf("-s"),r>=0&&(n.scale.set(parseFloat(i[r+1]),parseFloat(i[r+2])),i.splice(r,4)),r=i.indexOf("-o"),r>=0&&(n.offset.set(parseFloat(i[r+1]),parseFloat(i[r+2])),i.splice(r,4)),n.url=i.join(" ").trim(),n}loadTexture(e,t,n,i,r){const a=void 0!==this.manager?this.manager:al;let s=a.getHandler(e);null===s&&(s=new dl(a)),s.setCrossOrigin&&s.setCrossOrigin(this.crossOrigin);const o=s.load(e,n,i,r);return void 0!==t&&(o.mapping=t),o}}var Ec={onError:function(e){console.error(e)},loaders:{dae:function(e,t,n){var i=new oc(n.loader);return console.log("Loading collada: "+t),i.load(t,(function(t){var n=t.scene;e.add(n),console.log("Done loading collada")})),i.log=function(t){e.warnings&&console.warn(t)},i},obj:function(e,t,n){n.material;var i=new xc(n.loader);return i.log=function(t){e.warnings&&console.warn(t)},i.load(t,(function(r){var a=Rl.extractUrlBase(t);if(r.materialLibraries.length){var s=r.materialLibraries[0];new Mc(n.loader).setPath(a).load(s,(function(n){n.preload(),function(n,i){n.setMaterials(i).load(t,(function(t){e.add(t)}),null,Ec.onError)}(i,n)}),null,Ec.onError)}else e.add(r)}),null,Ec.onError),i},stl:function(e,t,n){var i=n.material,r=new bc(n.loader);return r.load(t,(function(t){var n;t.computeVertexNormals(),n=new yi(t,null!==i?i:new Hn({color:10066329})),e.add(n)}),null,Ec.onError),r}}};function Tc(e,t,n){return t=ql(t),Xl(e,wc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function wc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(wc=function(){return!!e})()}var Ac=function(e){function t(e){var n;Hl(this,t),n=Tc(this,t);var i=(e=e||{}).path||"/",r=e.resource;e.material,n.warnings=e.warnings,"/"!==i.substr(i.length-1)&&(i+="/");var a=i+r,s=a.substr(-3).toLowerCase(),o=Ec.loaders[s];return o?o(n,a,e):console.warn("Unsupported loader for file type: '"+s+"'"),n}return Kl(t,e),jl(t)}(bn);function Rc(e,t,n){return t=ql(t),Xl(e,Cc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Cc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Cc=function(){return!!e})()}var Pc=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).material||new Hn,r=e.vertices,a=e.colors;n=Rc(this,t),i.side=2;for(var s,o,l=new ti,c=new Float32Array(3*r.length),h=0;h0){var K=n.msgColor,Z=document.createElement("canvas"),J=Z.getContext("2d"),Q="normal 100px sans-serif";J.font=Q;var $=J.measureText(r.text).width;Z.width=$,Z.height=150,J.font=Q,J.fillStyle="rgba("+Math.round(255*K.r)+", "+Math.round(255*K.g)+", "+Math.round(255*K.b)+", "+K.a+")",J.textAlign="left",J.textBaseline="middle",J.fillText(r.text,0,Z.height/2);var ee=new ht(Z);ee.needsUpdate=!0;var te=new Fs({map:ee,useScreenCoordinates:!1}),ne=new Js(te),ie=r.scale.x;ne.scale.set($/Z.height*ie,ie,1),n.add(ne)}break;case 10:var re=null;0===r.color.r&&0===r.color.g&&0===r.color.b&&0===r.color.a||(re=a),n.msgMesh=r.mesh_resource.substr(10);var ae=new Ac({path:i,resource:n.msgMesh,material:re});n.add(ae);break;case 11:var se=new Pc({material:a,vertices:r.points,colors:r.colors});se.scale.set(r.scale.x,r.scale.y,r.scale.z),n.add(se);break;default:console.error("Currently unsupported marker type: "+r.type)}return n}return Kl(t,e),jl(t,[{key:"setPose",value:function(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()}},{key:"update",value:function(e){if(this.setPose(e.pose),e.color.r!==this.msgColor.r||e.color.g!==this.msgColor.g||e.color.b!==this.msgColor.b||e.color.a!==this.msgColor.a){var t=Fl(e.color.r,e.color.g,e.color.b,e.color.a);switch(e.type){case 4:case 5:case 8:break;case 0:case 1:case 2:case 3:case 11:case 9:this.traverse((function(e){e instanceof yi&&(e.material=t)}));break;case 10:var n=null;0===e.color.r&&0===e.color.g&&0===e.color.b&&0===e.color.a||(n=this.colorMaterial),this.traverse((function(e){e instanceof yi&&(e.material=n)}));break;default:return!1}this.msgColor=e.color}var i=Math.abs(this.msgScale[0]-e.scale.x)>1e-6||Math.abs(this.msgScale[1]-e.scale.y)>1e-6||Math.abs(this.msgScale[2]-e.scale.z)>1e-6;switch(this.msgScale=[e.scale.x,e.scale.y,e.scale.z],e.type){case 1:case 2:case 3:if(i)return!1;break;case 9:if(i||this.text!==e.text)return!1;break;case 10:if(e.mesh_resource.substr(10)!==this.msgMesh)return!1;if(i)return!1;break;case 0:case 4:case 5:case 6:case 7:case 8:case 11:return!1}return!0}},{key:"dispose",value:function(){this.children.forEach((function(e){e instanceof Ac?e.children.forEach((function(t){void 0!==t.material&&t.material.dispose(),t.children.forEach((function(e){void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose(),t.remove(e)})),e.remove(t)})):(void 0!==e.geometry&&e.geometry.dispose(),void 0!==e.material&&e.material.dispose()),e.parent.remove(e)}))}}])}(bn);function Uc(e,t,n){return t=ql(t),Xl(e,Dc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Dc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Dc=function(){return!!e})()}function Oc(e,t,n,i){var r=ec(ql(1&i?e.prototype:e),t,n);return 2&i?function(e){return r.apply(n,e)}:r}var Fc=function(e){function t(e){var n;Hl(this,t);var r=n=Uc(this,t);e=e||{},n.parent=e.parent;var a=e.handle,s=e.message;n.message=s,n.name=s.name,n.camera=e.camera,n.path=e.path||"/",n.loader=e.loader,n.dragging=!1,n.startMousePos=new We,n.isShift=!1;var o=new gt(s.orientation.x,s.orientation.y,s.orientation.z,s.orientation.w);o.normalize();var l=new vt(1,0,0);switch(l.applyQuaternion(o),n.currentControlOri=new gt,s.interaction_mode){case 9:case 7:n.addEventListener("mousemove",n.parent.move3d.bind(n.parent,n,l));break;case 3:n.addEventListener("mousemove",n.parent.moveAxis.bind(n.parent,n,l)),n.addEventListener("touchmove",n.parent.moveAxis.bind(n.parent,n,l));break;case 5:n.addEventListener("mousemove",n.parent.rotateAxis.bind(n.parent,n,o));break;case 4:n.addEventListener("mousemove",n.parent.movePlane.bind(n.parent,n,l));break;case 2:n.addEventListener("click",n.parent.buttonClick.bind(n.parent,n))}function c(e){e.stopPropagation()}0!==s.interaction_mode&&(n.addEventListener("mousedown",n.parent.startDrag.bind(n.parent,n)),n.addEventListener("mouseup",n.parent.stopDrag.bind(n.parent,n)),n.addEventListener("contextmenu",n.parent.showMenu.bind(n.parent,n)),n.addEventListener("mouseup",(function(e){0===r.startMousePos.distanceToSquared(e.mousePos)&&(e.type="contextmenu",r.dispatchEvent(e))})),n.addEventListener("mouseover",c),n.addEventListener("mouseout",c),n.addEventListener("click",c),n.addEventListener("mousedown",(function(e){r.startMousePos=e.mousePos})),n.addEventListener("touchstart",(function(e){1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,r.dispatchEvent(e))})),n.addEventListener("touchmove",(function(e){1===e.domEvent.touches.length&&(e.type="mousemove",e.domEvent.button=0,r.dispatchEvent(e))})),n.addEventListener("touchend",(function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",r.dispatchEvent(e),e.type="click",r.dispatchEvent(e))})),window.addEventListener("keydown",(function(e){16===e.keyCode&&(r.isShift=!0)})),window.addEventListener("keyup",(function(e){16===e.keyCode&&(r.isShift=!1)})));var h=new gt,u=n.parent.position.clone().multiplyScalar(-1);switch(s.orientation_mode){case 0:h=n.parent.quaternion.clone().inverse();break;case 1:case 2:break;default:console.error("Unkown orientation mode: "+s.orientation_mode)}var d=new i.TFClient({ros:a.tfClient.ros,fixedFrame:a.message.header.frame_id,serverName:a.tfClient.serverName});return s.markers.forEach((function(e){var t=function(t){var n=new Nc({message:e,path:r.path,loader:r.loader});if(null!==t){var a=new i.Pose({position:n.position,orientation:n.quaternion});a.applyTransform(new i.Transform(t));var s=new Nc({message:e,path:r.path,loader:r.loader});s.position.add(u),s.position.applyQuaternion(h),s.quaternion.multiplyQuaternions(h,s.quaternion);var o=new vt(s.position.x,s.position.y,s.position.z),l=new i.Transform({translation:o,orientation:s.quaternion});a.applyTransform(l),n.setPose(a),n.updateMatrixWorld(),d.unsubscribe(e.header.frame_id)}r.add(n)};""!==e.header.frame_id?d.subscribe(e.header.frame_id,t):t(null)})),n}return Kl(t,e),jl(t,[{key:"updateMatrixWorld",value:function(e){var n=this,i=this.message;switch(i.orientation_mode){case 0:Oc(t,"updateMatrixWorld",this,3)([e]),n.currentControlOri.copy(n.quaternion),n.currentControlOri.normalize();break;case 1:n.quaternion.copy(n.parent.quaternion.clone().inverse()),n.updateMatrix(),n.matrixWorldNeedsUpdate=!0,Oc(t,"updateMatrixWorld",this,3)([e]),n.currentControlOri.copy(n.quaternion);break;case 2:n.camera.updateMatrixWorld();var r=(new qt).extractRotation(n.camera.matrixWorld),a=new qt,s=.5*Math.PI,o=new rn(-s,0,s);a.makeRotationFromEuler(o);var l=new qt;l.getInverse(n.parent.matrixWorld),r.multiplyMatrices(r,a),r.multiplyMatrices(l,r),n.currentControlOri.setFromRotationMatrix(r),i.independent_marker_orientation||(n.quaternion.copy(n.currentControlOri),n.updateMatrix(),n.matrixWorldNeedsUpdate=!0),Oc(t,"updateMatrixWorld",this,3)([e]);break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}}}])}(bn);function kc(e,t,n){return t=ql(t),Xl(e,Bc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Bc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Bc=function(){return!!e})()}var zc=function(e){function t(e){var n;Hl(this,t);var i=n=kc(this,t),r=(e=e||{}).menuEntries,a=e.className||"default-interactive-marker-menu";e.entryClassName;var s,o,l,c=e.overlayClassName||"default-interactive-marker-overlay",h=e.menuFontSize||"0.8em",u=[];if(u[0]={children:[]},null===document.getElementById("default-interactive-marker-menu-css")){var d=document.createElement("style");d.id="default-interactive-marker-menu-css",d.type="text/css",d.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: "+h+";z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(d)}for(n.menuDomElem=document.createElement("div"),n.menuDomElem.style.position="absolute",n.menuDomElem.className=a,n.menuDomElem.addEventListener("contextmenu",(function(e){e.preventDefault()})),n.overlayDomElem=document.createElement("div"),n.overlayDomElem.className=c,n.hideListener=n.hide.bind(n),n.overlayDomElem.addEventListener("contextmenu",n.hideListener),n.overlayDomElem.addEventListener("click",n.hideListener),n.overlayDomElem.addEventListener("touchstart",n.hideListener),s=0;s0?(e(o,a[s]),l.addEventListener("click",i.hide.bind(i)),l.addEventListener("touchstart",i.hide.bind(i))):(l.addEventListener("click",f.bind(i,a[s])),l.addEventListener("touchstart",f.bind(i,a[s])),l.className="default-interactive-marker-menu-entry")}}(n.menuDomElem,u[0]),n}return Kl(t,e),jl(t,[{key:"show",value:function(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,void 0!==t.domEvent.changedTouches?(this.menuDomElem.style.left=t.domEvent.changedTouches[0].pageX+"px",this.menuDomElem.style.top=t.domEvent.changedTouches[0].pageY+"px"):(this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px"),document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)}},{key:"hide",value:function(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)}}])}(Ie);function Hc(e,t,n){return t=ql(t),Xl(e,Vc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Vc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Vc=function(){return!!e})()}var Gc=function(e){function t(e){var n;Hl(this,t),n=Hc(this,t);var i=(e=e||{}).handle;n.name=i.name;var r=e.camera,a=e.path||"/",s=e.loader;return n.dragging=!1,n.onServerSetPose({pose:i.pose}),n.dragStart={position:new vt,orientation:new gt,positionWorld:new vt,orientationWorld:new gt,event3d:{}},i.controls.forEach(function(e){this.add(new Fc({parent:this,handle:i,message:e,camera:r,path:a,loader:s}))}.bind(n)),i.menuEntries.length>0&&(n.menu=new zc({menuEntries:i.menuEntries,menuFontSize:i.menuFontSize}),n.menu.addEventListener("menu-select",function(e){this.dispatchEvent(e)}.bind(n))),n}return Kl(t,e),jl(t,[{key:"showMenu",value:function(e,t){this.menu&&this.menu.show(e,t)}},{key:"moveAxis",value:function(e,t,n){if(this.dragging){var i=e.currentControlOri,r=t.clone().applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),o=new Xt(a,s),l=zl(o,n.camera,n.mousePos),c=new vt;c.addVectors(this.dragStart.position,r.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(l)),this.setPosition(e,c),n.stopPropagation()}}},{key:"move3d",value:function(e,t,n){if(this.dragging)if(e.isShift);else{var i=e.camera.getWorldDirection(),r=Math.abs(i.x),a=Math.abs(i.y),s=Math.abs(i.z),o=new gt(1,0,0,1);a>r&&a>s?o=new gt(0,0,1,1):s>r&&s>a&&(o=new gt(0,1,0,1)),o.normalize(),(t=new vt(1,0,0)).applyQuaternion(o),this.movePlane(e,t,n)}}},{key:"movePlane",value:function(e,t,n){if(this.dragging){var i=e.currentControlOri,r=t.clone().applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.clone().applyQuaternion(this.dragStart.orientationWorld),o=kl(n.mouseRay,a,s),l=new vt;l.subVectors(o,a),l.add(this.dragStart.positionWorld),this.setPosition(e,l),n.stopPropagation()}}},{key:"rotateAxis",value:function(e,t,n){if(this.dragging){e.updateMatrixWorld();var i=e.currentControlOri.clone().multiply(t.clone()),r=new vt(1,0,0).applyQuaternion(i),a=this.dragStart.event3d.intersection.point,s=r.applyQuaternion(this.dragStart.orientationWorld),o=kl(n.mouseRay,a,s),l=new Xt(this.dragStart.positionWorld,s),c=kl(l,a,s),h=this.dragStart.orientationWorld.clone().multiply(i).clone().inverse();o.sub(c),o.applyQuaternion(h);var u=this.dragStart.event3d.intersection.point.clone();u.sub(c),u.applyQuaternion(h);var d=Math.atan2(o.y,o.z),p=Math.atan2(u.y,u.z)-d,f=new gt;f.setFromAxisAngle(r,p),this.setOrientation(e,f.multiply(this.dragStart.orientationWorld)),n.stopPropagation()}}},{key:"feedbackEvent",value:function(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})}},{key:"startDrag",value:function(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var n=new vt;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,n),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}}},{key:"stopDrag",value:function(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))}},{key:"buttonClick",value:function(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)}},{key:"setPosition",value:function(e,t){this.position.copy(t),this.feedbackEvent("user-pose-change",e)}},{key:"setOrientation",value:function(e,t){t.normalize(),this.quaternion.copy(t),this.feedbackEvent("user-pose-change",e)}},{key:"onServerSetPose",value:function(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.copy(t.position),this.quaternion.copy(t.orientation),this.updateMatrixWorld(!0)}}},{key:"dispose",value:function(){this.children.forEach(function(e){e.children.forEach((function(t){t.dispose(),e.remove(t)})),this.remove(e)}.bind(this))}}])}(bn);function Wc(e,t,n){return t=ql(t),Xl(e,jc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function jc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(jc=function(){return!!e})()}var Xc=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Wc(this,t)).message=e.message,n.feedbackTopic=e.feedbackTopic,n.tfClient=e.tfClient,n.menuFontSize=e.menuFontSize||"0.8em",n.name=n.message.name,n.header=n.message.header,n.controls=n.message.controls,n.menuEntries=n.message.menu_entries,n.dragging=!1,n.timeoutHandle=null,n.tfTransform=new i.Transform,n.pose=new i.Pose,n.setPoseFromClientBound=n.setPoseFromClient.bind(n),n.onMouseDownBound=n.onMouseDown.bind(n),n.onMouseUpBound=n.onMouseUp.bind(n),n.onButtonClickBound=n.onButtonClick.bind(n),n.onMenuSelectBound=n.onMenuSelect.bind(n),n.setPoseFromServer(n.message.pose),n.tfUpdateBound=n.tfUpdate.bind(n),n}return Kl(t,EventEmitter3),jl(t,[{key:"subscribeTf",value:function(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}},{key:"unsubscribeTf",value:function(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}},{key:"emitServerPoseUpdate",value:function(){var e=new i.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}},{key:"setPoseFromServer",value:function(e){this.pose=new i.Pose(e),this.emitServerPoseUpdate()}},{key:"tfUpdate",value:function(e){this.tfTransform=new i.Transform(e),this.emitServerPoseUpdate()}},{key:"setPoseFromClient",value:function(e){this.pose=new i.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}},{key:"onButtonClick",value:function(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}},{key:"onMouseDown",value:function(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}},{key:"onMouseUp",value:function(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}},{key:"onMenuSelect",value:function(e){this.sendFeedback(2,void 0,e.id,e.controlName)}},{key:"sendFeedback",value:function(e,t,n,i){var r=void 0!==t;t=t||{x:0,y:0,z:0};var a={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:i,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:r,menu_entry_id:n};this.feedbackTopic.publish(a)}}])}(),qc=function(){return jl((function e(t){Hl(this,e),t=t||{},this.ros=t.ros,this.tfClient=t.tfClient,this.topicName=t.topic,this.path=t.path||"/",this.camera=t.camera,this.rootObject=t.rootObject||new bn,this.loader=t.loader,this.menuFontSize=t.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.processUpdateBound=this.processUpdate.bind(this),this.topicName&&this.subscribe(this.topicName)}),[{key:"subscribe",value:function(e){this.unsubscribe(),this.updateTopic=new i.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdateBound),this.feedbackTopic=new i.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new i.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new i.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}},{key:"unsubscribe",value:function(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdateBound),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}},{key:"processInit",value:function(e){var t=e.msg;for(var n in t.erases=[],this.interactiveMarkers)t.erases.push(n);t.poses=[],this.processUpdate(t)}},{key:"processUpdate",value:function(e){e.erases.forEach((function(e){this.eraseIntMarker(e)})),e.poses.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&t.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var t=this.interactiveMarkers[e.name];t&&this.eraseIntMarker(t.name);var n=new Xc({message:e,feedbackTopic:this.feedbackTopic,tfClient:this.tfClient,menuFontSize:this.menuFontSize});this.interactiveMarkers[e.name]=n;var i=new Gc({handle:n,camera:this.camera,path:this.path,loader:this.loader});i.name=e.name,this.rootObject.add(i),n.on("pose",(function(e){i.onServerSetPose({pose:e})})),i.addEventListener("user-pose-change",n.setPoseFromClientBound),i.addEventListener("user-mousedown",n.onMouseDownBound),i.addEventListener("user-mouseup",n.onMouseUpBound),i.addEventListener("user-button-click",n.onButtonClickBound),i.addEventListener("menu-select",n.onMenuSelectBound),n.subscribeTf()}))}},{key:"eraseIntMarker",value:function(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var n=this.interactiveMarkers[e];n.unsubscribeTf(),t.removeEventListener("user-pose-change",n.setPoseFromClientBound),t.removeEventListener("user-mousedown",n.onMouseDownBound),t.removeEventListener("user-mouseup",n.onMouseUpBound),t.removeEventListener("user-button-click",n.onButtonClickBound),t.removeEventListener("menu-select",n.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}}])}();function Yc(e,t,n){return t=ql(t),Xl(e,Kc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Kc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Kc=function(){return!!e})()}var Zc=function(e){function t(e){var n;Hl(this,t),e=e||{},(n=Yc(this,t)).tfClient=e.tfClient,n.frameID=e.frameID;var r=e.object;return n.pose=e.pose||new i.Pose,n.visible=!1,n.add(r),n.updatePose(n.pose),n.tfUpdate=function(e){var t=new i.Transform(e),n=new i.Pose(this.pose);n.applyTransform(t),this.updatePose(n),this.visible=!0},n.tfUpdateBound=n.tfUpdate.bind(n),n.tfClient.subscribe(n.frameID,n.tfUpdateBound),n}return Kl(t,e),jl(t,[{key:"updatePose",value:function(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}},{key:"unsubscribeTf",value:function(){this.tfClient.unsubscribe(this.frameID,this.tfUpdateBound)}}])}(bn);function Jc(e,t,n){return t=ql(t),Xl(e,Qc()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Qc(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Qc=function(){return!!e})()}var $c=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Jc(this,t)).ros=e.ros,n.topicName=e.topic,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.path=e.path||"/",n.markers={},n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,EventEmitter3),jl(t,[{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var n=!1;if(t in this.markers&&((n=this.markers[t].children[0].update(e))||this.removeMarker(t)),!n){var i=new Nc({message:e,path:this.path});this.markers[t]=new Zc({frameID:e.header.frame_id,tfClient:this.tfClient,object:i}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var r in this.markers)this.removeMarker(r);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}},{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"removeMarker",value:function(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((function(e){e.dispose()})),delete this.markers[e])}}])}();function eh(e,t,n){return t=ql(t),Xl(e,th()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function th(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(th=function(){return!!e})()}var nh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=eh(this,t)).ros=e.ros,n.topicName=e.topic,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.path=e.path||"/",n.lifetime=e.lifetime||0,n.markers={},n.rosTopic=void 0,n.updatedTime={},n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,EventEmitter3),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"checkTime",value:function(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){var t=e.ns+e.id,n=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),n?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var i=new Nc({message:e,path:this.path});this.markers[t]=new Zc({frameID:e.header.frame_id,tfClient:this.tfClient,object:i}),this.rootObject.add(this.markers[t])}this.emit("change")}},{key:"removeMarker",value:function(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((function(e){e.dispose()})),delete this.markers[e])}}])}();function ih(e,t,n){return t=ql(t),Xl(e,rh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function rh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(rh=function(){return!!e})()}var ah=function(e){function t(e){Hl(this,t);var n=(e=e||{}).origin||new vt(0,0,0),i=e.direction||new vt(1,0,0),r=e.length||1;return e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Hn,ih(this,t,[i,n,r,16711680])}return Kl(t,e),jl(t,[{key:"dispose",value:function(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}])}(Ol);function sh(e,t,n){return t=ql(t),Xl(e,oh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function oh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(oh=function(){return!!e})()}var lh=function(e){function t(e){var n;Hl(this,t);var i=n=sh(this,t),r=(e=e||{}).shaftRadius||.008,a=e.headRadius||.023,s=e.headLength||.1,o=e.scale||1,l=e.lineType||"full",c=e.lineDashLength||.1;function h(e){var t=new Fn;t.setRGB(e.x,e.y,e.z);var n=new Hn({color:t.getHex()}),a=new vt;a.crossVectors(e,new vt(0,-1,0));var s=new gt;s.setFromAxisAngle(a,.5*Math.PI);var o,h=new yi(i.headGeom,n);if(h.position.copy(e),h.position.multiplyScalar(.95),h.quaternion.copy(s),h.updateMatrix(),i.add(h),"dashed"===l)for(var u=c,d=0;u/2+3*u*d+u/2<=1;++d){var p=new Do(r,r,u);(o=new yi(p,n)).position.copy(e),o.position.multiplyScalar(u/2+3*u*d),o.quaternion.copy(s),o.updateMatrix(),i.add(o)}else"full"===l?((o=new yi(i.lineGeom,n)).position.copy(e),o.position.multiplyScalar(.45),o.quaternion.copy(s),o.updateMatrix(),i.add(o)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}return n.scale.set(o,o,o),n.lineGeom=new Do(r,r,1-s),n.headGeom=new Do(0,a,s),h(new vt(1,0,0)),h(new vt(0,1,0)),h(new vt(0,0,1)),n}return Kl(t,e),jl(t)}(bn);function ch(e,t,n){return t=ql(t),Xl(e,hh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function hh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(hh=function(){return!!e})()}var uh=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).num_cells||10,r=e.color||"#cccccc",a=e.lineWidth||1,s=e.cellSize||1;n=ch(this,t);for(var o=new mo({color:r,linewidth:a}),l=[],c=0;c<=i;++c){var h=s*i/2,u=h-c*s;l.push(new vt(-h,u,0),new vt(h,u,0)),l.push(new vt(u,-h,0),new vt(u,h,0))}var d=(new ti).setFromPoints(l),p=new Ao(d,o);return n.add(p),n}return Kl(t,e),jl(t)}(bn);function dh(e,t,n){return t=ql(t),Xl(e,ph()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function ph(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(ph=function(){return!!e})()}var fh=function(e){function t(e){var n;Hl(this,t);var i=(e=e||{}).message,r=e.opacity||1,a=e.color||{r:255,g:255,b:255,a:255},s=i.info,o=s.origin,l=s.width,c=s.height,h=new ji(l,c),u=new Uint8Array(l*c*4),d=new ho(u,l,c,I);d.flipY=!0,d.minFilter=m,d.magFilter=m,d.needsUpdate=!0;var p=new Hn({map:d,transparent:r<1,opacity:r});p.side=2,n=dh(this,t,[h,p]),Object.assign(n,e),n.quaternion.copy(new gt(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),n.position.x=l*s.resolution/2+o.position.x,n.position.y=c*s.resolution/2+o.position.y,n.position.z=o.position.z,n.scale.x=s.resolution,n.scale.y=s.resolution;var f=i.data;n.color=a,n.material=p,n.texture=d;for(var g=0;ge.length)&&(t=e.length);for(var n=0,i=Array(t);nn.length)throw new Error("Cannot read data stream. Overflow. Len="+n.length+" crsr="+n._cursor);var t=n._dataView[i](n._cursor,n.isLittleEndian);return n._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:function(){return n.cursor>=n.data.length}}),this}var wh=function(){return jl((function e(t){Hl(this,e),this.resolution=void 0!==t.resolution?t.resolution:1,this.color=new Fn(void 0!==t.color?t.color:"green"),this.opacity=void 0!==t.opacity?t.opacity:1,this.voxelRenderMode=void 0!==t.voxelRenderMode?t.voxelRenderMode:bh,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);for(var n=this.resolution,i=this._treeDepth-1;i>=0;--i)this.nodeSizeTable[i]=n,n*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}),[{key:"searchAtDepth",value:function(e,t){t=void 0!==t&&t>0?t:this._treeDepth;for(var n=this._adjustKeyAtDepth(e,t),i=this._treeDepth-t,r=this._rootNode,a=this._treeDepth-1;a>=i;--a){var s=this._computeChildIdx(n,a);if(!r.hasChildAt(s))return r.hasChildren()?null:r;r=r.getChildAt(s)}return r}},{key:"_computeCoordFromKey",value:function(e){var t=this;return e.map((function(e){return t.resolution*(e-t._treeMaxKeyVal)}))}},{key:"_computeChildIdx",value:function(e,t){var n=0;return e[0]&1<>i<0;)for(var i=n.pop(),r=t.readUint16(),a=8;0!==a;){var s=(r&3<<2*--a)>>2*a;if(s!==this._BINARY_UNALLOCATED){var o=this._newNode();this._BINARY_CHILD_BUILD_TABLE[s].bind(this)(o),i.createChildNodeAt(o,a),s===this._BINARY_HAS_CHILDREN&&n.push(o)}}}},{key:"read",value:function(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();var t=new Th(e,!0),n=new Array;for(n.push(this._rootNode);n.length>0;){var i=n.pop();this._readNodeData(t,i);for(var r=t.readUint8(),a=8;0!==a;){if(r&1<<--a){var s=this._newNode();s.value=null,i.createChildNodeAt(s,a),n.push(s)}}}}},{key:"_readNodeData",value:function(e,t){console.error("Not implemented")}},{key:"buildGeometry",value:function(){console.assert(null!==this._rootNode,"No tree data");var e=this._buildFaces(),t=e.vertices,n=e.normals,i=e.colors,r=e.indices,a=new ti,s=new Hn({color:"white",flatShading:!0,vertexColors:!0,transparent:this.opacity<1,opacity:this.opacity});a.addAttribute("position",new Wn(new Float32Array(t),3)),a.addAttribute("normal",new Wn(new Float32Array(n),3)),a.addAttribute("color",new Wn(new Float32Array(i),3)),a.setIndex(r);var o=new yi(a,s);this.object=new bn,this.object.add(o)}},{key:"_traverseLeaves",value:function(e){var t=new Array;for(t.push({node:this._rootNode,depth:0,key:[0,0,0]});t.length>0;){var n=t.pop();if(n.node.isLeafNode())e(n.node,n.key,n.depth-1);else for(var i=0;i<8;++i)if(n.node.hasChildAt(i)){var r=this._computeKeyFromChildIdx(i,n.key,n.depth);t.push({node:n.node.getChildAt(i),depth:n.depth+1,key:r})}}}},{key:"_obtainColor",value:function(e){return this.color}},{key:"_checkOccupied",value:function(e){return!1!==e.value}},{key:"_buildFaces",value:function(){var e=this,t={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,n,i){var r,a,s=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*n,t[1]+e[1]*n,t[2]+e[2]*n)}));var o=[i.r,i.g,i.b];(r=this.colors).push.apply(r,o.concat(o,o,o)),(a=this.normals).push.apply(a,yh(e.normal).concat(yh(e.normal),yh(e.normal),yh(e.normal))),this.indices.push(s,s+1,s+2,s+2,s+1,s+3)},_checkNeighborsTouchingFace:function(e,t,n){var i=new Array;i.push(t);for(var r=function(){var t=i.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;var r=t.getChildAt(e),a=this._checkOccupied(t);(a&&n===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!a&&n===Mh)&&i.push(r)}))};0!==i.length;)r();return!1}};return this._traverseLeaves((function(n,i,r){var a=e._computeCoordFromKey(i),s=e.nodeSizeTable[r],o=e._treeDepth-r,l=e._checkOccupied(n);(l||e.voxelRenderMode!==bh)&&(l&&e.voxelRenderMode===Mh||e._FACES.forEach((function(e){var l=[i[0]+e.normal[0]*o*o,i[1]+e.normal[1]*o*o,i[2]+e.normal[2]*o*o],c=this.searchAtDepth(l);null===c?t._insertFace(e,a,s,this._obtainColor(n)):r=this.palette.length-1?this.palette[this.palette.length-1]:{r:i*this.palette[n].r+(1-i)*this.palette[n+1].r,g:i*this.palette[n].g+(1-i)*this.palette[n+1].g,b:i*this.palette[n].b+(1-i)*this.palette[n+1].b}}},{key:"_checkOccupied",value:function(e){return e.value>=this.occupancyThreshold}}])}(wh);function Ph(e,t,n){return t=ql(t),Xl(e,Lh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Lh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Lh=function(){return!!e})()}var Ih=function(e){function t(e){var n;return Hl(this,t),(n=Ph(this,t,[e])).useOwnColor=void 0!==e.palette&&e.colorMode===Eh,n}return Kl(t,e),jl(t,[{key:"_readNodeData",value:function(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}},{key:"_obtainColor",value:function(e){return this.useOwnColor?e.color:Ch.prototype._obtainColor.call(this,e)}}])}(Ch);function Nh(e,t,n){return t=ql(t),Xl(e,Uh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Uh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Uh=function(){return!!e})()}var Dh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Nh(this,t)).ros=e.ros,n.topicName=e.topic||"/octomap",n.compression=e.compression||"cbor",n.continuous=e.continuous,n.tfClient=e.tfClient,n.rootObject=e.rootObject||new bn,n.offsetPose=e.offsetPose||new i.Pose,n.options={},void 0!==e.color&&(n.options.color=e.color),void 0!==e.opacity&&(n.options.opacity=e.opacity),void 0!==e.colorMode&&(n.options.colorMode=e.colorMode),void 0!==e.palette&&(n.options.palette=e.palette),void 0!==e.paletteScale&&(n.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(n.options.voxelRenderMode=e.voxelRenderMode),n.currentMap=null,n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,EventEmitter3),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"_loadOcTree",value:function(e){return new Promise(function(t,n){var i=Object.assign({resolution:e.resolution},this.options),r=null;if(e.binary)(r=new wh(i)).readBinary(e.data);else{var a={OcTree:Ch,ColorOcTree:Ih};e.id in a&&(console.log(e.id,a),(r=new a[e.id](i)).read(e.data))}r.buildGeometry(),t(r)}.bind(this))}},{key:"_processMessagePrivate",value:function(e){this._loadOcTree(e).then(function(t){var n=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new Zc({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(n),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}}])}();function Oh(e,t,n){return t=ql(t),Xl(e,Fh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Fh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Fh=function(){return!!e})()}var kh=function(e){function t(e){var n;return Hl(this,t),(n=Oh(this,t)).options=e||{},n.ros=e.ros,n.topicName=e.topic||"/particlecloud",n.tfClient=e.tfClient,n.color=e.color||13369599,n.length=e.length||1,n.rootObject=e.rootObject||new bn,n.keep=e.keep||1,n.sns=[],n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new vt(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new gt(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new vt(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Hn({color:this.color});var n=new ic(this.options);this.sns.push(new Zc({frameID:e.header.frame_id,tfClient:this.tfClient,object:n})),this.rootObject.add(this.sns[this.sns.length-1])}}])}(bn);function Bh(e,t,n){return t=ql(t),Xl(e,zh()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function zh(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(zh=function(){return!!e})()}var Hh=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=Bh(this,t)).ros=e.ros,n.topicName=e.topic||"/path",n.tfClient=e.tfClient,n.color=e.color||13369599,n.rootObject=e.rootObject||new bn,n.sn=null,n.line=null,n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new ti,n=0;n=e.range_min&&r<=e.range_max){var a=e.angle_min+i*e.angle_increment;this.points.positions.array[n++]=r*Math.cos(a),this.points.positions.array[n++]=r*Math.sin(a),this.points.positions.array[n++]=0}}this.points.update(n/3)}}}])}(bn);function cu(e,t,n){return t=ql(t),Xl(e,hu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function hu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(hu=function(){return!!e})()}var uu=function(e){function t(e){var n;Hl(this,t),e=e||{},(n=cu(this,t)).ros=e.ros,n.topicName=e.topic||"/gps/fix",n.rootObject=e.rootObject||new bn,n.object3d=e.object3d||new bn;var i=e.material||{};return n.altitudeNaN=e.altitudeNaN||0,n.keep=e.keep||100,n.convert=e.convert||function(e,t,n){return new vt(e,t,n)},n.count=0,n.next1=0,n.next2=n.keep,n.geom=new ti,n.vertices=new Wn(new Float32Array(6*n.keep),3),n.geom.addAttribute("position",n.vertices),n.material=i.isMaterial?i:new mo(i),n.line=new So(n.geom,n.material),n.rootObject.add(n.object3d),n.rootObject.add(n.line),n.rosTopic=void 0,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,n=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(n),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=n.x,this.vertices.array[3*this.next1+1]=n.y,this.vertices.array[3*this.next1+2]=n.z,this.vertices.array[3*this.next2]=n.x,this.vertices.array[3*this.next2+1]=n.y,this.vertices.array[3*this.next2+2]=n.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}])}(bn);function du(e,t,n){return t=ql(t),Xl(e,pu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function pu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(pu=function(){return!!e})()}function fu(e,t,n,i){var r,a=0,s=0,o=0,l=e.length,c=t.length,h=((i=i||1)-1)*(n=n||c)*8;for(r=0;r=8&&(s-=8,t[o++]=a>>>s&255,o%n==0&&(r+=Math.ceil((h-s)/6),(s%=8)>0&&(a=fu.e[e.charAt(r)])));return Math.floor(o/n)}fu.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fu.e={};for(var mu=0;mu<64;mu++)fu.e[fu.S.charAt(mu)]=mu;var gu=function(e){function t(e){var n;return Hl(this,t),e=e||{},(n=du(this,t)).ros=e.ros,n.topicName=e.topic||"/points",n.throttle_rate=e.throttle_rate||null,n.compression=e.compression||"cbor",n.max_pts=e.max_pts||1e4,n.points=new au(e),n.rosTopic=void 0,n.buffer=null,n.processMessageBound=n.processMessage.bind(n),n.subscribe(),n}return Kl(t,e),jl(t,[{key:"unsubscribe",value:function(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessageBound)}},{key:"subscribe",value:function(){this.unsubscribe(),this.rosTopic=new i.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessageBound)}},{key:"processMessage",value:function(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,n=this.points.pointRatio,i=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,i)),t=Math.min(e.height*e.width/n,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(i=p[0].object,d.intersection=this.lastIntersection=p[0]):i=this.fallbackTarget,i!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(i,"mouseover",d);0===f?this.notify(this.lastTarget,"mouseout",d):1===f&&(i=this.fallbackTarget)!==this.lastTarget&&(this.notify(i,"mouseover",d),this.notify(this.lastTarget,"mouseout",d))}i!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(i,e.type,d)?(this.notify(this.lastTarget,"touchleave",d),this.notify(this.lastTarget,"touchend",d)):(i=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",d),this.notify(this.lastTarget,"touchend",d)));this.notify(i,e.type,d),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=i}},{key:"notify",value:function(e,t,n){for(n.type=t,n.cancelBubble=!1,n.continueBubble=!1,n.stopPropagation=function(){n.cancelBubble=!0},n.continuePropagation=function(){n.continueBubble=!0},n.currentTarget=e;n.currentTarget;){if(n.currentTarget.dispatchEvent&&n.currentTarget.dispatchEvent instanceof Function){if(n.currentTarget.dispatchEvent(n),n.cancelBubble)return this.dispatchEvent(n),0;if(n.continueBubble)return 2}n.currentTarget=n.currentTarget.parent}return 1}}])}(Ie);function Ru(e,t,n){return t=ql(t),Xl(e,Cu()?Reflect.construct(t,n||[],ql(e).constructor):t.apply(e,n))}function Cu(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(Cu=function(){return!!e})()}var Pu=function(e){function t(e){var n;Hl(this,t);var i=n=Ru(this,t),r=(e=e||{}).scene;n.camera=e.camera,n.center=new vt,n.userZoom=!0,n.userZoomSpeed=e.userZoomSpeed||1,n.userRotate=!0,n.userRotateSpeed=e.userRotateSpeed||1,n.autoRotate=e.autoRotate,n.autoRotateSpeed=e.autoRotateSpeed||2,n.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,n.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",n.camera.up=new vt(0,0,1);var a=1800,s=new We,o=new We,l=new We,c=new We,h=new We,u=new We,d=new vt,p=new vt,f=new vt,m=new vt,g=new Array(2),v=new Array(2);n.phiDelta=0,n.thetaDelta=0,n.scale=1,n.lastPosition=new vt;var _=-1,y=0,x=1,b=2,M=_;function S(e,t,n){var i=new vt;new vt;i.subVectors(t,e.origin);var r=e.direction.dot(n);if(Math.abs(r)0?i.zoomIn():i.zoomOut(),this.showAxes()}}return n.axes=new lh({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:n.lineTypePanAndZoomFrame}),n.displayPanAndZoomFrame&&(r.add(n.axes),n.axes.traverse((function(e){e.visible=!1}))),n.addEventListener("mousedown",(function(e){var t=e.domEvent;switch(t.preventDefault(),t.button){case 0:M=y,s.set(t.clientX,t.clientY);break;case 1:M=b,p=new vt(0,0,1);var n=(new qt).extractRotation(this.camera.matrix);p.applyMatrix4(n),d=i.center.clone(),f=i.camera.position.clone(),m=S(e.mouseRay,d,p);break;case 2:M=x,c.set(t.clientX,t.clientY)}this.showAxes()})),n.addEventListener("mouseup",(function(e){i.userRotate&&(M=_)})),n.addEventListener("mousemove",(function(e){var t=e.domEvent;if(M===y)o.set(t.clientX,t.clientY),l.subVectors(o,s),i.rotateLeft(2*Math.PI*l.x/a*i.userRotateSpeed),i.rotateUp(2*Math.PI*l.y/a*i.userRotateSpeed),s.copy(o),this.showAxes();else if(M===x)h.set(t.clientX,t.clientY),u.subVectors(h,c),u.y>0?i.zoomIn():i.zoomOut(),c.copy(h),this.showAxes();else if(M===b){var n=S(e.mouseRay,i.center,p);if(!n)return;var r=(new vt).subVectors(m.clone(),n.clone());i.center.addVectors(d.clone(),r.clone()),i.camera.position.addVectors(f.clone(),r.clone()),i.update(),i.camera.updateMatrixWorld(),this.showAxes()}})),n.addEventListener("touchstart",(function(e){var t=e.domEvent;switch(t.touches.length){case 1:M=y,s.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY);break;case 2:M=_,p=new vt(0,0,1);var n=(new qt).extractRotation(this.camera.matrix);p.applyMatrix4(n),d=i.center.clone(),f=i.camera.position.clone(),m=S(e.mouseRay,d,p),g[0]=new We(t.touches[0].pageX,t.touches[0].pageY),g[1]=new We(t.touches[1].pageX,t.touches[1].pageY),v[0]=new We(0,0),v[1]=new We(0,0)}this.showAxes(),t.preventDefault()})),n.addEventListener("touchmove",(function(e){var t=e.domEvent;if(M===y)o.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY),l.subVectors(o,s),i.rotateLeft(2*Math.PI*l.x/a*i.userRotateSpeed),i.rotateUp(2*Math.PI*l.y/a*i.userRotateSpeed),s.copy(o),this.showAxes();else{if(v[0].set(g[0].x-t.touches[0].pageX,g[0].y-t.touches[0].pageY),v[1].set(g[1].x-t.touches[1].pageX,g[1].y-t.touches[1].pageY),v[0].lengthSq()>10&&v[1].lengthSq()>10&&(g[0].set(t.touches[0].pageX,t.touches[0].pageY),g[1].set(t.touches[1].pageX,t.touches[1].pageY),v[0].dot(v[1])>0&&M!==x?M=b:v[0].dot(v[1])<0&&M!==b&&(M=x),M===x)){var n=new We;n.subVectors(g[0],g[1]),v[0].dot(n)<0&&v[1].dot(n)>0?i.zoomOut():v[0].dot(n)>0&&v[1].dot(n)<0&&i.zoomIn()}if(M===b){var r=S(e.mouseRay,i.center,p);if(!r)return;var c=(new vt).subVectors(m.clone(),r.clone());i.center.addVectors(d.clone(),c.clone()),i.camera.position.addVectors(f.clone(),c.clone()),i.update(),i.camera.updateMatrixWorld()}this.showAxes(),t.preventDefault()}})),n.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&M!==y?(M=y,s.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):M=_})),n.addEventListener("mousewheel",E),n.addEventListener("DOMMouseScroll",E),n}return Kl(t,e),jl(t,[{key:"showAxes",value:function(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}},{key:"rotateLeft",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}},{key:"rotateRight",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}},{key:"rotateUp",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}},{key:"rotateDown",value:function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}},{key:"zoomIn",value:function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}},{key:"zoomOut",value:function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}},{key:"update",value:function(){var e=this.camera.position,t=e.clone().sub(this.center),n=Math.atan2(t.y,t.x),i=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),n+=this.thetaDelta,i+=this.phiDelta;var r=1e-6;i=Math.max(r,Math.min(Math.PI-r,i));var a=t.length();t.set(a*Math.sin(i)*Math.cos(n),a*Math.sin(i)*Math.sin(n),a*Math.cos(i)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),a=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*a,.05*a,.05*a),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}])}(Ie),Lu=function(){return jl((function e(t){Hl(this,e),console.log("Here 1");var n=(t=t||{}).divID,i=t.elem,r=t.width,a=t.height,s=t.background||"#111111",o=t.antialias,l=t.intensity||.66,c=t.near||.01,h=t.far||1e3,u=t.alpha||1,d=t.cameraPose||{x:3,y:3,z:3},p=t.cameraZoomSpeed||.5,f=void 0===t.displayPanAndZoomFrame||!!t.displayPanAndZoomFrame,m=t.lineTypePanAndZoomFrame||"full";this.renderer=new Is({antialias:o,alpha:!0}),this.renderer.setClearColor(parseInt(s.replace("#","0x"),16),u),this.renderer.sortObjects=!1,this.renderer.setSize(r,a),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ns,this.camera=new Li(40,r/a,c,h),this.camera.position.x=d.x,this.camera.position.y=d.y,this.camera.position.z=d.z,this.cameraControls=new Pu({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:f,lineTypePanAndZoomFrame:m}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Al(5592405)),this.directionalLight=new wl(16777215,l),this.scene.add(this.directionalLight),console.log("Here 2"),this.selectableObjects=new Ss,this.scene.add(this.selectableObjects);var g=new Au({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Eu({mouseHandler:g}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(n)).appendChild(this.renderer.domElement),this.start(),console.log("Here 3")}),[{key:"start",value:function(){this.stopped=!1,this.draw()}},{key:"draw",value:function(){this.stopped||(this.cameraControls.update(),console.log("Here 5"),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}},{key:"stop",value:function(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}},{key:"addObject",value:function(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}},{key:"resize",value:function(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}}])}();return e.Arrow=ic,e.Arrow2=ah,e.Axes=lh,e.ColorOcTree=Ih,e.DepthCloud=Ql,e.Grid=uh,e.Highlighter=Eu,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=Gc,e.InteractiveMarkerClient=qc,e.InteractiveMarkerControl=Fc,e.InteractiveMarkerHandle=Xc,e.InteractiveMarkerMenu=zc,e.LaserScan=lu,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=Nc,e.MarkerArrayClient=$c,e.MarkerClient=nh,e.MeshLoader=Ec,e.MeshResource=Ac,e.MouseHandler=Au,e.NavSatFix=uu,e.OcTree=Ch,e.OcTreeClient=Dh,e.OccupancyGrid=fh,e.OccupancyGridClient=vh,e.Odometry=kh,e.OrbitControls=Pu,e.Path=Hh,e.Point=Wh,e.PointCloud2=gu,e.Points=au,e.Polygon=qh,e.Pose=Zh,e.PoseArray=$h,e.PoseWithCovariance=nu,e.SceneNode=Zc,e.TFAxes=yu,e.TriangleList=Pc,e.Urdf=Mu,e.UrdfClient=Su,e.Viewer=Lu,e.closestAxisPoint=zl,e.findClosestPoint=Bl,e.intersectPlane=kl,e.makeColorMaterial=Fl,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); diff --git a/package-lock.json b/package-lock.json index f5a27ba1..a1d735eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@babel/preset-env": "^7.25.2", "@babel/runtime": "^7.25.0", "@rollup/plugin-babel": "^6.0.4", - "eventemitter2": "^6.4.0", + "eventemitter3": "^5.0.1", "roslib": "^1.0.0", "three": "^0.167.0" }, @@ -4219,10 +4219,9 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" }, "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/exit": { "version": "0.1.2", @@ -5518,6 +5517,12 @@ "node": ">= 6" } }, + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -12854,10 +12859,9 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" }, "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "exit": { "version": "0.1.2", @@ -13819,6 +13823,14 @@ "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + } } }, "http-proxy-agent": { diff --git a/package.json b/package.json index 9ee45c4c..4f1e6c65 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@babel/preset-env": "^7.25.2", "@babel/runtime": "^7.25.0", "@rollup/plugin-babel": "^6.0.4", - "eventemitter2": "^6.4.0", + "eventemitter3": "^5.0.1", "roslib": "^1.0.0", "three": "^0.167.0" }, diff --git a/src/interactivemarkers/InteractiveMarkerHandle.js b/src/interactivemarkers/InteractiveMarkerHandle.js index c9c75484..af2ed1d4 100644 --- a/src/interactivemarkers/InteractiveMarkerHandle.js +++ b/src/interactivemarkers/InteractiveMarkerHandle.js @@ -43,7 +43,7 @@ ROS3D.InteractiveMarkerHandle = function(options) { this.setPoseFromServer(this.message.pose); this.tfUpdateBound = this.tfUpdate.bind(this); }; -ROS3D.InteractiveMarkerHandle.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.InteractiveMarkerHandle.prototype.__proto__ = EventEmitter3.prototype; /** * Subscribe to the TF associated with this interactive marker. diff --git a/src/markers/MarkerArrayClient.js b/src/markers/MarkerArrayClient.js index 6353c176..00be1831 100644 --- a/src/markers/MarkerArrayClient.js +++ b/src/markers/MarkerArrayClient.js @@ -35,7 +35,7 @@ ROS3D.MarkerArrayClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.MarkerArrayClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.MarkerArrayClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.MarkerArrayClient.prototype.subscribe = function(){ this.unsubscribe(); diff --git a/src/markers/MarkerClient.js b/src/markers/MarkerClient.js index 896f01f4..9cb5d4ed 100644 --- a/src/markers/MarkerClient.js +++ b/src/markers/MarkerClient.js @@ -37,7 +37,7 @@ ROS3D.MarkerClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.MarkerClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.MarkerClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.MarkerClient.prototype.unsubscribe = function(){ if(this.rosTopic){ diff --git a/src/navigation/OcTreeClient.js b/src/navigation/OcTreeClient.js index 1983b2b0..722e1dad 100644 --- a/src/navigation/OcTreeClient.js +++ b/src/navigation/OcTreeClient.js @@ -30,7 +30,7 @@ */ ROS3D.OcTreeClient = function(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/octomap'; @@ -60,7 +60,7 @@ ROS3D.OcTreeClient = function(options) { this.subscribe(); }; -ROS3D.OcTreeClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.OcTreeClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.OcTreeClient.prototype.unsubscribe = function () { if (this.rosTopic) { diff --git a/src/navigation/OccupancyGridClient.js b/src/navigation/OccupancyGridClient.js index 493831e2..011e69d4 100644 --- a/src/navigation/OccupancyGridClient.js +++ b/src/navigation/OccupancyGridClient.js @@ -24,7 +24,7 @@ * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) */ ROS3D.OccupancyGridClient = function(options) { - EventEmitter2.call(this); + EventEmitter3.call(this); options = options || {}; this.ros = options.ros; this.topicName = options.topic || '/map'; @@ -44,7 +44,7 @@ ROS3D.OccupancyGridClient = function(options) { this.processMessageBound = this.processMessage.bind(this); this.subscribe(); }; -ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter2.prototype; +ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter3.prototype; ROS3D.OccupancyGridClient.prototype.unsubscribe = function(){ if(this.rosTopic){ From 0f268a23225c74e6c160f73b248d0bb0bde1fb1e Mon Sep 17 00:00:00 2001 From: Anna-Maria Meer Date: Tue, 17 Sep 2024 16:47:47 +0200 Subject: [PATCH 5/8] Add proper lightning --- src/models/Grid.js | 2 +- src/models/MeshLoader.js | 4 ++++ src/urdf/Urdf.js | 5 ++--- src/visualization/Viewer.js | 15 +++++---------- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/models/Grid.js b/src/models/Grid.js index f83f42ac..8fa1167c 100644 --- a/src/models/Grid.js +++ b/src/models/Grid.js @@ -18,7 +18,7 @@ ROS3D.Grid = function(options) { options = options || {}; var num_cells = options.num_cells || 10; - var color = options.color || '#cccccc'; + var color = options.color || '#000000'; var lineWidth = options.lineWidth || 1; var cellSize = options.cellSize || 1; diff --git a/src/models/MeshLoader.js b/src/models/MeshLoader.js index 928b57a7..534b2e26 100644 --- a/src/models/MeshLoader.js +++ b/src/models/MeshLoader.js @@ -104,6 +104,10 @@ ROS3D.MeshLoader = { 'stl': function (meshRes, uri, options) { const material = options.material; const loader = new STLLoader(options.loader); + console.log('Loading stl: ' + uri); + console.log(options.material); + + { loader.load(uri, function (geometry) { diff --git a/src/urdf/Urdf.js b/src/urdf/Urdf.js index 2de3982c..c49d15bc 100644 --- a/src/urdf/Urdf.js +++ b/src/urdf/Urdf.js @@ -45,16 +45,15 @@ ROS3D.Urdf = function(options) { var uri = visual.geometry.filename; // strips package:// - console.log('uri ' +uri) var tmpIndex = uri.indexOf('package://'); - console.log('tmpIndex ' +tmpIndex) if (tmpIndex !== -1) { uri = uri.substr(tmpIndex + ('package://').length); } - console.log('uri2 ' +uri) var fileType = uri.substr(-3).toLowerCase(); + console.log('material ' +colorMaterial) + console.log('filetype ' +fileType) if (ROS3D.MeshLoader.loaders[fileType]) { // create the model diff --git a/src/visualization/Viewer.js b/src/visualization/Viewer.js index 0974905f..38bb5050 100644 --- a/src/visualization/Viewer.js +++ b/src/visualization/Viewer.js @@ -28,15 +28,14 @@ */ ROS3D.Viewer = function(options) { - console.log('Here 1'); options = options || {}; var divID = options.divID; var elem = options.elem; var width = options.width; var height = options.height; - var background = options.background || '#111111'; + var background = options.background || '#cccccc'; var antialias = options.antialias; - var intensity = options.intensity || 0.66; + var intensity = options.intensity || 0.8; var near = options.near || 0.01; var far = options.far || 1000; var alpha = options.alpha || 1.0; @@ -78,10 +77,9 @@ ROS3D.Viewer = function(options) { this.cameraControls.userZoomSpeed = cameraZoomSpeed; // lights - this.scene.add(new THREE.AmbientLight(0x555555)); + this.scene.add(new THREE.AmbientLight(0xffffff, 0.6)); this.directionalLight = new THREE.DirectionalLight(0xffffff, intensity); this.scene.add(this.directionalLight); - console.log('Here 2'); // propagates mouse events to three.js objects this.selectableObjects = new THREE.Group(); @@ -107,8 +105,6 @@ ROS3D.Viewer = function(options) { // begin the render loop this.start(); - console.log('Here 3'); - }; /** @@ -130,13 +126,12 @@ ROS3D.Viewer.prototype.draw = function(){ // update the controls this.cameraControls.update(); - console.log('Here 5') // put light to the top-left of the camera // BUG: position is a read-only property of DirectionalLight, // attempting to assign to it either does nothing or throws an error. - //this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); - this.directionalLight.position.normalize(); + // this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); + // this.directionalLight.position.normalize(); // set the scene this.renderer.clear(true, true, true); From 18777988b66d206400a505332063707a72a6fef5 Mon Sep 17 00:00:00 2001 From: Anna-Maria Meer Date: Mon, 25 Nov 2024 15:44:23 +0100 Subject: [PATCH 6/8] fix lightning --- src/visualization/Viewer.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/visualization/Viewer.js b/src/visualization/Viewer.js index 38bb5050..09a055d7 100644 --- a/src/visualization/Viewer.js +++ b/src/visualization/Viewer.js @@ -118,6 +118,7 @@ ROS3D.Viewer.prototype.start = function(){ /** * Renders the associated scene to the viewer. */ + ROS3D.Viewer.prototype.draw = function(){ if(this.stopped){ // Do nothing if stopped @@ -127,11 +128,9 @@ ROS3D.Viewer.prototype.draw = function(){ // update the controls this.cameraControls.update(); - // put light to the top-left of the camera - // BUG: position is a read-only property of DirectionalLight, - // attempting to assign to it either does nothing or throws an error. - // this.directionalLight.position = this.camera.localToWorld(new THREE.Vector3(-1, 1, 0)); - // this.directionalLight.position.normalize(); + // Update the directional light position to follow the camera + this.directionalLight.position.copy(this.camera.position); + this.directionalLight.position.add(new THREE.Vector3(1, 1, 1)); // Adjust this vector for light offset // set the scene this.renderer.clear(true, true, true); From e3141a83623dd34e96bcc0832b70dcfca032c7f7 Mon Sep 17 00:00:00 2001 From: Anna-Maria Meer Date: Mon, 25 Nov 2024 16:14:07 +0100 Subject: [PATCH 7/8] remove ambient light --- src/visualization/Viewer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/visualization/Viewer.js b/src/visualization/Viewer.js index 09a055d7..22973b03 100644 --- a/src/visualization/Viewer.js +++ b/src/visualization/Viewer.js @@ -77,7 +77,6 @@ ROS3D.Viewer = function(options) { this.cameraControls.userZoomSpeed = cameraZoomSpeed; // lights - this.scene.add(new THREE.AmbientLight(0xffffff, 0.6)); this.directionalLight = new THREE.DirectionalLight(0xffffff, intensity); this.scene.add(this.directionalLight); From c19f6d46081c71e20b266b42dd29a9674910ec11 Mon Sep 17 00:00:00 2001 From: Anna-Maria Meer Date: Mon, 2 Dec 2024 08:03:09 +0100 Subject: [PATCH 8/8] add parameters to improve lightning --- src/models/MeshLoader.js | 3 +-- src/urdf/Urdf.js | 22 +++++++++++++++++----- src/visualization/Viewer.js | 18 ++++++++++++------ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/models/MeshLoader.js b/src/models/MeshLoader.js index 534b2e26..05a0231c 100644 --- a/src/models/MeshLoader.js +++ b/src/models/MeshLoader.js @@ -30,10 +30,9 @@ ROS3D.MeshLoader = { const loader = new ColladaLoader(options.loader); - console.log('Loading collada: ' + uri) loader.load(uri, function (collada_mesh) { let model = collada_mesh.scene; - meshRes.add (model) + meshRes.add (model); console.log('Done loading collada'); }); diff --git a/src/urdf/Urdf.js b/src/urdf/Urdf.js index c49d15bc..1dae430b 100644 --- a/src/urdf/Urdf.js +++ b/src/urdf/Urdf.js @@ -23,7 +23,6 @@ ROS3D.Urdf = function(options) { var tfClient = options.tfClient; var tfPrefix = options.tfPrefix || ''; var loader = options.loader; - console.log('Path ' +path) THREE.Object3D.call(this); // load all models @@ -39,7 +38,14 @@ ROS3D.Urdf = function(options) { var colorMaterial = null; if (visual.material && visual.material.color) { var color = visual.material && visual.material.color; - colorMaterial = ROS3D.makeColorMaterial(color.r, color.g, color.b, color.a); + // This replaces the previous simple material setup + var colorMaterial = new THREE.MeshStandardMaterial({ + color: new THREE.Color(color.r, color.g, color.b), + roughness: 0.9, // Higher roughness makes shadows more defined + metalness: 0.7, // Slightly metallic to help with light reflection + }); + + //colorMaterial = ROS3D.makeColorMaterial(color.r, color.g, color.b, color.a); } if (visual.geometry.type === ROSLIB.URDF_MESH) { @@ -52,8 +58,6 @@ ROS3D.Urdf = function(options) { } var fileType = uri.substr(-3).toLowerCase(); - console.log('material ' +colorMaterial) - console.log('filetype ' +fileType) if (ROS3D.MeshLoader.loaders[fileType]) { // create the model @@ -64,6 +68,9 @@ ROS3D.Urdf = function(options) { material : colorMaterial }); + mesh.castShadow = true; // Enable the mesh to cast shadows + mesh.receiveShadow = true; // Enable the mesh to receive shadows + // check for a scale if(link.visuals[i].geometry.scale) { mesh.scale.copy(visual.geometry.scale); @@ -101,7 +108,12 @@ ROS3D.Urdf = function(options) { ROS3D.Urdf.prototype.createShapeMesh = function(visual, options) { var colorMaterial = null; if (!colorMaterial) { - colorMaterial = ROS3D.makeColorMaterial(0, 0, 0, 1); + var colorMaterial = new THREE.MeshStandardMaterial({ + color: new THREE.Color(0, 0, 1), // Color from URDF + metalness: 1.0, // Full metallic surface + roughness: 0.3, // Shiny surface (low roughness) + emissive: new THREE.Color(0, 0, 1), // Optional: emissive for glow + }); } var shapeMesh; // Create a shape diff --git a/src/visualization/Viewer.js b/src/visualization/Viewer.js index 22973b03..9ba1221e 100644 --- a/src/visualization/Viewer.js +++ b/src/visualization/Viewer.js @@ -33,16 +33,16 @@ ROS3D.Viewer = function(options) { var elem = options.elem; var width = options.width; var height = options.height; - var background = options.background || '#cccccc'; + var background = options.background || '#ffffff'; var antialias = options.antialias; - var intensity = options.intensity || 0.8; + var intensity = options.intensity || 2.5; var near = options.near || 0.01; var far = options.far || 1000; var alpha = options.alpha || 1.0; var cameraPosition = options.cameraPose || { x : 3, y : 3, - z : 3 + z : 7 }; var cameraZoomSpeed = options.cameraZoomSpeed || 0.5; var displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? true : !!options.displayPanAndZoomFrame; @@ -56,7 +56,7 @@ ROS3D.Viewer = function(options) { this.renderer.setClearColor(parseInt(background.replace('#', '0x'), 16), alpha); this.renderer.sortObjects = false; this.renderer.setSize(width, height); - this.renderer.shadowMap.enabled = false; + this.renderer.shadowMap.enabled = true; this.renderer.autoClear = false; // create the global scene @@ -129,8 +129,14 @@ ROS3D.Viewer.prototype.draw = function(){ // Update the directional light position to follow the camera this.directionalLight.position.copy(this.camera.position); - this.directionalLight.position.add(new THREE.Vector3(1, 1, 1)); // Adjust this vector for light offset - + this.directionalLight.position.add(new THREE.Vector3(0, 1, 1)); // Adjust this vector for light offset + + // Set up the directional light to cast shadows + this.directionalLight.castShadow = true; + this.directionalLight.shadow.mapSize.width = 2024; + this.directionalLight.shadow.mapSize.height = 1024; + this.directionalLight.shadow.bias = -0.005; // Prevents shadow acne (shadow artifacts) + this.directionalLight.shadow.radius = 5; // Larger radius creates softer shadows // set the scene this.renderer.clear(true, true, true); this.renderer.render(this.scene, this.camera);